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 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());