This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

INITIAL_ELIMINATION_OFFSET() in m68k backend


Hello Peter,

I'm still struggling to get the damn -fomit-frame-pointer to work
on m68k with all the ColdFire/uClinux patches applied.

After a full night debugging the Linux kernel, I found out why it
was crashing. Bad code in the middle __alloc_bootmem_core() is
spilling a variable in the frame, but the computed FP displacement
is off by 4 and it's trashing the first register saved on the stack
by the epilogue.

I was pretty sure the prologue and epilogue computed the frame size
correctly. After some more investigation, I discovered that
m68k_initial_frame_pointer_offset() was never being called because
m68k.h defines ELIMINABLE_REGS.

If I'm not mistaken, in your GCC 3.2.3 patches you made the m68k
backend use m68k_initial_elimination_offset() the same way the
i386 backend does.

This function is getting correct offsets for fetching arguments
from the stack, but accesses to store locals in the frame are all
off by 4 bytes.

I concluded that the function gets always called with
from = ARG_POINTER_REGNUM, to = STACK_POINTER_REGNUM,
therfore there's no way to make ad-hoc corrections.

I can't understand how the reload pass could figure out
how to access both function arguments and locals without
knowledge of the real function frame layout.

Perhaps this is relevant: but the variable overwriting
the register was previously stored in %fp.

Here's a code snippet helps illustrating the problem:

---------------------------------------------------------------------

__alloc_bootmem_core:
#PROLOGUE: fsize = 16
#PROLOGUE: num_saved_regs = 11
#PROLOGUE: fsize_with_regs = 60
#PROLOGUE: elimination_offset = 56
#PUSH:  60 (lea, !frame_pointer_needed, fsize_with_regs > 8)
        lea (-60,%sp),%sp
        movm.l #0x7cfc,(%sp)	; (a2-a6/d2-d7)
        move.l 64(%sp),%d7	; argument 1 at 64(sp)
        move.l 76(%sp),%d3	; argumen  4 at 76(sp)
        tst.l 68(%sp)		; argument 2 at 68(sp)

        [....]

        move.l 72(%sp),%d0	; argument 3 at 72(sp)
        moveq.l #12,%d2
        lsr.l %d2,%d0
        move.l %d0,%a6		; a6 (fp) holds a computed value

        [...]

        move.l %a6,%d0
        neg.l %d0
        move.l %d0,40(%sp)	; trashes old a6 saved by movem!!

	[...]

#EPILOGUE: nregs = 11
#EPILOGUE: fsize = 16
#EPILOGUE: offset = 44
#EPILOGUE: offset+fsize = 60
#EPILOGUE: restore_from_sp = 1
#POP: (restore_from_sp)
        movm.l (%sp),#0x7cfc
#POP: lea (60,sp),sp (fsize < 0x8000)
        lea (60,%sp),%sp
        rts

---------------------------------------------------------------------

Please note that the frame area for local variables should extend
from -44(sp) to to -56(sp), but no place in the function ever
writes to -56(sp).

-- 
  // Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/  http://www.develer.com/

Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]