diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index fa43a0f2c..b431ffef1 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -309,8 +309,6 @@ namespace FEXCore::Context { void CopyMemoryMapping(FEXCore::Core::InternalThreadState *ParentThread, FEXCore::Core::InternalThreadState *ChildThread); - uint8_t GetGPRSize() const { return Config.Is64BitMode ? 8 : 4; } - FEXCore::JITSymbols Symbols; void GetVDSOSigReturn(VDSOSigReturn *VDSOPointers) override { diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 61ef3ed86..60206caa8 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -544,7 +544,7 @@ namespace FEXCore::Context { bool HadDispatchError {false}; - Thread->FrontendDecoder->DecodeInstructionsAtEntry(GuestCode, GuestRIP, MaxInst, [Thread](uint64_t BlockEntry, uint64_t Start, uint64_t Length) { + Thread->FrontendDecoder->DecodeInstructionsAtEntry(Thread, GuestCode, GuestRIP, MaxInst, [Thread](uint64_t BlockEntry, uint64_t Start, uint64_t Length) { if (Thread->LookupCache->AddBlockExecutableRange(BlockEntry, Start, Length)) { static_cast(Thread->CTX)->SyscallHandler->MarkGuestExecutableRange(Thread, Start, Length); } @@ -553,9 +553,9 @@ namespace FEXCore::Context { auto BlockInfo = Thread->FrontendDecoder->GetDecodedBlockInfo(); auto CodeBlocks = &BlockInfo->Blocks; - Thread->OpDispatcher->BeginFunction(GuestRIP, CodeBlocks, BlockInfo->TotalInstructionCount); + Thread->OpDispatcher->BeginFunction(GuestRIP, CodeBlocks, BlockInfo->TotalInstructionCount, BlockInfo->Is64BitMode); - const uint8_t GPRSize = GetGPRSize(); + const uint8_t GPRSize = Thread->OpDispatcher->GetGPRSize(); for (size_t j = 0; j < CodeBlocks->size(); ++j) { FEXCore::Frontend::Decoder::DecodedBlocks const &Block = CodeBlocks->at(j); @@ -640,8 +640,6 @@ namespace FEXCore::Context { } if (NeedsBlockEnd) { - const uint8_t GPRSize = GetGPRSize(); - // We had some instructions. Early exit Thread->OpDispatcher->_ExitFunction(Thread->OpDispatcher->_EntrypointOffset(IR::SizeToOpSize(GPRSize), Block.Entry + BlockInstructionsLength - GuestRIP)); break; diff --git a/FEXCore/Source/Interface/Core/Frontend.cpp b/FEXCore/Source/Interface/Core/Frontend.cpp index 8673a1502..d6ce12d5a 100644 --- a/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/FEXCore/Source/Interface/Core/Frontend.cpp @@ -311,7 +311,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, uint8_t DestSize{}; const bool HasWideningDisplacement = (FEXCore::X86Tables::DecodeFlags::GetOpAddr(DecodeInst->Flags, 0) & FEXCore::X86Tables::DecodeFlags::FLAG_WIDENING_SIZE_LAST) != 0 || - (Options.w && CTX->Config.Is64BitMode); + (Options.w && BlockInfo.Is64BitMode); const bool HasNarrowingDisplacement = (FEXCore::X86Tables::DecodeFlags::GetOpAddr(DecodeInst->Flags, 0) & FEXCore::X86Tables::DecodeFlags::FLAG_OPERAND_SIZE_LAST) != 0; const bool HasXMMFlags = (Info->Flags & InstFlags::FLAGS_XMM_FLAGS) != 0; @@ -332,7 +332,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, const bool HasMODRM = !!(Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_MODRM); const bool HasREX = !!(DecodeInst->Flags & DecodeFlags::FLAG_REX_PREFIX); - const bool Has16BitAddressing = !CTX->Config.Is64BitMode && + const bool Has16BitAddressing = !BlockInfo.Is64BitMode && DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE; // This is used for ModRM register modification @@ -387,7 +387,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, DestSize = 2; } else if ( - (HasXMMDst || HasMMDst || CTX->Config.Is64BitMode) && + (HasXMMDst || HasMMDst || BlockInfo.Is64BitMode) && (HasWideningDisplacement || DstSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BIT || DstSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BITDEF)) { @@ -425,7 +425,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op, DecodeInst->Flags |= DecodeFlags::GenSizeSrcSize(DecodeFlags::SIZE_16BIT); } else if ( - (HasXMMSrc || HasMMSrc || CTX->Config.Is64BitMode) && + (HasXMMSrc || HasMMSrc || BlockInfo.Is64BitMode) && (HasWideningDisplacement || SrcSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BIT || SrcSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BITDEF)) { @@ -693,7 +693,7 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16 DecodedHeader options{}; if ((Byte1 & 0b10000000) == 0) { - LOGMAN_THROW_A_FMT(CTX->Config.Is64BitMode, "VEX.R shouldn't be 0 in 32-bit mode!"); + LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode, "VEX.R shouldn't be 0 in 32-bit mode!"); DecodeInst->Flags |= DecodeFlags::FLAG_REX_XGPR_R; } @@ -710,10 +710,10 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16 options.w = (Byte2 & 0b10000000) != 0; options.L = (Byte2 & 0b100) != 0; if ((Byte1 & 0b01000000) == 0) { - LOGMAN_THROW_A_FMT(CTX->Config.Is64BitMode, "VEX.X shouldn't be 0 in 32-bit mode!"); + LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode, "VEX.X shouldn't be 0 in 32-bit mode!"); DecodeInst->Flags |= DecodeFlags::FLAG_REX_XGPR_X; } - if (CTX->Config.Is64BitMode && (Byte1 & 0b00100000) == 0) { + if (BlockInfo.Is64BitMode && (Byte1 & 0b00100000) == 0) { DecodeInst->Flags |= DecodeFlags::FLAG_REX_XGPR_B; } if (!(map_select >= 1 && map_select <= 3)) { @@ -788,7 +788,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) { FEXCore::X86Tables::ModRMDecoded ModRM; ModRM.Hex = DecodeInst->ModRM; - const bool Has16BitAddressing = !CTX->Config.Is64BitMode && + const bool Has16BitAddressing = !BlockInfo.Is64BitMode && DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE; // All 3DNow! instructions have the second argument as the rm handler @@ -899,17 +899,17 @@ bool Decoder::DecodeInstruction(uint64_t PC) { DecodeInst->Flags |= DecodeFlags::FLAG_ADDRESS_SIZE; break; case 0x26: // ES legacy prefix - if (!CTX->Config.Is64BitMode) { + if (!BlockInfo.Is64BitMode) { DecodeInst->Flags |= DecodeFlags::FLAG_ES_PREFIX; } break; case 0x2E: // CS legacy prefix - if (!CTX->Config.Is64BitMode) { + if (!BlockInfo.Is64BitMode) { DecodeInst->Flags |= DecodeFlags::FLAG_CS_PREFIX; } break; case 0x36: // SS legacy prefix - if (!CTX->Config.Is64BitMode) { + if (!BlockInfo.Is64BitMode) { DecodeInst->Flags |= DecodeFlags::FLAG_SS_PREFIX; } break; @@ -917,7 +917,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) { // Annoyingly GCC generates NOP ops with these prefixes // Just ignore them for now // eg. 66 2e 0f 1f 84 00 00 00 00 00 nop WORD PTR cs:[rax+rax*1+0x0] - if (!CTX->Config.Is64BitMode) { + if (!BlockInfo.Is64BitMode) { DecodeInst->Flags |= DecodeFlags::FLAG_DS_PREFIX; } break; @@ -943,7 +943,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) { auto Info = &FEXCore::X86Tables::BaseOps[Op]; if (Info->Type == FEXCore::X86Tables::TYPE_REX_PREFIX) { - LOGMAN_THROW_A_FMT(CTX->Config.Is64BitMode, "Got REX prefix in 32bit mode"); + LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode, "Got REX prefix in 32bit mode"); DecodeInst->Flags |= DecodeFlags::FLAG_REX_PREFIX; // Widening displacement @@ -986,7 +986,7 @@ void Decoder::BranchTargetInMultiblockRange() { // If the RIP setting is conditional AND within our symbol range then it can be considered for multiblock uint64_t TargetRIP = 0; - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); bool Conditional = true; switch (DecodeInst->OP) { @@ -1053,7 +1053,7 @@ bool Decoder::BranchTargetCanContinue(bool FinalInstruction) const { } uint64_t TargetRIP = 0; - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); if (DecodeInst->OP == 0xE8) { // Call - immediate target const uint64_t NextRIP = DecodeInst->PC + DecodeInst->InstSize; @@ -1095,7 +1095,7 @@ const uint8_t *Decoder::AdjustAddrForSpecialRegion(uint8_t const* _InstStream, u return _InstStream - EntryPoint + RIP; } -void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC, uint64_t MaxInst, std::function AddContainedCodePage) { +void Decoder::DecodeInstructionsAtEntry(FEXCore::Core::InternalThreadState *Thread, uint8_t const* _InstStream, uint64_t PC, uint64_t MaxInst, std::function AddContainedCodePage) { FEXCORE_PROFILE_SCOPED("DecodeInstructions"); BlockInfo.TotalInstructionCount = 0; BlockInfo.Blocks.clear(); @@ -1107,6 +1107,11 @@ void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC, MaxCondBranchBackwards = ~0ULL; DecodedBuffer = PoolObject.ReownOrClaimBuffer(); + // Decode operating mode from thread's CS segment. + const auto CSSegment = Thread->CurrentFrame->State.gdt[Thread->CurrentFrame->State.cs_idx >> 3]; + BlockInfo.Is64BitMode = CSSegment.L == 1; + LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode == CTX->Config.Is64BitMode, "Expected operating mode to not change at runtime!"); + // XXX: Load symbol data SymbolAvailable = false; EntryPoint = PC; diff --git a/FEXCore/Source/Interface/Core/Frontend.h b/FEXCore/Source/Interface/Core/Frontend.h index 6f0eab8ef..656f184d6 100644 --- a/FEXCore/Source/Interface/Core/Frontend.h +++ b/FEXCore/Source/Interface/Core/Frontend.h @@ -29,12 +29,13 @@ public: struct DecodedBlockInformation final { uint64_t TotalInstructionCount; + bool Is64BitMode{}; fextl::vector Blocks; }; Decoder(FEXCore::Context::ContextImpl *ctx); ~Decoder(); - void DecodeInstructionsAtEntry(uint8_t const* InstStream, uint64_t PC, uint64_t MaxInst, std::function AddContainedCodePage); + void DecodeInstructionsAtEntry(FEXCore::Core::InternalThreadState *Thread, uint8_t const* InstStream, uint64_t PC, uint64_t MaxInst, std::function AddContainedCodePage); DecodedBlockInformation const *GetDecodedBlockInfo() const { return &BlockInfo; @@ -81,6 +82,7 @@ private: size_t DecodedSize {}; uint8_t const *InstStream; + uint8_t GetGPRSize() const { return BlockInfo.Is64BitMode ? 8 : 4; } static constexpr size_t MAX_INST_SIZE = 15; uint8_t InstructionSize; diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index dfd71fcd4..f923b7b9e 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -106,7 +106,7 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) { // Calculate flags early. CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); auto NewRIP = GetRelocatedPC(Op, -Op->InstSize); _StoreContext(GPRSize, GPRClass, NewRIP, offsetof(FEXCore::Core::CPUState, rip)); @@ -154,10 +154,10 @@ void OpDispatchBuilder::ThunkOp(OpcodeArgs) { // Calculate flags early. CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); uint8_t *sha256 = (uint8_t *)(Op->PC + 2); - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { // x86-64 ABI puts the function argument in RDI _Thunk( LoadGPRRegister(X86State::REG_RDI), @@ -190,14 +190,14 @@ void OpDispatchBuilder::LEAOp(OpcodeArgs) { // LEA specifically ignores segment prefixes const auto SrcSize = GetSrcSize(Op); - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { const uint32_t DstSize = X86Tables::DecodeFlags::GetOpAddr(Op->Flags, 0) == X86Tables::DecodeFlags::FLAG_OPERAND_SIZE_LAST ? 2 : X86Tables::DecodeFlags::GetOpAddr(Op->Flags, 0) == X86Tables::DecodeFlags::FLAG_WIDENING_SIZE_LAST ? 8 : 4; auto Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], SrcSize, Op->Flags, {.LoadData = false}); if (DstSize != SrcSize) { // If the SrcSize isn't the DstSize then we need to zero extend. - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); Src = _Bfe(IR::SizeToOpSize(GPRSize), SrcSize * 8, 0, Src); } StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, DstSize, -1); @@ -214,7 +214,7 @@ void OpDispatchBuilder::NOPOp(OpcodeArgs) { } void OpDispatchBuilder::RETOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // ABI Optimization: Flags don't survive calls or rets if (CTX->Config.ABILocalFlags) { @@ -269,7 +269,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) { // Calculate flags early. CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); auto Constant = _Constant(GPRSize); @@ -289,7 +289,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) { SetPackedRFLAG(false, eflags); SP = _Add(IR::SizeToOpSize(GPRSize), SP, Constant); - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { // RSP and SS only happen in 64-bit mode or if this is a CPL mode jump! // FEX doesn't support a CPL mode switch, so don't need to worry about this on 32-bit StoreGPRRegister(X86State::REG_RSP, _LoadMem(GPRClass, GPRSize, SP, GPRSize)); @@ -313,7 +313,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) { } void OpDispatchBuilder::CallbackReturnOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // Store the new RIP _CallbackReturn(); auto NewRIP = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, rip)); @@ -507,7 +507,7 @@ void OpDispatchBuilder::PUSHOp(OpcodeArgs) { auto OldSP = LoadGPRRegister(X86State::REG_RSP); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); auto NewSP = _Push(GPRSize, Size, Src, OldSP); // Store the new stack pointer @@ -521,7 +521,7 @@ void OpDispatchBuilder::PUSHREGOp(OpcodeArgs) { {.AllowUpperGarbage = true}); auto OldSP = LoadGPRRegister(X86State::REG_RSP); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); auto NewSP = _Push(GPRSize, Size, Src, OldSP); // Store the new stack pointer StoreGPRRegister(X86State::REG_RSP, NewSP); @@ -546,7 +546,7 @@ void OpDispatchBuilder::PUSHAOp(OpcodeArgs) { OrderedNode *Src{}; OrderedNode *NewSP = OldSP; - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); Src = LoadGPRRegister(X86State::REG_RAX); NewSP = _Push(GPRSize, Size, Src, NewSP); @@ -584,7 +584,7 @@ void OpDispatchBuilder::PUSHSegmentOp(OpcodeArgs) { auto OldSP = LoadGPRRegister(X86State::REG_RSP); OrderedNode *Src{}; - if (!CTX->Config.Is64BitMode()) { + if (!Is64BitMode) { switch (SegmentReg) { case FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX: Src = _LoadContext(SrcSize, GPRClass, offsetof(FEXCore::Core::CPUState, es_idx)); @@ -631,7 +631,7 @@ void OpDispatchBuilder::PUSHSegmentOp(OpcodeArgs) { } } - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // Store our value to the new stack location // AMD hardware zexts segment selector to 32bit // Intel hardware inserts segment selector @@ -764,7 +764,7 @@ void OpDispatchBuilder::LEAVEOp(OpcodeArgs) { } void OpDispatchBuilder::CALLOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); BlockSetRIP = true; @@ -935,7 +935,7 @@ void OpDispatchBuilder::SETccOp(OpcodeArgs) { } void OpDispatchBuilder::CMOVOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // Calculate flags early. CalculateDeferredFlags(); @@ -967,7 +967,7 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) { uint64_t InstRIP = Op->PC + Op->InstSize; uint64_t Target = InstRIP + TargetOffset; - if (CTX->GetGPRSize() == 4) { + if (GetGPRSize() == 4) { // If the GPRSize is 4 then we need to be careful about PC wrapping if (TargetOffset < 0 && -TargetOffset > InstRIP) { // Invert the signed value if we are underflowing @@ -1042,7 +1042,7 @@ void OpDispatchBuilder::CondJUMPRCXOp(OpcodeArgs) { CalculateDeferredFlags(); BlockSetRIP = true; - uint8_t JcxGPRSize = CTX->GetGPRSize(); + uint8_t JcxGPRSize = GetGPRSize(); JcxGPRSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? (JcxGPRSize >> 1) : JcxGPRSize; IRPair TakeBranch; @@ -1195,7 +1195,7 @@ void OpDispatchBuilder::JUMPOp(OpcodeArgs) { uint64_t InstRIP = Op->PC + Op->InstSize; uint64_t TargetRIP = InstRIP + TargetOffset; - if (CTX->GetGPRSize() == 4) { + if (GetGPRSize() == 4) { // If the GPRSize is 4 then we need to be careful about PC wrapping if (TargetOffset < 0 && -TargetOffset > InstRIP) { // Invert the signed value if we are underflowing @@ -1481,7 +1481,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { break; case FEXCore::X86State::REG_RBP: // GS case FEXCore::X86State::REG_R13: // GS - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, gs_idx)); UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX); } else { @@ -1491,7 +1491,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { break; case FEXCore::X86State::REG_RSP: // FS case FEXCore::X86State::REG_R12: // FS - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { _StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, fs_idx)); UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX); } else { @@ -1527,7 +1527,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { break; case FEXCore::X86State::REG_RBP: // GS case FEXCore::X86State::REG_R13: // GS - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { Segment = _Constant(0); } else { @@ -1536,7 +1536,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) { break; case FEXCore::X86State::REG_RSP: // FS case FEXCore::X86State::REG_R12: // FS - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { Segment = _Constant(0); } else { @@ -1583,7 +1583,7 @@ void OpDispatchBuilder::MOVOffsetOp(OpcodeArgs) { } void OpDispatchBuilder::CPUIDOp(OpcodeArgs) { - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = GetGPRSize(); OrderedNode *Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GPRSize, Op->Flags); OrderedNode *Leaf = LoadGPRRegister(X86State::REG_RCX); @@ -2174,7 +2174,7 @@ 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 GPRSize = GetGPRSize(); const auto Size = GetSrcSize(Op); const auto SrcSize = Op->Src[0].IsGPR() ? GPRSize : Size; @@ -2236,7 +2236,7 @@ void OpDispatchBuilder::RORX(OpcodeArgs) { const auto Amount = Op->Src[1].Data.Literal.Value; const auto SrcSize = GetSrcSize(Op); const auto SrcSizeBits = SrcSize * 8; - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = GetGPRSize(); const auto DoRotation = Amount != 0 && Amount < SrcSizeBits; const auto IsSameGPR = Op->Src[0].IsGPR() && Op->Dest.IsGPR() && @@ -2269,7 +2269,7 @@ void OpDispatchBuilder::MULX(OpcodeArgs) { // 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 = GetGPRSize(); const auto Src1Size = Op->Src[1].IsGPR() ? GPRSize : OperandSize; OrderedNode* Src1 = LoadSource_WithOpSize(GPRClass, Op, Op->Src[1], Src1Size, Op->Flags); @@ -2756,7 +2756,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs) { 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, GetGPRSize(), Op->Flags); Value = Dest; // Get the bit selection from the src. We need to mask for 8/16-bit, but @@ -2992,7 +2992,7 @@ void OpDispatchBuilder::IMULOp(OpcodeArgs) { StoreGPRRegister(X86State::REG_RDX, LocalResultHigh); } else if (Size == 8) { - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { LogMan::Msg::EFmt("Doesn't exist in 32bit mode"); DecodeFailure = true; return; @@ -3042,7 +3042,7 @@ void OpDispatchBuilder::MULOp(OpcodeArgs) { StoreGPRRegister(X86State::REG_RDX, ResultHigh); } else if (Size == 8) { - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { LogMan::Msg::EFmt("Doesn't exist in 32bit mode"); DecodeFailure = true; return; @@ -3089,7 +3089,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 uint8_t GPRSize = GetGPRSize(); OrderedNode *Src = LoadSource_WithOpSize(GPRClass, Op, Dest, GPRSize, Op->Flags); // For 8/16-bit, use 64-bit invert so we invert in place, while getting @@ -3453,7 +3453,7 @@ void OpDispatchBuilder::WriteSegmentReg(OpcodeArgs) { } void OpDispatchBuilder::EnterOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); LOGMAN_THROW_A_FMT(Op->Src[0].IsLiteral(), "Src1 needs to be literal here"); const uint64_t Value = Op->Src[0].Data.Literal.Value; @@ -3462,7 +3462,7 @@ void OpDispatchBuilder::EnterOp(OpcodeArgs) { const uint8_t Level = (Value >> 16) & 0x1F; const auto PushValue = [&](uint8_t Size, OrderedNode *Src) -> OrderedNode* { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); auto OldSP = LoadGPRRegister(X86State::REG_RSP); auto NewSP = _Push(GPRSize, Size, Src, OldSP); @@ -3503,7 +3503,7 @@ void OpDispatchBuilder::SGDTOp(OpcodeArgs) { // Operand size prefix is ignored on this instruction, size purely depends on operating mode. uint64_t GDTAddress = 0xFFFFFFFFFFFE0000ULL; size_t GDTStoreSize = 8; - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { // Mask off upper bits if 32-bit result. GDTAddress &= ~0U; GDTStoreSize = 4; @@ -3607,7 +3607,7 @@ void OpDispatchBuilder::STOSOp(OpcodeArgs) { // Calculate direction. auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); // Offset the pointer OrderedNode *TailDest = LoadGPRRegister(X86State::REG_RDI); @@ -3669,7 +3669,7 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) { } else { auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); OrderedNode *RSI = LoadGPRRegister(X86State::REG_RSI); OrderedNode *RDI = LoadGPRRegister(X86State::REG_RDI); @@ -3716,7 +3716,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); // Offset the pointer Dest_RDI = _Add(OpSize::i64Bit, Dest_RDI, PtrDir); @@ -3735,7 +3735,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { // read DF once auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); auto JumpStart = Jump(); // Make sure to start a new block after ending this one @@ -3829,7 +3829,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); // Offset the pointer OrderedNode *TailDest_RSI = LoadGPRRegister(X86State::REG_RSI); @@ -3850,7 +3850,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { // Read DF once auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); auto JumpStart = Jump(); // Make sure to start a new block after ending this one @@ -3927,7 +3927,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); // Offset the pointer OrderedNode *TailDest_RDI = LoadGPRRegister(X86State::REG_RDI); @@ -3944,7 +3944,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { // read DF once auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); auto SizeConst = _Constant(Size); - auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); + auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1); auto JumpStart = Jump(); // Make sure to start a new block after ending this one @@ -4019,7 +4019,7 @@ void OpDispatchBuilder::BSWAPOp(OpcodeArgs) { Dest = _Constant(0); } else { - Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPRSize(), Op->Flags); + Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, GetGPRSize(), Op->Flags); Dest = _Rev(IR::SizeToOpSize(Size), Dest); } StoreResult(GPRClass, Op, Dest, -1); @@ -4035,7 +4035,7 @@ void OpDispatchBuilder::PUSHFOp(OpcodeArgs) { auto OldSP = LoadGPRRegister(X86State::REG_RSP); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); auto NewSP = _Push(GPRSize, Size, Src, OldSP); // Store the new stack pointer @@ -4092,7 +4092,7 @@ void OpDispatchBuilder::DIVOp(OpcodeArgs) { // This loads the divisor OrderedNode *Divisor = LoadSource(GPRClass, Op, Op->Dest, Op->Flags); - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = GetGPRSize(); const auto Size = GetSrcSize(Op); if (Size == 1) { @@ -4125,7 +4125,7 @@ void OpDispatchBuilder::DIVOp(OpcodeArgs) { StoreGPRRegister(X86State::REG_RDX, URemOp); } else if (Size == 8) { - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { LogMan::Msg::EFmt("Doesn't exist in 32bit mode"); DecodeFailure = true; return; @@ -4145,7 +4145,7 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) { // This loads the divisor OrderedNode *Divisor = LoadSource(GPRClass, Op, Op->Dest, Op->Flags); - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = GetGPRSize(); const auto Size = GetSrcSize(Op); if (Size == 1) { @@ -4180,7 +4180,7 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) { StoreGPRRegister(X86State::REG_RDX, URemOp); } else if (Size == 8) { - if (!CTX->Config.Is64BitMode) { + if (!Is64BitMode) { LogMan::Msg::EFmt("Doesn't exist in 32bit mode"); DecodeFailure = true; return; @@ -4197,7 +4197,7 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) { } void OpDispatchBuilder::BSFOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); const uint8_t DstSize = GetDstSize(Op) == 2 ? 2 : GPRSize; OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags); OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); @@ -4218,7 +4218,7 @@ void OpDispatchBuilder::BSFOp(OpcodeArgs) { } void OpDispatchBuilder::BSROp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); const uint8_t DstSize = GetDstSize(Op) == 2 ? 2 : GPRSize; OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags); OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); @@ -4254,7 +4254,7 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) { // *Xn = Xt // Xs = MemData - const auto GPRSize = CTX->GetGPRSize(); + const auto GPRSize = GetGPRSize(); auto Size = GetSrcSize(Op); // This is our source register @@ -4448,8 +4448,11 @@ void OpDispatchBuilder::CreateJumpBlocks(fextl::vector const *Blocks, uint32_t NumInstructions) { +void OpDispatchBuilder::BeginFunction(uint64_t RIP, fextl::vector const *Blocks, uint32_t NumInstructions, bool _Is64BitMode) { Entry = RIP; + Is64BitMode = _Is64BitMode; + LOGMAN_THROW_A_FMT(Is64BitMode == CTX->Config.Is64BitMode, "Expected operating mode to not change at runtime!"); + auto IRHeader = _IRHeader(InvalidNode, RIP, 0, NumInstructions); CreateJumpBlocks(Blocks); @@ -4464,7 +4467,7 @@ void OpDispatchBuilder::Finalize() { // Calculate flags early. // This usually doesn't emit any IR but in the case of hitting the block instruction limit it will CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // Node 0 is invalid node OrderedNode *RealNode = reinterpret_cast(GetNode(1)); @@ -4505,7 +4508,7 @@ uint32_t OpDispatchBuilder::GetDstBitSize(X86Tables::DecodedOp Op) const { } OrderedNode *OpDispatchBuilder::GetSegment(uint32_t Flags, uint32_t DefaultPrefix, bool Override) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); if (CTX->Config.Is64BitMode) { if (Flags & FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX) { @@ -4652,8 +4655,14 @@ void OpDispatchBuilder::UpdatePrefixFromSegment(OrderedNode *Segment, uint32_t S // Use BFE to extract the selector index in bits [15,3] of the segment register. // In some cases the upper 16-bits of the 32-bit GPR contain garbage to ignore. Segment = _Bfe(OpSize::i32Bit, 16 - 3, 3, Segment); - auto NewSegment = _LoadContextIndexed(Segment, 4, offsetof(FEXCore::Core::CPUState, gdt[0]), 4, GPRClass); + OrderedNode *NewSegment = _LoadContextIndexed(Segment, 8, offsetof(FEXCore::Core::CPUState, gdt[0]), 8, GPRClass); CheckLegacySegmentWrite(NewSegment, SegmentReg); + + // Extract the 32-bit base from the GDT segment. + auto Upper32 = _Lshr(OpSize::i64Bit, NewSegment, _Constant(32)); + auto Masked = _And(OpSize::i32Bit, Upper32, _Constant(0xFF00'0000)); + OrderedNode *Merged = _Orlshr(OpSize::i32Bit, Masked, NewSegment, 16); + NewSegment = _Bfi(OpSize::i32Bit, 8, 16, Merged, Upper32); switch (SegmentReg) { case FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX: _StoreContext(4, GPRClass, NewSegment, offsetof(FEXCore::Core::CPUState, es_cached)); @@ -4691,7 +4700,7 @@ OrderedNode *OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, X OrderedNode *Src {nullptr}; bool LoadableType = false; - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); const uint32_t AddrSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) != 0 ? (GPRSize >> 1) : GPRSize; if (Operand.IsLiteral()) { @@ -4749,7 +4758,7 @@ OrderedNode *OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, X } } else if (Operand.IsRIPRelative()) { - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { Src = GetRelocatedPC(Op, Operand.Data.RIPLiteral.Value.s); } else { @@ -4851,12 +4860,12 @@ OrderedNode *OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, X } OrderedNode *OpDispatchBuilder::GetRelocatedPC(FEXCore::X86Tables::DecodedOp const& Op, int64_t Offset) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); return _EntrypointOffset(IR::SizeToOpSize(GPRSize), Op->PC + Op->InstSize + Offset - Entry); } OrderedNode *OpDispatchBuilder::LoadGPRRegister(uint32_t GPR, int8_t Size, uint8_t Offset, bool AllowUpperGarbage) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); if (Size == -1) { Size = GPRSize; } @@ -4884,7 +4893,7 @@ OrderedNode *OpDispatchBuilder::LoadXMMRegister(uint32_t XMM) { } void OpDispatchBuilder::StoreGPRRegister(uint32_t GPR, OrderedNode *const Src, int8_t Size, uint8_t Offset) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); if (Size == -1) { Size = GPRSize; } @@ -4927,7 +4936,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl // 32bit ops ZEXT the result to 64bit OrderedNode *MemStoreDst {nullptr}; bool MemStore = false; - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); const uint32_t AddrSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) != 0 ? (GPRSize >> 1) : GPRSize; if (Operand.IsLiteral()) { @@ -5005,7 +5014,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl } } else if (Operand.IsRIPRelative()) { - if (CTX->Config.Is64BitMode) { + if (Is64BitMode) { MemStoreDst = GetRelocatedPC(Op, Operand.Data.RIPLiteral.Value.s); } else { @@ -5272,7 +5281,7 @@ void OpDispatchBuilder::INTOp(OpcodeArgs) { // Calculate flags early. CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); if (SetRIPToNext) { BlockSetRIP = SetRIPToNext; @@ -5331,7 +5340,7 @@ void OpDispatchBuilder::LZCNT(OpcodeArgs) { } void OpDispatchBuilder::MOVBEOp(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); const auto SrcSize = GetSrcSize(Op); OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1}); @@ -5421,7 +5430,7 @@ void OpDispatchBuilder::RDTSCPOp(OpcodeArgs) { } void OpDispatchBuilder::CRC32(OpcodeArgs) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // Destination GPR size is always 4 or 8 bytes depending on widening uint8_t DstSize = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? 8 : 4; @@ -5454,7 +5463,7 @@ void OpDispatchBuilder::UnimplementedOp(OpcodeArgs) { // Ensure flags are calculated on invalid op. CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // We don't actually support this instruction // Multiblock may hit it though @@ -5479,7 +5488,7 @@ void OpDispatchBuilder::InvalidOp(OpcodeArgs) { // Ensure flags are calculated on invalid op. CalculateDeferredFlags(); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // We don't actually support this instruction // Multiblock may hit it though diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index a1dd7b15b..17a887dc3 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -186,7 +186,7 @@ public: auto it = JumpTargets.find(NextRIP); if (it == JumpTargets.end()) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // If we don't have a jump target to a new block then we have to leave // Set the RIP to the next instruction and leave auto RelocatedNextRIP = _EntrypointOffset(IR::SizeToOpSize(GPRSize), NextRIP - Entry); @@ -246,7 +246,7 @@ public: void SetDumpIR(bool DumpIR) { ShouldDump = DumpIR; } bool ShouldDumpIR() const { return ShouldDump; } - void BeginFunction(uint64_t RIP, fextl::vector const *Blocks, uint32_t NumInstructions); + void BeginFunction(uint64_t RIP, fextl::vector const *Blocks, uint32_t NumInstructions, bool Is64BitMode); void Finalize(); // Dispatch builder functions @@ -923,6 +923,8 @@ public: } } + uint8_t GetGPRSize() const { return Is64BitMode ? 8 : 4; } + protected: void SaveNZCV(IROps Op = OP_DUMMY) override { /* Some opcodes are conservatively marked as clobbering flags, but in fact @@ -1365,9 +1367,9 @@ private: if (IsNZCV(BitOffset)) { InsertNZCV(BitOffset, Value, ValueOffset, MustMask); } else if (BitOffset == FEXCore::X86State::RFLAG_PF_RAW_LOC) { - _StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize()); + _StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, GetGPRSize()); } else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) { - _StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize()); + _StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, GetGPRSize()); } else { if (ValueOffset || MustMask) Value = _Bfe(OpSize::i32Bit, 1, ValueOffset, Value); @@ -1421,9 +1423,9 @@ private: _Constant(1), _Constant(0)); } } else if (BitOffset == FEXCore::X86State::RFLAG_PF_RAW_LOC) { - return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize()); + return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, GetGPRSize()); } else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) { - return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize()); + return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, GetGPRSize()); } else { return _LoadFlag(BitOffset); } @@ -2152,6 +2154,7 @@ private: bool Multiblock{}; uint64_t Entry; + bool Is64BitMode{}; OrderedNode* _StoreMemAutoTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, OrderedNode *Addr, OrderedNode *Value, uint8_t Align = 1) { if (CTX->IsAtomicTSOEnabled()) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 5ccec1d4c..bd06819c0 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -698,7 +698,7 @@ OrderedNode* OpDispatchBuilder::InsertCVTGPR_To_FPRImpl(OpcodeArgs, 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, GetGPRSize(), Op->Flags); return _VSToFGPRInsert(IR::SizeToOpSize(DstSize), DstElementSize, SrcSize, Src1, Src2, ZeroUpperBits); } else if (SrcSize != DstElementSize) { @@ -1060,7 +1060,7 @@ void OpDispatchBuilder::MOVMSKOp(OpcodeArgs) { GPR = _Bfi(OpSize::i64Bit, 32, 31, GPR, GPR); // Shift right to only get the two sign bits we care about. GPR = _Lshr(OpSize::i64Bit, GPR, _Constant(62)); - StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, CTX->GetGPRSize(), -1); + StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, GetGPRSize(), -1); } else if (Size == 16 && ElementSize == 4) { // Shift all the sign bits to the bottom of their respective elements. @@ -1073,7 +1073,7 @@ void OpDispatchBuilder::MOVMSKOp(OpcodeArgs) { Src = _VAddV(Size, 4, Src); // Extract to a GPR. OrderedNode *GPR = _VExtractToGPR(Size, 4, Src, 0); - StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, CTX->GetGPRSize(), -1); + StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, GetGPRSize(), -1); } else { OrderedNode *CurrentVal = _Constant(0); @@ -1759,7 +1759,7 @@ void OpDispatchBuilder::VBROADCASTOp(OpcodeArgs) { Result = _VDupElement(DstSize, ElementSize, Src, 0); } else { // Get the address to broadcast from into a GPR. - OrderedNode *Address = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags, + OrderedNode *Address = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GetGPRSize(), Op->Flags, {.LoadData = false}); Address = AppendSegmentOffset(Address, Op->Flags); @@ -1795,7 +1795,7 @@ OrderedNode* OpDispatchBuilder::PINSROpImpl(OpcodeArgs, size_t ElementSize, 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, GetGPRSize(), Op->Flags); return _VInsGPR(Size, ElementSize, Index, Src1, Src2); } @@ -1924,7 +1924,7 @@ void OpDispatchBuilder::PExtrOp(OpcodeArgs) { Index &= NumElements - 1; if (Op->Dest.IsGPR()) { - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); // Extract already zero extends the result. OrderedNode *Result = _VExtractToGPR(16, OverridenElementSize, Src, Index); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Result, GPRSize, -1); @@ -2477,7 +2477,7 @@ OrderedNode* OpDispatchBuilder::CVTGPR_To_FPRImpl(OpcodeArgs, size_t DstElementS OrderedNode *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, GetGPRSize(), Op->Flags); Converted = _Float_FromGPR_S(DstElementSize, SrcSize, Src2); } else if (SrcSize != DstElementSize) { @@ -2826,7 +2826,7 @@ void OpDispatchBuilder::VMASKMOVOpImpl(OpcodeArgs, size_t ElementSize, size_t Da const X86Tables::DecodedOperand& DataOp) { const auto MakeAddress = [this, Op](const X86Tables::DecodedOperand& Data) { - OrderedNode *BaseAddr = LoadSource_WithOpSize(GPRClass, Op, Data, CTX->GetGPRSize(), Op->Flags, + OrderedNode *BaseAddr = LoadSource_WithOpSize(GPRClass, Op, Data, GetGPRSize(), Op->Flags, {.LoadData = false}); return AppendSegmentOffset(BaseAddr, Op->Flags); }; @@ -2877,7 +2877,7 @@ void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs) { Op->Dest.Data.GPR.GPR >= FEXCore::X86State::REG_XMM_0) { if (Op->Src[0].IsGPR()) { // Loading from GPR and moving to Vector. - OrderedNode *Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags); + OrderedNode *Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], GetGPRSize(), Op->Flags); // zext to 128bit auto Converted = _VCastFromGPR(16, GetSrcSize(Op), Src); StoreResult(FPRClass, Op, Op->Dest, Converted, -1); @@ -3011,7 +3011,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) { // for features that are in the lower 32 bits, so EAX only is sufficient. OrderedNode *Mask = LoadGPRRegister(X86State::REG_RAX); OrderedNode *Base = XSaveBase(); - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); const auto StoreIfFlagSet = [&](uint32_t BitIndex, auto fn, uint32_t FieldSize = 1){ OrderedNode *BitFlag = _Bfe(OpSize, FieldSize, BitIndex, Mask); @@ -3065,7 +3065,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) { } void OpDispatchBuilder::SaveX87State(OpcodeArgs, OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); // Saves 512bytes to the memory location provided // Header changes depending on if REX.W is set or not if (Op->Flags & X86Tables::DecodeFlags::FLAG_REX_WIDENING) { @@ -3151,8 +3151,8 @@ void OpDispatchBuilder::SaveX87State(OpcodeArgs, OrderedNode *MemBase) { } void OpDispatchBuilder::SaveSSEState(OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); + const auto NumRegs = Is64BitMode ? 16U : 8U; for (uint32_t i = 0; i < NumRegs; ++i) { OrderedNode *XMMReg = LoadXMMRegister(i); @@ -3163,7 +3163,7 @@ void OpDispatchBuilder::SaveSSEState(OrderedNode *MemBase) { } void OpDispatchBuilder::SaveMXCSRState(OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); OrderedNode *MXCSR = GetMXCSR(); OrderedNode *MXCSRLocation = _Add(OpSize, MemBase, _Constant(24)); @@ -3175,8 +3175,8 @@ void OpDispatchBuilder::SaveMXCSRState(OrderedNode *MemBase) { } void OpDispatchBuilder::SaveAVXState(OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); + const auto NumRegs = Is64BitMode ? 16U : 8U; for (uint32_t i = 0; i < NumRegs; ++i) { OrderedNode *Upper = _VDupElement(32, 16, LoadXMMRegister(i), 1); @@ -3194,7 +3194,7 @@ OrderedNode *OpDispatchBuilder::GetMXCSR() { } void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false}); Mem = AppendSegmentOffset(Mem, Op->Flags); @@ -3208,7 +3208,7 @@ void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) { } void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); const auto XSaveBase = [this, Op] { OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); @@ -3283,7 +3283,7 @@ void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) { } void OpDispatchBuilder::RestoreX87State(OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); auto NewFCW = _LoadMem(GPRClass, 2, MemBase, 2); _StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); @@ -3309,8 +3309,8 @@ void OpDispatchBuilder::RestoreX87State(OrderedNode *MemBase) { } void OpDispatchBuilder::RestoreSSEState(OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); + const auto NumRegs = Is64BitMode ? 16U : 8U; for (uint32_t i = 0; i < NumRegs; ++i) { OrderedNode *MemLocation = _Add(OpSize, MemBase, _Constant(i * 16 + 160)); @@ -3326,8 +3326,8 @@ void OpDispatchBuilder::RestoreMXCSRState(OrderedNode *MXCSR) { } void OpDispatchBuilder::RestoreAVXState(OrderedNode *MemBase) { - const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto OpSize = IR::SizeToOpSize(GetGPRSize()); + const auto NumRegs = Is64BitMode ? 16U : 8U; for (uint32_t i = 0; i < NumRegs; ++i) { OrderedNode *XMMReg = LoadXMMRegister(i); @@ -3352,7 +3352,7 @@ void OpDispatchBuilder::DefaultX87State(OpcodeArgs) { } void OpDispatchBuilder::DefaultSSEState() { - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto NumRegs = Is64BitMode ? 16U : 8U; OrderedNode *ZeroVector = LoadAndCacheNamedVectorConstant(Core::CPUState::XMM_SSE_REG_SIZE, FEXCore::IR::NamedVectorConstant::NAMED_VECTOR_ZERO); for (uint32_t i = 0; i < NumRegs; ++i) { @@ -3361,7 +3361,7 @@ void OpDispatchBuilder::DefaultSSEState() { } void OpDispatchBuilder::DefaultAVXState() { - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto NumRegs = Is64BitMode ? 16U : 8U; for (uint32_t i = 0; i < NumRegs; i++) { OrderedNode* Reg = LoadXMMRegister(i); @@ -5360,7 +5360,7 @@ void OpDispatchBuilder::VPBLENDWOp(OpcodeArgs) { void OpDispatchBuilder::VZEROOp(OpcodeArgs) { const auto DstSize = GetDstSize(Op); const auto IsVZEROALL = DstSize == Core::CPUState::XMM_AVX_REG_SIZE; - const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U; + const auto NumRegs = Is64BitMode ? 16U : 8U; if (IsVZEROALL) { // NOTE: Despite the name being VZEROALL, this will still only ever @@ -5564,7 +5564,7 @@ void OpDispatchBuilder::PCMPXSTRXOpImpl(OpcodeArgs, bool IsExplicit, bool IsMask OrderedNode *Result = _Select(IR::COND_EQ, ResultNoFlags, ZeroConst, IfZero, IfNotZero); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = GetGPRSize(); if (GPRSize == 8) { // If being stored to an 8-byte register, zero extend the 4-byte result. Result = _Bfe(OpSize::i64Bit, 32, 0, Result); diff --git a/FEXCore/Source/Interface/HLE/Thunks/Thunks.cpp b/FEXCore/Source/Interface/HLE/Thunks/Thunks.cpp index 72df41bcb..72ffa5a92 100644 --- a/FEXCore/Source/Interface/HLE/Thunks/Thunks.cpp +++ b/FEXCore/Source/Interface/HLE/Thunks/Thunks.cpp @@ -239,7 +239,7 @@ namespace FEXCore { IRHeader.first->Blocks = emit->WrapNode(Block); emit->SetCurrentCodeBlock(Block); - const uint8_t GPRSize = CTX->GetGPRSize(); + const uint8_t GPRSize = CTX->Config.Is64BitMode ? 8 : 4; if (GPRSize == 8) { emit->_StoreRegister(emit->_Constant(Entrypoint), false, offsetof(Core::CPUState, gregs[X86State::REG_R11]), IR::GPRClass, IR::GPRFixedClass, GPRSize);