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.