[TUHS] PDP-11 MARK (was: Early Unix function calls: expensive?)

Johnny Billquist bqt at update.uu.se
Wed Jan 6 06:35:47 AEST 2016


On 2016-01-05 18:43, Ronald Natalie<ron at ronnatalie.com> wrote:
>
> Just never figured out how to make good use of the MARK instruction on the PDP-11.

Not surprising. As others noted, few ever did. And apparently none 
responding actually do either.

It *is* a stupid instruction in many ways. And it's not for multiple 
returns either.

It's an odd way of handling stack cleanup without a frame pointer.

It's extremely bad, since it actually requires the stack to be in 
instruction space. And yes, you are expected to execute on the stack.

The idea is that the caller pushes arguments on the stack, but the 
cleanup of the stack is implicitly done in the subroutine itself, and at 
the same time you get an argument pointer.

Example:

Calling:

     MOV R5,-(SP)       ; Save old R5
     MOV <argn>,-(SP)
     MOV <argn-1>,-(SP)
     .
     MOV <arg1>,-(SP)
     MOV #MARKN,-(SP)   ; Where the N in MARK N is the number of 
arguments you just pushed.
     MOV SP,R5
     JSR PC,SUB
     .
     .

In the subroutine you then have the arguments available relative to R5. 
So that arg1 is available at 2(R5) for example.

SUB: .
      .
      .
      RTS  R5


There is a lot going on at this point. The trick is to note that the 
code does an RTS R5 to return. If people remember what happens at that 
point, PC gets loaded with R5, while R5 gets loaded with the PC that we 
actually would like to return to (since that's what is at the top of the 
stack).
And R5 is pointing into the stack, at the MARK instruction, so execution 
continues with actually performing the MARK.
MARK, in turn, will case SP <- PC + 2*N, thus restoring the stack 
pointer to point to the place where the original R5 was stored.
Next, it does a PC <- R5, so that we now have the PC point to where we 
actually want to return.
Next it does a R5 <- (SP)+, meaning we actually restored the original R5.

And so we have cleaned up the stack, preserved R5, and returned to the 
caller again.

Also notice that the subroutine could have pushed any amount of data on 
the stack before the return, and I suspect the idea was that the process 
would not have needed to clean that up either. However, that fails, 
since the RTS needs the return address at the top. But you can 
essentially solve that by pushing -2(R5) before returning.

Ugly, isn't it? :-)

	Johnny




More information about the TUHS mailing list