The PDP-11 MARK instruction

leichterj at rani.DEC leichterj at rani.DEC
Thu Feb 28 12:37:07 AEST 1985


Gary Ansok writes:

	Newsgroups: net.unix-wizards
	Path: decwrl!decvax!genrad!panda!talcott!harvard!seismo!brl-tgr
		!tgr!geacc022%timevx at lbl.arpa
	Subject: Curiosity
	Posted: Fri Feb 22 17:53:17 1985


	All right, you guys!  I've been watching this conversation fly by for
	some weeks now, and I have one burning question to ask:

	What the #%$@ does the MARK instruction do??!?

			Gary Ansok
			GEACC022%TIMEVX%CITHEX @ LBL-G.ARPA
			GEA @ CALTECH.BITNET
			...ucbvax!cithep!timevx#geacc022

	"All the world loves a straight man."

"You want this knowledge?  How much you pay for this knowledge?"  (Where IS 
that from?)

Here is the formal definition of MARK, as given in the (1979-80 edition of)
the PDP-11 Processor Handbook:

	MARK; opcode 0064NN.
	
		SP <- PC + 2*NN
		PC <- R5
		R5 <- (SP)+
		Condition codes:  Unaffected

		NN is the number of parameters.  [Really, locals.]

	Used as part of the standard PDP-11 subroutine return convention.
	MARK facilitates the stack cleanup procedures involved in subroutine
	exit.

It's been a while; let me see if I can make some sense of this.

First off, PC is the program counter, SP is the stack pointer, R5 is just
register 5, which will be used as a linkage register.  Stacks grow down-
ward in memory; MOV <something>,-(SP) is a PUSH; MOV (SP)+,<something> is
a POP.

To understand how MARK might be used, you have to first off realize that
it is meant to be executed off the stack!  The first instruction shows
this:  SP is set to PC plus something, so PC better have SOMETHING to do
with the stack.  In fact, the way you use MARK is as follows:

	JSR	R5,SUB		;Call subroutine with R5 as the linkage
				;register:  (R5) is where to return to, old
				;value of R5 is on the top of the stack.
	...
SUB:				;The subroutine
	SUB	#2*NN,SP	;Claim NN words (2*NN bytes) of stack space
				;for locals
	MOV	(PC)+,-(SP)	;Push next word onto stack
	   MARK	NN

	(execute subroutine; locals are 2(SP),4(SP), to 2*NN(SP).  Args,
		if pushed before the JSR, are at 2*NN+4(SP), 2*NN+6(SP),
		etc. - 2*NN+2(SP) contains the saved R5 value.)

	JMP	(SP)		;Return by executing the MARK instruction
				;on the stack.

Note what the MARK instruction does:

	SP<-PC+2*NN		;Cancel the words claimed for locals, plus
				;the MARK itself (since the value of PC used
				;is that AFTER the increment over the MARK.)
				;SP is now where the JSR left it.
	PC<-R5			;Restore PC from the linkage register, where
				;the JSR put it.
	R5<-(SP)+		;Restore the linkage register value saved by
				;the JSR.

Simple, no?  (Right.)

The real problem with MARK was two-fold:

	a)  It implemented a convention that was ALMOST what people wanted
		to use, but usually not exactly right; and it didn't gain
		much in performance over doing it yourself anyway.  Besides,
		MARK wasn't available on most PDP-11's, and it's a little
		tough to build portable code around a non-portable calling
		convention.
	b)  MARK HAD to execute off the stack to work.  However, this was
		inherently impossible in a system running with an I/D space
		split.

In general, the PDP-11 has a fairly tight set of op codes; just about every-
thing was useful, and actually got used.  The MARK was a glaring exception.
(The Commercial Instruction Set extensions also never caught on in any big
way, mainly because they came along too late.)

It's amusing to look for analogous things in other architectures.  Some
Interdata machine - probably the 6/32 - had a large set of op codes to
transfer from user state to system state, with all sorts of variations on
how arguments were passed, and so on.  (This is second hand; I'd give
more details if I knew them.)  In fact, only one of the variations was
ever used.
							-- Jerry



More information about the Comp.unix.wizards mailing list