mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
Improve code and clarify parameters to ABI_Push/PopRegistersAndAdjustStack.
- Factor common work into a helper function. - Replace confusingly named "noProlog" with "rsp_alignment". Now that x86 is not supported, we can just specify it explicitly as 8 for clarity. - Add the option to include more frame size, which I'll need later. - Revert a change by magumagu in March which replaced MOVAPD with MOVUPD on account of 32-bit Windows, since it's no longer supported. True, apparently recent processors don't execute the former any faster if the pointer is, in fact, aligned, but there's no point using MOVUPD for something that's guaranteed to be aligned... (I discovered that GenFrsqrte and GenFres were incorrectly passing false to noProlog - they were, in fact, functions without prologs, the original meaning of the parameter - which caused the previous change to break. This is now fixed.)
This commit is contained in:
@ -36,67 +36,86 @@ void XEmitter::ABI_RestoreStack(unsigned int frameSize, bool noProlog)
|
||||
}
|
||||
}
|
||||
|
||||
void XEmitter::ABI_PushRegistersAndAdjustStack(u32 mask, bool noProlog)
|
||||
void XEmitter::ABI_CalculateFrameSize(u32 mask, size_t rsp_alignment, size_t needed_frame_size, size_t* shadowp, size_t* subtractionp, size_t* xmm_offsetp)
|
||||
{
|
||||
int regSize = 8;
|
||||
int shadow = 0;
|
||||
size_t shadow = 0;
|
||||
#if defined(_WIN32)
|
||||
shadow = 0x20;
|
||||
#endif
|
||||
|
||||
int count = 0;
|
||||
for (int r = 0; r < 16; r++)
|
||||
{
|
||||
if (mask & (1 << r))
|
||||
{
|
||||
PUSH((X64Reg) r);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
int size = ((noProlog ? -regSize : 0) - (count * regSize)) & 0xf;
|
||||
rsp_alignment -= count * 8;
|
||||
size_t subtraction = 0;
|
||||
if (mask & 0xffff0000)
|
||||
{
|
||||
// If we have any XMMs to save, we must align the stack here.
|
||||
subtraction = rsp_alignment & 0xf;
|
||||
}
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
if (mask & (1 << (16 + x)))
|
||||
size += 16;
|
||||
}
|
||||
size += shadow;
|
||||
if (size)
|
||||
SUB(regSize * 8, R(RSP), size >= 0x80 ? Imm32(size) : Imm8(size));
|
||||
int offset = shadow;
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
if (mask & (1 << (16 + x)))
|
||||
{
|
||||
MOVUPD(MDisp(RSP, offset), (X64Reg) x);
|
||||
offset += 16;
|
||||
}
|
||||
subtraction += 16;
|
||||
}
|
||||
size_t xmm_base_subtraction = subtraction;
|
||||
subtraction += needed_frame_size;
|
||||
subtraction += shadow;
|
||||
// Final alignment.
|
||||
rsp_alignment -= subtraction;
|
||||
subtraction += rsp_alignment & 0xf;
|
||||
|
||||
*shadowp = shadow;
|
||||
*subtractionp = subtraction;
|
||||
*xmm_offsetp = subtraction - xmm_base_subtraction;
|
||||
}
|
||||
|
||||
void XEmitter::ABI_PopRegistersAndAdjustStack(u32 mask, bool noProlog)
|
||||
size_t XEmitter::ABI_PushRegistersAndAdjustStack(u32 mask, size_t rsp_alignment, size_t needed_frame_size)
|
||||
{
|
||||
int regSize = 8;
|
||||
int size = 0;
|
||||
#if defined(_WIN32)
|
||||
size += 0x20;
|
||||
#endif
|
||||
size_t shadow, subtraction, xmm_offset;
|
||||
ABI_CalculateFrameSize(mask, rsp_alignment, needed_frame_size, &shadow, &subtraction, &xmm_offset);
|
||||
|
||||
for (int r = 0; r < 16; r++)
|
||||
{
|
||||
if (mask & (1 << r))
|
||||
PUSH((X64Reg) r);
|
||||
}
|
||||
|
||||
if (subtraction)
|
||||
SUB(64, R(RSP), subtraction >= 0x80 ? Imm32((u32)subtraction) : Imm8((u8)subtraction));
|
||||
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
if (mask & (1 << (16 + x)))
|
||||
{
|
||||
MOVUPD((X64Reg) x, MDisp(RSP, size));
|
||||
size += 16;
|
||||
MOVAPD(MDisp(RSP, (int)xmm_offset), (X64Reg) x);
|
||||
xmm_offset += 16;
|
||||
}
|
||||
}
|
||||
int count = 0;
|
||||
for (int r = 0; r < 16; r++)
|
||||
{
|
||||
if (mask & (1 << r))
|
||||
count++;
|
||||
}
|
||||
size += ((noProlog ? -regSize : 0) - (count * regSize)) & 0xf;
|
||||
|
||||
if (size)
|
||||
ADD(regSize * 8, R(RSP), size >= 0x80 ? Imm32(size) : Imm8(size));
|
||||
return shadow;
|
||||
}
|
||||
|
||||
void XEmitter::ABI_PopRegistersAndAdjustStack(u32 mask, size_t rsp_alignment, size_t needed_frame_size)
|
||||
{
|
||||
size_t shadow, subtraction, xmm_offset;
|
||||
ABI_CalculateFrameSize(mask, rsp_alignment, needed_frame_size, &shadow, &subtraction, &xmm_offset);
|
||||
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
if (mask & (1 << (16 + x)))
|
||||
{
|
||||
MOVAPD((X64Reg) x, MDisp(RSP, (int)xmm_offset));
|
||||
xmm_offset += 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (subtraction)
|
||||
ADD(64, R(RSP), subtraction >= 0x80 ? Imm32((u32)subtraction) : Imm8((u8)subtraction));
|
||||
|
||||
for (int r = 15; r >= 0; r--)
|
||||
{
|
||||
if (mask & (1 << r))
|
||||
|
Reference in New Issue
Block a user