microinstruction: Introduce convenience informational functions

Whenever more rigorous optimizations are attempted (or even basic ones),
it's usually helpful to know what overall kind of instruction is being
dealt with, in the event certain classes of instructions may be eligible
for optimization.
This commit is contained in:
Lioncash 2016-08-22 12:54:47 -04:00 committed by MerryMage
parent 06ec4b5977
commit 47f285249b
2 changed files with 253 additions and 0 deletions

View file

@ -10,6 +10,210 @@
namespace Dynarmic { namespace Dynarmic {
namespace IR { namespace IR {
bool Inst::IsArithmeticShift() const {
return op == Opcode::ArithmeticShiftRight;
}
bool Inst::IsCircularShift() const {
return op == Opcode::RotateRight ||
op == Opcode::RotateRightExtended;
}
bool Inst::IsLogicalShift() const {
switch (op) {
case Opcode::LogicalShiftLeft:
case Opcode::LogicalShiftRight:
case Opcode::LogicalShiftRight64:
return true;
default:
return false;
}
}
bool Inst::IsShift() const {
return IsArithmeticShift() ||
IsCircularShift() ||
IsLogicalShift();
}
bool Inst::IsSharedMemoryRead() const {
switch (op) {
case Opcode::ReadMemory8:
case Opcode::ReadMemory16:
case Opcode::ReadMemory32:
case Opcode::ReadMemory64:
return true;
default:
return false;
}
}
bool Inst::IsSharedMemoryWrite() const {
switch (op) {
case Opcode::WriteMemory8:
case Opcode::WriteMemory16:
case Opcode::WriteMemory32:
case Opcode::WriteMemory64:
return true;
default:
return false;
}
}
bool Inst::IsSharedMemoryReadOrWrite() const {
return IsSharedMemoryRead() || IsSharedMemoryWrite();
}
bool Inst::IsExclusiveMemoryWrite() const {
switch (op) {
case Opcode::ExclusiveWriteMemory8:
case Opcode::ExclusiveWriteMemory16:
case Opcode::ExclusiveWriteMemory32:
case Opcode::ExclusiveWriteMemory64:
return true;
default:
return false;
}
}
bool Inst::IsMemoryRead() const {
return IsSharedMemoryRead();
}
bool Inst::IsMemoryWrite() const {
return IsSharedMemoryWrite() || IsExclusiveMemoryWrite();
}
bool Inst::IsMemoryReadOrWrite() const {
return IsMemoryRead() || IsMemoryWrite();
}
bool Inst::ReadsFromCPSR() const {
switch (op) {
case Opcode::GetCpsr:
case Opcode::GetNFlag:
case Opcode::GetZFlag:
case Opcode::GetCFlag:
case Opcode::GetVFlag:
return true;
default:
return false;
}
}
bool Inst::WritesToCPSR() const {
switch (op) {
case Opcode::SetCpsr:
case Opcode::SetNFlag:
case Opcode::SetZFlag:
case Opcode::SetCFlag:
case Opcode::SetVFlag:
case Opcode::OrQFlag:
return true;
default:
return false;
}
}
bool Inst::ReadsFromCoreRegister() const {
switch (op) {
case Opcode::GetRegister:
case Opcode::GetExtendedRegister32:
case Opcode::GetExtendedRegister64:
return true;
default:
return false;
}
}
bool Inst::WritesToCoreRegister() const {
switch (op) {
case Opcode::SetRegister:
case Opcode::SetExtendedRegister32:
case Opcode::SetExtendedRegister64:
case Opcode::BXWritePC:
return true;
default:
return false;
}
}
bool Inst::ReadsFromFPSCR() const {
switch (op) {
case Opcode::FPAbs32:
case Opcode::FPAbs64:
case Opcode::FPAdd32:
case Opcode::FPAdd64:
case Opcode::FPDiv32:
case Opcode::FPDiv64:
case Opcode::FPMul32:
case Opcode::FPMul64:
case Opcode::FPNeg32:
case Opcode::FPNeg64:
case Opcode::FPSqrt32:
case Opcode::FPSqrt64:
case Opcode::FPSub32:
case Opcode::FPSub64:
return true;
default:
return false;
}
}
bool Inst::WritesToFPSCR() const {
switch (op) {
case Opcode::FPAbs32:
case Opcode::FPAbs64:
case Opcode::FPAdd32:
case Opcode::FPAdd64:
case Opcode::FPDiv32:
case Opcode::FPDiv64:
case Opcode::FPMul32:
case Opcode::FPMul64:
case Opcode::FPNeg32:
case Opcode::FPNeg64:
case Opcode::FPSqrt32:
case Opcode::FPSqrt64:
case Opcode::FPSub32:
case Opcode::FPSub64:
return true;
default:
return false;
}
}
bool Inst::CausesCPUException() const {
return op == Opcode::Breakpoint ||
op == Opcode::CallSupervisor;
}
bool Inst::AltersExclusiveState() const {
return op == Opcode::ClearExclusive ||
op == Opcode::SetExclusive ||
IsExclusiveMemoryWrite();
}
bool Inst::MayHaveSideEffects() const {
return op == Opcode::PushRSB ||
CausesCPUException() ||
WritesToCoreRegister() ||
WritesToCPSR() ||
WritesToFPSCR() ||
AltersExclusiveState() ||
IsMemoryWrite();
}
Value Inst::GetArg(size_t index) const { Value Inst::GetArg(size_t index) const {
DEBUG_ASSERT(index < GetNumArgsOf(op)); DEBUG_ASSERT(index < GetNumArgsOf(op));
DEBUG_ASSERT(!args[index].IsEmpty()); DEBUG_ASSERT(!args[index].IsEmpty());

View file

@ -24,6 +24,55 @@ class Inst final : public Common::IntrusiveListNode<Inst> {
public: public:
explicit Inst(Opcode op) : op(op) {} explicit Inst(Opcode op) : op(op) {}
/// Determines whether or not this instruction performs an arithmetic shift.
bool IsArithmeticShift() const;
/// Determines whether or not this instruction performs a logical shift.
bool IsLogicalShift() const;
/// Determines whether or not this instruction performs a circular shift.
bool IsCircularShift() const;
/// Determines whether or not this instruction performs any kind of shift.
bool IsShift() const;
/// Determines whether or not this instruction performs a shared memory read.
bool IsSharedMemoryRead() const;
/// Determines whether or not this instruction performs a shared memory write.
bool IsSharedMemoryWrite() const;
/// Determines whether or not this instruction performs a shared memory read or write.
bool IsSharedMemoryReadOrWrite() const;
/// Determines whether or not this instruction performs an atomic memory write.
bool IsExclusiveMemoryWrite() const;
/// Determines whether or not this instruction performs any kind of memory read.
bool IsMemoryRead() const;
/// Determines whether or not this instruction performs any kind of memory write.
bool IsMemoryWrite() const;
/// Determines whether or not this instruction performs any kind of memory access.
bool IsMemoryReadOrWrite() const;
/// Determines whether or not this instruction reads from the CPSR.
bool ReadsFromCPSR() const;
/// Determines whether or not this instruction writes to the CPSR.
bool WritesToCPSR() const;
/// Determines whether or not this instruction reads from a core register.
bool ReadsFromCoreRegister() const;
/// Determines whether or not this instruction writes to a core register.
bool WritesToCoreRegister() const;
/// Determines whether or not this instruction reads from the FPSCR.
bool ReadsFromFPSCR() const;
/// Determines whether or not this instruction writes to the FPSCR.
bool WritesToFPSCR() const;
/// Determines whether or not this instruction alters memory-exclusivity.
bool AltersExclusiveState() const;
/// Determines whether or not this instruction causes a CPU exception.
bool CausesCPUException() const;
/// Determines whether or not this instruction may have side-effects.
bool MayHaveSideEffects() const;
bool HasUses() const { return use_count > 0; } bool HasUses() const { return use_count > 0; }
/// Get the microop this microinstruction represents. /// Get the microop this microinstruction represents.