|[14 earlier articles]|
|Re: When/why did function calls get cheap? email@example.com (Peter Finderup Lund) (2003-03-09)|
|Re: When/why did function calls get cheap? firstname.lastname@example.org (Joachim Durchholz) (2003-03-09)|
|Re: When/why did function calls get cheap? email@example.com (Andreas Klimas) (2003-03-09)|
|Re: When/why did function calls get cheap? firstname.lastname@example.org (2003-03-14)|
|Re: When/why did function calls get cheap? email@example.com (Jack Crenshaw) (2003-03-14)|
|Re: When/why did function calls get cheap? firstname.lastname@example.org (David Thompson) (2003-03-22)|
|Re: When/why did function calls get cheap? email@example.com (Alex McDonald) (2003-03-22)|
|Re: When/why did function calls get cheap? firstname.lastname@example.org (Terrence Enger) (2003-03-23)|
|Re: When/why did function calls get cheap? email@example.com (Glen Herrmannsfeldt) (2003-03-24)|
|From:||"Alex McDonald" <firstname.lastname@example.org>|
|Date:||22 Mar 2003 17:02:19 -0500|
|References:||03-02-073 03-03-087 03-03-119|
|Posted-Date:||22 Mar 2003 17:02:19 EST|
"David Thompson" <email@example.com> wrote
> Jack Crenshaw <firstname.lastname@example.org> wrote (bottom-quoting fixed):
> > Peter Seibel wrote:
> > The old IBM mainframes didn't have a stack pointer or other hardware
> > to support a call stack. They used register 14, as I recall, as a
> > dedicated register pointing to the return address. Sort of a
> > one-level stack. If your subroutine called another subroutine, it had
> > to save off register 14 in memory first, then restore it after
> > returning from the next level down.
> R14 was used for return address, and R15 often callee address
> (and default savearea) by convention, but not set in hardware.
> And it was usual for callee to save caller registers, including R14,
> at entry and restore before exit, using SToreMultiple and LoadMultiple.
Register 13 is used as a save area (normally pointed to at least a 18 32bit
word area) and is provided by the caller. Register 15 is used as both entry
point and return code, and register 14 is used as the return address. R1 is
the parameter pointer. Typical entry & exit code:
EP EQU *
STM R14,R12,12(R13) store reg12 thru 14 12 bytes up savearea provided
LR R12,R15 r12 is my EP
USING R12, EP
ST R13,4(R14) complete doubly...
ST R14,8(R13) ...linked list
LA R13,SAVEAREA save area for anyone I call
... use any regs except r12 and r13
SR R15,R15 return code
L R13,4(R13) unlink save area
LM R0,R12,20(R13) restore regs
BR R14 back to caller
Register 13 is normally maintained pointing to the save area (it
simplifies dump reading). So each save area is a doubly linked list --
essential for tracking back and forth through calls.
I'd say this is essentially a doubly linked-list LIFO stack, but with
72 byte entries... We didn't think of it as a stack, but I suppose
that's what it was.
The S360 architecure had a maximum 4K immediate offset from a register, so
large code sections were possible but difficult to manage. "Rebasing" by
calling was very common, resulting in large numbers of subroutine calls in
fairly short sections of code. So common coding techniques inside your own
code (certainly when I was writing this stuff in the mid to late 70s) was to
have a large area as a call stack, with the first word (or a register)
pointing to the next save address (top of stack?), and only "pushing"
registers that you needed to "pop" off later.
There ain't nuthin' new under the sun...
[That's still the calling sequence, although in recent years IBM has added
a whole lot of extra stuff to support recursive calls (beyond the hacks
they wrote for PL/I in the 1960s), interlanguage calls, and DLL libraries.
Return to the
Search the comp.compilers archives again.