This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
INITIAL_ELIMINATION_OFFSET() in m68k backend
- From: Bernardo Innocenti <bernie at develer dot com>
- To: Peter Barada <pbarada at mail dot wm dot sps dot mot dot com>
- Cc: gcc at gcc dot gnu dot org,uClinux development list <uclinux-dev at uclinux dot org>,Paul Dale <pauli at moreton dot com dot au>
- Date: Mon, 14 Jul 2003 07:38:25 +0200
- Subject: INITIAL_ELIMINATION_OFFSET() in m68k backend
- Organization: Develer S.r.l.
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