This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Backend Stack-/Framepointer
- From: Frank Riese <hippo at informatik dot uni-bremen dot de>
- To: gcc-help at gcc dot gnu dot org
- Date: Sun, 15 Jan 2006 12:27:21 +0000
- Subject: Backend Stack-/Framepointer
Hi,
I'm writing a backend for gcc (gcc 4.0.2) for a target machine that neither
has its stack pointer accessible through any register visible to GCC nor does
it have a seperate frame pointer. The only instructions to access the stack I
have on that machine are PUSH and POP.
I have thought about using one of the general purpose registers to substitute
for the stackpointer as the machine has a simple load/store architecture
where I can LOAD and STORE a word at an address specified in a register and
thus do my own POP and PUSH through LOAD and STORE. However, this seemed a
blind alley because the only way to return from a function on that machine is
through a RET instruction that takes the instruction pointer to return to
from that internal stack.
My Problem is that GCC keeps generating code like this (obtained from gcc -dP)
where it tries to access the stack pointer like a hardware register and
expects a frame pointer:
example function:
int foo (short i) {
i = 100;
return i+50;
}
(insn 3 6 4 (set (reg/f:HI 3 R[3] [15])
(reg/f:HI 6 BP)) 22 {movhi} (nil) <-- frame pointer access
(nil))
(insn 9 4 29 (set (mem/i:HI (reg/f:HI 3 R[3] [15]) [0 i+0 S2 A16])
(const_int 100 [0x64])) 5 {*zykluno.md:37} (nil)
(nil))
(insn 29 9 11 (set (reg:HI 3 R[3] [orig:13 D.1079 ] [13])
(mem/i:HI (reg/f:HI 3 R[3] [15]) [0 i+0 S2 A16])) 22 {movhi} (nil)
(nil))
(insn 11 29 12 (set (reg:HI 3 R[3] [orig:13 D.1079 ] [13])
(plus:HI (reg:HI 3 R[3] [orig:13 D.1079 ] [13])
(const_int 50 [0x32]))) 27 {addhi3} (nil)
(nil))
(insn/f 31 30 32 (set (reg/f:HI 7 SP)
(reg/f:HI 6 BP)) 22 {movhi} (nil)
(nil))
(jump_insn 32 31 33 (return) 7 {return} (nil)
(nil))
If compiled with -fomit-frame-pointer:
(insn 29 6 3 (set (reg/f:HI 3 R[3] [15])
(reg/f:HI 7 SP)) 22 {movhi} (nil) <-- stack pointer access
(nil))
(insn 3 29 4 (set (reg/f:HI 3 R[3] [15])
(plus:HI (reg/f:HI 3 R[3] [15])
(const_int 13 [0xd]))) 27 {addhi3} (nil)
(nil))
(insn 9 4 30 (set (mem/i:HI (reg/f:HI 3 R[3] [15]) [0 i+0 S2 A16])
(const_int 100 [0x64])) 5 {*zykluno.md:37} (nil)
(nil))
(insn 30 9 11 (set (reg:HI 3 R[3] [orig:13 D.1079 ] [13])
(mem/i:HI (reg/f:HI 3 R[3] [15]) [0 i+0 S2 A16])) 22 {movhi} (nil)
(nil))
(insn 11 30 12 (set (reg:HI 3 R[3] [orig:13 D.1079 ] [13])
(plus:HI (reg:HI 3 R[3] [orig:13 D.1079 ] [13])
(const_int 50 [0x32]))) 27 {addhi3} (nil)
(nil))
(jump_insn 32 31 33 (return) 7 {return} (nil)
(nil))
I've tried to eliminate the frame pointer wherever possible by defining the
following in <machine.h>:
#define ELIMINABLE_REGS \
{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
#define CAN_ELIMINATE(FROM, TO) 1
This did not seem to have helped as I still get the unwanted access to the
frame pointer as in the first code above.
Could I be missing instructions in <machine>.md? I have defined the following
instructions but GCC only seems to use PSH:
(define_insn "pushhi1"
[(match_operand:HI 0 "register_operand" "")]
""
"PSH %0"
)
(define_insn "pushsi1"
[(match_operand:SI 0 "general_operand" "")]
""
"PSH %0"
)
(define_insn "pophi1"
[(match_operand:HI 0 "general_operand" "")]
""
"POP %0"
)
(define_insn "popsi1"
[(match_operand:SI 0 "register_operand" "")]
""
"POP %0"
)
I have read most of the documentation about backends under
http://gcc.gnu.org/onlinedocs/gccint/ and had a look at other backend.
However, I haven't been able to come up with any solution yet on how to write
a backend for such a machine.
I would be eternally grateful if someone could provide me with pointers to
resources where I can find out more, to what I've overlooked or has a
solution.
I hope I have posted everything of relevance to my problem. If you need
anything else, please don't hesitate to ask.
Thanks,
Frank