OpcodeDispatcher: optimize POPA

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2024-08-11 09:37:32 -04:00
parent 881c940693
commit ee339b5960

View File

@ -514,52 +514,22 @@ void OpDispatchBuilder::POPAOp(OpcodeArgs) {
// 32bit only
const uint8_t Size = GetSrcSize(Op);
auto Constant = _Constant(Size);
auto OldSP = LoadGPRRegister(X86State::REG_RSP);
Ref SP = _RMWHandle(LoadGPRRegister(X86State::REG_RSP));
// POPA order:
// pop EDI
// pop ESI
// pop EBP
// ESP += 4; // Skip RSP because it'll be correct at the end
// pop EBX
// pop EDX
// pop ECX
// pop EAX
StoreGPRRegister(X86State::REG_RDI, Pop(Size, SP), Size);
StoreGPRRegister(X86State::REG_RSI, Pop(Size, SP), Size);
StoreGPRRegister(X86State::REG_RBP, Pop(Size, SP), Size);
Ref Src {};
Ref NewSP = OldSP;
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RDI, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, Constant);
// Skip loading RSP because it'll be correct at the end
SP = _RMWHandle(_Add(OpSize::i64Bit, SP, _Constant(Size)));
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RSI, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, Constant);
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RBP, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, _Constant(Size * 2));
// Skip SP loading
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RBX, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, Constant);
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RDX, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, Constant);
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RCX, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, Constant);
Src = _LoadMem(GPRClass, Size, NewSP, Size);
StoreGPRRegister(X86State::REG_RAX, Src, Size);
NewSP = _Add(OpSize::i64Bit, NewSP, Constant);
StoreGPRRegister(X86State::REG_RBX, Pop(Size, SP), Size);
StoreGPRRegister(X86State::REG_RDX, Pop(Size, SP), Size);
StoreGPRRegister(X86State::REG_RCX, Pop(Size, SP), Size);
StoreGPRRegister(X86State::REG_RAX, Pop(Size, SP), Size);
// Store the new stack pointer
StoreGPRRegister(X86State::REG_RSP, NewSP);
StoreGPRRegister(X86State::REG_RSP, SP);
}
template<uint32_t SegmentReg>