MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / StoreResult_WithOpSize

Method StoreResult_WithOpSize

FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp:4313–4393  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

4311}
4312
4313void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op,
4314 const FEXCore::X86Tables::DecodedOperand& Operand, const Ref Src, IR::OpSize OpSize,
4315 IR::OpSize Align, MemoryAccessType AccessType) {
4316 if (Operand.IsGPR()) {
4317 // 8Bit and 16bit destination types store their result without effecting the upper bits
4318 // 32bit ops ZEXT the result to 64bit
4319 const auto GPRSize = GetGPROpSize();
4320
4321 const auto gpr = Operand.Data.GPR.GPR;
4322 if (gpr >= FEXCore::X86State::REG_MM_0) {
4323 LOGMAN_THROW_A_FMT(OpSize == OpSize::i64Bit, "full");
4324 LOGMAN_THROW_A_FMT(Class == FPRClass, "MMX is floaty");
4325
4326 if (MMXState != MMXState_MMX) {
4327 ChgStateX87_MMX();
4328 }
4329
4330 uint8_t Index = MM0Index + gpr - FEXCore::X86State::REG_MM_0;
4331 StoreContext(Index, Src);
4332 RegCache.Partial |= (1ull << (uint64_t)Index);
4333 } else if (gpr >= FEXCore::X86State::REG_XMM_0) {
4334 const auto gprIndex = gpr - X86State::REG_XMM_0;
4335 const auto VectorSize = GetGuestVectorLength();
4336
4337 auto Result = Src;
4338 if (OpSize != VectorSize) {
4339 // Partial writes can come from FPRs.
4340 // TODO: Fix the instructions doing partial writes rather than dealing with it here.
4341
4342 LOGMAN_THROW_A_FMT(Class != IR::GPRClass, "Partial writes from GPR not allowed. Instruction: {}", Op->TableInfo->Name);
4343
4344 // XMM-size is handled in implementations.
4345 if (VectorSize != OpSize::i256Bit || OpSize != OpSize::i128Bit) {
4346 auto SrcVector = LoadXMMRegister(gprIndex);
4347 Result = _VInsElement(VectorSize, OpSize, 0, 0, SrcVector, Src);
4348 }
4349 }
4350
4351 StoreXMMRegister(gprIndex, Result);
4352 } else {
4353 if (GPRSize == OpSize::i64Bit && OpSize == OpSize::i32Bit) {
4354 // If the Source IR op is 64 bits, we need to zext the upper bits
4355 // For all other sizes, the upper bits are guaranteed to already be zero
4356 Ref Value = GetOpSize(Src) == OpSize::i64Bit ? ARef(Src).Bfe(0, 32).Ref() : Src;
4357 StoreGPRRegister(gpr, Value, GPRSize);
4358
4359 LOGMAN_THROW_A_FMT(!Operand.Data.GPR.HighBits, "Can't handle 32bit store to high 8bit register");
4360 } else {
4361 LOGMAN_THROW_A_FMT(!(GPRSize == OpSize::i32Bit && OpSize > OpSize::i32Bit), "Oops had a {} GPR load", OpSize);
4362
4363 if (GPRSize != OpSize) {
4364 // if the GPR isn't the full size then we need to insert.
4365 // eg:
4366 // mov al, 2 ; Move in to lower 8-bits.
4367 // mov ah, 2 ; Move in to upper 8-bits of 16-bit reg.
4368 // mov ax, 2 ; Move in to lower 16-bits of reg.
4369 StoreGPRRegister(gpr, Src, OpSize, Operand.Data.GPR.HighBits * 8);
4370 } else {

Callers

nothing calls this directly

Calls 4

LoadEffectiveAddressFunction · 0.85
RefMethod · 0.80
BfeMethod · 0.80
IsGPRMethod · 0.45

Tested by

no test coverage detected