diff --git a/FEXCore/Scripts/json_ir_generator.py b/FEXCore/Scripts/json_ir_generator.py index 465026abf..5a589697f 100755 --- a/FEXCore/Scripts/json_ir_generator.py +++ b/FEXCore/Scripts/json_ir_generator.py @@ -219,11 +219,8 @@ def parse_ops(ops): OpArg.DefaultInitializer = DefaultInit[1][:-1] # If SSA type then we can generate validation for this op - if (OpArg.IsSSA and - (OpArg.Type == "GPR" or - OpArg.Type == "GPRPair" or - OpArg.Type == "FPR")): - OpDef.EmitValidation.append(f"GetOpRegClass({ArgName}) == InvalidClass || WalkFindRegClass({ArgName}) == {OpArg.Type}Class") + if OpArg.IsSSA and OpArg.Type in {"GPR", "GPRPair", "FPR"}: + OpDef.EmitValidation.append(f"GetOpRegClass({ArgName}) == RegClass::Invalid || WalkFindRegClass({ArgName}) == RegClass::{OpArg.Type}") OpArg.Name = ArgName OpArg.NameWithPrefix = NameWithPrefix @@ -415,7 +412,7 @@ def print_ir_sizes(): [[nodiscard, gnu::const]] std::string_view const& GetName(IROps Op); [[nodiscard, gnu::const]] uint8_t GetArgs(IROps Op); [[nodiscard, gnu::const]] uint8_t GetRAArgs(IROps Op); - [[nodiscard, gnu::const]] FEXCore::IR::RegisterClassType GetRegClass(IROps Op); + [[nodiscard, gnu::const]] FEXCore::IR::RegClass GetRegClass(IROps Op); [[nodiscard, gnu::const]] bool HasSideEffects(IROps Op); [[nodiscard, gnu::const]] bool ImplicitFlagClobber(IROps Op); [[nodiscard, gnu::const]] bool GetHasDest(IROps Op); @@ -429,30 +426,29 @@ def print_ir_sizes(): def print_ir_reg_classes(): output_file.write("#ifdef IROP_REG_CLASSES_IMPL\n") - output_file.write("constexpr std::array IRRegClasses = {\n") + output_file.write("constexpr std::array IRRegClasses = {\n") for op in IROps: if op.Name == "Last": - output_file.write("\tFEXCore::IR::InvalidClass,\n") + output_file.write("\tRegClass::Invalid,\n") else: - Class = "Invalid" - if op.HasDest and op.DestType == None: + if op.HasDest and op.DestType is None: ExitError("IR op {} has destination with no destination class".format(op.Name)) if op.HasDest and op.DestType == "SSA": # Special case SSA type - output_file.write("\tFEXCore::IR::ComplexClass,\n") + output_file.write("\tRegClass::Complex,\n") elif op.HasDest: - output_file.write("\tFEXCore::IR::{}Class,\n".format(op.DestType)) + output_file.write("\tRegClass::{},\n".format(op.DestType)) else: # No destination so it has an invalid destination class - output_file.write("\tFEXCore::IR::InvalidClass, // No destination\n") + output_file.write("\tRegClass::Invalid, // No destination\n") output_file.write("};\n\n") output_file.write("// Make sure our array maps directly to the IROps enum\n") - output_file.write("static_assert(IRRegClasses[IROps::OP_LAST] == FEXCore::IR::InvalidClass);\n\n") + output_file.write("static_assert(IRRegClasses[IROps::OP_LAST] == RegClass::Invalid);\n\n") - output_file.write("FEXCore::IR::RegisterClassType GetRegClass(IROps Op) { return IRRegClasses[Op]; }\n\n") + output_file.write("FEXCore::IR::RegClass GetRegClass(IROps Op) { return IRRegClasses[Op]; }\n\n") output_file.write("#undef IROP_REG_CLASSES_IMPL\n") output_file.write("#endif\n\n") @@ -678,7 +674,7 @@ def print_ir_allocator_helpers(): output_file.write("\t\treturn HeaderOp->Op;\n") output_file.write("\t}\n\n") - output_file.write("\tFEXCore::IR::RegisterClassType GetOpRegClass(const OrderedNode *Op) const {\n") + output_file.write("\tFEXCore::IR::RegClass GetOpRegClass(const OrderedNode *Op) const {\n") output_file.write("\t\treturn GetRegClass(GetOpType(Op));\n") output_file.write("\t}\n\n") diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index bfc95c45e..23e0beb1f 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -947,7 +947,7 @@ void ContextImpl::AddThunkTrampolineIRHandler(uintptr_t Entrypoint, uintptr_t Gu if (GPRSize == IR::OpSize::i64Bit) { IR::Ref R = emit->_StoreRegister(emit->Constant(Entrypoint), GPRSize); - R->Reg = IR::PhysicalRegister(IR::GPRFixedClass, X86State::REG_R11).Raw; + R->Reg = IR::PhysicalRegister(IR::RegClass::GPRFixed, X86State::REG_R11).Raw; } else { emit->_StoreContextFPR(GPRSize, emit->_VCastFromGPR(IR::OpSize::i64Bit, IR::OpSize::i64Bit, emit->Constant(Entrypoint)), offsetof(Core::CPUState, mm[0][0])); diff --git a/FEXCore/Source/Interface/Core/JIT/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/JIT.cpp index 0db77dcda..5bf618c0c 100644 --- a/FEXCore/Source/Interface/Core/JIT/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/JIT.cpp @@ -625,10 +625,10 @@ Arm64JITCore::Arm64JITCore(FEXCore::Context::ContextImpl* ctx, FEXCore::Core::In RAPass = Thread->PassManager->GetPass("RA"); - RAPass->AddRegisters(FEXCore::IR::GPRClass, GeneralRegisters.size()); - RAPass->AddRegisters(FEXCore::IR::GPRFixedClass, StaticRegisters.size()); - RAPass->AddRegisters(FEXCore::IR::FPRClass, GeneralFPRegisters.size()); - RAPass->AddRegisters(FEXCore::IR::FPRFixedClass, StaticFPRegisters.size()); + RAPass->AddRegisters(IR::RegClass::GPR, GeneralRegisters.size()); + RAPass->AddRegisters(IR::RegClass::GPRFixed, StaticRegisters.size()); + RAPass->AddRegisters(IR::RegClass::FPR, GeneralFPRegisters.size()); + RAPass->AddRegisters(IR::RegClass::FPRFixed, StaticFPRegisters.size()); RAPass->PairRegs = PairRegisters; { diff --git a/FEXCore/Source/Interface/Core/JIT/JITClass.h b/FEXCore/Source/Interface/Core/JIT/JITClass.h index 5a1ea663c..d005fa9e9 100644 --- a/FEXCore/Source/Interface/Core/JIT/JITClass.h +++ b/FEXCore/Source/Interface/Core/JIT/JITClass.h @@ -95,11 +95,13 @@ private: [[nodiscard]] ARMEmitter::Register GetReg(IR::PhysicalRegister Reg) const { - LOGMAN_THROW_A_FMT(Reg.Class == IR::GPRFixedClass.Val || Reg.Class == IR::GPRClass.Val, "Unexpected Class: {}", Reg.Class); + const auto RegClass = Reg.AsRegClass(); - if (Reg.Class == IR::GPRFixedClass.Val) { + LOGMAN_THROW_A_FMT(RegClass == IR::RegClass::GPRFixed || RegClass == IR::RegClass::GPR, "Unexpected Class: {}", Reg.Class); + + if (RegClass == IR::RegClass::GPRFixed) { return StaticRegisters[Reg.Reg]; - } else if (Reg.Class == IR::GPRClass.Val) { + } else if (RegClass == IR::RegClass::GPR) { return GeneralRegisters[Reg.Reg]; } @@ -118,11 +120,13 @@ private: [[nodiscard]] ARMEmitter::VRegister GetVReg(IR::PhysicalRegister Reg) const { - LOGMAN_THROW_A_FMT(Reg.Class == IR::FPRFixedClass.Val || Reg.Class == IR::FPRClass.Val, "Unexpected Class: {}", Reg.Class); + const auto RegClass = Reg.AsRegClass(); - if (Reg.Class == IR::FPRFixedClass.Val) { + LOGMAN_THROW_A_FMT(RegClass == IR::RegClass::FPRFixed || RegClass == IR::RegClass::FPR, "Unexpected Class: {}", Reg.Class); + + if (RegClass == IR::RegClass::FPRFixed) { return StaticFPRegisters[Reg.Reg]; - } else if (Reg.Class == IR::FPRClass.Val) { + } else if (RegClass == IR::RegClass::FPR) { return GeneralFPRegisters[Reg.Reg]; } @@ -140,8 +144,8 @@ private: } [[nodiscard]] - static IR::RegisterClassType GetRegClass(IR::Ref Node) { - return IR::RegisterClassType {IR::PhysicalRegister(Node).Class}; + static IR::RegClass GetRegClass(IR::Ref Node) { + return IR::PhysicalRegister(Node).AsRegClass(); } [[nodiscard]] @@ -266,13 +270,13 @@ private: } [[nodiscard]] - static bool IsFPR(IR::RegisterClassType Class) { - return Class == IR::FPRClass || Class == IR::FPRFixedClass; + static bool IsFPR(IR::RegClass Class) { + return Class == IR::RegClass::FPR || Class == IR::RegClass::FPRFixed; } [[nodiscard]] - static bool IsGPR(IR::RegisterClassType Class) { - return Class == IR::GPRClass || Class == IR::GPRFixedClass; + static bool IsGPR(IR::RegClass Class) { + return Class == IR::RegClass::GPR || Class == IR::RegClass::GPRFixed; } [[nodiscard]] @@ -287,12 +291,12 @@ private: [[nodiscard]] static bool IsGPR(IR::OrderedNodeWrapper Wrap) { - return IsGPR(IR::RegisterClassType {IR::PhysicalRegister(Wrap).Class}); + return IsGPR(IR::PhysicalRegister(Wrap).AsRegClass()); } [[nodiscard]] static bool IsFPR(IR::OrderedNodeWrapper Wrap) { - return IsFPR(IR::RegisterClassType {IR::PhysicalRegister(Wrap).Class}); + return IsFPR(IR::PhysicalRegister(Wrap).AsRegClass()); } [[nodiscard]] diff --git a/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp b/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp index 33d9cdeb2..6d3f48f0d 100644 --- a/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/MemoryOps.cpp @@ -21,7 +21,7 @@ DEF_OP(LoadContext) { const auto Op = IROp->C(); const auto OpSize = IROp->Size; - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { auto Dst = GetReg(Node); switch (OpSize) { @@ -52,7 +52,7 @@ DEF_OP(LoadContext) { DEF_OP(LoadContextPair) { const auto Op = IROp->C(); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Dst1 = GetReg(Op->OutValue1); const auto Dst2 = GetReg(Op->OutValue2); @@ -78,7 +78,7 @@ DEF_OP(StoreContext) { const auto Op = IROp->C(); const auto OpSize = IROp->Size; - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { auto Src = GetZeroableReg(Op->Value); switch (OpSize) { @@ -110,7 +110,7 @@ DEF_OP(StoreContextPair) { const auto Op = IROp->C(); const auto OpSize = IROp->Size; - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { auto Src1 = GetZeroableReg(Op->Value1); auto Src2 = GetZeroableReg(Op->Value2); @@ -135,11 +135,11 @@ DEF_OP(StoreContextPair) { DEF_OP(LoadRegister) { const auto Op = IROp->C(); - if (Op->Class == IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { LOGMAN_THROW_A_FMT(Op->Reg < StaticRegisters.size(), "out of range reg"); mov(GetReg(Node).X(), StaticRegisters[Op->Reg].X()); - } else if (Op->Class == IR::FPRClass) { + } else if (Op->Class == IR::RegClass::FPR) { const auto regSize = HostSupportsAVX256 ? IR::OpSize::i256Bit : IR::OpSize::i128Bit; LOGMAN_THROW_A_FMT(Op->Reg < StaticFPRegisters.size(), "out of range reg"); LOGMAN_THROW_A_FMT(IROp->Size == regSize, "expected sized"); @@ -175,12 +175,13 @@ DEF_OP(LoadAF) { DEF_OP(StoreRegister) { const auto Op = IROp->C(); - auto Reg = IR::PhysicalRegister(Node); + const auto Reg = IR::PhysicalRegister(Node); + const auto RegClass = Reg.AsRegClass(); - if (Reg.Class == IR::GPRFixedClass) { + if (RegClass == IR::RegClass::GPRFixed) { // Always use 64-bit, it's faster. Upper bits ignored for 32-bit mode. mov(ARMEmitter::Size::i64Bit, GetReg(Reg), GetReg(Op->Value)); - } else if (Reg.Class == IR::FPRFixedClass) { + } else if (RegClass == IR::RegClass::FPRFixed) { const auto regSize = HostSupportsAVX256 ? IR::OpSize::i256Bit : IR::OpSize::i128Bit; LOGMAN_THROW_A_FMT(IROp->Size == regSize, "expected sized"); @@ -193,7 +194,7 @@ DEF_OP(StoreRegister) { mov(guest.Q(), host.Q()); } } else { - LOGMAN_THROW_A_FMT(false, "Unhandled Op->Class {}", Reg.Class); + LOGMAN_THROW_A_FMT(false, "Unhandled Op->Class {}", RegClass); } } @@ -225,7 +226,7 @@ DEF_OP(LoadContextIndexed) { const auto Index = GetReg(Op->Index); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { switch (Op->Stride) { case 1: case 2: @@ -288,7 +289,7 @@ DEF_OP(StoreContextIndexed) { const auto Index = GetReg(Op->Index); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Value = GetReg(Op->Value); switch (Op->Stride) { @@ -372,7 +373,7 @@ DEF_OP(SpillRegister) { const auto OpSize = IROp->Size; const uint32_t SlotOffset = Op->Slot * MaxSpillSlotSize; - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Src = GetReg(Op->Value); switch (OpSize) { case IR::OpSize::i8Bit: { @@ -413,7 +414,7 @@ DEF_OP(SpillRegister) { } default: LOGMAN_MSG_A_FMT("Unhandled SpillRegister size: {}", OpSize); break; } - } else if (Op->Class == FEXCore::IR::FPRClass) { + } else if (Op->Class == FEXCore::IR::RegClass::FPR) { const auto Src = GetVReg(Op->Value); switch (OpSize) { @@ -452,7 +453,7 @@ DEF_OP(SpillRegister) { default: LOGMAN_MSG_A_FMT("Unhandled SpillRegister size: {}", OpSize); break; } } else { - LOGMAN_MSG_A_FMT("Unhandled SpillRegister class: {}", Op->Class.Val); + LOGMAN_MSG_A_FMT("Unhandled SpillRegister class: {}", Op->Class); } } @@ -461,7 +462,7 @@ DEF_OP(FillRegister) { const auto OpSize = IROp->Size; const uint32_t SlotOffset = Op->Slot * MaxSpillSlotSize; - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); switch (OpSize) { case IR::OpSize::i8Bit: { @@ -502,7 +503,7 @@ DEF_OP(FillRegister) { } default: LOGMAN_MSG_A_FMT("Unhandled FillRegister size: {}", OpSize); break; } - } else if (Op->Class == FEXCore::IR::FPRClass) { + } else if (Op->Class == FEXCore::IR::RegClass::FPR) { const auto Dst = GetVReg(Node); switch (OpSize) { @@ -541,7 +542,7 @@ DEF_OP(FillRegister) { default: LOGMAN_MSG_A_FMT("Unhandled FillRegister size: {}", OpSize); break; } } else { - LOGMAN_MSG_A_FMT("Unhandled FillRegister class: {}", Op->Class.Val); + LOGMAN_MSG_A_FMT("Unhandled FillRegister class: {}", Op->Class); } } @@ -689,7 +690,7 @@ DEF_OP(LoadMem) { const auto MemReg = GetReg(Op->Addr); const auto MemSrc = GenerateMemOperand(OpSize, MemReg, Op->Offset, Op->OffsetType, Op->OffsetScale); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); switch (OpSize) { @@ -723,7 +724,7 @@ DEF_OP(LoadMemPair) { const auto Op = IROp->C(); const auto Addr = GetReg(Op->Addr); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Dst1 = GetReg(Op->OutValue1); const auto Dst2 = GetReg(Op->OutValue2); @@ -751,13 +752,13 @@ DEF_OP(LoadMemTSO) { const auto MemReg = GetReg(Op->Addr); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { LOGMAN_THROW_A_FMT(Op->Offset.IsInvalid() || CTX->HostFeatures.SupportsTSOImm9, "unexpected offset"); LOGMAN_THROW_A_FMT(Op->OffsetScale == 1, "unexpected offset scale"); LOGMAN_THROW_A_FMT(Op->OffsetType == IR::MemOffsetType::SXTX, "unexpected offset type"); } - if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == FEXCore::IR::GPRClass) { + if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); uint64_t Offset = 0; if (!Op->Offset.IsInvalid()) { @@ -779,7 +780,7 @@ DEF_OP(LoadMemTSO) { // Half-barrier once back-patched. nop(); } - } else if (CTX->HostFeatures.SupportsRCPC && Op->Class == FEXCore::IR::GPRClass) { + } else if (CTX->HostFeatures.SupportsRCPC && Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); if (OpSize == IR::OpSize::i8Bit) { // 8bit load is always aligned to natural alignment @@ -794,7 +795,7 @@ DEF_OP(LoadMemTSO) { // Half-barrier once back-patched. nop(); } - } else if (Op->Class == FEXCore::IR::GPRClass) { + } else if (Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); if (OpSize == IR::OpSize::i8Bit) { // 8bit load is always aligned to natural alignment @@ -1624,7 +1625,7 @@ DEF_OP(StoreMem) { const auto MemReg = GetReg(Op->Addr); const auto MemSrc = GenerateMemOperand(OpSize, MemReg, Op->Offset, Op->OffsetType, Op->OffsetScale); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Src = GetZeroableReg(Op->Value); switch (OpSize) { case IR::OpSize::i8Bit: strb(Src, MemSrc); break; @@ -1735,7 +1736,7 @@ DEF_OP(StoreMemPair) { const auto OpSize = IROp->Size; const auto Addr = GetReg(Op->Addr); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { const auto Src1 = GetZeroableReg(Op->Value1); const auto Src2 = GetZeroableReg(Op->Value2); switch (OpSize) { @@ -1762,13 +1763,13 @@ DEF_OP(StoreMemTSO) { const auto MemReg = GetReg(Op->Addr); - if (Op->Class == FEXCore::IR::GPRClass) { + if (Op->Class == IR::RegClass::GPR) { LOGMAN_THROW_A_FMT(Op->Offset.IsInvalid() || CTX->HostFeatures.SupportsTSOImm9, "unexpected offset"); LOGMAN_THROW_A_FMT(Op->OffsetScale == 1, "unexpected offset scale"); LOGMAN_THROW_A_FMT(Op->OffsetType == IR::MemOffsetType::SXTX, "unexpected offset type"); } - if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == FEXCore::IR::GPRClass) { + if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == IR::RegClass::GPR) { const auto Src = GetZeroableReg(Op->Value); uint64_t Offset = 0; if (!Op->Offset.IsInvalid()) { @@ -1789,7 +1790,7 @@ DEF_OP(StoreMemTSO) { default: LOGMAN_MSG_A_FMT("Unhandled StoreMemTSO size: {}", OpSize); break; } } - } else if (Op->Class == FEXCore::IR::GPRClass) { + } else if (Op->Class == IR::RegClass::GPR) { const auto Src = GetZeroableReg(Op->Value); if (OpSize == IR::OpSize::i8Bit) { @@ -2302,7 +2303,7 @@ DEF_OP(ParanoidLoadMemTSO) { auto MemReg = GetReg(Op->Addr); - if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == FEXCore::IR::GPRClass) { + if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); uint64_t Offset = 0; if (!Op->Offset.IsInvalid()) { @@ -2323,7 +2324,7 @@ DEF_OP(ParanoidLoadMemTSO) { default: LOGMAN_MSG_A_FMT("Unhandled ParanoidLoadMemTSO size: {}", OpSize); break; } } - } else if (CTX->HostFeatures.SupportsRCPC && Op->Class == FEXCore::IR::GPRClass) { + } else if (CTX->HostFeatures.SupportsRCPC && Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); MemReg = ApplyMemOperand(OpSize, MemReg, TMP4, Op->Offset, Op->OffsetType, Op->OffsetScale); if (OpSize == IR::OpSize::i8Bit) { @@ -2337,7 +2338,7 @@ DEF_OP(ParanoidLoadMemTSO) { default: LOGMAN_MSG_A_FMT("Unhandled ParanoidLoadMemTSO size: {}", OpSize); break; } } - } else if (Op->Class == FEXCore::IR::GPRClass) { + } else if (Op->Class == IR::RegClass::GPR) { const auto Dst = GetReg(Node); MemReg = ApplyMemOperand(OpSize, MemReg, TMP4, Op->Offset, Op->OffsetType, Op->OffsetScale); switch (OpSize) { @@ -2390,7 +2391,7 @@ DEF_OP(ParanoidStoreMemTSO) { auto MemReg = GetReg(Op->Addr); - if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == FEXCore::IR::GPRClass) { + if (CTX->HostFeatures.SupportsTSOImm9 && Op->Class == IR::RegClass::GPR) { const auto Src = GetZeroableReg(Op->Value); uint64_t Offset = 0; if (!Op->Offset.IsInvalid()) { @@ -2410,7 +2411,7 @@ DEF_OP(ParanoidStoreMemTSO) { default: LOGMAN_MSG_A_FMT("Unhandled ParanoidStoreMemTSO size: {}", OpSize); break; } } - } else if (Op->Class == FEXCore::IR::GPRClass) { + } else if (Op->Class == IR::RegClass::GPR) { const auto Src = GetZeroableReg(Op->Value); MemReg = ApplyMemOperand(OpSize, MemReg, TMP1, Op->Offset, Op->OffsetType, Op->OffsetScale); switch (OpSize) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 6b2451614..c4262c212 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -4251,7 +4251,7 @@ AddressMode OpDispatchBuilder::DecodeAddress(const X86Tables::DecodedOp& Op, con } -Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, +Ref OpDispatchBuilder::LoadSource_WithOpSize(RegClass Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, IR::OpSize OpSize, uint32_t Flags, const LoadSourceOptions& Options) { auto [Align, LoadData, ForceLoad, AccessType, AllowUpperGarbage] = Options; AddressMode A = DecodeAddress(Op, Operand, AccessType, true /* IsLoad */); @@ -4341,15 +4341,14 @@ void OpDispatchBuilder::StoreXMMRegister(uint32_t XMM, const Ref Src) { StoreRegister(XMM, true, Src); } -Ref OpDispatchBuilder::LoadSource(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, - uint32_t Flags, const LoadSourceOptions& Options) { +Ref OpDispatchBuilder::LoadSource(RegClass Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, + const LoadSourceOptions& Options) { const auto OpSize = OpSizeFromSrc(Op); return LoadSource_WithOpSize(Class, Op, Operand, OpSize, Flags, Options); } -void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, - const FEXCore::X86Tables::DecodedOperand& Operand, const Ref Src, IR::OpSize OpSize, - IR::OpSize Align, MemoryAccessType AccessType) { +void OpDispatchBuilder::StoreResult_WithOpSize(RegClass Class, FEXCore::X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, + Ref Src, IR::OpSize OpSize, IR::OpSize Align, MemoryAccessType AccessType) { if (Operand.IsGPR()) { // 8Bit and 16bit destination types store their result without effecting the upper bits // 32bit ops ZEXT the result to 64bit @@ -4358,7 +4357,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl const auto gpr = Operand.Data.GPR.GPR; if (gpr >= FEXCore::X86State::REG_MM_0) { LOGMAN_THROW_A_FMT(OpSize == OpSize::i64Bit, "full"); - LOGMAN_THROW_A_FMT(Class == FPRClass, "MMX is floaty"); + LOGMAN_THROW_A_FMT(Class == RegClass::FPR, "MMX is floaty"); if (MMXState != MMXState_MMX) { ChgStateX87_MMX(); @@ -4376,7 +4375,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl // Partial writes can come from FPRs. // TODO: Fix the instructions doing partial writes rather than dealing with it here. - LOGMAN_THROW_A_FMT(Class != IR::GPRClass, "Partial writes from GPR not allowed. Instruction: {}", Op->TableInfo->Name); + LOGMAN_THROW_A_FMT(Class != RegClass::GPR, "Partial writes from GPR not allowed. Instruction: {}", Op->TableInfo->Name); // XMM-size is handled in implementations. if (VectorSize != OpSize::i256Bit || OpSize != OpSize::i128Bit) { @@ -4429,14 +4428,12 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl } } -void OpDispatchBuilder::StoreResult(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, - const FEXCore::X86Tables::DecodedOperand& Operand, const Ref Src, IR::OpSize Align, - MemoryAccessType AccessType) { +void OpDispatchBuilder::StoreResult(RegClass Class, X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, + IR::OpSize Align, MemoryAccessType AccessType) { StoreResult_WithOpSize(Class, Op, Operand, Src, OpSizeFromDst(Op), Align, AccessType); } -void OpDispatchBuilder::StoreResult(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, const Ref Src, IR::OpSize Align, - MemoryAccessType AccessType) { +void OpDispatchBuilder::StoreResult(RegClass Class, X86Tables::DecodedOp Op, Ref Src, IR::OpSize Align, MemoryAccessType AccessType) { StoreResult(Class, Op, Op->Dest, Src, Align, AccessType); } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 79bbae000..dfb831401 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1110,8 +1110,8 @@ public: // End of AVX 128-bit implementation // AVX 256-bit operations - void StoreResult_WithAVXInsert(VectorOpType Type, FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, Ref Value, - IR::OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { + void StoreResult_WithAVXInsert(VectorOpType Type, RegClass Class, FEXCore::X86Tables::DecodedOp Op, Ref Value, IR::OpSize Align, + MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { if (Op->Dest.IsGPR() && Op->Dest.Data.GPR.GPR >= X86State::REG_XMM_0 && Op->Dest.Data.GPR.GPR <= X86State::REG_XMM_15 && GetGuestVectorLength() == OpSize::i256Bit && Type == VectorOpType::SSE) { const auto gpr = Op->Dest.Data.GPR.GPR; @@ -1162,7 +1162,7 @@ public: } } - void StoreContextHelper(IR::OpSize Size, RegisterClassType Class, Ref Value, uint32_t Offset) { + void StoreContextHelper(IR::OpSize Size, RegClass Class, Ref Value, uint32_t Offset) { // For i128Bit, we won't see a normal Constant to inline, but as a special // case we can replace with a 2x64-bit store which can use inline zeroes. if (Size == OpSize::i128Bit) { @@ -1174,7 +1174,7 @@ public: if (Const->Constant == IR::NamedVectorConstant::NAMED_VECTOR_ZERO) { Ref Zero = _Constant(0); - Ref STP = _StoreContextPair(IR::OpSize::i64Bit, GPRClass, Zero, Zero, Offset); + Ref STP = _StoreContextPair(IR::OpSize::i64Bit, RegClass::GPR, Zero, Zero, Offset); // XXX: This works around InlineConstant not having an associated // register class, else we'd just do InlineConstant above. @@ -1230,16 +1230,16 @@ public: if (Index >= GPR0Index && Index <= GPR15Index) { Ref R = _StoreRegister(Value, GPRSize); - R->Reg = PhysicalRegister(GPRFixedClass, Index - GPR0Index).Raw; + R->Reg = PhysicalRegister(RegClass::GPRFixed, Index - GPR0Index).Raw; } else if (Index == PFIndex) { _StorePF(Value, GPRSize); } else if (Index == AFIndex) { _StoreAF(Value, GPRSize); } else if (Index >= FPR0Index && Index <= FPR15Index) { Ref R = _StoreRegister(Value, VectorSize); - R->Reg = PhysicalRegister(FPRFixedClass, Index - FPR0Index).Raw; + R->Reg = PhysicalRegister(RegClass::FPRFixed, Index - FPR0Index).Raw; } else if (Index == DFIndex) { - _StoreContext(OpSize::i8Bit, GPRClass, Value, offsetof(Core::CPUState, flags[X86State::RFLAG_DF_RAW_LOC])); + _StoreContextGPR(OpSize::i8Bit, Value, offsetof(Core::CPUState, flags[X86State::RFLAG_DF_RAW_LOC])); } else { bool Partial = RegCache.Partial & (1ull << Index); auto Size = Partial ? OpSize::i64Bit : CacheIndexToOpSize(Index); @@ -1264,7 +1264,7 @@ public: StoreContextHelper(Size, Class, Value, Offset); // If Partial and MMX register, then we need to store all 1s in bits 64-80 if (Partial && Index >= MM0Index && Index <= MM7Index) { - _StoreContext(OpSize::i16Bit, IR::GPRClass, Constant(0xFFFF), Offset + 8); + _StoreContextGPR(OpSize::i16Bit, Constant(0xFFFF), Offset + 8); } } } @@ -1555,63 +1555,63 @@ private: AddressMode DecodeAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, MemoryAccessType AccessType, bool IsLoad); - Ref LoadSource(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, + Ref LoadSource(RegClass Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, const LoadSourceOptions& Options = {}); Ref LoadSourceGPR(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, const LoadSourceOptions& Options = {}) { - return LoadSource(GPRClass, Op, Operand, Flags, Options); + return LoadSource(RegClass::GPR, Op, Operand, Flags, Options); } Ref LoadSourceFPR(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, const LoadSourceOptions& Options = {}) { - return LoadSource(FPRClass, Op, Operand, Flags, Options); + return LoadSource(RegClass::FPR, Op, Operand, Flags, Options); } - Ref LoadSource_WithOpSize(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, - IR::OpSize OpSize, uint32_t Flags, const LoadSourceOptions& Options = {}); + Ref LoadSource_WithOpSize(RegClass Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, IR::OpSize OpSize, + uint32_t Flags, const LoadSourceOptions& Options = {}); Ref LoadSourceGPR_WithOpSize(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, IR::OpSize OpSize, uint32_t Flags, const LoadSourceOptions& Options = {}) { - return LoadSource_WithOpSize(GPRClass, Op, Operand, OpSize, Flags, Options); + return LoadSource_WithOpSize(RegClass::GPR, Op, Operand, OpSize, Flags, Options); } Ref LoadSourceFPR_WithOpSize(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, IR::OpSize OpSize, uint32_t Flags, const LoadSourceOptions& Options = {}) { - return LoadSource_WithOpSize(FPRClass, Op, Operand, OpSize, Flags, Options); + return LoadSource_WithOpSize(RegClass::FPR, Op, Operand, OpSize, Flags, Options); } - void StoreResult_WithOpSize(RegisterClassType Class, X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, - IR::OpSize OpSize, IR::OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); + void StoreResult_WithOpSize(RegClass Class, X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, IR::OpSize OpSize, + IR::OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); void StoreResultGPR_WithOpSize(X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, IR::OpSize OpSize, IR::OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { - StoreResult_WithOpSize(GPRClass, Op, Operand, Src, OpSize, Align, AccessType); + StoreResult_WithOpSize(RegClass::GPR, Op, Operand, Src, OpSize, Align, AccessType); } void StoreResultFPR_WithOpSize(X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, IR::OpSize OpSize, IR::OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { - StoreResult_WithOpSize(FPRClass, Op, Operand, Src, OpSize, Align, AccessType); + StoreResult_WithOpSize(RegClass::FPR, Op, Operand, Src, OpSize, Align, AccessType); } - void StoreResult(RegisterClassType Class, X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, OpSize Align, + void StoreResult(RegClass Class, X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); void StoreResultGPR(X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { - StoreResult(GPRClass, Op, Operand, Src, Align, AccessType); + StoreResult(RegClass::GPR, Op, Operand, Src, Align, AccessType); } void StoreResultFPR(X86Tables::DecodedOp Op, const X86Tables::DecodedOperand& Operand, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { - StoreResult(FPRClass, Op, Operand, Src, Align, AccessType); + StoreResult(RegClass::FPR, Op, Operand, Src, Align, AccessType); } - void StoreResult(RegisterClassType Class, X86Tables::DecodedOp Op, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); + void StoreResult(RegClass Class, X86Tables::DecodedOp Op, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); void StoreResultGPR(X86Tables::DecodedOp Op, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { - StoreResult(GPRClass, Op, Src, Align, AccessType); + StoreResult(RegClass::GPR, Op, Src, Align, AccessType); } void StoreResultFPR(X86Tables::DecodedOp Op, Ref Src, OpSize Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT) { - StoreResult(FPRClass, Op, Src, Align, AccessType); + StoreResult(RegClass::FPR, Op, Src, Align, AccessType); } // In several instances, it's desirable to get a base address with the segment offset // applied to it. This pulls all the common-case appending into a single set of functions. [[nodiscard]] Ref MakeSegmentAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, IR::OpSize OpSize) { - Ref Mem = LoadSource_WithOpSize(GPRClass, Op, Operand, OpSize, Op->Flags, {.LoadData = false}); + Ref Mem = LoadSourceGPR_WithOpSize(Op, Operand, OpSize, Op->Flags, {.LoadData = false}); return AppendSegmentOffset(Mem, Op->Flags); } [[nodiscard]] @@ -1847,14 +1847,14 @@ private: // For DF, we need to transform 0/1 into 1/-1 StoreDF(_SubShift(OpSize::i64Bit, Constant(1), Value, ShiftType::LSL, 1)); } else if (BitOffset == FEXCore::X86State::RFLAG_TF_RAW_LOC) { - auto PackedTF = _LoadContext(OpSize::i8Bit, GPRClass, offsetof(FEXCore::Core::CPUState, flags[BitOffset])); + auto PackedTF = _LoadContextGPR(OpSize::i8Bit, offsetof(FEXCore::Core::CPUState, flags[BitOffset])); // An exception should still be raised after an instruction that unsets TF, leave the unblocked bit set but unset // the TF bit to cause such behaviour. The handling code at the start of the next block will then unset the // unblocked bit before raising the exception. auto NewPackedTF = _Select(CondClass::EQ, Value, Constant(0), _And(OpSize::i32Bit, PackedTF, Constant(~1)), Constant(1)); - _StoreContext(OpSize::i8Bit, GPRClass, NewPackedTF, offsetof(FEXCore::Core::CPUState, flags[BitOffset])); + _StoreContextGPR(OpSize::i8Bit, NewPackedTF, offsetof(FEXCore::Core::CPUState, flags[BitOffset])); } else { - _StoreContext(OpSize::i8Bit, GPRClass, Value, offsetof(FEXCore::Core::CPUState, flags[BitOffset])); + _StoreContextGPR(OpSize::i8Bit, Value, offsetof(FEXCore::Core::CPUState, flags[BitOffset])); } } @@ -1916,11 +1916,11 @@ private: } [[nodiscard]] - static RegisterClassType CacheIndexClass(int Index) { + static RegClass CacheIndexClass(int Index) { if ((Index >= MM0Index && Index <= MM7Index) || Index >= FPR0Index) { - return FPRClass; + return RegClass::FPR; } else { - return GPRClass; + return RegClass::GPR; } } @@ -1952,14 +1952,14 @@ private: RegCache.Written &= ~Bit; } - Ref LoadRegCache(uint64_t Offset, uint8_t Index, RegisterClassType RegClass, IR::OpSize Size) { + Ref LoadRegCache(uint64_t Offset, uint8_t Index, RegClass Class, IR::OpSize Size) { LOGMAN_THROW_A_FMT(Index < 64, "valid index"); uint64_t Bit = (1ull << (uint64_t)Index); if (Size == OpSize::i128Bit && (RegCache.Partial & Bit)) { // We need to load the full register extend if we previously did a partial access. Ref Value = RegCache.Value[Index]; - Ref Full = _LoadContext(Size, RegClass, Offset); + Ref Full = _LoadContext(Size, Class, Offset); // If we did a partial store, we're inserting into the full register if (RegCache.Written & Bit) { @@ -1973,7 +1973,7 @@ private: if (Index == DFIndex) { RegCache.Value[Index] = _LoadDF(); } else if ((Index >= MM0Index && Index <= MM7Index) || Index >= AVXHigh0Index) { - RegCache.Value[Index] = _LoadContext(Size, RegClass, Offset); + RegCache.Value[Index] = _LoadContext(Size, Class, Offset); // We may have done a partial load, this requires special handling. if (Size == OpSize::i64Bit) { @@ -1984,7 +1984,7 @@ private: } else if (Index == AFIndex) { RegCache.Value[Index] = _LoadAF(Size); } else { - RegCache.Value[Index] = _LoadRegister(Offset, RegClass, Size); + RegCache.Value[Index] = _LoadRegister(Offset, Class, Size); } RegCache.Cached |= Bit; @@ -1993,21 +1993,21 @@ private: return RegCache.Value[Index]; } - RefPair AllocatePair(FEXCore::IR::RegisterClassType Class, IR::OpSize Size) { - if (Class == FPRClass) { + RefPair AllocatePair(RegClass Class, IR::OpSize Size) { + if (Class == RegClass::FPR) { return {_AllocateFPR(Size, Size), _AllocateFPR(Size, Size)}; } else { return {_AllocateGPR(false), _AllocateGPR(false)}; } } - RefPair LoadContextPair_Uncached(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, unsigned Offset) { + RefPair LoadContextPair_Uncached(RegClass Class, IR::OpSize Size, unsigned Offset) { RefPair Values = AllocatePair(Class, Size); _LoadContextPair(Size, Class, Offset, Values.Low, Values.High); return Values; } - RefPair LoadRegCachePair(uint64_t Offset, uint8_t Index, RegisterClassType RegClass, IR::OpSize Size) { + RefPair LoadRegCachePair(uint64_t Offset, uint8_t Index, RegClass Class, IR::OpSize Size) { LOGMAN_THROW_A_FMT(Index != DFIndex, "must be pairable"); LOGMAN_THROW_A_FMT(Size != IR::OpSize::iUnsized, "Invalid size!"); @@ -2015,7 +2015,7 @@ private: uint64_t Bits = (3ull << (uint64_t)Index); const auto SizeInt = IR::OpSizeToSize(Size); if (((RegCache.Partial | RegCache.Cached) & Bits) == 0 && ((Offset / SizeInt) < 64)) { - auto Values = LoadContextPair_Uncached(RegClass, Size, Offset); + auto Values = LoadContextPair_Uncached(Class, Size, Offset); RegCache.Value[Index] = Values.Low; RegCache.Value[Index + 1] = Values.High; RegCache.Cached |= Bits; @@ -2027,13 +2027,13 @@ private: // Fallback on a pair of loads return { - .Low = LoadRegCache(Offset, Index, RegClass, Size), - .High = LoadRegCache(Offset + SizeInt, Index + 1, RegClass, Size), + .Low = LoadRegCache(Offset, Index, Class, Size), + .High = LoadRegCache(Offset + SizeInt, Index + 1, Class, Size), }; } Ref LoadGPR(uint8_t Reg) { - return LoadRegCache(Reg, GPR0Index + Reg, GPRClass, GetGPROpSize()); + return LoadRegCache(Reg, GPR0Index + Reg, RegClass::GPR, GetGPROpSize()); } Ref LoadContext(IR::OpSize Size, uint8_t Index) { @@ -2049,7 +2049,7 @@ private: } Ref LoadXMMRegister(uint8_t Reg) { - return LoadRegCache(Reg, FPR0Index + Reg, FPRClass, GetGuestVectorLength()); + return LoadRegCache(Reg, FPR0Index + Reg, RegClass::FPR, GetGuestVectorLength()); } Ref LoadDF() { @@ -2104,7 +2104,7 @@ private: // Recover the sign bit, it is the logical DF value return _Lshr(OpSize::i64Bit, LoadDF(), Constant(63)); } else { - return _LoadContext(OpSize::i8Bit, GPRClass, offsetof(Core::CPUState, flags[BitOffset])); + return _LoadContextGPR(OpSize::i8Bit, offsetof(Core::CPUState, flags[BitOffset])); } } @@ -2221,7 +2221,7 @@ private: HandleNZCV_RMW(); CalculatePF(_ShiftFlags(OpSizeFromSrc(Op), Result, Dest, Shift, Src, OldPF, CFInverted)); - StoreResult(GPRClass, Op, Result, OpSize::iInvalid); + StoreResultGPR(Op, Result, OpSize::iInvalid); } // Helper to derive Dest by a given builder-using Expression with the opcode @@ -2309,8 +2309,8 @@ private: if (Size != OpSize::i32Bit) { return; } - auto Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags); - StoreResult(GPRClass, Op, Dest, OpSize::iInvalid); + auto Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags); + StoreResultGPR(Op, Dest, OpSize::iInvalid); } using ZeroShiftFunctionPtr = void (OpDispatchBuilder::*)(FEXCore::X86Tables::DecodedOp Op); @@ -2407,7 +2407,7 @@ private: LOGMAN_THROW_A_FMT(MMXState == MMXState_X87, "Expected state to be x87"); _StackForceSlow(); SetX87Top(Constant(0)); // top reset to zero - _StoreContext(OpSize::i8Bit, GPRClass, Constant(0xFFFFUL), offsetof(FEXCore::Core::CPUState, AbridgedFTW)); + _StoreContextGPR(OpSize::i8Bit, Constant(0xFFFFUL), offsetof(FEXCore::Core::CPUState, AbridgedFTW)); MMXState = MMXState_MMX; } @@ -2444,19 +2444,19 @@ private: IROp_IRHeader* CurrentHeader {}; [[nodiscard]] - bool IsTSOEnabled(FEXCore::IR::RegisterClassType Class) const { + bool IsTSOEnabled(RegClass Class) const { if (ForceTSO == ForceTSOMode::ForceEnabled) { return true; } else if (ForceTSO == ForceTSOMode::ForceDisabled) { return false; - } else if (Class == FPRClass) { + } else if (Class == RegClass::FPR) { return CTX->IsVectorAtomicTSOEnabled(); } else { return CTX->IsAtomicTSOEnabled(); } } - Ref _StoreMemAutoTSO(RegisterClassType Class, OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { + Ref _StoreMemAutoTSO(RegClass Class, OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { if (IsTSOEnabled(Class)) { return _StoreMemTSO(Class, Size, Value, Addr, Invalid(), Align, MemOffsetType::SXTX, 1); } else { @@ -2464,13 +2464,13 @@ private: } } Ref _StoreMemGPRAutoTSO(OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { - return _StoreMemAutoTSO(GPRClass, Size, Addr, Value, Align); + return _StoreMemAutoTSO(RegClass::GPR, Size, Addr, Value, Align); } Ref _StoreMemFPRAutoTSO(OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { - return _StoreMemAutoTSO(FPRClass, Size, Addr, Value, Align); + return _StoreMemAutoTSO(RegClass::FPR, Size, Addr, Value, Align); } - Ref _LoadMemAutoTSO(RegisterClassType Class, OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { + Ref _LoadMemAutoTSO(RegClass Class, OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { if (IsTSOEnabled(Class)) { return _LoadMemTSO(Class, Size, ssa0, Invalid(), Align, MemOffsetType::SXTX, 1); } else { @@ -2478,15 +2478,15 @@ private: } } Ref _LoadMemGPRAutoTSO(OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { - return _LoadMemAutoTSO(GPRClass, Size, ssa0, Align); + return _LoadMemAutoTSO(RegClass::GPR, Size, ssa0, Align); } Ref _LoadMemFPRAutoTSO(OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { - return _LoadMemAutoTSO(GPRClass, Size, ssa0, Align); + return _LoadMemAutoTSO(RegClass::FPR, Size, ssa0, Align); } - Ref _LoadMemAutoTSO(RegisterClassType Class, OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { + Ref _LoadMemAutoTSO(RegClass Class, OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; - A = SelectAddressMode(this, A, GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, AtomicTSO, Class != GPRClass, Size); + A = SelectAddressMode(this, A, GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, AtomicTSO, Class != RegClass::GPR, Size); if (AtomicTSO) { return _LoadMemTSO(Class, Size, A.Base, A.Index, Align, A.IndexType, A.IndexScale); @@ -2495,10 +2495,10 @@ private: } } Ref _LoadMemGPRAutoTSO(OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { - return _LoadMemAutoTSO(GPRClass, Size, A, Align); + return _LoadMemAutoTSO(RegClass::GPR, Size, A, Align); } Ref _LoadMemFPRAutoTSO(OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { - return _LoadMemAutoTSO(FPRClass, Size, A, Align); + return _LoadMemAutoTSO(RegClass::FPR, Size, A, Align); } AddressMode SelectPairAddressMode(AddressMode A, IR::OpSize Size) { @@ -2517,16 +2517,16 @@ private: } - RefPair LoadMemPair(RegisterClassType Class, OpSize Size, Ref Base, uint32_t Offset) { + RefPair LoadMemPair(RegClass Class, OpSize Size, Ref Base, uint32_t Offset) { RefPair Values = AllocatePair(Class, Size); _LoadMemPair(Class, Size, Base, Offset, Values.Low, Values.High); return Values; } RefPair LoadMemPairFPR(OpSize Size, Ref Base, uint32_t Offset) { - return LoadMemPair(FPRClass, Size, Base, Offset); + return LoadMemPair(RegClass::FPR, Size, Base, Offset); } - RefPair _LoadMemPairAutoTSO(RegisterClassType Class, OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { + RefPair _LoadMemPairAutoTSO(RegClass Class, OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; // Use ldp if possible, otherwise fallback on two loads. @@ -2544,12 +2544,12 @@ private: } } RefPair _LoadMemPairFPRAutoTSO(OpSize Size, AddressMode A, OpSize Align = OpSize::i8Bit) { - return _LoadMemPairAutoTSO(FPRClass, Size, A, Align); + return _LoadMemPairAutoTSO(RegClass::FPR, Size, A, Align); } - Ref _StoreMemAutoTSO(RegisterClassType Class, OpSize Size, AddressMode A, Ref Value, OpSize Align = OpSize::i8Bit) { + Ref _StoreMemAutoTSO(RegClass Class, OpSize Size, AddressMode A, Ref Value, OpSize Align = OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; - A = SelectAddressMode(this, A, GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, AtomicTSO, Class != GPRClass, Size); + A = SelectAddressMode(this, A, GetGPROpSize(), CTX->HostFeatures.SupportsTSOImm9, AtomicTSO, Class != RegClass::GPR, Size); if (AtomicTSO) { return _StoreMemTSO(Class, Size, Value, A.Base, A.Index, Align, A.IndexType, A.IndexScale); @@ -2558,13 +2558,13 @@ private: } } Ref _StoreMemGPRAutoTSO(OpSize Size, AddressMode A, Ref Value, OpSize Align = OpSize::i8Bit) { - return _StoreMemAutoTSO(GPRClass, Size, A, Value, Align); + return _StoreMemAutoTSO(RegClass::GPR, Size, A, Value, Align); } Ref _StoreMemFPRAutoTSO(OpSize Size, AddressMode A, Ref Value, OpSize Align = OpSize::i8Bit) { - return _StoreMemAutoTSO(FPRClass, Size, A, Value, Align); + return _StoreMemAutoTSO(RegClass::FPR, Size, A, Value, Align); } - void _StoreMemPairAutoTSO(RegisterClassType Class, OpSize Size, AddressMode A, Ref Value1, Ref Value2, OpSize Align = OpSize::i8Bit) { + void _StoreMemPairAutoTSO(RegClass Class, OpSize Size, AddressMode A, Ref Value1, Ref Value2, OpSize Align = OpSize::i8Bit) { const auto SizeInt = IR::OpSizeToSize(Size); bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; @@ -2579,7 +2579,7 @@ private: } } void _StoreMemPairFPRAutoTSO(OpSize Size, AddressMode A, Ref Value1, Ref Value2, OpSize Align = OpSize::i8Bit) { - return _StoreMemPairAutoTSO(FPRClass, Size, A, Value1, Value2, Align); + return _StoreMemPairAutoTSO(RegClass::FPR, Size, A, Value1, Value2, Align); } Ref Pop(IR::OpSize Size, Ref SP_RMW) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 2a45f0235..527615f09 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -2406,7 +2406,7 @@ void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs, VectorOpType VectorType) { Result = LoadSourceFPR(Op, Op->Src[0], Op->Flags); } - StoreResult_WithAVXInsert(VectorType, FPRClass, Op, Result, OpSize::iInvalid); + StoreResult_WithAVXInsert(VectorType, RegClass::FPR, Op, Result, OpSize::iInvalid); } else { Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags); diff --git a/FEXCore/Source/Interface/IR/IR.h b/FEXCore/Source/Interface/IR/IR.h index 86ad21e10..d3fa9ebd4 100644 --- a/FEXCore/Source/Interface/IR/IR.h +++ b/FEXCore/Source/Interface/IR/IR.h @@ -431,17 +431,6 @@ static_assert(sizeof(OrderedNode) == (sizeof(OrderedNodeHeader) + 2 * sizeof(uin // }; using Ref = OrderedNode*; -struct FEX_PACKED RegisterClassType final { - using value_type = uint32_t; - - value_type Val; - [[nodiscard]] constexpr operator value_type() const { - return Val; - } - [[nodiscard]] - friend constexpr bool operator==(const RegisterClassType&, const RegisterClassType&) = default; -}; - /* This iterator can be used to step though nodes. * Due to how our IR is laid out, this can be used to either step * though the CodeBlocks or though the code within a single block. @@ -727,12 +716,12 @@ struct fmt::formatter : fmt::formatter -struct fmt::formatter : fmt::formatter { - using Base = fmt::formatter; +struct fmt::formatter : fmt::formatter> { + using Base = fmt::formatter>; template - auto format(const FEXCore::IR::RegisterClassType& Class, FormatContext& ctx) const { - return Base::format(Class.Val, ctx); + auto format(const FEXCore::IR::RegClass& Class, FormatContext& ctx) const { + return Base::format(FEXCore::ToUnderlying(Class), ctx); } }; diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index 4c7e59e07..69bebb12f 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -91,6 +91,14 @@ "UXTW = 1,", "SXTW = 2," ], + "class RegClass : uint32_t": [ + "Invalid = 0,", + "GPR = 1,", + "GPRFixed = 2,", + "FPR = 3,", + "FPRFixed = 4,", + "Complex = 5," + ], "class RoundMode : uint8_t": [ "Nearest = 0,", "NegInfinity = 1,", @@ -100,14 +108,8 @@ ] }, "Defines": [ - "constexpr FEXCore::IR::RegisterClassType InvalidClass {0}", - "constexpr FEXCore::IR::RegisterClassType GPRClass {1}", - "constexpr FEXCore::IR::RegisterClassType GPRFixedClass {2}", - "constexpr FEXCore::IR::RegisterClassType FPRClass {3}", - "constexpr FEXCore::IR::RegisterClassType FPRFixedClass {4}", - "constexpr FEXCore::IR::RegisterClassType ComplexClass {5}", "constexpr uint8_t NumClasses {6}", - "", + "constexpr uint8_t FCMP_FLAG_EQ = 0", "constexpr uint8_t FCMP_FLAG_LT = 1", "constexpr uint8_t FCMP_FLAG_UNORDERED = 2", @@ -134,7 +136,7 @@ "GPR": "OrderedNode*", "FPR": "OrderedNode*", "FenceType": "FenceType", - "RegisterClass": "RegisterClassType", + "RegisterClass": "RegClass", "CondClass": "CondClass", "SyscallFlags": "FEXCore::IR::SyscallFlags", "SHA256Sum": "SHA256Sum", @@ -409,8 +411,8 @@ ], "DestSize": "ByteSize", "EmitValidation": [ - "($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass", - "($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass", + "($Class == RegClass::GPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == RegClass::FPR", + "($Class == RegClass::FPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == RegClass::GPR", "!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't LoadContext to GPR\"", "!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't LoadContext to XMM\"" ] @@ -423,8 +425,8 @@ "HasSideEffects": true, "DestSize": "ByteSize", "EmitValidation": [ - "($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass", - "($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass", + "($Class == RegClass::GPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == RegClass::FPR", + "($Class == RegClass::FPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == RegClass::GPR", "!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't LoadContext to GPR\"", "!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't LoadContext to XMM\"" ] @@ -440,8 +442,8 @@ "HasSideEffects": true, "DestSize": "ByteSize", "EmitValidation": [ - "($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass", - "($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass", + "($Class == RegClass::GPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == RegClass::FPR", + "($Class == RegClass::FPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == RegClass::GPR", "!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't StoreContext to GPR\"", "!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't StoreContext to XMM\"" ] @@ -458,8 +460,8 @@ "EmitValidation": [ "WalkFindRegClass($Value1) == $Class", "WalkFindRegClass($Value2) == $Class", - "($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass", - "($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass", + "($Class == RegClass::GPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == RegClass::FPR", + "($Class == RegClass::FPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == RegClass::GPR", "!($Offset >= offsetof(Core::CPUState, gregs[0]) && $Offset < offsetof(Core::CPUState, gregs[16])) && \"Can't StoreContext to GPR\"", "!($Offset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $Offset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't StoreContext to XMM\"" ] @@ -471,8 +473,8 @@ ], "DestSize": "ByteSize", "EmitValidation": [ - "($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass", - "($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass", + "($Class == RegClass::GPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == RegClass::FPR", + "($Class == RegClass::FPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == RegClass::GPR", "!($BaseOffset >= offsetof(Core::CPUState, gregs[0]) && $BaseOffset < offsetof(Core::CPUState, gregs[16])) && \"Can't LoadContextIndexed to GPR\"", "!($BaseOffset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $BaseOffset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't LoadContextIndexed to XMM\"" ] @@ -485,8 +487,8 @@ "DestSize": "ByteSize", "EmitValidation": [ "WalkFindRegClass($Value) == $Class", - "($Class == GPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == FPRClass", - "($Class == FPRClass && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == GPRClass", + "($Class == RegClass::GPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit)) || $Class == RegClass::FPR", + "($Class == RegClass::FPR && (#ByteSize == IR::OpSize::i8Bit || #ByteSize == IR::OpSize::i16Bit || #ByteSize == IR::OpSize::i32Bit || #ByteSize == IR::OpSize::i64Bit || #ByteSize == IR::OpSize::i128Bit || #ByteSize == IR::OpSize::i256Bit)) || $Class == RegClass::GPR", "!($BaseOffset >= offsetof(Core::CPUState, gregs[0]) && $BaseOffset < offsetof(Core::CPUState, gregs[16])) && \"Can't StoreContextIndexed to GPR\"", "!($BaseOffset >= offsetof(Core::CPUState, xmm.avx.data[0]) && $BaseOffset < offsetof(Core::CPUState, xmm.avx.data[16])) && \"Can't StoreContextIndexed to XMM\"" ] @@ -2827,7 +2829,7 @@ "Int: 64-bit, 32-bit, 16-bit" ], "EmitValidation": [ - "WalkFindRegClass($OriginalValue) == FPRClass || WalkFindRegClass($OriginalValue) == GPRClass" + "WalkFindRegClass($OriginalValue) == RegClass::FPR || WalkFindRegClass($OriginalValue) == RegClass::GPR" ], "HasSideEffects": true, "X87": true diff --git a/FEXCore/Source/Interface/IR/IRDumper.cpp b/FEXCore/Source/Interface/IR/IRDumper.cpp index c6d40077d..ddb08e7b5 100644 --- a/FEXCore/Source/Interface/IR/IRDumper.cpp +++ b/FEXCore/Source/Interface/IR/IRDumper.cpp @@ -61,36 +61,36 @@ static void PrintArg(fextl::stringstream* out, const IRListView*, MemOffsetType *out << Names[FEXCore::ToUnderlying(Arg)]; } -static void PrintArg(fextl::stringstream* out, const IRListView*, RegisterClassType Arg) { - if (Arg == GPRClass.Val) { - *out << "GPR"; - } else if (Arg == GPRFixedClass.Val) { - *out << "GPRFixed"; - } else if (Arg == FPRClass.Val) { - *out << "FPR"; - } else if (Arg == FPRFixedClass.Val) { - *out << "FPRFixed"; - } else { - *out << "Unknown Registerclass " << Arg; - } +static void PrintArg(fextl::stringstream* out, const IRListView*, RegClass Arg) { + *out << [Arg] { + switch (Arg) { + case RegClass::Invalid: return "Invalid"; + case RegClass::GPR: return "GPR"; + case RegClass::GPRFixed: return "GPRFixed"; + case RegClass::FPR: return "FPR"; + case RegClass::FPRFixed: return "FPRFixed"; + case RegClass::Complex: return "Complex"; + } + return ""; + }(); } static void PrintArg(fextl::stringstream* out, const IRListView* IR, OrderedNodeWrapper Arg) { if (Arg.IsImmediate()) { auto PhyReg = PhysicalRegister(Arg); - switch (PhyReg.Class) { - case FEXCore::IR::GPRClass.Val: *out << "r"; break; - case FEXCore::IR::GPRFixedClass.Val: *out << "R"; break; - case FEXCore::IR::FPRClass.Val: *out << "v"; break; - case FEXCore::IR::FPRFixedClass.Val: *out << "V"; break; - case FEXCore::IR::ComplexClass.Val: *out << "c"; break; - case FEXCore::IR::InvalidClass.Val: *out << "invalid"; break; + switch (PhyReg.AsRegClass()) { + case RegClass::GPR: *out << "r"; break; + case RegClass::GPRFixed: *out << "R"; break; + case RegClass::FPR: *out << "v"; break; + case RegClass::FPRFixed: *out << "V"; break; + case RegClass::Complex: *out << "c"; break; + case RegClass::Invalid: *out << "invalid"; break; default: *out << "unknown"; break; } - if (PhyReg.Class != FEXCore::IR::InvalidClass.Val) { - *out << std::dec << (uint32_t)PhyReg.Reg; + if (PhyReg.AsRegClass() != RegClass::Invalid) { + *out << std::dec << uint32_t(PhyReg.Reg); } return; @@ -397,17 +397,17 @@ void Dump(fextl::stringstream* out, const IRListView* IR) { auto PhyReg = PhysicalRegister(CodeNode); if (!PhyReg.IsInvalid()) { - switch (PhyReg.Class) { - case FEXCore::IR::GPRClass.Val: *out << "(r"; break; - case FEXCore::IR::GPRFixedClass.Val: *out << "(R"; break; - case FEXCore::IR::FPRClass.Val: *out << "(v"; break; - case FEXCore::IR::FPRFixedClass.Val: *out << "(V"; break; - case FEXCore::IR::ComplexClass.Val: *out << "(complex"; break; - case FEXCore::IR::InvalidClass.Val: *out << "(invalid"; break; + switch (PhyReg.AsRegClass()) { + case RegClass::GPR: *out << "(r"; break; + case RegClass::GPRFixed: *out << "(R"; break; + case RegClass::FPR: *out << "(v"; break; + case RegClass::FPRFixed: *out << "(V"; break; + case RegClass::Complex: *out << "(complex"; break; + case RegClass::Invalid: *out << "(invalid"; break; default: *out << "(unknown"; break; } - if (PhyReg.Class != FEXCore::IR::InvalidClass.Val) { - *out << std::dec << (uint32_t)PhyReg.Reg << ")"; + if (PhyReg.AsRegClass() != RegClass::Invalid) { + *out << std::dec << uint32_t(PhyReg.Reg) << ")"; } else { *out << ")"; } diff --git a/FEXCore/Source/Interface/IR/IREmitter.cpp b/FEXCore/Source/Interface/IR/IREmitter.cpp index 3afd72257..8eab63541 100644 --- a/FEXCore/Source/Interface/IR/IREmitter.cpp +++ b/FEXCore/Source/Interface/IR/IREmitter.cpp @@ -33,14 +33,14 @@ bool IsBlockExit(FEXCore::IR::IROps Op) { } } -FEXCore::IR::RegisterClassType IREmitter::WalkFindRegClass(Ref Node) { +RegClass IREmitter::WalkFindRegClass(Ref Node) { auto Class = GetOpRegClass(Node); switch (Class) { - case GPRClass: - case FPRClass: - case GPRFixedClass: - case FPRFixedClass: - case InvalidClass: return Class; + case RegClass::GPR: + case RegClass::FPR: + case RegClass::GPRFixed: + case RegClass::FPRFixed: + case RegClass::Invalid: return Class; default: break; } @@ -82,7 +82,7 @@ FEXCore::IR::RegisterClassType IREmitter::WalkFindRegClass(Ref Node) { } default: LOGMAN_MSG_A_FMT("Unhandled op type: {} {} in argument class validation", ToUnderlying(IROp->Op), GetOpName(Node)); break; } - return InvalidClass; + return RegClass::Invalid; } void IREmitter::ResetWorkingList() { diff --git a/FEXCore/Source/Interface/IR/IREmitter.h b/FEXCore/Source/Interface/IR/IREmitter.h index 472253f32..9fa1a177e 100644 --- a/FEXCore/Source/Interface/IR/IREmitter.h +++ b/FEXCore/Source/Interface/IR/IREmitter.h @@ -46,7 +46,7 @@ public: * * @{ */ - FEXCore::IR::RegisterClassType WalkFindRegClass(Ref Node); + RegClass WalkFindRegClass(Ref Node); // These inlining helpers are used by IRDefines.inc so define first. Ref InlineMem(OpSize Size, Ref Offset, MemOffsetType OffsetType, uint8_t& OffsetScale, bool TSO = false) { @@ -124,67 +124,67 @@ public: } IRPair _LoadContextGPR(OpSize ByteSize, uint32_t Offset) { - return _LoadContext(ByteSize, GPRClass, Offset); + return _LoadContext(ByteSize, RegClass::GPR, Offset); } IRPair _LoadContextFPR(OpSize ByteSize, uint32_t Offset) { - return _LoadContext(ByteSize, FPRClass, Offset); + return _LoadContext(ByteSize, RegClass::FPR, Offset); } IRPair _StoreContextGPR(OpSize ByteSize, Ref Value, uint32_t Offset) { - return _StoreContext(ByteSize, GPRClass, Value, Offset); + return _StoreContext(ByteSize, RegClass::GPR, Value, Offset); } IRPair _StoreContextFPR(OpSize ByteSize, Ref Value, uint32_t Offset) { - return _StoreContext(ByteSize, FPRClass, Value, Offset); + return _StoreContext(ByteSize, RegClass::FPR, Value, Offset); } IRPair _LoadContextGPRIndexed(Ref Index, OpSize ByteSize, uint32_t BaseOffset, uint32_t Stride) { - return _LoadContextIndexed(Index, ByteSize, BaseOffset, Stride, GPRClass); + return _LoadContextIndexed(Index, ByteSize, BaseOffset, Stride, RegClass::GPR); } IRPair _LoadContextFPRIndexed(Ref Index, OpSize ByteSize, uint32_t BaseOffset, uint32_t Stride) { - return _LoadContextIndexed(Index, ByteSize, BaseOffset, Stride, FPRClass); + return _LoadContextIndexed(Index, ByteSize, BaseOffset, Stride, RegClass::FPR); } IRPair _StoreContextGPRIndexed(Ref Value, Ref Index, OpSize ByteSize, uint32_t BaseOffset, uint32_t Stride) { - return _StoreContextIndexed(Value, Index, ByteSize, BaseOffset, Stride, GPRClass); + return _StoreContextIndexed(Value, Index, ByteSize, BaseOffset, Stride, RegClass::GPR); } IRPair _StoreContextFPRIndexed(Ref Value, Ref Index, OpSize ByteSize, uint32_t BaseOffset, uint32_t Stride) { - return _StoreContextIndexed(Value, Index, ByteSize, BaseOffset, Stride, FPRClass); + return _StoreContextIndexed(Value, Index, ByteSize, BaseOffset, Stride, RegClass::FPR); } - IRPair _LoadMem(RegisterClassType Class, OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { + IRPair _LoadMem(RegClass Class, OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { return _LoadMem(Class, Size, ssa0, Invalid(), Align, MemOffsetType::SXTX, 1); } IRPair _LoadMemGPR(OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { - return _LoadMem(GPRClass, Size, ssa0, Invalid(), Align, MemOffsetType::SXTX, 1); + return _LoadMem(RegClass::GPR, Size, ssa0, Invalid(), Align, MemOffsetType::SXTX, 1); } IRPair _LoadMemGPR(OpSize Size, Ref Addr, Ref Offset, OpSize Align, MemOffsetType OffsetType, uint8_t OffsetScale) { - return _LoadMem(GPRClass, Size, Addr, Offset, Align, OffsetType, OffsetScale); + return _LoadMem(RegClass::GPR, Size, Addr, Offset, Align, OffsetType, OffsetScale); } IRPair _LoadMemFPR(OpSize Size, Ref ssa0, OpSize Align = OpSize::i8Bit) { - return _LoadMem(FPRClass, Size, ssa0, Invalid(), Align, MemOffsetType::SXTX, 1); + return _LoadMem(RegClass::FPR, Size, ssa0, Invalid(), Align, MemOffsetType::SXTX, 1); } IRPair _LoadMemFPR(OpSize Size, Ref Addr, Ref Offset, OpSize Align, MemOffsetType OffsetType, uint8_t OffsetScale) { - return _LoadMem(FPRClass, Size, Addr, Offset, Align, OffsetType, OffsetScale); + return _LoadMem(RegClass::FPR, Size, Addr, Offset, Align, OffsetType, OffsetScale); } - IRPair _StoreMem(RegisterClassType Class, OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { + IRPair _StoreMem(RegClass Class, OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { return _StoreMem(Class, Size, Value, Addr, Invalid(), Align, MemOffsetType::SXTX, 1); } IRPair _StoreMemGPR(OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { - return _StoreMem(GPRClass, Size, Value, Addr, Invalid(), Align, MemOffsetType::SXTX, 1); + return _StoreMem(RegClass::GPR, Size, Value, Addr, Invalid(), Align, MemOffsetType::SXTX, 1); } IRPair _StoreMemGPR(OpSize Size, Ref Value, Ref Addr, Ref Offset, OpSize Align, MemOffsetType OffsetType, uint8_t OffsetScale) { - return _StoreMem(GPRClass, Size, Value, Addr, Offset, Align, OffsetType, OffsetScale); + return _StoreMem(RegClass::GPR, Size, Value, Addr, Offset, Align, OffsetType, OffsetScale); } IRPair _StoreMemFPR(OpSize Size, Ref Addr, Ref Value, OpSize Align = OpSize::i8Bit) { - return _StoreMem(FPRClass, Size, Value, Addr, Invalid(), Align, MemOffsetType::SXTX, 1); + return _StoreMem(RegClass::FPR, Size, Value, Addr, Invalid(), Align, MemOffsetType::SXTX, 1); } IRPair _StoreMemFPR(OpSize Size, Ref Value, Ref Addr, Ref Offset, OpSize Align, MemOffsetType OffsetType, uint8_t OffsetScale) { - return _StoreMem(FPRClass, Size, Value, Addr, Offset, Align, OffsetType, OffsetScale); + return _StoreMem(RegClass::FPR, Size, Value, Addr, Offset, Align, OffsetType, OffsetScale); } IRPair _StoreMemPairGPR(OpSize Size, Ref Value1, Ref Value2, Ref Addr, uint32_t Offset) { - return _StoreMemPair(GPRClass, Size, Value1, Value2, Addr, Offset); + return _StoreMemPair(RegClass::GPR, Size, Value1, Value2, Addr, Offset); } IRPair _StoreMemPairFPR(OpSize Size, Ref Value1, Ref Value2, Ref Addr, uint32_t Offset) { - return _StoreMemPair(FPRClass, Size, Value1, Value2, Addr, Offset); + return _StoreMemPair(RegClass::FPR, Size, Value1, Value2, Addr, Offset); } IRPair Select01(FEXCore::IR::OpSize CompareSize, CondClass Cond, OrderedNode* Cmp1, OrderedNode* Cmp2) { @@ -308,7 +308,7 @@ public: } /** @} */ - FEXCore::IR::RegisterClassType WalkFindRegClass(OrderedNodeWrapper ssa) { + RegClass WalkFindRegClass(OrderedNodeWrapper ssa) { Ref RealNode = ssa.GetNode(DualListData.ListBegin()); return WalkFindRegClass(RealNode); } diff --git a/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp b/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp index fc46e290e..dbbb0d484 100644 --- a/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp +++ b/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp @@ -93,11 +93,11 @@ void IRValidation::Run(IREmitter* IREmit) { // After RA, the destination needs to be assigned a register and class auto PhyReg = PhysicalRegister(CodeNode); - FEXCore::IR::RegisterClassType ExpectedClass = IR::GetRegClass(IROp->Op); - FEXCore::IR::RegisterClassType AssignedClass = FEXCore::IR::RegisterClassType {PhyReg.Class}; + const auto ExpectedClass = IR::GetRegClass(IROp->Op); + const auto AssignedClass = PhyReg.AsRegClass(); // If no register class was assigned - if (AssignedClass == IR::InvalidClass) { + if (AssignedClass == IR::RegClass::Invalid) { HadError |= true; Errors << "%" << ID << ": Had destination but with no register class assigned" << std::endl; } @@ -109,10 +109,10 @@ void IRValidation::Run(IREmitter* IREmit) { } // Assigned class wasn't the expected class and it is a non-complex op - if (AssignedClass != ExpectedClass && ExpectedClass != IR::ComplexClass) { + if (AssignedClass != ExpectedClass && ExpectedClass != IR::RegClass::Complex) { HadWarning |= true; - Warnings << "%" << ID << ": Destination had register class " << AssignedClass.Val << " When register class " - << ExpectedClass.Val << " Was expected" << std::endl; + Warnings << "%" << ID << ": Destination had register class " << uint32_t(AssignedClass) << " When register class " + << uint32_t(ExpectedClass) << " Was expected" << std::endl; } } } diff --git a/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp b/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp index 80ef39c0c..69e21a18d 100644 --- a/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp +++ b/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp @@ -12,6 +12,7 @@ $end_info$ #include "Interface/IR/Passes.h" #include "Interface/Core/CPUID.h" #include +#include #include #include #include @@ -22,7 +23,7 @@ using namespace FEXCore; namespace FEXCore::IR { namespace { - struct RegisterClass { + struct RegisterClassData { uint32_t Available; uint32_t Count; @@ -32,9 +33,9 @@ namespace { Ref RegToSSA[32]; }; - IR::RegisterClassType GetRegClassFromNode(IR::IRListView* IR, IR::IROp_Header* IROp) { - IR::RegisterClassType Class = IR::GetRegClass(IROp->Op); - if (Class != IR::ComplexClass) { + IR::RegClass GetRegClassFromNode(IR::IRListView* IR, IR::IROp_Header* IROp) { + const auto Class = IR::GetRegClass(IROp->Op); + if (Class != IR::RegClass::Complex) { return Class; } @@ -46,7 +47,7 @@ namespace { case IR::OP_LOADMEM: case IR::OP_LOADMEMTSO: return IROp->C()->Class; case IR::OP_FILLREGISTER: return IROp->C()->Class; - default: return IR::InvalidClass; + default: return IR::RegClass::Invalid; } }; } // Anonymous namespace @@ -56,11 +57,11 @@ public: explicit ConstrainedRAPass(const FEXCore::CPUIDEmu* CPUID) : CPUID {CPUID} {} void Run(IREmitter* IREmit) override; - void AddRegisters(IR::RegisterClassType Class, uint32_t RegisterCount) override; + void AddRegisters(IR::RegClass Class, uint32_t RegisterCount) override; bool TryPostRAMerge(Ref LastNode, Ref CodeNode, IROp_Header* IROp); private: - RegisterClass Classes[IR::NumClasses]; + RegisterClassData Classes[IR::NumClasses]; IREmitter* IREmit; IRListView* IR; @@ -101,7 +102,7 @@ private: uint32_t SlotPlusOne = SpillSlots[IR->GetID(Node).Value]; LOGMAN_THROW_A_FMT(SlotPlusOne >= 1, "Node must have been spilled"); - RegisterClassType RegClass = GetRegClassFromNode(IR, IROp); + const auto RegClass = GetRegClassFromNode(IR, IROp); return IREmit->_FillRegister(IROp->Size, IROp->ElementSize, SlotPlusOne - 1, RegClass); }; @@ -120,7 +121,7 @@ private: return Op != OP_INLINECONSTANT && Op != OP_INLINEENTRYPOINTOFFSET; }; - RegisterClass* GetClass(PhysicalRegister Reg) { + RegisterClassData* GetClass(PhysicalRegister Reg) { return &Classes[Reg.Class]; }; @@ -133,13 +134,13 @@ private: LOGMAN_THROW_A_FMT(ID < SSAToReg.size(), "Only old nodes looked up"); PhysicalRegister Reg = SSAToReg[ID]; - RegisterClass* Class = GetClass(Reg); + RegisterClassData* Class = GetClass(Reg); return (Class->Available & GetRegBits(Reg)) == 0 && Class->RegToSSA[Reg.Reg] == Node; }; void FreeReg(PhysicalRegister Reg) { - RegisterClass* Class = GetClass(Reg); + RegisterClassData* Class = GetClass(Reg); uint32_t RegBits = GetRegBits(Reg); LOGMAN_THROW_A_FMT(!(Class->Available & RegBits), "Register double-free"); @@ -187,22 +188,22 @@ private: }; PhysicalRegister DecodeSRAReg(const IROp_Header* IROp, Ref Node) { - uint8_t FlagOffset = Classes[GPRFixedClass.Val].Count - 2; + uint8_t FlagOffset = Classes[FEXCore::ToUnderlying(RegClass::GPRFixed)].Count - 2; if (IROp->Op == OP_STOREREGISTER) { return PhysicalRegister(Node); } else if (IROp->Op == OP_LOADPF || IROp->Op == OP_STOREPF) { - return PhysicalRegister {GPRFixedClass, FlagOffset}; + return PhysicalRegister {RegClass::GPRFixed, FlagOffset}; } else if (IROp->Op == OP_LOADAF || IROp->Op == OP_STOREAF) { - return PhysicalRegister {GPRFixedClass, (uint8_t)(FlagOffset + 1)}; + return PhysicalRegister {RegClass::GPRFixed, uint8_t(FlagOffset + 1)}; } else { const IROp_LoadRegister* Op = IROp->C(); - LOGMAN_THROW_A_FMT(Op->Class == GPRClass || Op->Class == FPRClass, "SRA classes"); - if (Op->Class == FPRClass) { - return PhysicalRegister {FPRFixedClass, (uint8_t)Op->Reg}; + LOGMAN_THROW_A_FMT(Op->Class == RegClass::GPR || Op->Class == RegClass::FPR, "SRA classes"); + if (Op->Class == RegClass::FPR) { + return PhysicalRegister {RegClass::FPRFixed, uint8_t(Op->Reg)}; } else { - return PhysicalRegister {GPRFixedClass, (uint8_t)Op->Reg}; + return PhysicalRegister {RegClass::GPRFixed, uint8_t(Op->Reg)}; } } }; @@ -267,7 +268,7 @@ private: SourceIndex = SourcesNextUses.size(); } - void SpillReg(RegisterClass* Class, IROp_CodeBlock* Block, IROp_Header* Exclude) { + void SpillReg(RegisterClassData* Class, IROp_CodeBlock* Block, IROp_Header* Exclude) { // We're about to use next-use information, so calculate it. if (!AnySpilled) { CalculateNextUses(Block, Exclude); @@ -318,7 +319,7 @@ private: // If we already spilled the Candidate, we don't need to spill again. // Similarly, if we can rematerialize the instruction, we don't spill it. if (!Spilled && Header->Op != OP_CONSTANT) { - LOGMAN_THROW_A_FMT(Reg.Class == GetRegClassFromNode(IR, Header), "Consistent"); + LOGMAN_THROW_A_FMT(Reg.AsRegClass() == GetRegClassFromNode(IR, Header), "Consistent"); // SpillSlots allocation is deferred. if (SpillSlots.empty()) { @@ -329,7 +330,7 @@ private: uint32_t Slot = IR->GetHeader()->SpillSlots++; // We must map here in case we're spilling something we shuffled. - auto SpillOp = IREmit->_SpillRegister(OrderedNodeWrapper::FromImmediate(Reg.Raw), Slot, RegisterClassType {Reg.Class}); + auto SpillOp = IREmit->_SpillRegister(OrderedNodeWrapper::FromImmediate(Reg.Raw), Slot, Reg.AsRegClass()); SpillOp.first->Header.Size = Header->Size; SpillOp.first->Header.ElementSize = Header->ElementSize; SpillSlots[Value] = Slot + 1; @@ -341,7 +342,7 @@ private: }; void RemapReg(Ref Node, PhysicalRegister Reg) { - RegisterClass* Class = GetClass(Reg); + RegisterClassData* Class = GetClass(Reg); Class->RegToSSA[Reg.Reg] = Node; uint32_t Index = IR->GetID(Node).Value; @@ -352,7 +353,7 @@ private: // Record a given assignment of register Reg to Node. void SetReg(Ref Node, PhysicalRegister Reg) { - RegisterClass* Class = GetClass(Reg); + RegisterClassData* Class = GetClass(Reg); uint32_t RegBits = GetRegBits(Reg); LOGMAN_THROW_A_FMT((Class->Available & RegBits) == RegBits, "Precondition"); @@ -370,7 +371,7 @@ private: // Prioritize preferred registers. if (Node < PreferredReg.size()) { if (PhysicalRegister Reg = PreferredReg[Node]; !Reg.IsInvalid()) { - RegisterClass* Class = GetClass(Reg); + RegisterClassData* Class = GetClass(Reg); uint32_t RegBits = GetRegBits(Reg); if ((Class->Available & RegBits) == RegBits) { @@ -383,10 +384,10 @@ private: // Try to handle tied registers. This can fail, the JIT will insert moves. if (int TiedIdx = IR::TiedSource(IROp->Op); TiedIdx >= 0) { auto Reg = PhysicalRegister(IROp->Args[TiedIdx]); - RegisterClass* Class = GetClass(Reg); + RegisterClassData* Class = GetClass(Reg); uint32_t RegBits = GetRegBits(Reg); - if (Reg.Class != GPRFixedClass && Reg.Class != FPRFixedClass && (Class->Available & RegBits) == RegBits) { + if (Reg.AsRegClass() != RegClass::GPRFixed && Reg.AsRegClass() != RegClass::FPRFixed && (Class->Available & RegBits) == RegBits) { SetReg(CodeNode, Reg); return; } @@ -394,7 +395,7 @@ private: // Try to coalesce reserved pairs. Just a heuristic to remove some moves. if (IROp->Op == OP_ALLOCATEGPR && IROp->C()->ForPair) { - uint32_t Available = Classes[GPRClass].Available; + uint32_t Available = Classes[FEXCore::ToUnderlying(RegClass::GPR)].Available; // Only choose base register R if R and R + 1 are both free Available &= (Available >> 1); @@ -405,20 +406,20 @@ private: if (Available) { unsigned Reg = std::countr_zero(Available); - SetReg(CodeNode, PhysicalRegister(GPRClass, Reg)); + SetReg(CodeNode, PhysicalRegister(RegClass::GPR, Reg)); return; } } else if (IROp->Op == OP_ALLOCATEGPRAFTER) { - uint32_t Available = Classes[GPRClass].Available; + uint32_t Available = Classes[FEXCore::ToUnderlying(RegClass::GPR)].Available; auto After = PhysicalRegister(IROp->Args[0]); if ((After.Reg & 1) == 0 && Available & (1ull << (After.Reg + 1))) { - SetReg(CodeNode, PhysicalRegister(GPRClass, After.Reg + 1)); + SetReg(CodeNode, PhysicalRegister(RegClass::GPR, After.Reg + 1)); return; } } - RegisterClassType ClassType = GetRegClassFromNode(IR, IROp); - RegisterClass* Class = &Classes[ClassType]; + RegClass ClassType = GetRegClassFromNode(IR, IROp); + RegisterClassData* Class = &Classes[FEXCore::ToUnderlying(ClassType)]; // Spill to make room in the register file. if (!Class->Available) { @@ -433,10 +434,10 @@ private: }; }; -void ConstrainedRAPass::AddRegisters(IR::RegisterClassType Class, uint32_t RegisterCount) { +void ConstrainedRAPass::AddRegisters(IR::RegClass Class, uint32_t RegisterCount) { LOGMAN_THROW_A_FMT(RegisterCount <= 31, "Up to 31 regs supported"); - Classes[Class].Count = RegisterCount; + Classes[FEXCore::ToUnderlying(Class)].Count = RegisterCount; } inline bool KillMove(IROp_Header* LastOp, IROp_Header* IROp, Ref LastNode, Ref CodeNode) { @@ -663,7 +664,7 @@ void ConstrainedRAPass::Run(IREmitter* IREmit_) { // Static registers must be consistent at SRA load/store. Evict to ensure. if (auto Node = DecodeSRANode(IROp, CodeNode); Node != nullptr) { auto Reg = DecodeSRAReg(IROp, CodeNode); - RegisterClass* Class = &Classes[Reg.Class]; + RegisterClassData* Class = &Classes[Reg.Class]; if (!(Class->Available & (1u << Reg.Reg))) { Ref Old = Class->RegToSSA[Reg.Reg]; @@ -678,7 +679,7 @@ void ConstrainedRAPass::Run(IREmitter* IREmit_) { Ref Copy; - if (Reg.Class == FPRFixedClass) { + if (Reg.AsRegClass() == RegClass::FPRFixed) { IROp_Header* Header = IR->GetOp(Old); Copy = IREmit->_VMov(Header->Size, OrderedNodeWrapper::FromImmediate(Reg.Raw)); } else { diff --git a/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.h b/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.h index a5f29de13..862dba5b6 100644 --- a/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.h +++ b/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.h @@ -12,11 +12,11 @@ $end_info$ #include namespace FEXCore::IR { -struct RegisterClassType; +enum class RegClass : uint32_t; class RegisterAllocationPass : public FEXCore::IR::Pass { public: - virtual void AddRegisters(FEXCore::IR::RegisterClassType Class, uint32_t RegisterCount) = 0; + virtual void AddRegisters(RegClass Class, uint32_t RegisterCount) = 0; // Number of GPRs usable for pairs at start of GPR set. Must be even. uint32_t PairRegs; diff --git a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp index dc3e3c392..97c7c672b 100644 --- a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp +++ b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp @@ -1014,8 +1014,8 @@ void X87StackOptimization::Run(IREmitter* Emit) { // or similar. As long as the source size and dest size are one and the same. // This will avoid any conversions between source and stack element size and conversion back. if (!SlowPath && Value->Source && Value->Source->Size == Op->StoreSize && Value->InterpretAsFloat) { - IREmit->_StoreMem(Value->InterpretAsFloat ? FPRClass : GPRClass, Op->StoreSize, Value->Source->Node, AddrNode, Offset, Align, - OffsetType, OffsetScale); + const auto ClassType = Value->InterpretAsFloat ? RegClass::FPR : RegClass::GPR; + IREmit->_StoreMem(ClassType, Op->StoreSize, Value->Source->Node, AddrNode, Offset, Align, OffsetType, OffsetScale); break; } diff --git a/FEXCore/Source/Interface/IR/RegisterAllocationData.h b/FEXCore/Source/Interface/IR/RegisterAllocationData.h index 24d767af8..378da3274 100644 --- a/FEXCore/Source/Interface/IR/RegisterAllocationData.h +++ b/FEXCore/Source/Interface/IR/RegisterAllocationData.h @@ -19,9 +19,9 @@ union PhysicalRegister { return Raw == Other.Raw; } - PhysicalRegister(RegisterClassType Class, uint8_t Reg) + PhysicalRegister(RegClass Class, uint8_t Reg) : Reg(Reg) - , Class(Class.Val) {} + , Class(uint8_t(Class)) {} PhysicalRegister(OrderedNodeWrapper Arg) : Raw(Arg.GetImmediate()) {} @@ -29,12 +29,16 @@ union PhysicalRegister { PhysicalRegister(Ref Node) : Raw(Node->Reg) {} + RegClass AsRegClass() const { + return RegClass {Class}; + } + static const PhysicalRegister Invalid() { - return PhysicalRegister(InvalidClass, 0); + return PhysicalRegister(RegClass::Invalid, 0); } bool IsInvalid() const { - static_assert(InvalidClass == 0); + static_assert(uint8_t(RegClass::Invalid) == 0); return Raw == 0; } };