blob: d96bcfe1b1fffb88936f7016e4ca20d9e1a7081b [file] [log] [blame]
/* Copyright (c) 2007-2008 The Florida State University
* Copyright (c) 2009 The University of Edinburgh
* Copyright (c) 2021 IBM Corporation
* 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 gem5
{
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 or absolute address branches.
*/
class BranchOp : public PCDependentDisassembly
{
protected:
bool aa;
bool lk;
int64_t li;
/// Constructor
BranchOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PCDependentDisassembly(mnem, _machInst, __opClass),
aa(machInst.aa),
lk(machInst.lk),
li(sext<26>(machInst.li << 2))
{
}
std::unique_ptr<PCStateBase> 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;
};
/**
* Base class for conditional branches.
*/
class BranchCondOp : public PCDependentDisassembly
{
protected:
bool lk;
uint8_t bi;
uint8_t bo;
/// Constructor
BranchCondOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: PCDependentDisassembly(mnem, _machInst, __opClass),
lk(machInst.lk),
bi(machInst.bi),
bo(machInst.bo)
{
}
inline bool
ctrOk(uint64_t& ctr) const
{
if (bits(bo, 2)) {
return true;
}
ctr--;
return !((ctr != 0) ^ (bits(bo, 1) == 0));
}
inline bool
condOk(uint32_t cr) const
{
if (bits(bo, 4)) {
return true;
}
return bits(cr >> (31 - bi), 0) == bits(bo >> 3, 0);
}
};
/**
* Base class for conditional, PC-relative or absolute address branches.
*/
class BranchDispCondOp : public BranchCondOp
{
protected:
bool aa;
int64_t bd;
/// Constructor
BranchDispCondOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: BranchCondOp(mnem, _machInst, __opClass),
aa(machInst.aa),
bd(sext<16>(machInst.bd << 2))
{
}
std::unique_ptr<PCStateBase> 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;
};
/**
* Base class for conditional, register-based branches.
*/
class BranchRegCondOp : public BranchCondOp
{
protected:
/// TODO: Branch hints are currently ignored
uint8_t bh;
/// Constructor.
BranchRegCondOp(const char *mnem, MachInst _machInst, OpClass __opClass)
: BranchCondOp(mnem, _machInst, __opClass),
bh(machInst.bh)
{
}
std::unique_ptr<PCStateBase> 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
} // namespace gem5
#endif //__ARCH_POWER_INSTS_BRANCH_HH__