; BFSTestMc.mu -- main microcode source for BFSTest
; Copyright Xerox Corporation 1979
; Last modified September 12, 1979  3:39 AM by Boggs

#AltoConsts23.mu;

!17,20, ExitRam;	force ExitRam to be at location 0

!37,1, TRAP1;

$START		$L4020, 0, 0;	Top of the emulator main loop


; Standard R-registers usable by the emulator task

$AC3		$R0;	Accumulators
$AC2		$R1;
$AC1		$R2;
$AC0		$R3;
$SAD		$R5;	Temporary private to emulator
$PC		$R6;	Program Counter for emulated Nova
$XREG		$R7;	Temporary private to emulator.
;			Contains instruction LCY 8 upon dispatch to TRAP1.
$XH		$R10;	Temporary private to emulator
$MTEMP		$R25;	Temporary usable by any task

$LREG		$R40;	Another name for the M-register

; Trap handler and dispatcher for instructions that trap into
; the RAM.  In the following predefinition, the tags correspond
; to opcodes 60000, 60400, 61000, 61400, ... 77400.
; Note that opcodes 60000, 60400, 61000, 64400, 65000, 67000, and 77400
; cannot be used since control never gets to the RAM for these).

;			61400     62000   62400        63000   63400
!37,40, TrapDispatch,,, GetFrame, Return, BcplUtility, BlkCmp, BlkChk;


; Control comes here with the instruction LCY 8 in XREG
TRAP1:	T←37;
	L←XREG AND T;
TrapDispatch:
	SINK←LREG, BUS, TASK;
	:TrapDispatch;

#GetFrame.mu;
#BcplUtil.mu;


; Block compare routine
;	AC0!0 = first address of buffer 1
;	AC0!1 = first address of buffer 2
;	AC0!2 = number of words to compare
; Returns AC0 = number of non-equal words

!1,2, CmpCont, CmpExit;
!1,2, CmpFail, CmpLoop;

BlkCmp:	MAR←T←AC0;  		get first buffer addr
	NOP;
	L←MD-1;
	SAD←L, MAR←T←0+T+1;	get second buffer addr
	NOP;
	L←MD-1;
	XREG←L, MAR←0+T+1;	get word count
	L←0;
	AC0←L;			initialize error to 0
	L←MD, TASK;
	AC3←L;

CmpLoop: MAR←L←SAD+1;		get word from first buffer
	SAD←L;
	L←AC3-1, BUS=0;
	AC3←L, :CmpCont;	[CmpCont, CmpExit]
CmpCont: T←MD;
	MAR←L←XREG+1;  		get word from second buffer
	XREG←L;
	L←MD XOR T;
	SH=0, TASK;		test for words equal
	:CmpFail;		[CmpFail, CmpLoop]

CmpFail: L←AC0+1, TASK;		count error
	AC0←L, :CmpLoop;

CmpExit::ExitRam;

ExitRam:SWMODE;
	:START;

; Block check routine
;	AC0!0 = address
;	AC0!1 = value
;	AC0!2 = count
;  Returns AC0 = 0 if all ok; otherwise AC0 = bad address

BlkChk:	MAR←T←AC0;  		get buffer address
	NOP;
	L←MD-1;
	AC0←L, MAR←T←0+T+1;	get value
	NOP;
	L←MD;
	SAD←L, MAR←0+T+1;	get word count
	NOP;
	L←MD, TASK;
	AC1←L;

!1,2,ChkCont, ChkDone;
!1,2,ChkBad, ChkLoop;

ChkLoop: MAR←L←AC0+1;
	AC0←L;
	SINK←AC1, BUS=0;
	T←SAD, :ChkCont;	[ChkCont, ChkDone]
ChkCont: L←MD-T;
	L←AC1-1, SH=0, TASK;
	AC1←L, :ChkBad;		[ChkBad, ChkLoop]

ChkDone: L←0, TASK;
	AC0←L, :ExitRam;

ChkBad:	:ExitRam;