http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56807
--- Comment #19 from H.J. Lu <hjl.tools at gmail dot com> --- (In reply to Anton Mitrofanov from comment #18) > This patch is ok for mingw32 target but may produce incorrect code for > x86_64 linux target in case of saving/restoring both rax and r10. In that > case during restoring of rax register (in "if (r10_live && eax_live)" path > of > http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/i386/i386. > c?r1=205860&r2=205859&pathrev=205860) we will make move from incorrect > address [rsp + allocate - UNITS_PER_WORD] while the saved value will be at > address [rsp + allocate + UNITS_PER_WORD]. Here is possible code that can be > generated (by looking at current gcc source code): > > // suppose rsp == 1000 here > push rax // rsp == 992 ; [992] == rax > push r10 // rsp == 984 ; [984] == r10 > mov rax, 400 // where 400 is allocate value > call allocate_stack > sub rsp, rax // rax == 400 so rsp == 584 > mov r10, [rsp + 400] // 584 + 400 == 984 ; r10 = [984] > mov rax, [rsp + 400 - 8] // 584 + 400 - 8 == 976 ; rax = [976] <- WRONG > > Instead the last instruction should be > > mov rax, [rsp + 400 + 8] // 584 + 400 + 8 == 992 ; rax = [992] > There are if (eax_live) { insn = emit_insn (gen_push (eax)); allocate -= UNITS_PER_WORD; ... if (r10_live) { r10 = gen_rtx_REG (Pmode, R10_REG); insn = emit_insn (gen_push (r10)); allocate -= UNITS_PER_WORD; ... if (r10_live && eax_live) { t = plus_constant (Pmode, stack_pointer_rtx, allocate); emit_move_insn (gen_rtx_REG (word_mode, R10_REG), gen_frame_mem (word_mode, t)); t = plus_constant (Pmode, stack_pointer_rtx, allocate - UNITS_PER_WORD); emit_move_insn (gen_rtx_REG (word_mode, AX_REG), gen_frame_mem (word_mode, t)); } They look OK to me.