public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Backend Stack-/Framepointer
@ 2006-01-15 11:27 Frank Riese
  2006-01-15 18:38 ` Ian Lance Taylor
  0 siblings, 1 reply; 3+ messages in thread
From: Frank Riese @ 2006-01-15 11:27 UTC (permalink / raw)
  To: gcc-help

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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Backend Stack-/Framepointer
  2006-01-15 11:27 Backend Stack-/Framepointer Frank Riese
@ 2006-01-15 18:38 ` Ian Lance Taylor
  0 siblings, 0 replies; 3+ messages in thread
From: Ian Lance Taylor @ 2006-01-15 18:38 UTC (permalink / raw)
  To: Frank Riese; +Cc: gcc-help

Frank Riese <hippo@informatik.uni-bremen.de> writes:

This question is more appropriate for gcc@gcc.gnu.org than for
gcc-help.

> 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. 

gcc needs general access to some sort of stack frame.  It can't work
on a machine which doesn't provide that.

> 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.

Using a different register as the stack pointer is the way to go.
Don't get tied up with the fact that RET doesn't use that stack.  Just
use two stacks: one for the call sequence, and one for stack frame
used for local variables.

The main drawback is that it will be rather difficult to implement
setjmp/longjmp, and unwinding the stack for exceptions.  Those are
going to be very difficult to implement on your processor now matter
how you do it, since they require the ability to set the stack pointer
to an arbitrary position higher on the call stack.

Ian

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Backend Stack-/Framepointer
@ 2006-01-15 11:23 Frank Riese
  0 siblings, 0 replies; 3+ messages in thread
From: Frank Riese @ 2006-01-15 11:23 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 4190 bytes --]

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

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-01-15 18:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-15 11:27 Backend Stack-/Framepointer Frank Riese
2006-01-15 18:38 ` Ian Lance Taylor
  -- strict thread matches above, loose matches on Subject: below --
2006-01-15 11:23 Frank Riese

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).