Some notes on the CADR "principles of operation"
Brad Parker
10/17/04
brad@heeltoe.com
Notes on (my) confusion or discrepancies in MIT AI Memo 528

While writing a CADR emulator I ran into some issues and/or discrepancies in the available documentation. I've tried to list them here.

[These are my conclusions; If you read them and disagree, please send me email and set me straight. I do not have a functional hardware description (i.e. verilog) yet, so some things are assuptions based on quick scans of the schematics]

First, let me quote from "lmdocs: popj.2", a document which I found illuminating.

POPJ-AFTER-NEXT in combination with JUMP and DISPATCH			[CONTRL]

Dispatch	R	P	N	PC	SPC	NOP
		0	0	0	jump	pop	no
		0	0	1	jump	pop	yes
		0	1	0	jump	push	no
		0	1	1	jump	push	yes
		1	0	0	popj	pop	no
		1	0	1	popj	pop	yes
		1	1	0	popj	pop	no
		1	1	1	popj	pop	yes

Jump		R	P	N	PC	SPC	NOP
(cond		0	0	0	jump	pop	no
 satisfied)	0	0	1	jump	pop	yes
		0	1	0	jump	push	no
		0	1	1	jump	push	yes
		1	0	0	popj	pop	no
		1	0	1	popj	pop	yes
		1	1	0	iwrite
		1	1	1	iwrite

Jump with condition not satisfied is similar to ALU and BYTE instructions.

Possible mods to increase usefulness:
A dispatch-call or jump-call in combination with popj-after-next
should neither popj nor pushj but just jump.  If it's xct-next
the right thing happens.  If the next instruction is inhibited, well
that's OK.  However, if the next instruction is not inhibited,
and it's a CALL, normally (without the previous call) would be
like tail recursive, but here will end up with two return addresses
on pdl, however, the top one is the address of the place called
in the first instruction and the one under that is the original
return so that's right too.

Dispatch example - POPJ+DISPATCH, enumerating cases
001 LABEL	(CHECK-PAGE-READ)
002	(POPJ-AFTER-NEXT DISPATCH TRANSPORT READ-MEMORY-DATA) ;FOLLOW ALL INVZ
003       ((M-T) Q-TYPED-POINTER READ-MEMORY-DATA)	;RETURN C(E) IN M-T
004
005

dispatch yields N=0,P=0,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   new pc<- dispatch address
   (disable popj)
- exec alu                              fetch new pc (dispatch address)

dispatch yields N=0,P=0,R=1

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   new pc <- spc[spc-ptr--]
   (disable popj)
- exec alu                              fetch new pc (from stack)

dispatch yields N=0,P=1,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   spc[++spc-ptr] <- 004
   new pc <- dispatch address
   (disable popj)
- exec alu                              fetch new pc (dispatch address)

dispatch yields N=0,P=1,R=1

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   ignore dispatch, do popj
   new pc <- spc[spc-ptr--]
   if pc14, advance-lc
- exec alu                              fetch new pc

dispatch yields N=1,P=0,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   new pc<- dispatch address
   (disable popj)
- (nop - pipe flush)                    fetch new pc

dispatch yields N=1,P=0,R=1

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   new pc <- spc[spc-ptr--]
   if pc14, advance-lc
   (disable popj)
- (nop - pipe flush)                    fetch new pc

dispatch yields N=1,P=1,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/alu
   spc[++spc-ptr] <- 005
   new pc <- dispatch address
   (disable popj)
- exec alu                              fetch new pc

Another Dispatch example - POPJ+DISPATCH with CALL, enumerating cases

001 LABEL	(CHECK-PAGE-READ)
002	(POPJ-AFTER-NEXT DISPATCH TRANSPORT READ-MEMORY-DATA) ;FOLLOW ALL INVZ
003    	(CALL-XCT-NEXT FUNC)
004
005

dispatch yields N=0,P=0,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   new pc<- dispatch address
   (disable popj)
- exec call                             fetch new pc (dispatch address)
   spc[++spc-ptr] <- new pc+1
   new pc<- call address
- exec 1st inst @ dispatch address	fetch call address
- exec 1st inst @ call address

[help! I'm confused here. I don't think the action above is correct.  When the call returns
it will return to new pc + 1...]

dispatch yields N=0,P=0,R=1

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   new pc <- spc[spc-ptr--]
   (disable popj)
- exec call                             fetch new pc (from stack)
   spc[++spc-ptr] <- new pc+1
   new pc<- call address
- exec 1st inst @ new pc		fetch call address
- exec 1st inst @ call address

[again; I don't think the action above is correct.  When the call returns it will
return to new pc + 1...]

dispatch yields N=0,P=1,R=0a

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   spc[++spc-ptr] <- 004
   new pc <- dispatch address
   (disable popj)
- exec call                             fetch new pc (dispatch address)
   spc[++spc-ptr] <- new pc+1
   new pc<- call address
- exec 1st inst @ dispatch address	fetch call address
- exec 1st inst @ call address

dispatch yields N=0,P=1,R=1

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   ignore dispatch, do popj
   new pc <- spc[spc-ptr--]
   if pc14, advance-lc
- exec call                             fetch new pc (from stack)
   spc[++spc-ptr] <- new pc+1
   new pc<- call address
- exec 1st inst @ new pc		fetch call address
- exec 1st inst @ call address

dispatch yields N=1,P=0,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   new pc<- dispatch address
   (disable popj)
- (nop - pipe flush)                    fetch new pc (dispatch address)
- exec 1st inst @ new pc		fetch new pc+1

dispatch yields N=1,P=0,R=1

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   new pc <- spc[spc-ptr--]
   if pc14, advance-lc
   (disable popj)
- (nop - pipe flush)                    fetch new pc (from stack)
- exec 1st inst @ new pc		fetch new pc+1

dispatch yields N=1,P=1,R=0

- exec check-page-read jump		fetch 002/popj
- exec popj + dispatch			fetch 003/call
   spc[++spc-ptr] <- 005
   new pc <- dispatch address
   (disable popj)
- exec call                             fetch new pc (dispatch address)
   spc[++spc-ptr] <- dispatch address+1
   new pc<- call address
- exec 1st inst @ new pc		fetch call address
- exec 1st inst @ call address


Another Dispatch example - with CALL, enumerating cases

001	(NOP)
002	(DISPATCH TRANSPORT READ-MEMORY-DATA) ;FOLLOW ALL INVZ
003    	(CALL FUNC)
004
005

dispatch yields N=0,P=0,R=0

- exec check-page-read jump		fetch 002/dispatch
- exec dispatch				fetch 003/call
   new pc <- dispatch address
- exec call w/n-bit			fetch new pc (dispatch address)
   spc[++spc-ptr] <- new pc+1
   new pc<- call address
- (nop - pipe flush)			fetch call address
- exec 1nd inst @ call address

The call pushes the dispatch address + 1 and the pipe stalls because
the call has the N bit set, followed by the 1st instruction at the
call address.