| 2963 | } |
| 2964 | |
| 2965 | void OpDispatchBuilder::EnterOp(OpcodeArgs) { |
| 2966 | const auto GPRSize = GetGPROpSize(); |
| 2967 | const auto OperandSize = (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_OPERAND_SIZE) ? OpSize::i16Bit : GPRSize; |
| 2968 | const uint64_t Value = Op->Src[0].Literal(); |
| 2969 | |
| 2970 | const uint16_t AllocSpace = Value & 0xFFFF; |
| 2971 | const uint8_t Level = (Value >> 16) & 0x1F; |
| 2972 | |
| 2973 | const auto PushValue = [&](IR::OpSize Size, Ref Src) -> Ref { |
| 2974 | auto OldSP = LoadGPRRegister(X86State::REG_RSP); |
| 2975 | auto NewSP = _Push(GPRSize, Size, Src, OldSP); |
| 2976 | |
| 2977 | // Store the new stack pointer |
| 2978 | StoreGPRRegister(X86State::REG_RSP, NewSP); |
| 2979 | return NewSP; |
| 2980 | }; |
| 2981 | |
| 2982 | auto OldBP = LoadGPRRegister(X86State::REG_RBP); |
| 2983 | auto NewSP = PushValue(OperandSize, OldBP); |
| 2984 | auto temp_RBP = NewSP; |
| 2985 | |
| 2986 | if (Level > 0) { |
| 2987 | for (uint8_t i = 1; i < Level; ++i) { |
| 2988 | auto MemLoc = Sub(GPRSize, OldBP, i * IR::OpSizeToSize(OperandSize)); |
| 2989 | auto Mem = _LoadMem(GPRClass, OperandSize, MemLoc, OperandSize); |
| 2990 | NewSP = PushValue(OperandSize, Mem); |
| 2991 | } |
| 2992 | NewSP = PushValue(OperandSize, temp_RBP); |
| 2993 | } |
| 2994 | NewSP = Sub(GPRSize, NewSP, AllocSpace); |
| 2995 | StoreGPRRegister(X86State::REG_RSP, NewSP); |
| 2996 | StoreGPRRegister(X86State::REG_RBP, temp_RBP); |
| 2997 | } |
| 2998 | |
| 2999 | void OpDispatchBuilder::SGDTOp(OpcodeArgs) { |
| 3000 | auto DestAddress = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); |
nothing calls this directly
no test coverage detected