According to the Microsoft 64-bit ABI specification, registers RDI, RSI
and XMM6-15 are non-volatile and the stack alignment is 16 bytes. In
practice, the Windows implementation appears to not be so picky about
the 16-byte alignment requirement, probably because it never to save SSE
registers and instead just never uses them. This led to a large list
(https://bugs.winehq.org/show_bug.cgi?id=27680) of Win64 programs
violating the ABI with impunity, but crashing in Wine until
force_align_arg_pointer was added to gcc and used in Wine.
Stack re-alignment was originally done prior to int register saves, but
was moved to after SSE saves in 2010 to better facilitate
parallelization, and for simplicity's sake, the stack pointer was
considered invalid after stack re-alignment and SSE movs were emitted
unaligned relative to the frame pointer. But now that forced stack
re-alignment is the new normal for Wine64, it means that it always gets
the unaligned movs in Wine. This patch set fixes the problem while
preserving the improved parallelization of int register saves of Richard
Henderson's patch in 2010.
This patchset is a prerequisite to another I'm still refining that
out-of-lines these pro/epilogues. I'm still pretty new to this project,
so I hope I haven't missed anything. (No additional failures in tests.)
Daniel Santos
2016-12-21 Daniel Santos <daniel.san...@pobox.com>
* config/i386/i386.h (struct machine_frame_state): New fields
sp_realigned and sp_realigned_offset.
* config/i386/i386.c
(struct ix86_frame): New fields stack_realign_allocate_offset and
stack_realign_offset.
(ix86_compute_frame_layout): Modify re-alignment calculations.
(sp_valid_at, fp_valid_at): New inline functions.
(choose_basereg): New function.
(choose_baseaddr): Add align parameter, use choose_basereg and modify
all callers.
(ix86_emit_save_reg_using_mov, ix86_emit_restore_sse_regs_using_mov):
Use align parameter of choose_baseaddr to generated aligned SSE movs
when possible.
(pro_epilogue_adjust_stack): Modify to track
machine_frame_state::sp_realigned.
(ix86_expand_prologue): Modify stack re-alignment code.
(ix86_emit_leave): Clear machine_frame_state::sp_realigned.
(ix86_expand_epilogue): Modify validity checks of frame and stack
pointers.