From 47f285249bc9cc2b9f7b19bd7d7afe69839a4836 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 22 Aug 2016 12:54:47 -0400 Subject: [PATCH] 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. --- src/frontend/ir/microinstruction.cpp | 204 +++++++++++++++++++++++++++ src/frontend/ir/microinstruction.h | 49 +++++++ 2 files changed, 253 insertions(+) diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index 4dd6811c..bb764eaf 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -10,6 +10,210 @@ namespace Dynarmic { 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 { DEBUG_ASSERT(index < GetNumArgsOf(op)); DEBUG_ASSERT(!args[index].IsEmpty()); diff --git a/src/frontend/ir/microinstruction.h b/src/frontend/ir/microinstruction.h index 708577f4..15acac3d 100644 --- a/src/frontend/ir/microinstruction.h +++ b/src/frontend/ir/microinstruction.h @@ -24,6 +24,55 @@ class Inst final : public Common::IntrusiveListNode { public: 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; } /// Get the microop this microinstruction represents.