*-----------------------------------------------------------
Title[LoadRam.mc...June 19, 1982  12:31 PM...Taft];
* Loads microcode from main memory and starts it
*-----------------------------------------------------------


% *--------------------------------------------------------------------
LoadRam loads microcode from an array of "Items" in main memory:

Item: TYPE = MACHINE DEPENDENT RECORD [
  extraIM: [0..17B], zero: [0..1] ← 0, unused: [0..377B], type: ItemType,
  addr: WORD,
  word0: WORD,
  word1: WORD];
ItemType: TYPE = MACHINE DEPENDENT {IM (0), IFUM (1), End (2), RM (3)};

The array consists of any number of non-End Items followed by an End Item.
Interpretation of Items:

IM:	word0:   RSTK[1:3] ,, ALUF[0:3] ,, BSEL[0:2] ,, LC[0:2] ,, ASEL[0:2]
	word1:   FF[0:7] ,, JCN[0:7]
	extraIM: LHparityBad ,, RSTK[0] ,, RHparityBad ,, BLOCK
	Note: the Item is ignored if addr selects LoadRamPage [7600..7677].

IFUM:	word0:   PackedAlpha ,, IFaddr'[0:9]
	word1:   Sign ,, IPar[0:2] ,, Length'[0:1] ,, RBaseB' ,, MemB[0:2] ,,
		 TPause' ,, TJump' ,, N[0:3]

RM:	word0:   RM value
	Note: it is illegal for addr to select registers used by LoadRam
	(LRFlag, LRItem, LRTemp0, LRTemp1, or LRTemp2).
	This is NOT checked -- LoadRam will malfunction if this rule is violated.

End:	word0:   checksum
	word1:   start address

LoadRam entry conditions:
	Currently selected BR contains long pointer to first Item
	LRFlag[15] = 0 to load Ram with tasking off and jump to start
		address given in End item (complete microcode replacement).
		  = 1 to leave tasking on and return at end of loading
		rather than using start address (microcode overlay).
	RBase = RBase[LRFlag]
Exit conditions:
	LRItem points to word after last Item loaded (the End Item)
	LRFlag, LRTemp0, LRTemp1, LRTemp2, T, Q clobbered
	IFU reset
	TaskingOff if it goes to start address, TaskingOn if it returns

Note: the PreFetch←s in this code are not essential.  They speed things up,
and they cost no space because they are combined with other operations.
% *--------------------------------------------------------------------

Set[XTask, IP[EMU]];
TopLevel;
OnPage[LoadRamPage];	* All other assemblies avoid this page
Set[LoadRamLoc, LShift[LoadRamPage, 6]];
KnowRBase[LRFlag];

* RBase-relative definitions for RM registers
RVRel[RX0, 0];   RVRel[RX1, 1];   RVRel[RX2, 2];   RVRel[RX3, 3]; 
RVRel[RX4, 4];   RVRel[RX5, 5];   RVRel[RX6, 6];   RVRel[RX7, 7]; 
RVRel[RX10, 10]; RVRel[RX11, 11]; RVRel[RX12, 12]; RVRel[RX13, 13]; 
RVRel[RX14, 14]; RVRel[RX15, 15]; RVRel[RX16, 16]; RVRel[RX17, 17]; 


*-----------------------------------------------------------
LoadRam: At[LoadRamLoc],	* Global entry point
*-----------------------------------------------------------
	LRTemp2← Link;
	LRItem← A0, IFUReset, Branch[.+2]; * Init memory addr (LPTR-relative)

* Top of loop in TaskingOn case.
* The IM and IFUM loads require TaskingOff, so here we turn TaskingOn
* briefly to allow I/O tasks to run.
LRLoopTOn:
	TaskingOn;

* Top of loop in TaskingOff case.
LRLoopTOff:
	T← (Fetch← LRItem)+1;
	T← (Fetch← T)+1, LRTemp0← MD, Q← MD, * LRTemp0← Item type (and extraIM)
		Call[TOffRet];		* TaskingOff
	T← (Fetch← T)+1, LRTemp1← MD,	* LRTemp1← addr
		BDispatch← Q;		* Dispatch on Item type
	LRItem← (Fetch← T)+1, Q← MD;	* Q← word0, MD← word1

* This table contains the first instruction of each case.
* These instructions are duplicated as comments in the body of each case's code.
LRTypeTable: DispTable[4];
	T← LDF[LRTemp1, 10, 6], Branch[LRTypeIM];
	T← (LRTemp1) OR (100000C), Branch[LRTypeIFUM];
	LRFlag, Link← MD, BRGO@[0] RETCL@[2] JCN[45]; * LRTypeEnd (see code there!)
	T← RSH[LRTemp1, 4], Branch[LRTypeRM];

*--------------------------------------------------------------------
* Item type = IM
*--------------------------------------------------------------------
LRTypeIM:
* ↑↑↑	T← LDF[LRTemp1, 10, 6];		* Extract page part of addr
	PD← T-(Add[LoadRamPage]C);
	LRTemp0← RSH[LRTemp0, 13], T← MD, * LRTemp0← extraIM lsh 1, T← word1
		Branch[LRNoPrefNext, ALU=0]; * Branch if would overwrite LoadRam
	BDispatch← LRTemp0;		* Dispatch on RHparity,,BLOCK,,0
	Link← LRTemp1;			* Link← addr

IMRHTable: DispTable[10];
	IMRHB'POK← T;			* RHparity=0, BLOCK=0
	T← RSH[LRTemp0, 2], Branch[LoadIMLH]; * T← extraIM rsh 1

	IMRHBPOK← T;			* RHparity=0, BLOCK=1
	T← RSH[LRTemp0, 2], Branch[LoadIMLH];

	IMRHB'PBad← T;			* RHparity=1, BLOCK=0
	T← RSH[LRTemp0, 2], Branch[LoadIMLH];

	IMRHBPBad← T;			* RHparity=1, BLOCK=1
	T← RSH[LRTemp0, 2], Branch[LoadIMLH];

LoadIMLH:
	T← LRItem, BDispatch← T;	* Dispatch on LHparity,,RSTK[0],,?
	Link← LRTemp1;			* Link← addr

IMLHTable: DispTable[10, 17, 1];
	T← A← T, Carry20, IMLHR0'POK← Q; * LHparity=0, RSTK[0]=0
	PreFetch← T, LRFlag, DblBranch[LRLoopTOn, LRLoopTOff, R odd];

	T← A← T, Carry20, IMLHR0POK← Q;	* LHparity=0, RSTK[0]=0
	PreFetch← T, LRFlag, DblBranch[LRLoopTOn, LRLoopTOff, R odd];

	T← A← T, Carry20, IMLHR0'PBad← Q; * LHparity=0, RSTK[0]=0
	PreFetch← T, LRFlag, DblBranch[LRLoopTOn, LRLoopTOff, R odd];

	T← A← T, Carry20, IMLHR0PBad← Q; * LHparity=0, RSTK[0]=0
LRPrefNext:	* Tail of IFUM and RM cases also
	PreFetch← T, B← MD;		* Fall thru for sake of LRTypeIFUM case

* Here if IM word would overwrite LoadRam.  Just skip over it.
LRNoPrefNext:
	IFUReset, LRFlag, DblBranch[LRLoopTOn, LRLoopTOff, R odd];


*--------------------------------------------------------------------
* Item type = IFUM
*--------------------------------------------------------------------
LRTypeIFUM:
* ↑↑↑	T← (LRTemp1) OR (100000C);	* Flag to load InsSet
	InsSetOrEvent← T;		* Load InsSet from addr[6:7]
	T← LSH[LRTemp1, 10], LRTemp1← MD; * BrkIns loads from B[0:7]
	BrkIns← T, Call[TOffRet];	* Load BrkIns from addr[8:15], delay 1 cycle
	IFUMLH← Q;			* Load LH from word0 & let it settle
	T← A← LRItem, Carry20, B← Q;
	IFUMRH← LRTemp1, Branch[LRPrefNext]; * Load RH from word1 & let it settle

*--------------------------------------------------------------------
* Item type = RM
*--------------------------------------------------------------------
LRTypeRM:
* ↑↑↑	T← RSH[LRTemp1, 4];		* T[12:15] ← addr[8:11]; puts
					* cycled unmasked result thru ALU
	BDispatch← LRTemp1,		* Dispatch on addr[13:15]
		DblBranch[LowRM, HighRM, ALU>=0]; * Branch on addr[12]

* Registers 0 through 7 in bank
LowRM:	T← (LRItem)+(RBase← T)+1;	* Select bank; T← advanced Item addr
DispTable[10];
	RX0← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX1← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX2← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX3← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX4← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX5← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX6← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX7← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];

* Registers 10 through 17 in bank
HighRM:	T← (LRItem)+(RBase← T)+1;	* Select bank; T← advanced Item addr
DispTable[10];
	RX10← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX11← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX12← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX13← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX14← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX15← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX16← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];
	RX17← Q, RBase← RBase[LRFlag], Branch[LRPrefNext];


*--------------------------------------------------------------------
* Item type = End
*--------------------------------------------------------------------
LRTypeEnd:
* ↑↑↑	LRFlag, Link← MD,		* Link← word1
* ↑↑↑		Branch[.+2, R odd];	* Which way to exit?
* ↑↑↑		BRGO@[0] RETCL@[2] JCN[45]; * MicroD can't place this, but I can!

Subroutine;
TOffRet:
	TaskingOff, Return,		* Jump to addr given in word1
		At[LoadRamLoc, 20];
TopLevel;

	Link← LRTemp2,			* Return to caller
		At[LoadRamLoc, 21];
Subroutine;
	TaskingOn, Return;
TopLevel;



* Fill out rest of page, to make it unavailable to other programs
* loaded with LoadRam.

Repeat[Sub[100, IP[ILC]], ILC[(Branch[.], Breakpoint)]];