/* Copyright (c) 2007-2008 The Florida State University
 * Copyright (c) 2009 The University of Edinburgh
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __ARCH_POWER_INSTS_BRANCH_HH__
#define __ARCH_POWER_INSTS_BRANCH_HH__

#include "arch/power/insts/static_inst.hh"

namespace PowerISA
{

/**
 * Base class for instructions whose disassembly is not purely a
 * function of the machine instruction (i.e., it depends on the
 * PC).  This class overrides the disassemble() method to check
 * the PC and symbol table values before re-using a cached
 * disassembly string.  This is necessary for branches and jumps,
 * where the disassembly string includes the target address (which
 * may depend on the PC and/or symbol table).
 */
class PCDependentDisassembly : public PowerStaticInst
{
  protected:
    /// Cached program counter from last disassembly
    mutable Addr cachedPC;
    /// Cached symbol table pointer from last disassembly
    mutable const Loader::SymbolTable *cachedSymtab;

    /// Constructor
    PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
                           OpClass __opClass)
        : PowerStaticInst(mnem, _machInst, __opClass),
          cachedPC(0), cachedSymtab(0)
    {
    }

    const std::string &
    disassemble(Addr pc, const Loader::SymbolTable *symtab) const;
};

/**
 * Base class for unconditional, PC-relative branches.
 */
class BranchPCRel : public PCDependentDisassembly
{
  protected:

    /// Displacement
    uint32_t disp;

    /// Constructor.
    BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
        : PCDependentDisassembly(mnem, _machInst, __opClass),
          disp(machInst.li << 2)
    {
        // If bit 26 is 1 then sign extend
        if (disp & 0x2000000) {
            disp |= 0xfc000000;
        }
    }

    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;

    /// Explicitly import the otherwise hidden branchTarget
    using StaticInst::branchTarget;

    std::string generateDisassembly(
            Addr pc, const Loader::SymbolTable *symtab) const override;
};

/**
 * Base class for unconditional, non PC-relative branches.
 */
class BranchNonPCRel : public PCDependentDisassembly
{
  protected:

    /// Target address
    uint32_t targetAddr;

    /// Constructor.
    BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
        : PCDependentDisassembly(mnem, _machInst, __opClass),
          targetAddr(machInst.li << 2)
    {
        // If bit 26 is 1 then sign extend
        if (targetAddr & 0x2000000) {
            targetAddr |= 0xfc000000;
        }
    }

    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;

    /// Explicitly import the otherwise hidden branchTarget
    using StaticInst::branchTarget;

    std::string generateDisassembly(
            Addr pc, const Loader::SymbolTable *symtab) const override;
};

/**
 * Base class for conditional branches.
 */
class BranchCond : public PCDependentDisassembly
{
  protected:

    /// Fields needed for conditions
    uint32_t bo;
    uint32_t bi;

    /// Constructor.
    BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass)
        : PCDependentDisassembly(mnem, _machInst, __opClass),
          bo(machInst.bo),
          bi(machInst.bi)
    {
    }

    inline bool
    ctrOk(uint32_t& ctr) const
    {
        bool ctr_ok;
        if (bo & 4) {
            ctr_ok = true;
        } else {
            ctr--;
            if (ctr != 0) {
                ctr_ok = ((bo & 2) == 0);
            } else {
                ctr_ok = ((bo & 2) != 0);
            }
        }
        return ctr_ok;
    }

    inline bool
    condOk(uint32_t cr) const
    {
        bool cond_ok;
        if (bo & 16) {
            cond_ok = true;
        } else {
            cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1));
        }
        return cond_ok;
    }
};

/**
 * Base class for conditional, PC-relative branches.
 */
class BranchPCRelCond : public BranchCond
{
  protected:

    /// Displacement
    uint32_t disp;

    /// Constructor.
    BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
        : BranchCond(mnem, _machInst, __opClass),
          disp(machInst.bd << 2)
    {
        // If bit 16 is 1 then sign extend
        if (disp & 0x8000) {
            disp |= 0xffff0000;
        }
    }

    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;

    /// Explicitly import the otherwise hidden branchTarget
    using StaticInst::branchTarget;

    std::string generateDisassembly(
            Addr pc, const Loader::SymbolTable *symtab) const override;
};

/**
 * Base class for conditional, non PC-relative branches.
 */
class BranchNonPCRelCond : public BranchCond
{
  protected:

    /// Target address
    uint32_t targetAddr;

    /// Constructor.
    BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
        : BranchCond(mnem, _machInst, __opClass),
          targetAddr(machInst.bd << 2)
    {
        // If bit 16 is 1 then sign extend
        if (targetAddr & 0x8000) {
            targetAddr |= 0xffff0000;
        }
    }

    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;

    /// Explicitly import the otherwise hidden branchTarget
    using StaticInst::branchTarget;

    std::string generateDisassembly(
            Addr pc, const Loader::SymbolTable *symtab) const override;
};

/**
 * Base class for conditional, register-based branches
 */
class BranchRegCond : public BranchCond
{
  protected:

    /// Constructor.
    BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass)
        : BranchCond(mnem, _machInst, __opClass)
    {
    }

    PowerISA::PCState branchTarget(ThreadContext *tc) const override;

    /// Explicitly import the otherwise hidden branchTarget
    using StaticInst::branchTarget;

    std::string generateDisassembly(
            Addr pc, const Loader::SymbolTable *symtab) const override;
};

} // namespace PowerISA

#endif //__ARCH_POWER_INSTS_BRANCH_HH__
