diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 709fb7456..89b998e9a 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -132,7 +132,7 @@ void OpDispatchBuilder::ThunkOp(OpcodeArgs) { void OpDispatchBuilder::LEAOp(OpcodeArgs) { // LEA specifically ignores segment prefixes - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); if (CTX->Config.Is64BitMode) { const uint32_t DstSize = @@ -702,7 +702,7 @@ void OpDispatchBuilder::SETccOp(OpcodeArgs) { } void OpDispatchBuilder::CMOVOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); // Calculate flags early. CalculateDeferredFlags(); @@ -861,12 +861,12 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { bool ZFTrue = Op->OP == 0xE1; BlockSetRIP = true; - uint32_t SrcSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? OpSize::i32Bit : OpSize::i64Bit; + auto SrcSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? OpSize::i32Bit : OpSize::i64Bit; auto OpSize = SrcSize == OpSize::i64Bit ? OpSize::i64Bit : OpSize::i32Bit; if (!CTX->Config.Is64BitMode) { // RCX size is 32-bit or 16-bit when executing in 32-bit mode. - SrcSize >>= 1; + SrcSize = IR::SizeToOpSize(IR::OpSizeToSize(SrcSize) >> 1); OpSize = OpSize::i32Bit; } @@ -1041,7 +1041,7 @@ void OpDispatchBuilder::MOVSXDOp(OpcodeArgs) { // else // Zext(32, Src) // - uint8_t Size = std::min(OpSize::i32Bit, GetSrcSize(Op)); + auto Size = std::min(OpSize::i32Bit, OpSizeFromSrc(Op)); bool Sext = (Size != OpSize::i16Bit) && Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING; Ref Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], Size, Op->Flags, {.AllowUpperGarbage = Sext}); @@ -1333,7 +1333,7 @@ void OpDispatchBuilder::MOVOffsetOp(OpcodeArgs) { } void OpDispatchBuilder::CPUIDOp(OpcodeArgs) { - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); Ref Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GPRSize, Op->Flags); Ref Leaf = LoadGPRRegister(X86State::REG_RCX); @@ -1765,8 +1765,8 @@ void OpDispatchBuilder::BLSRBMIOp(OpcodeArgs) { void OpDispatchBuilder::BMI2Shift(OpcodeArgs) { // In the event the source is a memory operand, use the // exact width instead of the GPR size. - const auto GPRSize = CTX->GetGPRSize(); - const auto Size = GetSrcSize(Op); + const auto GPRSize = CTX->GetGPROpSize(); + const auto Size = OpSizeFromSrc(Op); const auto SrcSize = Op->Src[0].IsGPR() ? GPRSize : Size; auto* Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], SrcSize, Op->Flags); @@ -1854,12 +1854,12 @@ void OpDispatchBuilder::RORX(OpcodeArgs) { void OpDispatchBuilder::MULX(OpcodeArgs) { // RDX is the implied source operand in the instruction - const auto OperandSize = GetSrcSize(Op); + const auto OperandSize = OpSizeFromSrc(Op); const auto OpSize = IR::SizeToOpSize(OperandSize); // Src1 can be a memory operand, so ensure we constrain to the // absolute width of the access in that scenario. - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); const auto Src1Size = Op->Src[1].IsGPR() ? GPRSize : OperandSize; Ref Src1 = LoadSource_WithOpSize(GPRClass, Op, Op->Src[1], Src1Size, Op->Flags); @@ -2401,7 +2401,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { if (Op->Dest.IsGPR()) { // When the destination is a GPR, we don't care about garbage in the upper bits. // Load the full register. - auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPRSize(), Op->Flags); + auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPROpSize(), Op->Flags); Value = Dest; // Get the bit selection from the src. We need to mask for 8/16-bit, but @@ -2473,7 +2473,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { switch (Action) { case BTAction::BTNone: { - Value = _LoadMemAutoTSO(GPRClass, 1, Address, 1); + Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); break; } @@ -2484,7 +2484,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { HandledLock = true; Value = _AtomicFetchCLR(OpSize::i8Bit, BitMask, LoadEffectiveAddress(Address, true)); } else { - Value = _LoadMemAutoTSO(GPRClass, 1, Address, 1); + Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); auto Modified = _Andn(OpSize::i64Bit, Value, BitMask); _StoreMemAutoTSO(GPRClass, 1, Address, Modified, 1); @@ -2499,7 +2499,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { HandledLock = true; Value = _AtomicFetchOr(OpSize::i8Bit, BitMask, LoadEffectiveAddress(Address, true)); } else { - Value = _LoadMemAutoTSO(GPRClass, 1, Address, 1); + Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); auto Modified = _Or(OpSize::i64Bit, Value, BitMask); _StoreMemAutoTSO(GPRClass, 1, Address, Modified, 1); @@ -2514,7 +2514,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) { HandledLock = true; Value = _AtomicFetchXor(OpSize::i8Bit, BitMask, LoadEffectiveAddress(Address, true)); } else { - Value = _LoadMemAutoTSO(GPRClass, 1, Address, 1); + Value = _LoadMemAutoTSO(GPRClass, OpSize::i8Bit, Address, OpSize::i8Bit); auto Modified = _Xor(OpSize::i64Bit, Value, BitMask); _StoreMemAutoTSO(GPRClass, 1, Address, Modified, 1); @@ -2738,7 +2738,7 @@ void OpDispatchBuilder::NOTOp(OpcodeArgs) { // Always load full size, we explicitly want the upper bits to get the // insert behaviour for free/implicitly. - const uint8_t GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); Ref Src = LoadSource_WithOpSize(GPRClass, Op, Dest, GPRSize, Op->Flags); // For 8/16-bit, use 64-bit invert so we invert in place, while getting @@ -2956,7 +2956,7 @@ void OpDispatchBuilder::WriteSegmentReg(OpcodeArgs, OpDispatchBuilder::Segment S } void OpDispatchBuilder::EnterOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); const uint64_t Value = Op->Src[0].Literal(); const uint16_t AllocSpace = Value & 0xFFFF; @@ -3041,7 +3041,7 @@ void OpDispatchBuilder::SMSWOp(OpcodeArgs) { if (!IsMemDst && DstSize == OpSize::i32Bit) { // Special-case version of `smsw ebx`. This instruction does an insert in to the lower 32-bits on 64-bit hosts. // Override and insert. - auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPRSize(), Op->Flags); + auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPROpSize(), Op->Flags); Const = _Bfi(OpSize::i64Bit, 32, 0, Dest, Const); DstSize = OpSize::i64Bit; } @@ -3214,7 +3214,7 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { } // RA now can handle these to be here, to avoid DF accesses - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); if (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) { auto SrcAddr = LoadGPRRegister(X86State::REG_RSI); @@ -3272,7 +3272,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { return; } - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); bool Repeat = Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX); if (!Repeat) { @@ -3392,7 +3392,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { return; } - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) != 0; if (!Repeat) { @@ -3475,7 +3475,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { return; } - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX)) != 0; if (!Repeat) { @@ -3560,13 +3560,13 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { void OpDispatchBuilder::BSWAPOp(OpcodeArgs) { Ref Dest; - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); if (Size == OpSize::i16Bit) { // BSWAP of 16bit is undef. ZEN+ causes the lower 16bits to get zero'd Dest = _Constant(0); } else { - Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPRSize(), Op->Flags); - Dest = _Rev(IR::SizeToOpSize(Size), Dest); + Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPROpSize(), Op->Flags); + Dest = _Rev(Size, Dest); } StoreResult(GPRClass, Op, Dest, -1); } @@ -3712,8 +3712,8 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) { } void OpDispatchBuilder::BSFOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); - const uint8_t DstSize = GetDstSize(Op) == OpSize::i16Bit ? OpSize::i16Bit : GPRSize; + const auto GPRSize = CTX->GetGPROpSize(); + const auto DstSize = OpSizeFromDst(Op) == OpSize::i16Bit ? OpSize::i16Bit : GPRSize; Ref Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags, {.AllowUpperGarbage = true}); Ref Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); @@ -3734,8 +3734,8 @@ void OpDispatchBuilder::BSFOp(OpcodeArgs) { } void OpDispatchBuilder::BSROp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); - const uint8_t DstSize = GetDstSize(Op) == OpSize::i16Bit ? OpSize::i16Bit : GPRSize; + const auto GPRSize = CTX->GetGPROpSize(); + const auto DstSize = OpSizeFromDst(Op) == OpSize::i16Bit ? OpSize::i16Bit : GPRSize; Ref Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags, {.AllowUpperGarbage = true}); Ref Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); @@ -3767,8 +3767,8 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) { // *Xn = Xt // Xs = MemData - const auto GPRSize = CTX->GetGPRSize(); - auto Size = GetSrcSize(Op); + const auto GPRSize = CTX->GetGPROpSize(); + auto Size = OpSizeFromSrc(Op); if (Op->Dest.IsGPR()) { // This is our source register @@ -4292,7 +4292,7 @@ AddressMode OpDispatchBuilder::DecodeAddress(const X86Tables::DecodedOp& Op, con Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, - uint8_t OpSize, uint32_t Flags, const LoadSourceOptions& Options) { + IR::OpSize OpSize, uint32_t Flags, const LoadSourceOptions& Options) { auto [Align, LoadData, ForceLoad, AccessType, AllowUpperGarbage] = Options; AddressMode A = DecodeAddress(Op, Operand, AccessType, true /* IsLoad */); @@ -4322,7 +4322,7 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T } if ((IsOperandMem(Operand, true) && LoadData) || ForceLoad) { - return _LoadMemAutoTSO(Class, OpSize, A, Align == -1 ? OpSize : Align); + return _LoadMemAutoTSO(Class, OpSize, A, Align == OpSize::iInvalid ? OpSize : Align); } else { return LoadEffectiveAddress(A, false, AllowUpperGarbage); } @@ -4373,7 +4373,7 @@ void OpDispatchBuilder::StoreXMMRegister(uint32_t XMM, const Ref Src) { Ref OpDispatchBuilder::LoadSource(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, const LoadSourceOptions& Options) { - const uint8_t OpSize = GetSrcSize(Op); + const auto OpSize = OpSizeFromSrc(Op); return LoadSource_WithOpSize(Class, Op, Operand, OpSize, Flags, Options); } @@ -4504,12 +4504,12 @@ void OpDispatchBuilder::UnhandledOp(OpcodeArgs) { void OpDispatchBuilder::MOVGPROp(OpcodeArgs, uint32_t SrcIndex) { // StoreResult will store with the same size as the input, so we allow upper // garbage on the input. The zero extension would be pointless. - Ref Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, {.Align = 1, .AllowUpperGarbage = true}); + Ref Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, {.Align = OpSize::i8Bit, .AllowUpperGarbage = true}); StoreResult(GPRClass, Op, Src, OpSize::i8Bit); } void OpDispatchBuilder::MOVGPRNTOp(OpcodeArgs) { - Ref Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1}); + Ref Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = OpSize::i8Bit}); StoreResult(GPRClass, Op, Src, OpSize::i8Bit, MemoryAccessType::STREAM); } @@ -4745,7 +4745,7 @@ void OpDispatchBuilder::LZCNT(OpcodeArgs) { } void OpDispatchBuilder::MOVBEOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); const auto SrcSize = GetSrcSize(Op); Ref Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = OpSize::i8Bit}); @@ -4837,7 +4837,7 @@ void OpDispatchBuilder::RDPIDOp(OpcodeArgs) { } void OpDispatchBuilder::CRC32(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const auto GPRSize = CTX->GetGPROpSize(); // Destination GPR size is always 4 or 8 bytes depending on widening uint8_t DstSize = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? OpSize::i64Bit : OpSize::i32Bit; @@ -4848,7 +4848,7 @@ void OpDispatchBuilder::CRC32(OpcodeArgs) { if (Op->Src[0].IsGPR()) { Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GPRSize, Op->Flags); } else { - Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1}); + Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = OpSize::i8Bit}); } auto Result = _CRC32(Dest, Src, GetSrcSize(Op)); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Result, DstSize, -1); @@ -5080,8 +5080,8 @@ void OpDispatchBuilder::InstallHostSpecificOpcodeHandlers() { {OPD(1, 0b00, 0x5A), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::Vector_CVT_Float_To_Float, 8, 4, true>}, {OPD(1, 0b01, 0x5A), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::Vector_CVT_Float_To_Float, 4, 8, true>}, - {OPD(1, 0b10, 0x5A), 1, &OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float<8, 4>}, - {OPD(1, 0b11, 0x5A), 1, &OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float<4, 8>}, + {OPD(1, 0b10, 0x5A), 1, &OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float}, + {OPD(1, 0b11, 0x5A), 1, &OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float}, {OPD(1, 0b00, 0x5B), 1, &OpDispatchBuilder::AVXVector_CVT_Int_To_Float<4, false>}, {OPD(1, 0b01, 0x5B), 1, &OpDispatchBuilder::AVXVector_CVT_Float_To_Int<4, false, true>}, @@ -5257,10 +5257,10 @@ void OpDispatchBuilder::InstallHostSpecificOpcodeHandlers() { {OPD(2, 0b01, 0x29), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::AVXVectorALUOp, IR::OP_VCMPEQ, 8>}, {OPD(2, 0b01, 0x2A), 1, &OpDispatchBuilder::MOVVectorNTOp}, {OPD(2, 0b01, 0x2B), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::VPACKUSOp, 4>}, - {OPD(2, 0b01, 0x2C), 1, &OpDispatchBuilder::VMASKMOVOp<4, false>}, - {OPD(2, 0b01, 0x2D), 1, &OpDispatchBuilder::VMASKMOVOp<8, false>}, - {OPD(2, 0b01, 0x2E), 1, &OpDispatchBuilder::VMASKMOVOp<4, true>}, - {OPD(2, 0b01, 0x2F), 1, &OpDispatchBuilder::VMASKMOVOp<8, true>}, + {OPD(2, 0b01, 0x2C), 1, &OpDispatchBuilder::VMASKMOVOp}, + {OPD(2, 0b01, 0x2D), 1, &OpDispatchBuilder::VMASKMOVOp}, + {OPD(2, 0b01, 0x2E), 1, &OpDispatchBuilder::VMASKMOVOp}, + {OPD(2, 0b01, 0x2F), 1, &OpDispatchBuilder::VMASKMOVOp}, {OPD(2, 0b01, 0x30), 1, &OpDispatchBuilder::ExtendVectorElements<1, 2, false>}, {OPD(2, 0b01, 0x31), 1, &OpDispatchBuilder::ExtendVectorElements<1, 4, false>}, diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 79bc263ab..3720e2e9c 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -47,8 +47,8 @@ enum class BTAction { }; struct LoadSourceOptions { - // Alignment of the load in bytes. -1 signifies unaligned - int8_t Align = -1; + // Alignment of the load in bytes. iInvalid signifies opsize aligned. + IR::OpSize Align = OpSize::iInvalid; // Whether or not to load the data if a memory access occurs. // If set to false, then the address that would have been loaded from @@ -464,7 +464,7 @@ public: void CVTFPR_To_GPR(OpcodeArgs); template void Vector_CVT_Int_To_Float(OpcodeArgs); - template + template void Scalar_CVT_Float_To_Float(OpcodeArgs); void Vector_CVT_Float_To_Float(OpcodeArgs, size_t DstElementSize, size_t SrcElementSize, bool IsAVX); template @@ -513,7 +513,7 @@ public: template void AVXVectorRound(OpcodeArgs); - template + template void AVXScalar_CVT_Float_To_Float(OpcodeArgs); template @@ -590,7 +590,7 @@ public: void VINSERTOp(OpcodeArgs); void VINSERTPSOp(OpcodeArgs); - template + template void VMASKMOVOp(OpcodeArgs); void VMOVHPOp(OpcodeArgs); @@ -934,7 +934,7 @@ public: void AVX128_StoreResult_WithOpSize(FEXCore::X86Tables::DecodedOp Op, const FEXCore::X86Tables::DecodedOperand& Operand, const RefPair Src, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); void InstallAVX128Handlers(); - void AVX128_VMOVScalarImpl(OpcodeArgs, size_t ElementSize); + void AVX128_VMOVScalarImpl(OpcodeArgs, IR::OpSize ElementSize); void AVX128_VectorALU(OpcodeArgs, IROps IROp, size_t ElementSize); void AVX128_VectorUnary(OpcodeArgs, IROps IROp, size_t ElementSize); void AVX128_VectorUnaryImpl(OpcodeArgs, size_t SrcSize, size_t ElementSize, std::function Helper); @@ -1424,11 +1424,11 @@ private: Ref SHUFOpImpl(OpcodeArgs, size_t DstSize, size_t ElementSize, Ref Src1, Ref Src2, uint8_t Shuffle); - void VMASKMOVOpImpl(OpcodeArgs, size_t ElementSize, size_t DataSize, bool IsStore, const X86Tables::DecodedOperand& MaskOp, + void VMASKMOVOpImpl(OpcodeArgs, IR::OpSize ElementSize, IR::OpSize DataSize, bool IsStore, const X86Tables::DecodedOperand& MaskOp, const X86Tables::DecodedOperand& DataOp); - void MOVScalarOpImpl(OpcodeArgs, size_t ElementSize); - void VMOVScalarOpImpl(OpcodeArgs, size_t ElementSize); + void MOVScalarOpImpl(OpcodeArgs, IR::OpSize ElementSize); + void VMOVScalarOpImpl(OpcodeArgs, IR::OpSize ElementSize); Ref VFCMPOpImpl(OpSize Size, size_t ElementSize, Ref Src1, Ref Src2, uint8_t CompType); @@ -1446,26 +1446,26 @@ private: // - Example 32bit ADDSS Dest, Src // - Dest[31:0] = Dest[31:0] + Src[31:0] // - Dest[{256,128}:32] = (Unmodified) - Ref VectorScalarInsertALUOpImpl(OpcodeArgs, IROps IROp, size_t DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, + Ref VectorScalarInsertALUOpImpl(OpcodeArgs, IROps IROp, IR::OpSize DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits); - Ref VectorScalarUnaryInsertALUOpImpl(OpcodeArgs, IROps IROp, size_t DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, - const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits); + Ref VectorScalarUnaryInsertALUOpImpl(OpcodeArgs, IROps IROp, IR::OpSize DstSize, size_t ElementSize, + const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits); - Ref InsertCVTGPR_To_FPRImpl(OpcodeArgs, size_t DstSize, size_t DstElementSize, const X86Tables::DecodedOperand& Src1Op, + Ref InsertCVTGPR_To_FPRImpl(OpcodeArgs, IR::OpSize DstSize, size_t DstElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits); - Ref InsertScalar_CVT_Float_To_FloatImpl(OpcodeArgs, size_t DstSize, size_t DstElementSize, size_t SrcElementSize, + Ref InsertScalar_CVT_Float_To_FloatImpl(OpcodeArgs, IR::OpSize DstSize, size_t DstElementSize, size_t SrcElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits); - Ref InsertScalarRoundImpl(OpcodeArgs, size_t DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, + Ref InsertScalarRoundImpl(OpcodeArgs, IR::OpSize DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, uint64_t Mode, bool ZeroUpperBits); Ref InsertScalarFCMPOpImpl(OpSize Size, uint8_t OpDstSize, size_t ElementSize, Ref Src1, Ref Src2, uint8_t CompType, bool ZeroUpperBits); Ref VectorRoundImpl(OpSize Size, size_t ElementSize, Ref Src, uint64_t Mode); - Ref Scalar_CVT_Float_To_FloatImpl(OpcodeArgs, size_t DstElementSize, size_t SrcElementSize, const X86Tables::DecodedOperand& Src1Op, - const X86Tables::DecodedOperand& Src2Op); + Ref Scalar_CVT_Float_To_FloatImpl(OpcodeArgs, IR::OpSize DstElementSize, IR::OpSize SrcElementSize, + const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op); Ref Vector_CVT_Float_To_IntImpl(OpcodeArgs, size_t SrcElementSize, bool Narrow, bool HostRoundingMode); @@ -1518,7 +1518,7 @@ private: Ref LoadSource(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint32_t Flags, const LoadSourceOptions& Options = {}); Ref LoadSource_WithOpSize(RegisterClassType Class, const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, - uint8_t OpSize, uint32_t Flags, const LoadSourceOptions& Options = {}); + IR::OpSize OpSize, uint32_t Flags, const LoadSourceOptions& Options = {}); void StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, const FEXCore::X86Tables::DecodedOperand& Operand, const Ref Src, uint8_t OpSize, int8_t Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); @@ -1530,13 +1530,13 @@ private: // 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, uint8_t OpSize) { + 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}); return AppendSegmentOffset(Mem, Op->Flags); } [[nodiscard]] Ref MakeSegmentAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand) { - return MakeSegmentAddress(Op, Operand, GetSrcSize(Op)); + return MakeSegmentAddress(Op, Operand, OpSizeFromSrc(Op)); } [[nodiscard]] Ref MakeSegmentAddress(X86State::X86Reg Reg, uint32_t Flags, uint32_t DefaultPrefix = 0, bool Override = false) { @@ -2406,7 +2406,7 @@ private: } } - Ref _LoadMemAutoTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, Ref ssa0, uint8_t Align = 1) { + Ref _LoadMemAutoTSO(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, Ref ssa0, IR::OpSize Align = IR::OpSize::i8Bit) { if (IsTSOEnabled(Class)) { return _LoadMemTSO(Class, Size, ssa0, Invalid(), Align, MEM_OFFSET_SXTX, 1); } else { @@ -2414,7 +2414,7 @@ private: } } - Ref _LoadMemAutoTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, AddressMode A, uint8_t Align = 1) { + Ref _LoadMemAutoTSO(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, AddressMode A, IR::OpSize Align = IR::OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; A = SelectAddressMode(A, AtomicTSO, Class != GPRClass, Size); @@ -2445,7 +2445,7 @@ private: return Values; } - RefPair _LoadMemPairAutoTSO(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, AddressMode A, uint8_t Align = 1) { + RefPair _LoadMemPairAutoTSO(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, AddressMode A, IR::OpSize Align = IR::OpSize::i8Bit) { bool AtomicTSO = IsTSOEnabled(Class) && !A.NonTSO; // Use ldp if possible, otherwise fallback on two loads. diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp index 9158c87fc..2478a2710 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/AVX_128.cpp @@ -592,7 +592,7 @@ void OpDispatchBuilder::AVX128_VMOVAPS(OpcodeArgs) { } } -void OpDispatchBuilder::AVX128_VMOVScalarImpl(OpcodeArgs, size_t ElementSize) { +void OpDispatchBuilder::AVX128_VMOVScalarImpl(OpcodeArgs, IR::OpSize ElementSize) { if (Op->Dest.IsGPR() && Op->Src[0].IsGPR() && Op->Src[1].IsGPR()) { // VMOVSS/SD xmm1, xmm2, xmm3 // Lower 128-bits are merged @@ -961,7 +961,7 @@ void OpDispatchBuilder::AVX128_VBROADCAST(OpcodeArgs) { } } else { // Get the address to broadcast from into a GPR. - Ref Address = MakeSegmentAddress(Op, Op->Src[0], CTX->GetGPRSize()); + Ref Address = MakeSegmentAddress(Op, Op->Src[0], CTX->GetGPROpSize()); Src.Low = _VBroadcastFromMem(OpSize::i128Bit, ElementSize, Address); } @@ -1015,7 +1015,7 @@ void OpDispatchBuilder::AVX128_InsertCVTGPR_To_FPR(OpcodeArgs) { if (Op->Src[1].IsGPR()) { // If the source is a GPR then convert directly from the GPR. - auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Op->Src[1], CTX->GetGPRSize(), Op->Flags); + auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Op->Src[1], CTX->GetGPROpSize(), Op->Flags); Result.Low = _VSToFGPRInsert(OpSize::i128Bit, DstElementSize, SrcSize, Src1.Low, Src2, false); } else if (SrcSize != DstElementSize) { // If the source is from memory but the Source size and destination size aren't the same, @@ -1047,7 +1047,7 @@ void OpDispatchBuilder::AVX128_CVTFPR_To_GPR(OpcodeArgs) { if (Op->Src[0].IsGPR()) { Src = AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, false); } else { - Src.Low = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], GetSrcSize(Op), Op->Flags); + Src.Low = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], OpSizeFromSrc(Op), Op->Flags); } // GPR size is determined by REX.W @@ -1095,7 +1095,7 @@ void OpDispatchBuilder::AVX128_VPSIGN(OpcodeArgs) { template void OpDispatchBuilder::AVX128_UCOMISx(OpcodeArgs) { - const auto SrcSize = Op->Src[0].IsGPR() ? GetGuestVectorLength() : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? GetGuestVectorLength() : OpSizeFromSrc(Op); auto Src1 = AVX128_LoadSource_WithOpSize(Op, Op->Dest, Op->Flags, false); @@ -1116,7 +1116,7 @@ void OpDispatchBuilder::AVX128_VectorScalarInsertALU(OpcodeArgs, FEXCore::IR::IR // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); auto Src1 = AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, false); RefPair Src2 {}; @@ -1154,7 +1154,7 @@ void OpDispatchBuilder::AVX128_InsertScalarFCMP(OpcodeArgs) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); auto Src1 = AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, false); RefPair Src2 {}; @@ -1180,7 +1180,7 @@ void OpDispatchBuilder::AVX128_MOVBetweenGPR_FPR(OpcodeArgs) { RefPair Result {}; if (Op->Src[0].IsGPR()) { // Loading from GPR and moving to Vector. - Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags); + Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], CTX->GetGPROpSize(), Op->Flags); // zext to 128bit Result.Low = _VCastFromGPR(OpSize::i128Bit, GetSrcSize(Op), Src); } else { @@ -1249,8 +1249,8 @@ void OpDispatchBuilder::AVX128_ExtendVectorElements(OpcodeArgs, size_t ElementSi } else { // For memory operands the 256-bit variant loads twice the size specified in the table. const auto Is256Bit = DstSize == Core::CPUState::XMM_AVX_REG_SIZE; - const auto SrcSize = GetSrcSize(Op); - const auto LoadSize = Is256Bit ? SrcSize * 2 : SrcSize; + const auto SrcSize = OpSizeFromSrc(Op); + const auto LoadSize = Is256Bit ? IR::SizeToOpSize(IR::OpSizeToSize(SrcSize) * 2) : SrcSize; return LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], LoadSize, Op->Flags); } @@ -1382,7 +1382,7 @@ void OpDispatchBuilder::AVX128_PINSRImpl(OpcodeArgs, size_t ElementSize, const X if (Src2Op.IsGPR()) { // If the source is a GPR then convert directly from the GPR. - auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags); + auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPROpSize(), Op->Flags); Result.Low = _VInsGPR(OpSize::i128Bit, ElementSize, Index, Src1.Low, Src2); } else { // If loading from memory then we only load the element size @@ -1521,7 +1521,7 @@ void OpDispatchBuilder::AVX128_InsertScalar_CVT_Float_To_Float(OpcodeArgs) { // Gotta be careful with this operation. // It inserts in to the lowest element, retaining the remainder of the lower 128-bits. // Then zero extends the top 128-bit. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); auto Src1 = AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, false); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[1], SrcSize, Op->Flags, {.AllowUpperGarbage = true}); @@ -1531,8 +1531,8 @@ void OpDispatchBuilder::AVX128_InsertScalar_CVT_Float_To_Float(OpcodeArgs) { template void OpDispatchBuilder::AVX128_Vector_CVT_Float_To_Float(OpcodeArgs) { - const auto SrcSize = GetSrcSize(Op); - const auto DstSize = GetDstSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); + const auto DstSize = OpSizeFromDst(Op); const auto IsFloatSrc = SrcElementSize == 4; auto Is128BitSrc = SrcSize == Core::CPUState::XMM_SSE_REG_SIZE; @@ -1545,7 +1545,7 @@ void OpDispatchBuilder::AVX128_Vector_CVT_Float_To_Float(OpcodeArgs) { Is128BitDst = true; } - const auto LoadSize = IsFloatSrc && !Op->Src[0].IsGPR() ? SrcSize / 2 : SrcSize; + const auto LoadSize = IsFloatSrc && !Op->Src[0].IsGPR() ? IR::SizeToOpSize(IR::OpSizeToSize(SrcSize) / 2) : SrcSize; RefPair Src {}; if (Op->Src[0].IsGPR() || LoadSize >= OpSize::i128Bit) { @@ -1650,7 +1650,7 @@ void OpDispatchBuilder::AVX128_Vector_CVT_Float_To_Int(OpcodeArgs) { template void OpDispatchBuilder::AVX128_Vector_CVT_Int_To_Float(OpcodeArgs) { - const size_t Size = GetDstSize(Op); + const auto Size = OpSizeFromDst(Op); const auto Is128Bit = Size == Core::CPUState::XMM_SSE_REG_SIZE; RefPair Src = [&] { @@ -1658,7 +1658,7 @@ void OpDispatchBuilder::AVX128_Vector_CVT_Int_To_Float(OpcodeArgs) { // If loading a vector, use the full size, so we don't // unnecessarily zero extend the vector. Otherwise, if // memory, then we want to load the element size exactly. - const auto LoadSize = 8 * (Size / 16); + const auto LoadSize = IR::SizeToOpSize(8 * (IR::OpSizeToSize(Size) / 16)); return RefPair {.Low = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], LoadSize, Op->Flags)}; } else { return AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, !Is128Bit); @@ -1805,7 +1805,7 @@ void OpDispatchBuilder::AVX128_InsertScalarRound(OpcodeArgs) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); auto Src1 = AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, false); RefPair Src2 {}; @@ -2068,7 +2068,7 @@ void OpDispatchBuilder::AVX128_VMASKMOVImpl(OpcodeArgs, size_t ElementSize, size auto Mask = AVX128_LoadSource_WithOpSize(Op, MaskOp, Op->Flags, !Is128Bit); const auto MakeAddress = [this, Op](const X86Tables::DecodedOperand& Data) { - return MakeSegmentAddress(Op, Data, CTX->GetGPRSize()); + return MakeSegmentAddress(Op, Data, CTX->GetGPROpSize()); }; if (IsStore) { @@ -2110,7 +2110,7 @@ void OpDispatchBuilder::AVX128_VMASKMOV(OpcodeArgs) { void OpDispatchBuilder::AVX128_MASKMOV(OpcodeArgs) { ///< This instruction only supports 128-bit. - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); const auto Is128Bit = Size == Core::CPUState::XMM_SSE_REG_SIZE; auto MaskSrc = AVX128_LoadSource_WithOpSize(Op, Op->Src[0], Op->Flags, !Is128Bit); @@ -2739,8 +2739,8 @@ void OpDispatchBuilder::AVX128_VPGATHER(OpcodeArgs) { } void OpDispatchBuilder::AVX128_VCVTPH2PS(OpcodeArgs) { - const auto DstSize = GetDstSize(Op); - const auto SrcSize = DstSize / 2; + const auto DstSize = OpSizeFromDst(Op); + const auto SrcSize = IR::SizeToOpSize(IR::OpSizeToSize(DstSize) / 2); const auto Is128BitSrc = SrcSize == Core::CPUState::XMM_SSE_REG_SIZE; const auto Is128BitDst = DstSize == Core::CPUState::XMM_SSE_REG_SIZE; diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 28d31266a..8c08b1138 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -38,7 +38,7 @@ void OpDispatchBuilder::MOVVectorUnalignedOp(OpcodeArgs) { // Nop return; } - Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1}); + Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = OpSize::i8Bit}); StoreResult(FPRClass, Op, Src, 1); } @@ -87,7 +87,7 @@ void OpDispatchBuilder::VMOVUPS_VMOVUPDOp(OpcodeArgs) { const auto SrcSize = GetSrcSize(Op); const auto Is128Bit = SrcSize == Core::CPUState::XMM_SSE_REG_SIZE; - Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1}); + Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = OpSize::i8Bit}); if (Is128Bit && Op->Dest.IsGPR()) { Src = _VMov(OpSize::i128Bit, Src); @@ -143,7 +143,7 @@ void OpDispatchBuilder::MOVLPOp(OpcodeArgs) { auto Result = _VInsElement(OpSize::i128Bit, OpSize::i64Bit, 0, 1, Dest, Src); StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Result, OpSize::i128Bit, OpSize::i128Bit); } else { - auto DstSize = GetDstSize(Op); + const auto DstSize = OpSizeFromDst(Op); Ref Src = MakeSegmentAddress(Op, Op->Src[0]); Ref Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, DstSize, Op->Flags); auto Result = _VLoadVectorElement(OpSize::i128Bit, OpSize::i64Bit, Dest, 0, Src); @@ -190,7 +190,7 @@ void OpDispatchBuilder::VMOVSLDUPOp(OpcodeArgs) { StoreResult(FPRClass, Op, Result, -1); } -void OpDispatchBuilder::MOVScalarOpImpl(OpcodeArgs, size_t ElementSize) { +void OpDispatchBuilder::MOVScalarOpImpl(OpcodeArgs, IR::OpSize ElementSize) { if (Op->Dest.IsGPR() && Op->Src[0].IsGPR()) { // MOVSS/SD xmm1, xmm2 Ref Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags); @@ -217,7 +217,7 @@ void OpDispatchBuilder::MOVSDOp(OpcodeArgs) { MOVScalarOpImpl(Op, OpSize::i64Bit); } -void OpDispatchBuilder::VMOVScalarOpImpl(OpcodeArgs, size_t ElementSize) { +void OpDispatchBuilder::VMOVScalarOpImpl(OpcodeArgs, IR::OpSize ElementSize) { if (Op->Dest.IsGPR() && Op->Src[0].IsGPR() && Op->Src[1].IsGPR()) { // VMOVSS/SD xmm1, xmm2, xmm3 Ref Src1 = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); @@ -301,19 +301,19 @@ void OpDispatchBuilder::VectorALUROp(OpcodeArgs, IROps IROp, size_t ElementSize) StoreResult(FPRClass, Op, ALUOp, -1); } -Ref OpDispatchBuilder::VectorScalarInsertALUOpImpl(OpcodeArgs, IROps IROp, size_t DstSize, size_t ElementSize, +Ref OpDispatchBuilder::VectorScalarInsertALUOpImpl(OpcodeArgs, IROps IROp, IR::OpSize DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, DstSize, Op->Flags); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Src2Op, SrcSize, Op->Flags, {.AllowUpperGarbage = true}); // If OpSize == ElementSize then it only does the lower scalar op - DeriveOp(ALUOp, IROp, _VFAddScalarInsert(IR::SizeToOpSize(DstSize), ElementSize, Src1, Src2, ZeroUpperBits)); + DeriveOp(ALUOp, IROp, _VFAddScalarInsert(DstSize, ElementSize, Src1, Src2, ZeroUpperBits)); return ALUOp; } @@ -357,13 +357,13 @@ template void OpDispatchBuilder::AVXVectorScalarInsertALUOp(OpcodeArgs); template void OpDispatchBuilder::AVXVectorScalarInsertALUOp(OpcodeArgs); -Ref OpDispatchBuilder::VectorScalarUnaryInsertALUOpImpl(OpcodeArgs, IROps IROp, size_t DstSize, size_t ElementSize, +Ref OpDispatchBuilder::VectorScalarUnaryInsertALUOpImpl(OpcodeArgs, IROps IROp, IR::OpSize DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, DstSize, Op->Flags); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Src2Op, SrcSize, Op->Flags, {.AllowUpperGarbage = true}); @@ -410,7 +410,7 @@ void OpDispatchBuilder::InsertMMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs) { // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. const auto DstSize = GetGuestVectorLength(); - const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i64Bit : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i64Bit : OpSizeFromSrc(Op); Ref Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, DstSize, Op->Flags); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); @@ -423,7 +423,7 @@ void OpDispatchBuilder::InsertMMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs) { StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Dest, DstSize, -1); } -Ref OpDispatchBuilder::InsertCVTGPR_To_FPRImpl(OpcodeArgs, size_t DstSize, size_t DstElementSize, const X86Tables::DecodedOperand& Src1Op, +Ref OpDispatchBuilder::InsertCVTGPR_To_FPRImpl(OpcodeArgs, IR::OpSize DstSize, size_t DstElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar @@ -434,7 +434,7 @@ Ref OpDispatchBuilder::InsertCVTGPR_To_FPRImpl(OpcodeArgs, size_t DstSize, size_ if (Src2Op.IsGPR()) { // If the source is a GPR then convert directly from the GPR. - auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags); + auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPROpSize(), Op->Flags); return _VSToFGPRInsert(IR::SizeToOpSize(DstSize), DstElementSize, SrcSize, Src1, Src2, ZeroUpperBits); } else if (SrcSize != DstElementSize) { // If the source is from memory but the Source size and destination size aren't the same, @@ -470,14 +470,14 @@ void OpDispatchBuilder::AVXInsertCVTGPR_To_FPR(OpcodeArgs) { template void OpDispatchBuilder::AVXInsertCVTGPR_To_FPR(OpcodeArgs); template void OpDispatchBuilder::AVXInsertCVTGPR_To_FPR(OpcodeArgs); -Ref OpDispatchBuilder::InsertScalar_CVT_Float_To_FloatImpl(OpcodeArgs, size_t DstSize, size_t DstElementSize, size_t SrcElementSize, +Ref OpDispatchBuilder::InsertScalar_CVT_Float_To_FloatImpl(OpcodeArgs, IR::OpSize DstSize, size_t DstElementSize, size_t SrcElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, bool ZeroUpperBits) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, DstSize, Op->Flags); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Src2Op, SrcSize, Op->Flags, {.AllowUpperGarbage = true}); @@ -519,12 +519,12 @@ RoundType OpDispatchBuilder::TranslateRoundType(uint8_t Mode) { return RoundControlSource ? Round_Host : SourceModes[RoundControl]; } -Ref OpDispatchBuilder::InsertScalarRoundImpl(OpcodeArgs, size_t DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, +Ref OpDispatchBuilder::InsertScalarRoundImpl(OpcodeArgs, IR::OpSize DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, uint64_t Mode, bool ZeroUpperBits) { // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, DstSize, Op->Flags); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Src2Op, SrcSize, Op->Flags, {.AllowUpperGarbage = true}); @@ -595,7 +595,7 @@ template void OpDispatchBuilder::InsertScalarFCMPOp(OpcodeArgs) { const uint8_t CompType = Op->Src[1].Literal(); const auto DstSize = GetGuestVectorLength(); - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, DstSize, Op->Flags); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags, {.AllowUpperGarbage = true}); @@ -611,7 +611,7 @@ template void OpDispatchBuilder::AVXInsertScalarFCMPOp(OpcodeArgs) { const uint8_t CompType = Op->Src[2].Literal(); const auto DstSize = GetGuestVectorLength(); - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); // We load the full vector width when dealing with a source vector, // so that we don't do any unnecessary zero extension to the scalar @@ -631,12 +631,11 @@ void OpDispatchBuilder::VectorUnaryOp(OpcodeArgs, IROps IROp, size_t ElementSize // we can specify the entire vector length in order to avoid // unnecessary sign extension on the element to be operated on. // In the event of a memory operand, we load the exact element size. - const auto SrcSize = GetSrcSize(Op); - const auto OpSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); - DeriveOp(ALUOp, IROp, _VFSqrt(OpSize, ElementSize, Src)); + DeriveOp(ALUOp, IROp, _VFSqrt(SrcSize, ElementSize, Src)); StoreResult(FPRClass, Op, ALUOp, -1); } @@ -646,12 +645,11 @@ void OpDispatchBuilder::AVXVectorUnaryOp(OpcodeArgs, IROps IROp, size_t ElementS // we can specify the entire vector length in order to avoid // unnecessary sign extension on the element to be operated on. // In the event of a memory operand, we load the exact element size. - const auto SrcSize = GetSrcSize(Op); - const auto OpSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); - DeriveOp(ALUOp, IROp, _VFSqrt(OpSize, ElementSize, Src)); + DeriveOp(ALUOp, IROp, _VFSqrt(SrcSize, ElementSize, Src)); // NOTE: We don't need to clear the upper lanes here, since the // IR ops make use of 128-bit AdvSimd for 128-bit cases, @@ -682,7 +680,7 @@ template void OpDispatchBuilder::VectorUnaryDuplicateOp(OpcodeArgs); void OpDispatchBuilder::MOVQOp(OpcodeArgs, VectorOpType VectorType) { - const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); // This instruction is a bit special that if the destination is a register then it'll ZEXT the 64bit source to 128bit if (Op->Dest.IsGPR()) { @@ -702,7 +700,7 @@ void OpDispatchBuilder::MOVQMMXOp(OpcodeArgs) { if (MMXState == MMXState_X87) { ChgStateX87_MMX(); } - Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1}); + Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = OpSize::i8Bit}); StoreResult(FPRClass, Op, Src, 1); } @@ -1473,7 +1471,7 @@ void OpDispatchBuilder::VBROADCASTOp(OpcodeArgs, size_t ElementSize) { Result = _VDupElement(DstSize, ElementSize, Src, 0); } else { // Get the address to broadcast from into a GPR. - Ref Address = MakeSegmentAddress(Op, Op->Src[0], CTX->GetGPRSize()); + Ref Address = MakeSegmentAddress(Op, Op->Src[0], CTX->GetGPROpSize()); Result = _VBroadcastFromMem(DstSize, ElementSize, Address); } @@ -1485,14 +1483,14 @@ void OpDispatchBuilder::VBROADCASTOp(OpcodeArgs, size_t ElementSize) { Ref OpDispatchBuilder::PINSROpImpl(OpcodeArgs, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op, const X86Tables::DecodedOperand& Imm) { - const auto Size = GetDstSize(Op); + const auto Size = OpSizeFromDst(Op); const auto NumElements = Size / ElementSize; const uint64_t Index = Imm.Literal() & (NumElements - 1); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, Size, Op->Flags); if (Src2Op.IsGPR()) { // If the source is a GPR then convert directly from the GPR. - auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags); + auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPROpSize(), Op->Flags); return _VInsGPR(Size, ElementSize, Index, Src1, Src2); } @@ -1544,7 +1542,7 @@ Ref OpDispatchBuilder::InsertPSOpImpl(OpcodeArgs, const X86Tables::DecodedOperan uint8_t CountD = (ImmValue >> 4) & 0b11; const uint8_t ZMask = ImmValue & 0xF; - const auto DstSize = GetDstSize(Op); + const auto DstSize = OpSizeFromDst(Op); Ref Dest {}; if (ZMask != 0xF) { @@ -1799,7 +1797,7 @@ void OpDispatchBuilder::VPSLLOp(OpcodeArgs, size_t ElementSize) { const auto Is128Bit = DstSize == Core::CPUState::XMM_SSE_REG_SIZE; Ref Src1 = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); - Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[1], 16, Op->Flags); + Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[1], OpSize::i128Bit, Op->Flags); Ref Result = PSLLImpl(Op, ElementSize, Src1, Src2); if (Is128Bit) { @@ -1972,8 +1970,8 @@ void OpDispatchBuilder::VPSRAIOp(OpcodeArgs, size_t ElementSize) { } void OpDispatchBuilder::AVXVariableShiftImpl(OpcodeArgs, IROps IROp) { - const auto DstSize = GetDstSize(Op); - const auto SrcSize = GetSrcSize(Op); + const auto DstSize = OpSizeFromDst(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Vector = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], DstSize, Op->Flags); Ref ShiftVector = LoadSource_WithOpSize(FPRClass, Op, Op->Src[1], DstSize, Op->Flags); @@ -1999,7 +1997,7 @@ void OpDispatchBuilder::MOVDDUPOp(OpcodeArgs) { // If loading a vector, use the full size, so we don't // unnecessarily zero extend the vector. Otherwise, if // memory, then we want to load the element size exactly. - const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); Ref Res = _VDupElement(OpSize::i128Bit, GetSrcSize(Op), Src, 0); @@ -2007,7 +2005,7 @@ void OpDispatchBuilder::MOVDDUPOp(OpcodeArgs) { } void OpDispatchBuilder::VMOVDDUPOp(OpcodeArgs) { - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); const auto IsSrcGPR = Op->Src[0].IsGPR(); const auto Is256Bit = SrcSize == Core::CPUState::XMM_AVX_REG_SIZE; const auto MemSize = Is256Bit ? OpSize::i256Bit : OpSize::i64Bit; @@ -2033,7 +2031,7 @@ Ref OpDispatchBuilder::CVTGPR_To_FPRImpl(OpcodeArgs, size_t DstElementSize, cons Ref Converted {}; if (Src2Op.IsGPR()) { // If the source is a GPR then convert directly from the GPR. - auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags); + auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPROpSize(), Op->Flags); Converted = _Float_FromGPR_S(DstElementSize, SrcSize, Src2); } else if (SrcSize != DstElementSize) { // If the source is from memory but the Source size and destination size aren't the same, @@ -2073,7 +2071,7 @@ void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) { // If loading a vector, use the full size, so we don't // unnecessarily zero extend the vector. Otherwise, if // memory, then we want to load the element size exactly. - const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); // GPR size is determined by REX.W @@ -2096,14 +2094,14 @@ template void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) template void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs); Ref OpDispatchBuilder::Vector_CVT_Int_To_FloatImpl(OpcodeArgs, size_t SrcElementSize, bool Widen) { - const size_t Size = GetDstSize(Op); + const auto Size = OpSizeFromDst(Op); Ref Src = [&] { if (Widen) { // If loading a vector, use the full size, so we don't // unnecessarily zero extend the vector. Otherwise, if // memory, then we want to load the element size exactly. - const auto LoadSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : 8 * (Size / 16); + const auto LoadSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : IR::SizeToOpSize(8 * (IR::OpSizeToSize(Size) / 16)); return LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], LoadSize, Op->Flags); } else { return LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); @@ -2200,7 +2198,7 @@ template void OpDispatchBuilder::AVXVector_CVT_Float_To_Int(OpcodeArgs); template void OpDispatchBuilder::AVXVector_CVT_Float_To_Int(OpcodeArgs); -Ref OpDispatchBuilder::Scalar_CVT_Float_To_FloatImpl(OpcodeArgs, size_t DstElementSize, size_t SrcElementSize, +Ref OpDispatchBuilder::Scalar_CVT_Float_To_FloatImpl(OpcodeArgs, IR::OpSize DstElementSize, IR::OpSize SrcElementSize, const X86Tables::DecodedOperand& Src1Op, const X86Tables::DecodedOperand& Src2Op) { // In the case of vectors, we can just specify the full vector length, // so that we don't unnecessarily zero-extend the entire vector. @@ -2215,7 +2213,7 @@ Ref OpDispatchBuilder::Scalar_CVT_Float_To_FloatImpl(OpcodeArgs, size_t DstEleme return _VInsElement(OpSize::i128Bit, DstElementSize, 0, 0, Src1, Converted); } -template +template void OpDispatchBuilder::Scalar_CVT_Float_To_Float(OpcodeArgs) { Ref Result = Scalar_CVT_Float_To_FloatImpl(Op, DstElementSize, SrcElementSize, Op->Dest, Op->Src[0]); StoreResult(FPRClass, Op, Result, -1); @@ -2224,7 +2222,7 @@ void OpDispatchBuilder::Scalar_CVT_Float_To_Float(OpcodeArgs) { template void OpDispatchBuilder::Scalar_CVT_Float_To_Float(OpcodeArgs); template void OpDispatchBuilder::Scalar_CVT_Float_To_Float(OpcodeArgs); -template +template void OpDispatchBuilder::AVXScalar_CVT_Float_To_Float(OpcodeArgs) { Ref Result = Scalar_CVT_Float_To_FloatImpl(Op, DstElementSize, SrcElementSize, Op->Src[0], Op->Src[1]); StoreResult(FPRClass, Op, Result, -1); @@ -2234,12 +2232,12 @@ template void OpDispatchBuilder::AVXScalar_CVT_Float_To_Float(OpcodeArgs); void OpDispatchBuilder::Vector_CVT_Float_To_Float(OpcodeArgs, size_t DstElementSize, size_t SrcElementSize, bool IsAVX) { - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); const auto IsFloatSrc = SrcElementSize == OpSize::i32Bit; const auto Is128Bit = SrcSize == Core::CPUState::XMM_SSE_REG_SIZE; - const auto LoadSize = IsFloatSrc && !Op->Src[0].IsGPR() ? SrcSize / 2 : SrcSize; + const auto LoadSize = IsFloatSrc && !Op->Src[0].IsGPR() ? IR::SizeToOpSize(IR::OpSizeToSize(SrcSize) / 2) : SrcSize; Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], LoadSize, Op->Flags); @@ -2288,7 +2286,7 @@ void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs) { // If loading a vector, use the full size, so we don't // unnecessarily zero extend the vector. Otherwise, if // memory, then we want to load the element size exactly. - const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? OpSize::i128Bit : OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); size_t ElementSize = SrcElementSize; @@ -2314,7 +2312,7 @@ template void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs); void OpDispatchBuilder::MASKMOVOp(OpcodeArgs) { - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); Ref MaskSrc = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); // Mask only cares about the top bit of each byte @@ -2333,11 +2331,11 @@ void OpDispatchBuilder::MASKMOVOp(OpcodeArgs) { _StoreMem(FPRClass, Size, MemDest, XMMReg, OpSize::i8Bit); } -void OpDispatchBuilder::VMASKMOVOpImpl(OpcodeArgs, size_t ElementSize, size_t DataSize, bool IsStore, +void OpDispatchBuilder::VMASKMOVOpImpl(OpcodeArgs, IR::OpSize ElementSize, IR::OpSize DataSize, bool IsStore, const X86Tables::DecodedOperand& MaskOp, const X86Tables::DecodedOperand& DataOp) { const auto MakeAddress = [this, Op](const X86Tables::DecodedOperand& Data) { - return MakeSegmentAddress(Op, Data, CTX->GetGPRSize()); + return MakeSegmentAddress(Op, Data, CTX->GetGPROpSize()); }; Ref Mask = LoadSource_WithOpSize(FPRClass, Op, MaskOp, DataSize, Op->Flags); @@ -2359,9 +2357,9 @@ void OpDispatchBuilder::VMASKMOVOpImpl(OpcodeArgs, size_t ElementSize, size_t Da } } -template +template void OpDispatchBuilder::VMASKMOVOp(OpcodeArgs) { - VMASKMOVOpImpl(Op, ElementSize, GetDstSize(Op), IsStore, Op->Src[0], Op->Src[1]); + VMASKMOVOpImpl(Op, ElementSize, OpSizeFromDst(Op), IsStore, Op->Src[0], Op->Src[1]); } template void OpDispatchBuilder::VMASKMOVOp(OpcodeArgs); template void OpDispatchBuilder::VMASKMOVOp(OpcodeArgs); @@ -2370,7 +2368,7 @@ template void OpDispatchBuilder::VMASKMOVOp(OpcodeArgs); template void OpDispatchBuilder::VPMASKMOVOp(OpcodeArgs) { - VMASKMOVOpImpl(Op, GetSrcSize(Op), GetDstSize(Op), IsStore, Op->Src[0], Op->Src[1]); + VMASKMOVOpImpl(Op, OpSizeFromSrc(Op), OpSizeFromDst(Op), IsStore, Op->Src[0], Op->Src[1]); } template void OpDispatchBuilder::VPMASKMOVOp(OpcodeArgs); template void OpDispatchBuilder::VPMASKMOVOp(OpcodeArgs); @@ -2380,7 +2378,7 @@ void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs, VectorOpType VectorType) { Ref Result {}; if (Op->Src[0].IsGPR()) { // Loading from GPR and moving to Vector. - Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags); + Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], CTX->GetGPROpSize(), Op->Flags); // zext to 128bit Result = _VCastFromGPR(OpSize::i128Bit, GetSrcSize(Op), Src); } else { @@ -2434,8 +2432,8 @@ template void OpDispatchBuilder::VFCMPOp(OpcodeArgs) { // No need for zero-extending in the scalar case, since // all we need is an insert at the end of the operation. - const auto SrcSize = GetSrcSize(Op); - const auto DstSize = GetDstSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); + const auto DstSize = OpSizeFromDst(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); Ref Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, DstSize, Op->Flags); @@ -2453,8 +2451,8 @@ template void OpDispatchBuilder::AVXVFCMPOp(OpcodeArgs) { // No need for zero-extending in the scalar case, since // all we need is an insert at the end of the operation. - const auto SrcSize = GetSrcSize(Op); - const auto DstSize = GetDstSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); + const auto DstSize = OpSizeFromDst(Op); const uint8_t CompType = Op->Src[2].Literal(); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], DstSize, Op->Flags); @@ -2859,7 +2857,7 @@ void OpDispatchBuilder::VPALIGNROp(OpcodeArgs) { template void OpDispatchBuilder::UCOMISxOp(OpcodeArgs) { - const auto SrcSize = Op->Src[0].IsGPR() ? GetGuestVectorLength() : GetSrcSize(Op); + const auto SrcSize = Op->Src[0].IsGPR() ? GetGuestVectorLength() : OpSizeFromSrc(Op); Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, GetGuestVectorLength(), Op->Flags); Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); @@ -3142,7 +3140,7 @@ template void OpDispatchBuilder::VPFCMPOp(OpcodeArgs) { auto Size = GetSrcSize(Op); Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); - Ref Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, GetDstSize(Op), Op->Flags); + Ref Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, OpSizeFromDst(Op), Op->Flags); Ref Result {}; // This maps 1:1 to an AArch64 NEON Op @@ -3551,7 +3549,7 @@ void OpDispatchBuilder::VPSADBWOp(OpcodeArgs) { } Ref OpDispatchBuilder::ExtendVectorElementsImpl(OpcodeArgs, size_t ElementSize, size_t DstElementSize, bool Signed) { - const auto DstSize = GetDstSize(Op); + const auto DstSize = OpSizeFromDst(Op); const auto GetSrc = [&] { if (Op->Src[0].IsGPR()) { @@ -3559,8 +3557,8 @@ Ref OpDispatchBuilder::ExtendVectorElementsImpl(OpcodeArgs, size_t ElementSize, } else { // For memory operands the 256-bit variant loads twice the size specified in the table. const auto Is256Bit = DstSize == Core::CPUState::XMM_AVX_REG_SIZE; - const auto SrcSize = GetSrcSize(Op); - const auto LoadSize = Is256Bit ? SrcSize * 2 : SrcSize; + const auto SrcSize = OpSizeFromSrc(Op); + const auto LoadSize = Is256Bit ? IR::SizeToOpSize(IR::OpSizeToSize(SrcSize) * 2) : SrcSize; return LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], LoadSize, Op->Flags); } @@ -3608,7 +3606,7 @@ template void OpDispatchBuilder::VectorRound(OpcodeArgs) { // No need to zero extend the vector in the event we have a // scalar source, especially since it's only inserted into another vector. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); const uint64_t Mode = Op->Src[1].Literal(); @@ -3626,7 +3624,7 @@ void OpDispatchBuilder::AVXVectorRound(OpcodeArgs) { // No need to zero extend the vector in the event we have a // scalar source, especially since it's only inserted into another vector. - const auto SrcSize = GetSrcSize(Op); + const auto SrcSize = OpSizeFromSrc(Op); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcSize, Op->Flags); Ref Result = VectorRoundImpl(OpSizeFromDst(Op), ElementSize, Src, Mode); @@ -4427,8 +4425,8 @@ void OpDispatchBuilder::VCVTPH2PSOp(OpcodeArgs) { // In the event that a memory operand is used as the source operand, // the access width will always be half the size of the destination vector width // (i.e. 128-bit vector -> 64-bit mem, 256-bit vector -> 128-bit mem) - const auto DstSize = GetDstSize(Op); - const auto SrcLoadSize = Op->Src[0].IsGPR() ? DstSize : DstSize / 2; + const auto DstSize = OpSizeFromDst(Op); + const auto SrcLoadSize = Op->Src[0].IsGPR() ? DstSize : IR::SizeToOpSize(IR::OpSizeToSize(DstSize) / 2); Ref Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], SrcLoadSize, Op->Flags); Ref Result = _Vector_FToF(DstSize, OpSize::i32Bit, Src, OpSize::i16Bit); @@ -4846,7 +4844,7 @@ void OpDispatchBuilder::PCMPXSTRXOpImpl(OpcodeArgs, bool IsExplicit, bool IsMask // // So, we specify Src2 as having an alignment of 1 to indicate this. Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, OpSize::i128Bit, Op->Flags); - Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], OpSize::i128Bit, Op->Flags, {.Align = 1}); + Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], OpSize::i128Bit, Op->Flags, {.Align = OpSize::i8Bit}); Ref IntermediateResult {}; if (IsExplicit) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index 343d7a75a..be1c36186 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -61,7 +61,7 @@ void OpDispatchBuilder::SetX87Top(Ref Value) { // Float LoaD operation with memory operand void OpDispatchBuilder::FLD(OpcodeArgs, size_t Width) { - size_t ReadWidth = (Width == 80) ? 16 : Width / 8; + const auto ReadWidth = (Width == 80) ? OpSize::i128Bit : IR::SizeToOpSize(Width / 8); Ref Data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], ReadWidth, Op->Flags); Ref ConvertedData = Data; @@ -97,12 +97,12 @@ void OpDispatchBuilder::FLD_Const(OpcodeArgs, NamedVectorConstant Constant) { } void OpDispatchBuilder::FILD(OpcodeArgs) { - size_t ReadWidth = GetSrcSize(Op); + const auto ReadWidth = OpSizeFromSrc(Op); // Read from memory Ref Data = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], ReadWidth, Op->Flags); // Sign extend to 64bits - if (ReadWidth != 8) { + if (ReadWidth != OpSize::i64Bit) { Data = _Sbfe(OpSize::i64Bit, ReadWidth * 8, 0, Data); } @@ -400,7 +400,7 @@ Ref OpDispatchBuilder::ReconstructX87StateFromFSW_Helper(Ref FSW) { void OpDispatchBuilder::X87LDENV(OpcodeArgs) { _StackForceSlow(); - auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); Ref Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false}); Mem = AppendSegmentOffset(Mem, Op->Flags); @@ -506,7 +506,7 @@ void OpDispatchBuilder::X87FNSAVE(OpcodeArgs) { void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) { _StackForceSlow(); - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); Ref Mem = MakeSegmentAddress(Op, Op->Src[0]); auto NewFCW = _LoadMem(GPRClass, OpSize::i16Bit, Mem, OpSize::i16Bit); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index 334f25e20..d916bb28b 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -26,7 +26,7 @@ class OrderedNode; void OpDispatchBuilder::X87LDENVF64(OpcodeArgs) { _StackForceSlow(); - const auto Size = GetSrcSize(Op); + const auto Size = OpSizeFromSrc(Op); Ref Mem = MakeSegmentAddress(Op, Op->Src[0]); auto NewFCW = _LoadMem(GPRClass, OpSize::i16Bit, Mem, OpSize::i16Bit); @@ -59,7 +59,7 @@ void OpDispatchBuilder::X87FLDCWF64(OpcodeArgs) { // F64 ops // Float load op with memory operand void OpDispatchBuilder::FLDF64(OpcodeArgs, size_t Width) { - size_t ReadWidth = (Width == 80) ? 16 : Width / 8; + const auto ReadWidth = (Width == 80) ? OpSize::i128Bit : IR::SizeToOpSize(Width / 8); Ref Data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], ReadWidth, Op->Flags); // Convert to 64bit float Ref ConvertedData = Data; @@ -92,14 +92,14 @@ void OpDispatchBuilder::FLDF64_Const(OpcodeArgs, uint64_t Num) { } void OpDispatchBuilder::FILDF64(OpcodeArgs) { - size_t ReadWidth = GetSrcSize(Op); + const auto ReadWidth = OpSizeFromSrc(Op); // Read from memory Ref Data = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], ReadWidth, Op->Flags); if (ReadWidth == OpSize::i16Bit) { Data = _Sbfe(OpSize::i64Bit, ReadWidth * 8, 0, Data); } - auto ConvertedData = _Float_FromGPR_S(OpSize::i64Bit, ReadWidth == 4 ? OpSize::i32Bit : OpSize::i64Bit, Data); + auto ConvertedData = _Float_FromGPR_S(OpSize::i64Bit, ReadWidth == OpSize::i32Bit ? OpSize::i32Bit : OpSize::i64Bit, Data); _PushStack(ConvertedData, Data, ReadWidth, false); } diff --git a/FEXCore/Source/Interface/IR/IR.h b/FEXCore/Source/Interface/IR/IR.h index edf6ea3c6..a8f899aba 100644 --- a/FEXCore/Source/Interface/IR/IR.h +++ b/FEXCore/Source/Interface/IR/IR.h @@ -553,8 +553,10 @@ enum OpSize : uint8_t { i16Bit = 2, i32Bit = 4, i64Bit = 8, + f80Bit = 10, i128Bit = 16, i256Bit = 32, + iInvalid = 0xFF, }; enum class FloatCompareOp : uint8_t { @@ -582,8 +584,25 @@ static inline OpSize SizeToOpSize(uint8_t Size) { case 2: return OpSize::i16Bit; case 4: return OpSize::i32Bit; case 8: return OpSize::i64Bit; + case 10: return OpSize::f80Bit; case 16: return OpSize::i128Bit; case 32: return OpSize::i256Bit; + case 0xFF: return OpSize::iInvalid; + default: FEX_UNREACHABLE; + } +} + +// This is a nop operation and will be eliminated by the compiler. +static inline uint8_t OpSizeToSize(IR::OpSize Size) { + switch (Size) { + case OpSize::i8Bit: return 1; + case OpSize::i16Bit: return 2; + case OpSize::i32Bit: return 4; + case OpSize::i64Bit: return 8; + case OpSize::f80Bit: return 10; + case OpSize::i128Bit: return 16; + case OpSize::i256Bit: return 32; + case OpSize::iInvalid: return 0xFF; default: FEX_UNREACHABLE; } } diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index bd0d928c2..ab83918cf 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -530,7 +530,7 @@ "DestSize": "8" }, - "SSA = LoadMem RegisterClass:$Class, u8:#Size, GPR:$Addr, GPR:$Offset, u8:$Align, MemOffsetType:$OffsetType, u8:$OffsetScale": { + "SSA = LoadMem RegisterClass:$Class, OpSize:#Size, GPR:$Addr, GPR:$Offset, OpSize:$Align, MemOffsetType:$OffsetType, u8:$OffsetScale": { "DestSize": "Size" }, diff --git a/FEXCore/Source/Interface/IR/IREmitter.h b/FEXCore/Source/Interface/IR/IREmitter.h index 5b0720e61..1c5383150 100644 --- a/FEXCore/Source/Interface/IR/IREmitter.h +++ b/FEXCore/Source/Interface/IR/IREmitter.h @@ -85,7 +85,7 @@ public: return _Select(IR::SizeToOpSize(std::max(4, std::max(GetOpSize(ssa2), GetOpSize(ssa3)))), IR::SizeToOpSize(CompareSize), CondClassType {Cond}, ssa0, ssa1, ssa2, ssa3); } - IRPair _LoadMem(FEXCore::IR::RegisterClassType Class, uint8_t Size, Ref ssa0, uint8_t Align = 1) { + IRPair _LoadMem(FEXCore::IR::RegisterClassType Class, IR::OpSize Size, Ref ssa0, IR::OpSize Align = OpSize::i8Bit) { return _LoadMem(Class, Size, ssa0, Invalid(), Align, MEM_OFFSET_SXTX, 1); } IRPair _LoadMemTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, Ref ssa0, uint8_t Align = 1) {