| 3975 | } |
| 3976 | |
| 3977 | Ref OpDispatchBuilder::GetSegment(uint32_t Flags, uint32_t DefaultPrefix, bool Override) { |
| 3978 | const auto GPRSize = GetGPROpSize(); |
| 3979 | uint32_t Prefix = Flags & FEXCore::X86Tables::DecodeFlags::FLAG_SEGMENTS; |
| 3980 | |
| 3981 | if (Is64BitMode) { |
| 3982 | if (Prefix == FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX) { |
| 3983 | return _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, fs_cached)); |
| 3984 | } else if (Prefix == FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX) { |
| 3985 | return _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, gs_cached)); |
| 3986 | } |
| 3987 | // If there was any other segment in 64bit then it is ignored |
| 3988 | } else { |
| 3989 | if (Prefix == FEXCore::X86Tables::DecodeFlags::FLAG_NO_PREFIX || Override) { |
| 3990 | // If there was no prefix then use the default one if available |
| 3991 | // Or the argument only uses a specific prefix (with override set) |
| 3992 | Prefix = DefaultPrefix; |
| 3993 | } |
| 3994 | // With the segment register optimization we store the GDT bases directly in the segment register to remove indexed loads |
| 3995 | Ref SegmentResult {}; |
| 3996 | switch (Prefix) { |
| 3997 | [[likely]] case FEXCore::X86Tables::DecodeFlags::FLAG_NO_PREFIX: return nullptr; |
| 3998 | case FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX: |
| 3999 | SegmentResult = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, es_cached)); |
| 4000 | break; |
| 4001 | case FEXCore::X86Tables::DecodeFlags::FLAG_CS_PREFIX: |
| 4002 | SegmentResult = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, cs_cached)); |
| 4003 | break; |
| 4004 | case FEXCore::X86Tables::DecodeFlags::FLAG_SS_PREFIX: |
| 4005 | SegmentResult = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, ss_cached)); |
| 4006 | break; |
| 4007 | case FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX: |
| 4008 | SegmentResult = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, ds_cached)); |
| 4009 | break; |
| 4010 | case FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX: |
| 4011 | SegmentResult = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, fs_cached)); |
| 4012 | break; |
| 4013 | case FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX: |
| 4014 | SegmentResult = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, gs_cached)); |
| 4015 | break; |
| 4016 | default: FEX_UNREACHABLE; |
| 4017 | } |
| 4018 | |
| 4019 | CheckLegacySegmentRead(SegmentResult, Prefix); |
| 4020 | return SegmentResult; |
| 4021 | } |
| 4022 | return nullptr; |
| 4023 | } |
| 4024 | |
| 4025 | Ref OpDispatchBuilder::AppendSegmentOffset(Ref Value, uint32_t Flags, uint32_t DefaultPrefix, bool Override) { |
| 4026 | auto Segment = GetSegment(Flags, DefaultPrefix, Override); |
nothing calls this directly
no outgoing calls
no test coverage detected