; IfsXMOps.mu
; Copyright Xerox Corporation 1979, 1980

; Last modified by Taft, February 26, 1980  5:46 PM
; - Add XMLoad, XMStore
; Last modified by Butterfield, September 7, 1979  11:24 AM
; - return to XBcplUtil's Start3 - 8/17/79

; Extended memory operations:
;	63400-63417	DoubleBlt (see below)
;	63420		XMLoad:   AC0 ← @AC1 in bank AC0
;	63421		XMStore:  (@AC1 in bank AC0) ← AC3

; These operations all save and restore the emulator's bank register.
; As written, this microcode can be executed only on an XM Alto; however,
; for a non-XM Alto, system initialization turns all the XMAR←s into
; MAR←s, so in fact the microcode can be executed on a non-XM Alto also
; (but of course it can operate only on bank 0).
; Additionally, DoubleBlt can only be executed on an Alto-II since
; it does double-word stores.

!1, 2, XLoadStore, DoubleBlt;
!1, 2, DBLoop, XMOpsExit;

XMOps:	MAR← 177740;			Read bank register for task 0
	L← MD;
	MAR← 177740;			Set bank register for task 0
	SINK← DISP, SINK← lgm20, BUS=0;	What operation?
	XREG← L, TASK, :XLoadStore;	[XLoadStore, DoubleBlt] Save old value

; Common exit sequence to restore the bank register and finish
	MAR← 177740;			Restore bank register for task 0
	MD← XREG, :Start3;		Return to Emulator
; Double-word block transfer, possibly using Extended Memory
;	AC0: first destination address (must be even)
;	AC1: first source address (must be even)
;	AC3: number of double-words to transfer
;	DISP[12-13]: destination bank number
;	DISP[14-15]: source bank number
; Timing: 14 cycles (2.38 microseconds) per double-word.
;	= 305 microseconds for 256 words
;	= 1.22 milliseconds for 1024 words

!1, 2, DBMayI, DBNoI;
!1, 2, DBInt, DBDisI;

	MD← DISP;			Set normal bank from bits 12-13,
;					Alternate bank from bits 14-15

; Main loop of double-word transfer
DBLoop:	XMAR← T← AC1;			Reference source address
	L← NWW, BUS=0;			Test for interrupts
	L← 2+T, SH<0, :DBMayI;		[DBMayI, DBNoI] Increment source by 2
DBNoI:	AC1← L;				Update source address
DBDisI:	L← MD;				L← First data word
	T← MD;				T← Second data word
	MTEMP← L, L← T;			MTEMP← first, L← second
	MAR← T← AC0;			Reference destination address
	T← ONE+T+1;			Increment destination by 2
	MD← MTEMP;			Store first data word
	MD← M;				Store second data word
	L← AC3-1;			Decrement and test double-word count
	AC3← L, L← T, SH=0, TASK;
	AC0← L, :DBLoop;		[DBLoop, XMOpsExit] Update dest adr

; Here if possible interrupt (SH<0 branch pending)
DBMayI:	AC1← L, L← T, :DBInt;		[DBInt, DBDisI]

; Here if interrupt definitely pending
DBInt:	AC1← L;				Restore old source address
	L← PC-1, TASK;			Back up PC
	PC← L, :XMOpsExit;

; Extended memory load/store
;	XMLoad:   AC0 ← @AC1 in bank AC0
;	XMStore:  (@AC1 in bank AC0) ← AC3

!1, 2, XLoad, XStore;

	MD← AC0;			Alternate bank from AC0[14:15]

	XMAR← AC1;			Start the reference
	SINK← DISP, BUSODD;		Which operation?
	:XLoad;				[XLoad, XStore]

XLoad:	L← MD;				Complete the load
	AC0← L, :XMOpsExit;

XStore:	MD← AC3, :XMOpsExit;		Complete the store