Trailing-Edge - PDP-10 Archives - klu2_442 - blt.mic
There are 5 other files named blt.mic in the archive. Click here to see a list.
.TOC	"BLT - Neatly Optimized"
;									;
;	This implementation of BLT is a complete rewrite of the		;
;	instruction.  BLT has been substantially optimized by splitting	;
;	the copy loops into three separate loops:  one for PXCT (which	;
;	supports only in section copying, and is clean only in section	;
;	zero or one), one for spraying a single word through a block	;
;	of memory, and one for all other cases (usually normal block	;
;	copies).  In all of these cases we attempt to keep the Mbox	;
;	busy as much as possible by starting each load on the same	;
;	microinstruction that completes the previous store, thus	;
;	eliminating a fair amount of Mbox dead time.  (Stores cannot	;
;	be similarly overlapped, due to the need to wait for the 	;
;	parity check on each load.)  We also avoid the overhead of	;
;	needless state register switching in the non PXCT cases.	;
;									;
;	This code gives up on the backwards BLT idea entirely, since	;
;	that broke many useful programs.				;
;									;
;						--QQSV			;
;									;

251:	EA,		J/BLT		;BLT--adjoins EXCH

311:					;[440] Near EXCH
BLT:	BR/AR,ARL_ARL,ARR_AC0,ARX/AD	;Generate initial dest address
=0	BRX/ARX,MQ_AR,AR_AR-BR,ARX/AD,	;MQ_current dest address.  Get copy
	    SC_#,#/18.,CALL [REPLIC]	; count-1; set up for source grab
	BR/AR,AR_SHIFT,ARX_ARX+1 (AD),	;Get source address half, and
	    GEN CRY18,SR_BLT(AC)	; bump both AC halves
	AR_ARX-BR,GEN CRY18,ARX_AR	;Finish AC; keep initial source
	AC0_AR,ARL_MQL,ARR_ARX		;Set AC; gen complete source addr
	BR/AR,SKP P!S XCT		;MQ_source addr; test PXCT
;	We are now just about set up.  BR will contain the current source
;	address; MQ will contain the current destination address.  ARX will
;	have -(count-1) of words remaining to be copied; it is incremented
;	each time a word is copied.  Thus, the copy terminates one word
;	AFTER ARX becomes positive (this makes sure that we always copy at
;	least one word).  BRX will contain a copy of ARX that is used only
;	if the instruction must quit prematurely; it is updated each time
;	a store completes.
;	Now figure out which loop to use.  If the destination address -
;	the source address = 1, we are spraying a word through memory.
=00	GEN BR,LOAD VMA(EA),ARX_BRX,	;Not PXCT. Read the first word
	AR_MQ-1,SR_BLT(PXCT SRC),J/BLTPX;PXCT. Back up dest vma, set up SR
	GEN MQ-BR-1,SKP AD NZ		;Got word. Are we spraying memory?
=0	GEN MQ,STORE VMA(EA),J/SPRAY	;Yes. Start first store
	GEN MQ,STORE VMA(EA),SKP AC REF	;No. Test for AC reference
=0	SKP AC REF,J/BLTLOD		;Load from memory. Test store
	ARX_ARX+1,SIGNS DISP,TIME/3T,	;Load from ACs. Leave SR alone and
	    J/BLTLUP			; test for completion
BLTLOD:	SR_BLT,ARX_ARX+1,SIGNS DISP,	;All references are to memory. Allow
	    TIME/3T,J/BLTLUP		; shadow AC reference. Test if done
XBLTGO:	ARX_ARX+1,SIGNS DISP,TIME/3T,	;Store to ACs. Leave SR alone. Test
	    J/BLTLUP			; completion
;	REPLIC--Subroutine to swap the ARX and the BRX, and to replicate
;	ARR in ARL.  It just happened to be useful.  Return 1.
	    RETURN [1]
;	The main copy loop.  The cache is as overlapped with the Ebox
;	as possible.  (Recall that we cannot immediately store data fresh
;	from memory; the AR_MEM forces an extra cycle of delay for parity
;	checking.)  The SR has been used to set up the proper VMA context
;	for shadow AC reference, so we can use the same loop even if ACs
;	are involved.
BLSTOR:	MQ_MQ+1,VMA/AD,STORE,ARX_ARX+1,	;Increment dest VMA and count,
	    SIGNS DISP,TIME/3T		; start store. Are we done?
BLTLUP:	FIN STORE,I FETCH,J/NOP		;Count expired. All done
	FIN STORE,BRX/ARX,AR_BR+1,	;More to do. Increment source VMA,
	    VMA/AD,LOAD AR,SKP INTRPT	; start the fetch, and test int
=0	BR/AR,AR_MEM,J/BLSTOR		;No int. Wait for load and loop
	AR_MEM,SR DISP,J/CLEAN		;Interrupted. Freeze BLT or XBLT
;	If we are spraying memory, we can use VMA_VMA+1 which preserves
;	globality.  Thus it does not matter whether ACs are in use here.
;	Indeed, once it gets started, PXCT can use this loop too.
SPRAY:	ARX_ARX+1,SIGNS DISP,TIME/3T	;Copying only one word?
SPRAYL:	FIN STORE,I FETCH,J/NOP		;Could be. Spray done
	SKP INTRPT			;More to do. Test interrupt
=0	FIN STORE,BRX/ARX,VMA_VMA+1,	;No interrupt. Proceed to next
	    STORE,ARX_ARX+1,SIGNS DISP,	; store, increment count, and
	    TIME/3T,J/SPRAYL		; test completion
	MEM_AR,BRX/ARX,SR DISP,J/CLEAN	;Interrupted. Freeze and clean up
;	Finally, the PXCT case.  We will optimize spraying memory (at
;	this writing, TOPS-10 still uses BLT to do that in some cases).
;	Note that this can be used only for copying within a section
;	(usually zero).  The state register must be swapped at each
;	operation (unless we are spraying memory) to activate the proper
;	PXCT bits.  SR bit 0 is off in order to force AC context.
BLTPX:	MQ_AR,VMA_BR,LOAD AR,ARX_BRX,	;Set up dest addr and count, do
	    SR_BLT(PXCT DST),CALL [XFERW];first load, and shuffle SR
	GEN MQ-BR,SKP AD NZ		;Is this a single word spray?
=0	VMA_MQ+1,STORE,ARX_ARX+1,	;Yes. Store first word here
	    SIGNS DISP,TIME/3T,J/SPRAYL	; and use standard loop
PXPUT:	MQ_MQ+1,VMA/AD,STORE,ARX_ARX+1,	;Bump dest VMA and count, start
	    SIGNS DISP,TIME/3T		; store, and test completion
=0111	FIN STORE,I FETCH,J/NOP		;All done. Blow out of here
	SR_BLT(PXCT SRC)		;More to do. Do the SR shuffle
	FIN STORE,BRX/ARX,AR_BR+1,	;Terminate store, freeze count, tick
	    INH CRY18,VMA/AD,LOAD AR,	; source VMA, start load,
	    SKP INTRPT			; and test for interrupt
=0	BR/AR,AR_MEM,SR_BLT(PXCT DST),	;No interrupt. Wait for load and
	    J/PXPUT			; swap state register
	AR_MEM,J/BLTFIX			;Interrupt. Common fixup code
;	If we get a page fault or an interrupt in the middle of this we
;	end up here.  The BRX keeps an accurate count of the actual
;	transfers complete.  We must subtract one from it, and add the
;	result to both halves of AC0.  ARX is set to -1 on the way in.
BLTPGF:	AR_ARX+BRX,CALL [REPLIC]	;Set up both halves of AR
	AR_AR+FM[AC0],INH CRY18,J/PGFAC0;Update AC0, then fault or int
.TOC	"XBLT--Also Neatly Modernized"
;									;
;	This XBLT rewrite makes use of what we learned when we up-	;
;	graded BLT--indeed, it shares code in a couple of cases.	;
;	Once again, we split this into separate loops, depending	;
;	upon the copy circumstances.  If we are copying forward (the	;
;	most common case), we distinguish the core clearing case, the	;
;	normal copy, and PXCT that does not clear core, using the BLT	;
;	code for the first two cases.  If we are copying backward, we	;
;	do not attempt to optimize clearing core, and there is no need	;
;	for a separate PXCT loop.  As a result, we have only one loop	;
;	for that case.							;
;									;

;	The dispatch for this instruction has been rewritten so that
;	EXTEND special cases op code 20.  As a result, we no longer
;	need special DRAM for this instruction.  We get here with
;	ARX_AC0,SKP AD NZ		;Get copy count. Anything to do?
XBLT:	I FETCH,J/NOP			;No. This is easy
	BRX/ARX,AR_AC1			;Yes. Fetch source address
	BR/AR,AR_ARX,ARX_AC2,SR_XBLT(SRC);Save it, grab destination address
	FM[T0]_AR,AR_AR+BR		;Save initial count; gen and save
	AC1_AR,AR_ARX+BRX,MQ_ARX	;final source addr; MQ_dest address
	AC2_AR,AR_0.M,ARX_-BRX		;Save final dest addr
	AC0_AR,ARX_ARX+1,SIGNS DISP,	;Clear final count; set up internal
	    TIME/3T			; count. Going forward or backward?
=0111	ARX_BRX COMP,J/BLBACK		;Backward. Fix internal count first
	BRX/ARX,VMA_BR,LOAD AR,		;Forward. Get first word
	    SR_XBLT(DST)		; and switch SR
	GEN MQ-BR-1,SKP AD NZ		;Are we spraying memory?
=0	AR_MEM,J/XSPRAY			;Yes. Wait; then start spray
	AR_MEM,SKP P!S XCT		;No. Is this PXCT?
=0	VMA_MQ,STORE,STORE,J/XBLTGO	;No. Store first word and loop
	MQ_MQ-1				;Yes. Back up to get correct start
;	The PXCT case.  As with BLT, this requires state register swapping.
XBLPX:	MQ_MQ+1,VMA/AD,STORE,ARX_ARX+1,	;Increment dest pointer, store word
	    SIGNS DISP,TIME/3T		;Are we done yet?
=0111	FIN STORE,I FETCH,J/NOP		;Yes. Leave now
	SR_XBLT(SRC)			;No. Switch state register
	FIN STORE,BRX/ARX,AR_BR+1,	;Terminate store, tick source, and
	    VMA/AD,LOAD AR,SKP INTRPT	; start next load. Interrupted?
=0	BR/AR,AR_MEM,SR_XBLT(DST),	;No. Wait for load and swap SR
	AR_MEM,J/XBLFIX			;Yes. Clean up, then interrupt
;	Spray a word through memory.  Get it started.
XSPRAY:	VMA_MQ,STORE,J/SPRAY		;Start spray properly for XBLT
;	Copy is going backwards.  We must spend a cycle to generate a -1
;	(since there is no way to generate something like AR_BR-1); the
;	extra cycle gives us time to swap the state register.  Thus there
;	is no need for special PXCT code.  We could make a backwards
;	memory spray run faster, but it doesn't seem worth the bother.
;	Note that both source and destination start out at one greater
;	than the actual first address used, so we do not need special
;	startup code.
BACLUP:	MQ_MQ-1,VMA/AD,STORE,		;Decrement destination pointer and
	    SIGNS DISP,TIME/3T		; store word. Are we done?
BLBACK:	MEM_AR,BRX/ARX,ARX_1S,		;More to do. Keep count and set to
	    SR_XBLT(SRC),J/BACKLD	; decrement count and source addr
	FIN STORE, I FETCH,J/NOP	;All done. Get out
BACKLD:	AR_ARX+BR,VMA/AD,LOAD AR,	;Decrement pointer, fetch next word
	    ARX_ARX+BRX,TIME/3T,SKP INTRPT; Decrement count. Interrupted?
=0	BR/AR,AR_MEM,SR_XBLT(DST),J/BACLUP;No. Wait; then loop on
	AR_MEM,J/XBLFIX			;Yes. Clean up before taking it
;	XBLT freeze comes here.  If we have an interrupt, we must restore
;	all three ACs to a usable state.  T0 tells which direction we are
;	going (the restore count must be generated differently for each
;	direction).
;	GEN FM[T0],SKP AD0		;Which way are we copying?
XBLFRZ:	ARX_1S,J/FORSUB			;Forward. Must subtract one
	AR_BRX+1			;Backward. Add one to count
FORFRZ:	BR/AR,ARX_AR,AR_AR+FM[AC1],SR_0	;Keep count. Adjust source addr
	ARX_ARX+FM[AC2]			;Adjust dest addr
	AC1_AR,AR_ARX			;Restore source
	AC2_AR,AR_-BR,J/PGFAC0		;Restore dest and count. Done
FORSUB:	AR_ARX+BRX,J/FORFRZ		;Subtract one and rejoin