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.

Reply via email to