:Title[LVARCONST];
*
* Edit History
* March 22 11:12AM, Masinter, formatting
* March 13, 1985  9:42 AM, Masinter, remove call to SAVEUCODESTATE
* January 8, 1985  4:12 AM, JonL, GVAR← and endofstack typos in constants
* January 6, 1985  2:50 AM, JonL, emmend GVAR, GVAR← and the global case of
*  FVAR lookup to permit 16-bit litatom indices
*February 18, 1984  3:14 PM, JonL, labels PUSHSMALLT1 & PUSHTRUE1 for opRWMufMan
* January 31, 1984  1:30 AM, JonL, Added subroutine .aconstfetch
* January 13, 1984  9:05 PM, JonL, linst and lfv merged into this file
*		PUSHTMD and TL.ST0TMD in from LSTACK
* December 30, 1983  3:33 PM, JonL, merged two insts in call to GCLOOKUP
* December 27, 1983  11:28 AM, JonL, opCOPY to LSTACK
* December 6, 1982  1:43 PM, Masinter

* Variable opcodes, including free variable lookup
*  and Constants opcodes

   knowrbase[LTEMP0];
   TOP LEVEL;
   InsSet[LispInsSet, 1];


*--------------------------------------------------------------------
* Some common tails for this file
*--------------------------------------------------------------------

*--------------------------------------------------------------------
PUSHTMD: 		* pushes  T,,MD, bumps TSP, and decrements LEFT
*--------------------------------------------------------------------
PAGEFAULTNOTOK;
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
     T← Md, TSP← (store← TSP) + 1, dbuf← T, branch[TL.PUSHT];

*--------------------------------------------------------------------
TL.ST0TMD:
   T← Md, LTEMP0← (store← LTEMP0) + 1, dbuf← T, branch[TL.ST0];
*--------------------------------------------------------------------
TL.ST0:
   store← LTEMP0, dbuf← T, NextOpCode;
*--------------------------------------------------------------------


*--------------------------------------------------------------------
opIVAR:
*--------------------------------------------------------------------
   T← (ifetch← IVAR) + 1;
   T← Md, ifetch← T, branch[PUSHTMD];

regOP1[100, StackBR, opIVAR, 0];		* IVAR
regOP1[101, StackBR, opIVAR, 2];
regOP1[102, StackBR, opIVAR, 4];
regOP1[103, StackBR, opIVAR, 6];
regOP1[104, StackBR, opIVAR, 10];
regOP1[105, StackBR, opIVAR, 12];
regOP1[106, StackBR, opIVAR, 14];
regOP2[107, StackBR, opIVAR, noNData];	* PVARX

*--------------------------------------------------------------------
opPVAR:
*--------------------------------------------------------------------
   T← (ifetch← PVAR) + 1;
   T← Md, ifetch← T, branch[PUSHTMD];

regOP1[110, StackBR, opPVAR, 0];		* PVAR
regOP1[111, StackBR, opPVAR, 2];
regOP1[112, StackBR, opPVAR, 4];
regOP1[113, StackBR, opPVAR, 6];
regOP1[114, StackBR, opPVAR, 10];
regOP1[115, StackBR, opPVAR, 12];
regOP1[116, StackBR, opPVAR, 14];
regOP2[117, StackBR, opPVAR, noNData];	* PVARX



*--------------------------------------------------------------------
opFVAR:
*--------------------------------------------------------------------
	T← (ifetch← PVAR) + 1;
	LTEMP0← Md, ifetch← T;
.retryfvar:
	branch[.+2, R even], LTEMP0, T← Md, memBase← ScratchLZBR;
		T← Id, branch[.FVFAIL];
	T← T and (rhmask);						* KLUDGE: LH IS DUPLICATED!!!!
	BRHi← T;
PAGEFAULTOK;
	LTEMP0← (FETCH← LTEMP0) + 1;
	T← MD, fetch← LTEMP0, branch[PUSHTMD];	
.FVFAIL:		
* T = offset of free variable, fill in and continue
	LTEMP0← T, call[FVLOOKUP];				* T passed and smashed by FVLOOKUP
	T← LTEMP0;
	T← T + (PVAR);
	T← (fetch← T) + 1;
	LTEMP0← Md, fetch← T, branch[.retryfvar];

regOP1[120, StackBR, opFVAR, 0];		* FVAR
regOP1[121, StackBR, opFVAR, 2];
regOP1[122, StackBR, opFVAR, 4];
regOP1[123, StackBR, opFVAR, 6];
regOP1[124, StackBR, opFVAR, 10];
regOP1[125, StackBR, opFVAR, 12];
regOP1[126, StackBR, opFVAR, 14];

regOP2[127, StackBR, opFVAR, noNData];		* FVARX

*--------------------------------------------------------------------
opGVAR:	* alpha + beta form atom number of global to fetch
*--------------------------------------------------------------------
	T← Id;								* hi bits
	T← LSH[T,10];						* shift left
	LTEMP0← ((Id) + T);
	branch[.+2, alu>=0], LTEMP0 ← (LTEMP0) lsh 1;
		flipMemBase; 					* use Val2BR instead
PAGEFAULTOK;
	LTEMP0← (FETCH← LTEMP0) + 1;
	T← MD, fetch← LTEMP0, branch[PUSHTMD];

regOP3[140, ValSpaceBR, opGVAR, noNData];


*--------------------------------------------------------------------
opSETPVAR:
*--------------------------------------------------------------------
	T← (fetch← TSP) - 1, flipMemBase;
	T← Md, fetch← T;
	LTEMP0← (Id) + (PVAR), branch[TL.ST0TMD];

regOP1[130, StackM2BR, opSETPVAR, 0];			* PVAR←
regOP1[131, StackM2BR, opSETPVAR, 2];
regOP1[132, StackM2BR, opSETPVAR, 4];
regOP1[133, StackM2BR, opSETPVAR, 6];
regOP1[134, StackM2BR, opSETPVAR, 10];
regOP1[135, StackM2BR, opSETPVAR, 12];
regOP1[136, StackM2BR, opSETPVAR, 14];

regOP2[137, StackM2BR, opSETPVAR, noNData];	* PVARX←

*--------------------------------------------------------------------
opSETPVARPOP:
*--------------------------------------------------------------------
	T← (fetch← TSP) - 1, flipMemBase;			* fetch TSP-2
	T← Md, TSP← (fetch← T) - 1;					* fetch TSP-1, TSP← TSP-2
	LTEMP0← (Id) + (PVAR);
	LEFT← (LEFT) + 1, BRANCH[TL.ST0TMD];

regOP1[270, StackM2BR, opSETPVARPOP, 0];
regOP1[271, StackM2BR, opSETPVARPOP, 2];
regOP1[272, StackM2BR, opSETPVARPOP, 4];
regOP1[273, StackM2BR, opSETPVARPOP, 6];
regOP1[274, StackM2BR, opSETPVARPOP, 10];
regOP1[275, StackM2BR, opSETPVARPOP, 12];
regOP1[276, StackM2BR, opSETPVARPOP, 14];

*--------------------------------------------------------------------
opSETIVAR:
*--------------------------------------------------------------------
	T← (fetch← TSP) - 1, flipMemBase;
	T← Md, fetch← T;
	LTEMP0← (Id) + (IVAR), branch[TL.ST0TMD];

regOP2[142, StackM2BR, opSETIVAR, noNData];	* IVARX←



*--------------------------------------------------------------------
opFVARgets: 
*--------------------------------------------------------------------
	T← (ifetch← PVAR) + 1;
	LTEMP0← Md, ifetch← T;
.retrysetfvar:
	branch[.+2, R even], LTEMP0, T← Md, memBase← StackM2BR;
		T← Id, branch[.setffail];		* Fvar not looked up  yet
	T← T and (rhmask);					* KLUDGE	- TOP BYTE IS FILLED IN TOO
	pd← T xor (StackHi);
	branch[.setfglobal, alu#0], TSP← (fetch← TSP) - 1, flipMemBase;
		T← Md, TSP← (fetch← TSP) + 1, branch[TL.ST0TMD];
.setfglobal:
	TSP← (TSP) + 1, memBase← LScratchBR, Branch[.setglobal];
   
.setffail:
	LTEMP0← T, call[FVLOOKUP];
	T← LTEMP0;
	T← T + (PVAR);
	T← (fetch← T) + 1;
	LTEMP0← Md, fetch← T, branch[.retrysetfvar];

regOP2[143, StackBR, opFVARgets, noNData];

*--------------------------------------------------------------------
SUBROUTINE;	SUB.PUSHT:
*--------------------------------------------------------------------
	TSP← (store← TSP) + 1, dbuf← T, return;
TOP LEVEL;


*--------------------------------------------------------------------
*   GVAR←	 alpha + beta form atom number of global to store TOS
*--------------------------------------------------------------------

:if[Reduced];
	UfnOps[27];
:else;

opGVARgets:
	LTEMP0← Id, memBase← LScratchBR;
	LTEMP0← LSH[LTEMP0, 10];
	LTEMP0← ((Id) + (LTEMP0));
	branch[.+2, alu>=0], LTEMP0 ← (LTEMP0) lsh 1;
		T← (add[VALspace!,1]c), branch[.setglobal]; 	* use Val2BR instead
	T← VALspace, branch[.setglobal];

.setglobal:
	BrLo← LTEMP0;
	BrHi← T, LTEMP4← A0;
PAGEFAULTOK;
	Case← T← (FETCH← 0s) + 1, Call[GCLOOKUP];		* deleteref old pointer
	memBase← StackM2BR, Branch[RPLPTRTAIL];		* addref for new pointer

regOP3[27, ifuBR, opGVARgets, noNData];
:endif;


*--------------------------------------------------------------------
opNIL:
*--------------------------------------------------------------------
	Branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
	TSP← (store← TSP) + 1, dbuf← (AtomHiVal), Branch[TL.PUSHNIL];
TL.PUSHNIL:
	TSP← (store← TSP) + 1, dbuf← (AT.NIL), NextOpCode;

regOP1[150, StackBR, opNIL, noNData];

*--------------------------------------------------------------------
opKT:
*--------------------------------------------------------------------
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
PUSHTRUE1:
	TSP← (store← TSP) + 1, dbuf← (AtomHiVal), branch[TL.PUSHTRUE];
TL.PUSHTRUE:
	TSP← (store← TSP) + 1, dbuf← AT.T, NextOpCode;

regOP1[151, StackBR, opKT, noNData];

*--------------------------------------------------------------------
op01SIC:
*--------------------------------------------------------------------
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
	TSP← (store← TSP) + 1, dbuf← SmallHi;
	TSP← (store← TSP) + 1, dbuf← T, TisID, NextOpCode;

regOP1[152, StackBR, op01SIC, 0];		* '0
regOP1[153, StackBR, op01SIC, 1];		* '1
regOP2[154, StackBR, op01SIC, noNData];	* SIC

*--------------------------------------------------------------------
opSNIC:
*--------------------------------------------------------------------
	T← (Id) - (400c);
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
	TSP← (store← TSP) + 1, dbuf← SmallNegHi, branch[TL.PUSHT];

regOP2[155, StackBR, opSNIC, noNData];		* SNIC

*--------------------------------------------------------------------
opSICX:
*--------------------------------------------------------------------
	T← Id, Call[.aconstfetch];
PUSHSMALLT:
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
PUSHSMALLT1:
	TSP← (store← TSP) + 1, dbuf← SmallHi, branch[TL.PUSHT];
TL.PUSHT:
	TSP← (store← TSP) + 1, dbuf← T, NextOpCode;


regOP3[156, StackBR, opSICX, noNData];		* SICX
regOP3[160, StackBR, opSICX, noNData];		* ATOMNUMBER
*--------------------------------------------------------------------
opACONST: 
*--------------------------------------------------------------------
	T← Id, Call[.aconstfetch];
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
	TSP← (store← TSP) + 1, dbuf← (AtomHiVal), branch[TL.PUSHT];

SUBROUTINE;
.aconstfetch:
	T← LSH[T,10];
	T← (Id) + (T), Return;
TOPLEVEL;

regOP3[147, StackBR, opACONST, noNData];

*--------------------------------------------------------------------
opGCONST:
*--------------------------------------------------------------------
* push 24 bit inline constant
* coded as a one byte jump opcode which jumps to .+4

	LTEMP0← not (PCX');							* current pc
	LTEMP0← (LTEMP0) + 1;						* byte# of hi byte
	T← (LTEMP0) rsh 1;							* word# of hi byte

PAGEFAULTOK;
	T← (FETCH← T) + 1;							* fetch it & next word
	branch[.+2, R even], LTEMP0, T← MD, FETCH← T;
		T← T and (rhmask), branch[PUSHTMD];
	LTEMP0← MD;				* rh T,,lh Md has low word, lh T has hi word.
PAGEFAULTNOTOK;

	LTEMP0← rcy[T, LTEMP0, 10];
	T← rsh[T, 10];
PUSHT0:				* pushes  T,,LTEMP0, bumps TSP, and decrements LEFT
	branch[.+2, R>=0], LEFT← (LEFT) - 1, memBase← StackBR;
		StackCheck;
PAGEFAULTNOTOK;
	T← (store← TSP) + 1, dbuf← T;
	TSP← (store← T) + 1, dbuf← LTEMP0, NextOpCode;


IFUjmp[157, 1, ifuBR, 0, opGCONST, 4];


:if[Reduced];
	UfnOps[57];
:else;

*--------------------------------------------------------------------
opSTKSCAN:
*--------------------------------------------------------------------
	T← (fetch← TSP) + 1;
	FVNAME← Md, fetch← T, T← (FX.PVAR);
	FVNAME← Md, pd← FVNAME;
	branch[.+2, alu=0], pd← FVNAME;
		CallUFN;									* not LITATOM
	branch[.+2, alu#0];
		CallUFN;									* NIL
	nop;											* placement constraints
	FVEP← (PVAR) - T, call[DOLOOKUP];
	memBase← StackM2BR, T← TSP;
	T← (store← T) + 1, dbuf← FVHI;
	store← T, dbuf← FVLO, NextOpCode;

REGOP1[57, StackM2BR, opSTKSCAN, noNData];

:endif;

*--------------------------------------------------------------------
SUBROUTINE;  FVLOOKUP:
*--------------------------------------------------------------------


* look up free variable # T/2 in current frame
* fill in location where value is bound
* preserve LTEMP0

   memBase← ifuBR;

	PAGEFAULTOK;

   FETCH← add[FNH.NLFV!]s;
   FVNAME← T rsh 1;		* free variable index
   FVCHAIN← (PVAR) + T + 1;	* where to fill in the indirection
   FVTMP← MD;			* nlocals, fvoffset

	PAGEFAULTNOTOK;

   T← rsh[FVTMP, 10];		* T← NLOCALS
   FVTMP← (FVTMP) and (rhmask);
   T← (FVTMP) - T;
   T← T + (FVNAME);
   fetch← T;
   FVNAME← Md, T← (FX.PVAR);
   FVEP← (PVAR) - T;
   memBase← StackBR;
   store← FVCHAIN, dbuf← 0c, branch[.newframe];

*--------------------------------------------------------------------
DOLOOKUP:
*--------------------------------------------------------------------
* Scan for free variable FVNAME starting at FVEP, return
* in FVHI,FVLO the pointer to where it is bound
* if FVCHAIN is odd, store indirection pointer at stackspace
* should check for reschedule!!!

   FVCHAIN← A0;

.newframe:
   T← (FVEP) + 1, memBase← StackBR;
   fetch← T;
   FVEP← Md;
   FVEP← (FVEP) and not (1c);
   FVEP← (FVEP) - (FX.PVAR);
   branch[.endofstack, alu=0], fetch← FVEP;
   FVTMP← Md;
   pd← (FVTMP) and (FXNTValid);
   T← (FVEP) + (FX.DEFLO), branch[.+2, alu=0];
	T← (FVEP) + (FX.NTLO);
   T← (fetch← T) + 1;
   FVTMP← Md, fetch← T, T← (rhmask);
   T← T and (Md), memBase← LScratchBR;
   BrHi← T;
   BrLo← FVTMP;
   FVINDEX← FNH.FIRSTNAME;

.lookforvar:

	PAGEFAULTOK;

   FETCH← add[FNH.NTSIZE!]s;	* can fault
   FVTMP← Cnt← MD;	* FVTMP = NTSIZE

	PAGEFAULTNOTOK;

.fvloop:	* this can really be done in a 2 inst loop
   branch[.newframe, Cnt=0&-1];
   FVINDEX← (fetch← FVINDEX) + 1;
   T← Md;
   pd← (FVNAME) xor T;
   branch[.fvloop, alu#0];

% this is what a 2 instruction loop would look like
   T← A0;					* # FVNAME
   branch[.+2, Cnt#0], pd← T-T-1;	* pd #0
		branch[.newframe];
   FVINDEX← (fetch← FVINDEX) + 1, branch[.fvfound, alu=0];
   T← Md, pd← (FVNAME) xor T, dblbranch[.notfound, .-1, Cnt=0&-1]
.fvfound:
   FVINDEX← (FVINDEX) - (2c);
%

.fvfound:				* found a match
   T← (FVTMP) - 1;   
   T← T + (FVINDEX);		* add NTSIZE, note FVINDEX already incremented
   fetch← T;
   FVHI← Md, T← (rhmask);
   T← (T and (FVHI)) lsh 1, branch[.fvpfvar, R<0];

.fvivar:
   FVEP← (FVEP) - 1, memBase← StackBR;
   FVEP← (fetch← FVEP) + 1;
   FVLO← T + Md;
   FVHI← StackHi, branch[.donefvlookup];

.fvpfvar:
   T← T + (FVEP), memBase← StackBR;
   T← T + (FX.PVAR);				* T is stack relative location
   T← (fetch← T) + 1;
   FVLO← Md, fetch← T;
   FVHI← Md, pd← (FVHI) and (40000c);	* check FVAR bit
	FVHI← (FVHI) and (rhmask), branch[.fvfvar, alu#0];

.fvpvar:
   branch[.+2, R>=0], FVLO, FVLO← T - 1, memBase← LScratchBR;
		branch[.fvloop];						* unbound PVAR
   FVHI← StackHi, branch[.donefvlookup];
.fvfvar:
   branch[.+2, R odd], FVLO;
		branch[.donefvlookup];
* should create chain here
	branch[.newframe];

.endofstack:
   FVLO← (FVNAME) + (FVNAME);
   FVHI← ValSpace, branch[.+2, carry'];
		FVHI← (FVHI) xor (1c);		* a bit like flipMembase

.donefvlookup:
   branch[.+2, R odd], FVCHAIN, memBase← StackBR;
		return;
* kludge!!!	* STORE FVHI in both halves
   T← LSH[FVHI, 10];
   T← T + (FVHI);
   T← (store← FVCHAIN) - 1, dbuf← T;
   store← T, dbuf← FVLO, return;

TOPLEVEL;