[net.sources] PDP-11 stack use

jfw (01/15/83)

A long time ago, I wanted to write a better setjump/longjump system.
This involved finding out what the C stack frame looks like.  After 3
days of poking through cc -S output, I determined the stack frame for the
PDP-11 and, not desiring to ever go through that work again, came up
with the following manual page for the stack frame:

**************** /usr/man/unix/chap5/stack.5 ****************

.nr LL 6.5
.TH STACK 5 PDP-11
.SH NAME
stack, C subroutine discipline
.SH DESCRIPTION
A C subroutine stack frame looks like the following:
.nf
.in +5
.ta 8 16 24 32 40 48 56 64

------------------
|...nth argument |		push arguments in reverse order
------------------
|second argument |
------------------
| first argument |
------------------		JSR PC,*$_FOO
| return address |
------------------		JSR R5,CSV
|  old R5 value  | <----- 
------------------	|
|	r4	 |	|
------------------	|
|	r3	 |	|
------------------	|
|	r2	 |	|
------------------	|
|   blank word	 |	|
------------------	| This is the top of the stack
|     routine	 |	| when the called routine "starts"
|    allocates	 |	|
|     storage	 |	|	SUB $n,SP
|    temporary	 |	|
------------------	|
| push arguments |	|
| of next routine|	|
------------------	|	JSR PC,*$_BAR
| return address |	|
------------------	|	JSR R5,CSV
| old R5 value---+-------
------------------	^
| r4/43/r2/...	 |	|
------------------
| and so on..... |

.fi
.in -5
Functions leave their return value in R0 (floating functions return it in FR0).
"long" functions leave return values in R1/R0; functions returning structures
leave a pointer to bss storage (one chunk of which is allocated for each such
routine) in R0, and the caller will copy from that bss storage to the
local destination.

Local variables are allocated in such a way that they are referred to
as "-N(R5)", arguments are referred to as "+N(R5)"; arguments start at 4(R5),
the first integer local declared will be at -10[8](R5).

It is important to note that routines know how many arguments they pass to a
function, and will adjust the stack accordingly after a function returns.

.SH AUTHOR
John F. Woods, MIT Concouse Computer Center

ka (01/17/83)

One corrections to John's article:  there is no blank word above the space
for local variables.  There IS a blank word below this if the routine con-
tains function calls with arguments; this is used to save the last function
argument to decrease the number of pushes and pops done on the stack pointer.
					Kenneth Almquist

jfw (01/18/83)

Could someone mail me a copy of what went out on the net for my PDP-11 stack
use manual page?  Ken Almquist's comment sounds like the older version of my
document, which I first submitted in a fit of narcolepsy.  I thought I editted
the version in /usr/spool/news, but uucp might have (for once) promptly logged
in and spirited it off before I noticed.  Sigh.
	John Woods

dmmartindale (01/18/83)

Note that the "blank word" in the PDP11 stack layout is always BELOW the
local variables, not between them and the saved registers.  One word of
space is reserved by csv, but if the routine has any local variables
one of these will use this word, and the stack address below all of the
locals becomes the "blank word".  Thus, unless an arithmetic temporary has
been stored on the stack, (sp) is always a free word, and so when calling
another routine, the last argument can be stuffed directly rather than using
auto-decrement addressing.  This saves a tiny bit of time, but the real
saving comes when adjusting the stack after that routine's return.  If you
passed only one word of arguments, no adjustment is necessary, if there
were two arguments you can use a tst (sp)+ instead of a cmp (sp)+,(sp)+, and
for three arguments you can use cmp instead of add.  Since an awful lot
of subroutine calls will have 1, 2, or 3 arguments this saving is worthwhile.