Some notes on the CADR "principles of operation"
Brad Parker 10/17/04 brad@heeltoe.com
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]
;NOTE THAT THE LC HARDWARE IGNORES THE LOW BIT ;AND READS IT BACK AS ZERO IN HALFWORD MODE
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.
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
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
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.