INITIAL_ELIMINATION_OFFSET() in m68k backend

Bernardo Innocenti bernie@develer.com
Mon Jul 14 09:01:00 GMT 2003


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




More information about the Gcc mailing list