Google
 

Trailing-Edge - PDP-10 Archives - BB-D480C-SB_1981 - regal2.bli
There are 26 other files named regal2.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
!  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.

!COPYRIGHT (C) 1972,1981 BY DIGITAL EQUIPMENT CORPORATION
!AUTHOR: S.MURPHY/HPW/MD/DCE/SJW/JNG/EGM/EDS

MODULE	REGAL2(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3)) =
BEGIN

GLOBAL BIND REGALV = 6^24 + 0^18 + 149;	! Version Date:	17-Jul-81

%(

***** Begin Revision History *****

114	-----	-----	DONT ALLOW REGISTER 0 TO BE THE REG TO WHICH AN ARRAY
			SUBSCRIPT IS TARGETED
115	-----	-----	IN "ALCA", IF ARG1 WAS LEFT IN SOME REGISTER
			(AS INDICATED BY "REGCONTAINING") - DO NOT
			USE THAT REG IF A1NEGFLG OR A1NOTFLG IS SET
			IN THIS EXPRESSION NODE (BECAUSE CAN THEN
			HAVE SAME,NEG,AND IMMED FLAGS ALL SET)
116	-----	-----	IN "ALCTPCNV", FOR A DUMMY TYPE CONVERSION NODE,
			WHEN THE SON OF THE TYPE CONVERSION IS DEALLOCATED
			FROM THE FN RETURN REG, MUST TURN OFF
			"A2SAMEFLG" IN THE SON AS WELL AS "A1SAMEFLG"
117	-----	-----	LIBRARY FUNCTIONS DO NOT CLOBBER EITHER
			COMMON OR EQUIVALENCED VARAIBLES
118	-----	-----	EXPCIOP MUST SAVE COMPUTED ARGUMENT IN
			A REGISTER UNLESS POWER IS A POWER OF 2

119	-----	-----	ADD ROUTINE "ALCTVARR" TO ALLOCATE AN ARRAY ELEM
			TO HAVE ITS VALUE STORED IN A TEMP (TO BE
			CALLED FOR OPEN STMNTS,UNIT NUMBERS,RECORD NUMBERS)
120	-----	-----	ADD ROUTINE "CLOBBNX" TO TEST WHETHER AN OPERATION
			CLOBBERS THE REG FOLLOWING THE REG BEING OPERATED ON.
			THIS ROUTINE  REPLACES THE MACRO "CLBNXREG",
			WHICH WAS INCORRECT IN THAT DIVISION OF VARIABLES
			OF TYPES LOGICAL AND INDEX WERE NOT BEING DETECTED
121	-----	-----	CHANGE ALL CALLS TO THE MACRO "CLBNXREG" INTO
			CALLS TO THE ROUTINE "CLOBBNX" (MUST ADD A DOT)
122	-----	-----	ADD CODE TO "ALCA" TO ALLOCATE THE ARGS UNDER
			THE IN LINE FN "CMPLX" IN SINGLE WD MODE
			(BUG IN CEXPO)
123	-----	-----	REMOVE ALL REFERENCES TO SQROP,CUBOP,P4OP
124	-----	-----	CHANGE REFS TO THE MACRO "POWEROF2"
			TO "POWOF2"
125	-----	-----	FIX BUG IN ALCARGS, MISSING DOT IN FRONT OF FREGCT
			IN A CALL TO ALCINREG
126	-----	-----	FIX ANOTHER BUG IN THE SAME BLOCK OF ALCARGS
			AS EDIT 125; DO NOT CLRBIT(.BSYRG1,.RA) IF RA
			IS THE ONLY REG IN BSYRG1
127	 237	-----	IN ALCARGS, IF HAVE A1VALFLG, IF RA IS THE ONLY
			REG IN BSYREGS - DONT TRY TO GET ANOTHER REG
			TO TARGET ARG2 TO (ARG2 MAY NOT REALLY NEED A
			REG AT ALL - EG IF ITS A FN CALL)
128	250	15356	IN ALCARGS, IF ALCRETREGFLG IS ON, DON'T ALLOCATE
			ANOTHER REGISTER (DON'T NEED IT, AND MAY NOT HAVE
			IT.
129	267	-----	IN 250, IF WE HAVE A RELATIONAL, DON'T SKIP ALLOCATION
130	274	16050	ALCINREG FUNCTION CALLS IN RIGHT ORDER AND INTO A
			FREE REGISTER
131	302	16181	DON'T SAVE REGS FOR ALL CASES OF CONTROL TYPE BOOLEANS
132	304	16441	CHECK DOUBLE TO SINGLE CONVERSION NODES FOR CLOBBERRING AC+1
133	326	17086	FIX TARGETING FOR AND/OR NODE INVOLVING FUNCTION CALL,
			(DCE)
134	341	17770	FIX REGISTER TARGETING FOR EXPONENTIATION, (DCE)
135	373	18242	DON'T CALL AFREEREG WITH BSYRG1=0, (DCE)
136	377	18476	FIX REG ALLOCATION FOR COS(X)*A(I), (DCE)

***** Begin Version 5 *****

137	412	-----	FIX REGTOUSE SO DOUBLE ARRAY REF LOADED INTO
			  SUBSCRIPT REG PAIR UNLESS FOR KA10
138	432	19037	FIX REGISTER ALLOCATION FOR TYPE CONVERSION
			NODES ABOVE ARRAY REFERENCES (ET AL), (DCE)
139	441	19231	FIX REGISTER ALLOCATION FOR A DOUBLE PRECISION
			ARRAYREF IN A FUNCTION CALL PARAMETER LIST, (DCE)
140	457	19805	TRY HARDER TO NOT ASK FOR A REGISTER UNLESS WE
			REALLY NEED ONE (MORE TO EDIT 250)., (DCE)
141	504	-----	FIX EDIT 412 TO KNOW THAT COMPLEX NUMBERS ARE
			FETCHED WITH TWO MOVN'S, NOT A DMOVN., (JNG)
142	545	22096	STORE FUNCTION VALUE IN REALLY FREE REG, (DCE)
143	550	21824	FIX TEMP ALLOCATION FOR KA WITH BIG EXPRESSION, (DCE)
144	552	21826	RESET ARGNODE PTR TO GIVE BETTER CODE, (DCE)
145	554	22324	NOT FLAG CAUSES PROBLEMS ON AND, OR NODES, (DCE)

***** Begin Version 5A *****

146	600	22990	REWRITE TO MAKE BETTER USE OF STACK, (DCE)

***** Begin Version 5B *****

147	672	25725	FIX BUG WITH NOT FLAG ON CONSTANT ARRAY REF, (DCE)

148	757	29149	ADD THE ROUTINE STORAC (BY SRM) WHICH FORCES THE RESULT
			OF A NODE OUT OF AN AC INTO A TEMP, AND USE THAT
			ROUTINE IF ALCARGS GIVES AWAY THE LAST FREE REGISTER
			PAIR WHEN IT REALLY NEEDS IT., (EGM)

***** Begin Version 6 *****

149	1064	EDS	28-Apr-81	Q20-01483
	Dont set A1SAMEFLG when allocating register for a REGCONTENTS
	node in ALCTVBOOL, this allows CGVBOOL to store ARG1.

***** End Revision History *****

)%

	EXTERNAL
		CGERR,NXTTMP,ALOCONST,TBLSEARCH,C1H,C1L,DNEGCNST,MAKEPR,
		MAKPR1;
	FORWARD
		ALCINREG(3),ALCREL(3),ALCRL1(2), ALCA(3),GETRGPR(2),
		ALCLIBFN(3),ALCARGS(3),RGTOSAVE(1), 
		ALCVBOOL(3),ALCCNB(3),ALCCNT(2), ALCNARG(2),
		ALCARRAY(2),ALCFNCALL(2), ALCFNARGS(2), ALCTPCNV(3),ALCNEGNOT(3),
		ALCSPECOP(3),ALCILF(3),  ALCINTMP(3), ALCTVBOOL(3),ALCTA(3),ALCTARY(2),
		REGTOUSE(5),RGTOU1(4),SETTARGINREG(2),SETTAC(2),CLOBBNX(1);



EXTERNAL  TREEPTR,GBSYREGS,RESNAME;
EXTERNAL EXCHARGS;

EXTERNAL REGCLOBB;	!THIS ROUTINE IS CALLED WHENEVER AN ALLOCATION
			! IS PERFORMED WHICH WILL CAUSE THE CONTENTS OF
			! A REGISTER TO BE CLOBBERED (IF THAT REGISTER
			! MIGHT HAVE CONTAINED THE VALUE OF SOME VARIABLE)
			! IT DELETES ANY ASSUMPTIONS ABOUT THE CONTENTS OF
			! THE REGISTER
EXTERNAL VARCLOBB;	!THIS ROUTINE IS CALLED WHENEVER THE VALUE OF A 
			! VARIABLE IS MODIFIED (OR MIGHT BE MODIFIED). IT
			! DELETES ANY ASSUMPTIONS ABOUT REGISTERS CONTAINING
			! THE VALUE OF THAT VARIABLE

EXTERNAL AFREEREG;	!THIS ROUTINE IS CALLED WHENEVER A FREE REGISTER
			! IS NEEDED. IF POSSIBLE IT SELECTS A REGISTER
			! THAT IS NOT OF FUTURE USE WITHIN THIS BASIC BLOCK
			! IF NOT, IT SELECTS THE REG WHOSE NEXT USE IS FURTHEST
			! IN THE FUTURE
EXTERNAL REGCONTAINING;	!ROUTINE TO DETERMINE WHETHER GIVEN VARIABLE
			! WAS LEFT IN A REG BY A PREVIOUS STMNT AND IF SO
			! TO RETURN THAT REG (IF NOT RETURNS -1)
EXTERNAL SAVEREG;	!ROUTINE TO REMEMBER THAT A GIVEN VAR IS IN A
			! GIVEN REG 
SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;

%(***************************************************************************
	LOCAL REGISTER ALLOCATION MODULE.
	INCLUDES 2 PASSES OVER AN EXPRESSION TREE.
	ON THE "COMPLEXITY WALK" (IE THE ROUTINE SETCOMPLEXITY AND ALL THE
	ROUTINES IT CALLS), THE NODES ARE REARRANGED TO REDUCE THE NUMBER
	OF REGISTERS NECESSARY TO COMPUTE THEM, AND THE MINIMUM NUMBER OF REGS NECESSARY
	IS SAVED IN EACH NODE.
	AT THIS TIME CONSTANTS THAT CAN BE USED "IMMED MODE" ARE RECOGNIZED
	AND SPACE IS ALLOCATED FOR ALL OTHERS.
	THE CONSTANT PART OF AN ARRAY ADDRESS CALC IS ALSO ADDED IN TO
	THE INSTRUCTION ADDRESS AT THIS TIME.
	THE 2ND WALK (THE ROUTINES "ALCINREG" AND "ALCINTMP") ALLOCATES
	REGISTERS(AND/OR TEMPORARIES) FOR EACH BINARY/UNARY OPERATION TO BE
	PERFORMED - TARGETING THE VALUE OF AN EXPRESSION TO A PARTICULAR
	REG/TMP
	THE GLOBAL "TREEPTR" IS USED IN BOTH THESE WALKS TO POINT TO
	THE NODE OF THE EXPRESSION TREE BEING PROCESSED.
***************************************************************************)%


MAP PEXPRNODE TREEPTR;


GLOBAL ROUTINE ALCINREG(RA,BSYREGS,FREGCT) =
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR SUBNODES OF THE NODE POINTED TO BY
	THE GLOBAL "TREEPTR" SUCH THAT THE VALUE OF THAT NODE
	WILL BE LEFT IN THE REG "RA"
	THIS ROUTINE IS ONLY CALLED WHEN THE COMPLEXITY OF THE
	NODE TO BE PROCESSED IS KNOWN TO BE LESS THAN THE NUMBER
	OF REGISTERS AVAILABLE TO PROCESS IT
	THE ARG "BSYREGS" HAS BITS 0-15 REPRESENTING THE 16 ACS
	THE BIT FOR A GIVEN AC IS 1 IF THAT IS AVAILABLE FOR USE
***************************************************************************)%

BEGIN
	EXTERNAL CLOBBCOMEQV;	!ROUTINE TO ASSUME THAT THE VALS OF ALL VARS
				! IN   COMMON (OR EQUIVALENCED)  HAVE BEEN CLOBBERED
	EXTERNAL BLOCKBSYREGS;
	LOCAL PEXPRNODE CNODE;
	CASE .TREEPTR[OPRCLS] OF SET

	%(****FOR A BOOLEAN OPERATOR***************)%
	ALCVBOOL(.RA,.BSYREGS,.FREGCT);

	%(****FOR A DATA REFERENCE - SHOULD ONLY GET HERE IN CERTAIN RARE CASES*******)%
	BEGIN END;

	%(****FOR RELATIONALS***************************************)%
	ALCREL(.RA,.BSYREGS,.FREGCT);

	%(*****FOR FUNCTION CALLS********************************)%
	BEGIN
		CNODE_.TREEPTR;		! SAVE ORIGINAL NODE
		ALCFNCALL(.BSYREGS,.FREGCT);	! ALLOCATE DOWN
		IF NOT .CNODE[ALCRETREGFLG]
		THEN
		%(***IF CANNOT LEAVE THE VALUE SITTING IN RETREG (BECAUSE IT WILL
			BE CLOBBERED BEFORE IT IS USED)***)%
		BEGIN
		! MUST NOT CONFLICT WITH A REG ALREADY USED IN BSYREGS TOO
			IF NOT BITSET (.BLOCKBSYREGS AND .BSYREGS,.RA)	! IF NEED IT LATER
			THEN
			RA_AFREEREG(.BSYREGS,FALSE,.CNODE[DBLFLG]);
			CNODE[STOREFLG]_1;
			SETTARGINREG(.CNODE,.RA);
		END;
	END;

	%(*****FOR ARITHMETIC EXPRESSIONS************************)%
	ALCA(.RA,.BSYREGS,.FREGCT);

	%(*****FOR TYPE CONVERSION******************************)%
	ALCTPCNV(.RA,.BSYREGS,.FREGCT,FALSE);

	%(*****FOR ARRAY REFERENCE**********)%
	ALCARRAY(.BSYREGS,.FREGCT);

	%(*****FOR COMMON SUBEXPRESSION*****)%
	%(******SHOULD NOT WALK DOWN OVER THEM (ONLY GET HERE AT ALL IN RARE CASES)***)%
	BEGIN END;

	%(*****FOR NEG/NOT****************)%
	ALCNEGNOT(.RA,.BSYREGS,.FREGCT);

	%(*****FOR SPECIAL-CASE OPS INTRODUCED BY PHASE 2 SKELETON****)%
	ALCSPECOP(.RA,.BSYREGS,.FREGCT);


	CGERR();				!FIELD-REF, NOT IN RELEASE 1
	CGERR();				!STORECLS: SHOULD NOT EXIST PRIOR TO
						! THIS PASS OVER THE TREE
	BEGIN  END;				!REGCONTENTS: SHOULD RARELY WALK DOWN HERE
	CGERR();				!LABOP: SHOULD NEVER WALK DOWN ON ONE
	CGERR();				!STATEMENT: SHOULD NOT OCCUR UNDER
						! AN EXPRESSION
	CGERR();				!IOLSCLS: SHOULD NOT OCCUR


	%(****FOR AN IN-LINE-FN*****)%
	ALCILF(.RA,.BSYREGS,.FREGCT);

	TES;

END;
GLOBAL ROUTINE ALCREL(RA,BSYREGS,FREGCT) =
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR RELATIONALS
***************************************************************************)%
BEGIN
	OWN PEXPRNODE ARGNODE;
	LOCAL ADJREGCT;


	ARGNODE_.TREEPTR[ARG1PTR];

	%(***IF THE ARGS OF THIS REL ARE DOUBLE-WD (AND HENCE WE ARE GOING DOWN
		FROM PROCESSING SINGLE-WD OPERATIONS TO PROCESSING DOUBLE-WD OPS)
		WE MUST ADJUST THE COUNT OF AVAILABLE REGS BEFORE DETERMINING WHETHER
		TO LEAVE THE VAL OF THE REL IN A REG***)%
	IF .ARGNODE[DBLFLG]
	THEN
	BEGIN
		OWN BSYRG1;
		BSYRG1_DPBSYREGS(.BSYREGS);
		ADJREGCT_ONESCOUNT(.BSYRG1);
	END
	ELSE ADJREGCT_.BSYREGS;


	IF .TREEPTR[COMPLEXITY] LEQ .ADJREGCT
	THEN
	BEGIN
		%(***COMPUTE THE VAL OF THE REL(TRUE OR FALSE) INTO THE REG RA***)%
		SETTARGINREG(.TREEPTR,.RA);

		%(***PERFORM REG ALLOCATION FOR THE COMPARISON***)%
		ALCRL1(CLRBIT(.BSYREGS,.RA),.FREGCT-1)
	END
	ELSE
	BEGIN
		%(***COMPUTE THE VAL OF THE REL INTO A TEMPORARY***)%
		TREEPTR[TARGTMEM]_NXTTMP(FALSE);
		%(***PERFORM REG ALLOCATION FOR THE COMPARISON***)%
		ALCRL1(.BSYREGS,.FREGCT)
	END;

END;


GLOBAL ROUTINE ALCRL1(BSYREGS,FREGCT)=
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR THE COMPARISON OPERATION OF A RELATIONAL
	(BUT NOT FOR THE STORING OF THE VALUE OF THE RELATIONAL).
	THIS ROUTINE IS CALLED BOTH FOR RELATIONALS USED ONLY FOR
	CONTROL PURPOSES AND FOR RELATIONALS WHOSE VALUES ARE COMPUTED.
	CALLED WITH THE ARGS
		BSYREGS - HAS BIT SET FOR EACH REGISTER AVAILABLE FOR USE
			BITS 0-15 REPRESENT THE 16 REGS
		FREGCT - NUMBER OF REGISTERS AVAILABLE
	CALLED WITH THE GLOBAL TREEPTR POINTING TO THE RELATIONAL NODE TO
		BE ALLOCATED.
***************************************************************************)%
BEGIN
	LOCAL RA;
	LOCAL RGFORCM;
	LOCAL PEXPRNODE ARG1NODE:ARG2NODE;
	REGISTER PEXPRNODE CNODE;
	EXTERNAL ALOCONST;

	CNODE_.TREEPTR;
	ARG1NODE_.CNODE[ARG1PTR];
	ARG2NODE_.CNODE[ARG2PTR];


	%(***IF THE ARGS UNDER THIS RELATIONAL ARE DOUBLE-WORD, MUST ADJUST THE
		SET OF AVAILABLE REGISTERS TO INCLUDE ONLY EVEN REGISTERS***)%
	IF .ARG1NODE[DBLFLG]
	THEN
	BEGIN
		BSYREGS_DPBSYREGS(.BSYREGS);
		FREGCT_ONESCOUNT(.BSYREGS);
		CNODE[COMPLEXITY]_.CNODE[COMPLEXITY]^(-1) + 1;	!CHANGE COMPLEXITY OF THE
								! RELAT TO BE IN TERMS OF PAIRS
	END;


	RGFORCM_AFREEREG(.BSYREGS,.CNODE[SAVREGFLG],.ARG1NODE[DBLFLG]);

	%(****PERFORM REGISTER ALLOCATION FOR THE 2 ARGS, TO GET THE FIRST ONE
		INTO THE 'REGFORCM' ("REGISTER FOR COMPARISON") IF POSSIBLE.*****)%
	IF NOT (.CNODE[A1VALFLG] AND .CNODE[A2VALFLG])
	THEN
	ALCARGS(.RGFORCM,.BSYREGS,.FREGCT);

	%(****IF POSSIBLE, DO THE COMPARISON IN WHATEVER REGISTER ARG1 WAS COMPUTED
		INTO************)%
	IF NOT .CNODE[ALCRETREGFLG]	!IF HAVE NOT ALREADY DECIDED TO DO THE COMPAR IN FN-RET REG
	THEN
	BEGIN
		%(***TEST WHETHER ARG1 WAS COMPUTED INTO A REG THAT CAN BE USED
			FOR THE COMPARISON****)%
		IF .ARG1NODE[OPRCLS] NEQ DATAOPR	!ARG1 NOT A SYMBOL TAB ENTRY
			AND .ARG1NODE[INREGFLG]		!ARG1 WAS LEFT IN A REG
			AND NOT .ARG1NODE[ALCRETREGFLG]	! OTHER THAN THE FN-RETURN REG
			AND NOT .CNODE[A1IMMEDFLG]	!ARG1 NOT RIGHT HALF OF AOBJN VAR
			AND NOT (.CNODE[A1NEGFLG] AND .CNODE[A1VALFLG])	!ARG1 NOT A REGCONTENTS
									! THAT HAS TO BE NEGATED WHEN
! PICKED UP
		THEN
		BEGIN
			%(***IF CAN USE THE REG USED FOR COMPUTATION OF ARG1 FOR THE COMPAR**)%
			CNODE[TARGAUX]_.ARG1NODE[TARGTAC];
			CNODE[A1SAMEFLG]_1;
		END

		ELSE
		%(***TEST WHETHER ARG1 IS A VARIABLE OR CONST WHOSE VAL WAS LEFT IN
			A REG BY THE COMPUTATION OF A PREVIOUS STMNT**)%
		IF (RA_REGCONTAINING(.ARG1NODE)) GEQ 0	!IF VAL OF ARG1 WAS LEFT IN A REG
			AND .CNODE[A1NGNTFLGS] EQL 0	! AND WE DONT NEED TO NEGATE 
								! OR COMPLEMENT IT
		THEN
		BEGIN
			CNODE[TARGAUX]_.RA;	!USE THE REG CONTAINING ARG1 FOR THE COMPAR
			CNODE[A1SAMEFLG]_1;	!DONT RELOAD THE REG
		END

		ELSE
			%(***IF  ARG1 IS NOT  IN A REG THAT CAN BE USED FOR THE COMPAR, USE
			SOME FREE REG****)%
		BEGIN
			RGFORCM_REGTOUSE(.CNODE,.ARG1NODE,.ARG2NODE,.RGFORCM,.BSYREGS);
			CNODE[TARGAUX]_.RGFORCM;
			REGCLOBB(.RGFORCM);	!THE PREVIOUS CONTENTS OF THE REG USED
							! WILL BE CLOBBERED. ADJUST BASIC-BLOCK
							! REG ALLOC TABLE FOR THIS
			IF .ARG1NODE[DBLFLG]	!IF THE VAL BEING LOADED IS DOUBLE-WD
			THEN				! THE CONTENTS OF THE NEXT
			REGCLOBB(.RGFORCM+1);	! REG WILL ALSO BE CLOBBERED
		END;
	END;	!END OF BLOCK TO DECIDE ON REG FOR COMPAR IF FN-RETURN REG NOT USED


	IF .CNODE[SAVREGFLG]	!IF IT WILL BE USEFUL LATER TO HAVE ARG1
				! LEFT IN A REG
	THEN
	BEGIN
		ARG1NODE_.CNODE[ARG1PTR];
		IF .ARG1NODE[OPRCLS] EQL DATAOPR	!BE SURE THAT ARG1 IS STILL A VAR
							! (IT MIGHT NOW BE A REGCONTENTS)
			 AND .CNODE[A1NGNTFLGS] EQL 0		!AND ARG1 WAS NOT PICKED UP BY "MOVN"
		THEN SAVEREG(.CNODE[TARGAUX],		!REMEMBER THAT REG USED FOR COMPAR
			.ARG1NODE,0,.CNODE[SONNXTUSE]);	! CONTAINS VAR ARG1
	END;



END;	!END OF ALCRL1




GLOBAL ROUTINE ALCA(RA,BSYREGS,FREGCT) = 
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR A BINARY NODE POINTED TO
	BY THE GLOBAL TREEPTR
	CALLED WITH THE ARGS
		RA - REGISTER INTO WHICH THE 1ST ARG TO BE "COMPUTED
			INTO THE RESULT" SHOULD BE MOVED
		BSYREGS - BITS 0-15 OF THIS WD REPRESENT THE 16 REGS,
			A BIT IS 1 IFF THE CORRESP REG IS AVAIL FOR USE
		FREGCT - NUMBER OF FREE REGISTERS AVAILABLE
***************************************************************************)%

BEGIN
	LOCAL PEXPRNODE CNODE;
	OWN PEXPRNODE ARG1NODE;
	OWN RB;					!REG IN WHICH VAL OF SON WAS LEFT
	OWN TEMPFLG; !TO GET BETTER CODE


	ROUTINE INLCMPLXFN(RA,BSYREGS)=
% THIS ROUTINE HANDLES IN LINE CMPLX FNS, AND IS INTRODUCED TO 
  MINIMIZE STACK USAGE IN ALCA%
		BEGIN
			REGISTER T;
			T_SPBSYREGS(.BSYREGS);
			ALCARGS(.RA,.T,ONESCOUNT(.T));
		END;

	CNODE_.TREEPTR;

	%(****IF THIS OPERATION CLOBBERS THE REGISTER FOLLOWING THE ONE ON
		WHICH IT IS PERFORMED, MUST BE SURE TO NOT
		PERFORM IT ON A REG PRECEEDING A REG WHOSE VAL MUST BE PRESERVED
	*******)%
	IF CLOBBNX(.CNODE)
	THEN
	RA_GETRGPR(.RA,.BSYREGS);


	%(****IF THIS OPERATION IS ONE WHICH WILL BE PERFORMED BY A LIBRARY FN,
		AND THE 2 ARGS ARE IDENTICAL,  THEN THE 2ND ARG
		MUST BE COMPUTED INTO A MEMORY LOC.
		IF SO, GO PERFORM THE REGISTER ALLICATION FOR THE ARGS OF THIS NODE.
	******)%
	IF USEFNCALL(CNODE) AND (.CNODE[ARG1PTR] EQL .CNODE[ARG2PTR])
	THEN
	ALCLIBFN(.RA,.BSYREGS,.FREGCT)

	ELSE
	%(****UNLESS BOTH ARGS ARE VARIABLES OR COMMON SUBEXPRESSIONS, GO PERFORM REGISTER
		ALLOCATION FOR THEM, COMPUTING ARG1 INTO RA IF POSSIBLE****)%
	IF NOT ( .TREEPTR[A1VALFLG] AND .TREEPTR[A2VALFLG])
	THEN

	IF .TREEPTR[OPERATOR] EQL CMPLXFNOP	!FOR IN LINE CMPLX FN
		THEN INLCMPLXFN(.RA,.BSYREGS)	!ALLOCATE ARGS IN SINGLE WORD MODE
		ELSE ALCARGS(.RA,.BSYREGS,.FREGCT);	!OTHERWISE NORMAL


	%(***IF HAVE ALREADY DETERMINED THAT CNODE SHOULD BE COMPUTED IN THE FN-RETURN REG, 
		ARE DONE WITH CNODE*****)%
	IF .CNODE[ALCRETREGFLG] THEN RETURN;

	ARG1NODE_.CNODE[ARG1PTR];

	%(***IF ARG1 WAS LEFT IN A REG THAT CAN BE USED FOR THE COMPUTATION OF CNODE,
		WE WANT TO USE THAT REG.
	*******)%

	TEMPFLG_ (NOT .CNODE[A1VALFLG]) AND (.ARG1NODE[INREGFLG]) AND (NOT .ARG1NODE[ALCRETREGFLG]);

	RB_IF .TEMPFLG THEN .ARG1NODE[TARGTAC]
			ELSE REGCONTAINING(.ARG1NODE);

	IF .RB GEQ 0	!IF ARG1 STILL IN A REG...
	THEN
		IF(CLOBBNX(.CNODE) AND (NOT NXREGFREE(.BSYREGS,.RB)))
		THEN RB_-1	!NEXT REG WOULD BE CLOBBERED, SO GET OUT
		ELSE
			IF NOT BITSET(.BSYREGS,.RB)
			THEN RB_-1	!CANNOT USE RB FOR CNODE, SO GET OUT
			ELSE
				IF (.TEMPFLG OR (.CNODE[A1NGNTFLGS] EQL 0))
				THEN	!ALL IS OK!
				BEGIN
					RA_.RB;	!THIS IS THE REG WE WANT
					CNODE[A1SAMEFLG]_1;
				END
				ELSE RB_-1;

	! IF REGISTER FOR ARG1 IS NO GOOD FOR CNODE, GET ANOTHER REGISTER.

	IF .RB LSS 0 
	THEN RA_REGTOUSE(.CNODE,.ARG1NODE,.CNODE[ARG2PTR],.RA,.BSYREGS);

	%(****SET UP THE TARGET FIELD OF CNODE***)%
	SETTARGINREG(.CNODE,.RA);


END;

GLOBAL ROUTINE GETRGPR(RA,BSYREGS)=
%(***************************************************************************
	ROUTINE TO RETURN THE NEXT AVAILABLE REGISTER SUCH THAT THE REGISTER FOLLOWIN
	THAT REGISTER IS ALSO AVAILABLE.
	USED FOR REGISTER ALLOCATION FOR OPERATIONS SUCH AS INTEGER DIVIDE,
	FIX, AND FLOAT WHICH CLOBBER THE REGISTER FOLLOWING THE REGISTER IN WHICH
	THE OPERATION IS PERFORMED.
	CALLED WITH THE ARG "RA" SET TO THE REG TO TRY FIRST, THE ARG "BSYREGS"
	SET TO INDICATE WHICH REGS ARE FREE
***************************************************************************)%
BEGIN
	IF BITSET(.BSYREGS,.RA+1)	!IF THE REG AFTER RA IS FREE, USE RA
	THEN RETURN .RA
	ELSE
	RETURN AFREEREG(DPBSYREGS(.BSYREGS),FALSE,TRUE)	!OTHERWISE GET AN EVEN-ODD  REGISTER PAIR
END;

GLOBAL ROUTINE ALCLIBFN(RA,BSYREGS,FREGCT)=
%(****************************************************************************
	TO PERFORM REGISTER ALLOCATION FOR THE ARGS OF AN ARITHMETIC OPERATION THAT IS PERFORMED
	BY A LIBRARY FUNCTION. (THESE INCLUDE EXPONENTIATION).
	FOR SUCH OPERATIONS THE SECOND ARGUMENT SHOULD NEVER BE LEFT IN A
	REGISTER.
	CALLED WITH THE GLOBAL TREEPTR POINTING TO THE ARITHMETIC NODE WHOSE ARGS
	ARE TO BE PROCESSED.
****************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:ARG2NODE;
	CNODE_.TREEPTR;
	ARG2NODE_.CNODE[ARG2PTR];


	%(***IF ARG2 IS A COMMON SUBEXPRESSION THAT WAS LEFT IN A REGISTER,
		IT MUST BE STORED IN A TEMPORARY BEFORE CALLING THE FUNCTION.
	****)%
	IF .CNODE[A2VALFLG]
	THEN
	BEGIN
		IF .ARG2NODE[OPRCLS] EQL CMNSUB
		THEN
		BEGIN
			IF .ARG2NODE[INREGFLG] AND NOT .ARG2NODE[STOREFLG]
			THEN
			BEGIN
				ARG2NODE[STOREFLG]_1;
				ARG2NODE[TARGTMEM]_NXTTMP(.ARG2NODE[DBLFLG]);
			END
		END
	END


	%(***IF ARG2 IS AN EXPRESSION WHICH MUST BE EVALUATED, EVALUATE IT INTO A TEMPORARY.
		ALWAYS EVALUATE ARG2 BEFORE ARG1****)%
	ELSE
	BEGIN
		CNODE[RVRSFLG]_1;
		TREEPTR_.ARG2NODE;
		ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
	END;

	%(***PERFORM REGISTER ALLOCATION TO GET ARG1 INTO RA***)%
	IF NOT .CNODE[A1VALFLG]
	THEN
	BEGIN
		TREEPTR_.CNODE[ARG1PTR];
		ALCINREG(.RA,.BSYREGS,.FREGCT);
	END;
END;


GLOBAL ROUTINE ALCARGS(RA,BSYREGS,FREGCT)=
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR THE 2 ARGS OF A BINARY NODE POINTED TO
	BY THE GLOBAL "TREEPTR".
	CALLED WITH THE ARGS
		RA - REGISTER INTO WHICH THE 1ST ARG TO BE "COMPUTED
			INTO THE RESULT" SHOULD BE MOVED
		BSYREGS - BITS 0-15 OF THIS WD REPRESENT THE 16 REGS,
			A BIT IS 1 IFF THE CORRESP REG IS AVAIL FOR USE
		FREGCT - NUMBER OF FREE REGISTERS AVAILABLE
***************************************************************************)%
BEGIN
	OWN BSYRG1,FRGCT1;
	REGISTER PEXPRNODE CNODE:ARG1NODE:ARG2NODE;
	LOCAL RB;
	OWN RSV;		!REG THAT MUST BE PRESERVED BECAUSE IT HOLDS THE
				! VAL OF THE ARG THAT WAS COMPUTED FIRST
	OWN FREERGPAIRS;	!NUMBER OF FREE REGISTER PAIRS
	OWN PEXPRNODE ARGCOMP1ST;	!ARG WHOSE VAL IS COMPUTED 1ST
	OWN PEXPRNODE ARGCOMP2ND;	!ARG WHOSE VAL IS COMPUTED 2ND
	OWN PAIRPROBLEM;	!LOCAL FLAG INDICATING THAT MAY RUN OUT OF ADJACENT
				! REG PAIRS WHILE COMPUTING THE SUBNODE THAT
				! IS COMPUTED 2ND - HENCE MUST ALLOC THE 1ST SUBNODE
				! TO RESIDE IN A TEMPORARY

	EXTERNAL FREEPAIRS;	!ROUTINE TO DETERMINE THE NUMBER OF FREE EVEN-ODD REG PAIRS
				! INDICATED BY A BIT PATTERN IN WHICH A 0
				! REPRESENTS A BUSY REG, 1 REPRESENTS A FREE REG

	EXTERNAL PAIRMODE;	!GLOBAL FLAG INDICATING THAT THE STMNT BEING PROCESSED
				! REQUIRES SOME REG PAIRS

%[757]%	EXTERNAL STORAC;	!ROUTINE TO STORE THE VALUE OF A NODE IN A TEMP
%[757]%				! IF IT DEPENDS ON ANY AC


	CNODE_.TREEPTR;
	ARG1NODE_.CNODE[ARG1PTR];
	ARG2NODE_.CNODE[ARG2PTR];


	IF .CNODE[A2VALFLG]
	THEN
	%(***IF ARG2 NEEDS NO EVALUATION, SIMPLY EVAL ARG1 INTO RA***)%
	BEGIN
		TREEPTR_.ARG1NODE;
		ALCINREG(.RA,.BSYREGS,.FREGCT);
		RETURN;
	END;

	IF .CNODE[A1VALFLG]
	THEN
	%(***IF ARG1 NEEDS NO EVALUATION, EVALUATE ARG2 INTO ANY REG EXCEPT RA (OR INTO A TMP)***)%
	BEGIN
		TREEPTR_.ARG2NODE;
		IF .CNODE[COMPLEXITY] LEQ .FREGCT
		THEN
		BEGIN
			IF .FREGCT EQL 1	!IF RA IS THE ONLY AC LEFT IN BSYREGS
						!(WHICH MAY HAPPEN IF ARG2 DOESNT REALLY NEED AN AC-
						!EG IF ITS A FN CALL, AN ARRAY REF WITH CONSTANT SS, ETC)
			THEN				!DONT TRY TO GET ANOTHER AC FOR ARG2
			ALCINREG(.RA,.BSYREGS,.FREGCT)
			ELSE
%[757]%			BEGIN
%[757]%			ALCINREG(AFREEREG(CLRBIT(.BSYREGS,.RA),FALSE,.ARG2NODE[DBLFLG]),.BSYREGS,.FREGCT);
%[757]%
%[757]%		%(*****	NOW IF THIS NODE PERFORMS AN OPERATION WHICH CLOBBERS
			THE NEXT REGISTER AFTER THE CURRENT ONE,  AND THERE IS
			ONLY ONE REGISTER PAIR LEFT, AND THE SON HAS USED ONE OF
			THE REGS IN THAT PAIR, MOVE THE SON TO A TEMP *****)%
%[757]%			IF CLOBBNX(.CNODE)
%[757]%			THEN
%[757]%			IF FREEPAIRS(.BSYREGS) EQL 1
%[757]%			THEN
%[757]%			IF .ARG2NODE[INREGFLG]
%[757]%			THEN
%[757]%			IF .ARG2NODE[TARGTAC] EQL .RA OR
%[757]%			   .ARG2NODE[TARGTAC] EQL .RA+1
%[757]%			THEN
%[757]%				CNODE[ARG2PTR] _ STORAC(.ARG2NODE,.BSYREGS)
%[757]%			END
		END
		ELSE ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
		RETURN;
	END;



	%(***IF ARG1 IS LEFT IN THE FN-RETURN REGISTER AND THE PARENT NODE IS NOT (PRESUMABLY
		BECAUSE THERE IS ANOTHER FN CALL THAT WOULD CLOBBER IT) THEN
		IF ARG2 IS NOT LEFT IN THE FN RETURN REG AND IT IS POSSIBLE TO
		EXCHANGE THE 2 ARGS, DO SO***)%
	IF .ARG1NODE[ALCRETREGFLG] AND (NOT .ARG2NODE[ALCRETREGFLG]) AND (NOT .CNODE[ALCRETREGFLG])
	THEN
	BEGIN
		IF EXCHARGS(.CNODE)
		THEN
		BEGIN
			%(***IF HAVE EXCHANGED THE ARGS, MUST COMPLEMENT THE BIT THAT
				INDICATES WHICH TO EVALUATE FIRST***)%
			CNODE[RVRSFLG]_NOT .CNODE[RVRSFLG];

			%(***MUST RESET THE LOCAL VARS ARG1NODE AND ARG2NODE***)%
			ARG1NODE_.CNODE[ARG1PTR];
			ARG2NODE_.CNODE[ARG2PTR];
		END
	END;


	%(****IF THE STATEMENT BEING PROCESSED INCLUDES SUBEXPRESSIONS THAT
		REQUIRE REG PAIRS, AND WE ARE NOT PRESENTLY ALLOCATING IN DP MODE (IE
		IN MODE WHERE "FREGCT" INDICATES NUMBER OF PAIRS AVAILABLE) - MUST
		TAKE PRECAUTIONS NOT TO RUN OUT OF PAIRS
	******)%
	IF .PAIRMODE AND NOT .ARG1NODE[DBLFLG]	!(FOR RELATIONALS, CNODE WILL NOT HAVE "DBLFLG"
						! EVEN THOUGH THE ARGS ARE DP AND WE ARE NOW IN DP MODE
						! HENCE WE MUST LOOK AT DBLFLG ON THE ARG TO SEE IF IN DP MODE)

	THEN
	BEGIN
		FREERGPAIRS_FREEPAIRS(.BSYREGS);	!NUMBER OF PAIRS LEFT
		IF .CNODE[RVRSFLG]	!IF ARG2 IS COMPUTED BEFORE ARG1
		THEN (ARGCOMP1ST_.ARG2NODE; ARGCOMP2ND_.ARG1NODE)
		ELSE (ARGCOMP1ST_.ARG1NODE; ARGCOMP2ND_.ARG2NODE);

		IF .ARGCOMP2ND[COMPLEXITY] GEQ 2	!IF THE ARG THAT WILL BE EVALUATED 2ND
						! REQUIRES 2 OR MORE REGS TO EVALUATE
						! MUST ASSUME THAT IT NEEDS A PAIR
			AND .FREERGPAIRS LSS 2	! AND IF THERE ARE NOT 2 PAIRS LEFT
			AND NOT .ARGCOMP1ST[ALCRETREGFLG]	!AND THE ARG COMPUTED 1ST WONT
								! BE LEFT IN THE FN-RET REG
		THEN PAIRPROBLEM_TRUE	!MUST TAKE SPECIAL ACTION TO ASSURE THAT
					! A REG FROM  THE LAST PAIR IS NOT USED TO HOLD THE 1ST ARG
					! WHILE THE 2ND ARG IS BEING COMPUTED
		ELSE PAIRPROBLEM_FALSE
	END
	ELSE
	PAIRPROBLEM_FALSE;

	!FORGET WHAT LIVES IN REGS 0 AND 1 IF A FUNCTION
	! CALL OCCURS ON THE SIDE OF THE TREE TO BE
	! ALLOCATED LAST.  THIS HELPS TO GET GOOD CODE
	! FOR COS(X)*A(I) WHERE I IS IN 0 OR 1
	IF .CNODE[FNCALLSFLG] AND 
		(IF .CNODE[RVRSFLG] THEN .ARG1NODE[FNCALLSFLG]
			ELSE .ARG2NODE[FNCALLSFLG])
		THEN BEGIN REGCLOBB(0); REGCLOBB(1) END;

	%(****IF BOTH SUBNODES REQUIRE COMPUTATION, PERFORM REGISTER ALLOCATION FOR THE
		2 COMPUTATIONS.
		IF THE FIRST SUBNODE COMPUTED HAS ITS VAL (OR A PTR
		TO IT VAL)  LEFT IN A REGISTER, THEN THAT
		REGISTER CANNOT BE USED IN COMPUTATION OF THE OTHER SUBNODE.
		(NOTE THAT EVEN IF A SUBNODE HAS BEEN DESIGNATED AS COMPUTED INTO "FN
		RETURN REG", MUST STILL DO ALLOCATION FOR SOME OF ITS SUBNODES)
	*************)%

	IF .CNODE[COMPLEXITY] LEQ .FREGCT AND NOT .PAIRPROBLEM
	THEN
	%(*****IF VAL OF THIS NODE CAN BE COMPUTED ENTIRELY IN REGS****)%
	BEGIN
		IF .CNODE[RVRSFLG]
		THEN
		%(***IF 2ND ARG IS EVALUATED BEFORE 1ST***)%
		BEGIN
			%(***IN COMPUTING ARG2 - DO NOT WANT TO LEAVE THEVAL OF ARG2
				IN RA IF CAN AVOID IT, SINCE WILL WANT TO COMPUTE
				THE 1ST ARG INTO RA SO THAT CAN THEN COMPUTE THE
				PARENT THERE***)%
			BSYRG1_CLRBIT(.BSYREGS,.RA);
			!IF THIS WAS THE LAST AVAILABLE REGISTER, THEN
			! USE IT ANYWAY.  THIS PREVENTS A CALL TO AFREEREG
			! WITH BSYRG1=0 WHICH CAN NOT BE HANDLED!
			IF .BSYRG1 EQL 0 THEN BSYRG1_.BSYREGS;

			%(***ALSO, IF ARG1 IS AN OPERATION THAT CLOBBERS THE REG
				FOLLOWING THE REG USED, THEN IF POSSIBLE DONT
				USE THE REG AFTER RA***)%
			IF CLOBBNX(.ARG1NODE)
			THEN
			BEGIN
				IF .FREGCT GTR 2
				THEN BSYRG1_CLRBIT(.BSYRG1,.RA+1);
			END;

			%(***NOW ALLOCATE A REGISTER FOR ARG2 TO BE COMPUTED
				INTO - MUST BE CAREFUL NOT TO ASK FOR A REG
				UNLESS WE REALLY NEED ONE, SINCE THERE MIGHT
				NOT BE ANY LEFT. THEREFORE, DON'T ALLOCATE
				A REGISTER IF ARG2 IS GOING INTO THE FUNCTION
				RETURN REGISTER, OR IF THE COMPLEXITY OF ARG2
				IS ZERO***)%
			IF (.ARG2NODE[ALCRETREGFLG] AND
				.ARG2NODE[OPRCLS] NEQ RELATIONAL)
			OR (.ARG2NODE[COMPLEXITY] EQL 0)
			THEN %DON'T NEED A REG, SO USE RA%
			RB_.RA
			ELSE %GO GET A NEW REGISTER%
			RB_AFREEREG(.BSYRG1,FALSE,.ARG2NODE[DBLFLG]);

			%(***PERFORM REGISTER ALLOC FOR COMPUTATION OF ARG2- TO LEAVE
				THE RESULT IN RB (WHERE RB NEQ RA)***)%
			TREEPTR_.ARG2NODE;
			ALCINREG(.RB,.BSYREGS,.FREGCT);

			%(***IN THE COMPUTATION OF ARG1, CANNOT USE THE REG WHICH
				MUST BE PRESERVED TO PRESERVE THE VAL OF ARG2***)%
			RSV_RGTOSAVE(.ARG2NODE);
			IF .RSV NEQ -1
			THEN
			%(***IF SOME REG MUST BE PRESERVED TO PRESERVE THE VAL OF ARG2,
				TAKE THAT REG OUT OF THE SET OF AVAILABLE REGS***)%
			(BSYREGS_CLRBIT(.BSYREGS,.RSV); FREGCT_.FREGCT-1);

			%(***WHEN COMPUTING ARG1, CANNOT USE THE REG THAT WE
				NEED TO SAVE TO PRESERVE THE VALUE OF ARG2.
				IF WE'RE ABOUT TO, GO GET ANOTHER REGISTER
				TO USE, AFTER FIRST MAKIING SURE THAT WE
				REALLY NEED IT (MIGHT BE LOW ON REGS)***)%
			IF %WE'RE ABOUT TO USE RSV% (.RA EQL .RSV)
			AND NOT %THIS COMPUTATION CAN DO WITHOUT A REG%
				((.ARG1NODE[ALCRETREGFLG] AND
					.ARG1NODE[OPRCLS] NEQ RELATIONAL)
				OR .ARG1NODE[COMPLEXITY] EQL 0)
			THEN %ALLOCATE A DIFFERENT REGISTER%
			RA_AFREEREG(.BSYREGS,FALSE,.ARG1NODE[DBLFLG]);

			%(***PERFORM REGISTER ALLOCATION FOR ARG1***)%
			TREEPTR_.ARG1NODE;
			ALCINREG(.RA,.BSYREGS,.FREGCT);
		END

		ELSE
		%(****IF 1ST ARG IS EVALUATED BEFORE 2ND****)%
		BEGIN
			TREEPTR_.ARG1NODE;
			ALCINREG(.RA,.BSYREGS,.FREGCT);

			%(***DETERMINE WHICH (IF ANY) REG MUST BE SAVED WHILE COMPUTING
				ARG2 BECAUSE IT HOLDS EITHER THE VAL OR A PTR TO THE
				VAL OF ARG1****)%
			RSV_RGTOSAVE(.ARG1NODE);
			IF .RSV NEQ -1
			THEN
			BEGIN
				BSYRG1_CLRBIT(.BSYREGS,.RSV);
				FRGCT1_.FREGCT-1;
			END
			ELSE
			BEGIN
				BSYRG1_.BSYREGS;
				FRGCT1_.FREGCT;
			END;

			TREEPTR_.ARG2NODE;
			RB_CLRBIT(.BSYRG1,.RA);	!PREFER NOT TO USE RA
					! TO HOLD ARG2 - SINCE THEN WONT BE
					! ABLE TO USE IT FOR THE PARENT
			IF .RB EQL 0	!HOWEVER IF IT WAS THE ONLY REG AVAILABLE
			THEN RB_.BSYRG1;	! THEN MUST USE IT

			%(***ALLOCATE A REG AS TARGET OF ARG2'S CALCULATION,
				AFTER USUAL CHECKS TO MAKE SURE WE REALLY
				NEED IT***)%
			IF (.ARG2NODE[ALCRETREGFLG] AND
				.ARG2NODE[OPRCLS] NEQ RELATIONAL)
			OR (.ARG2NODE[COMPLEXITY] EQL 0)
			THEN %USE THE OLD REG%
			RB_.RA
			ELSE
			RB_AFREEREG(.RB,FALSE,.ARG2NODE[DBLFLG]);

			ALCINREG(.RB,.BSYRG1,.FRGCT1);
		END;
	END

	ELSE
	%(*****IF VAL OF THIS NODE CANNOT BE COMPUTED ENTIRELY IN REGS****)%
	BEGIN
		IF .CNODE[RVRSFLG]
		THEN
		%(***IF ARG2 IS EVALUATED BEFORE ARG1***)%
		BEGIN
			TREEPTR_.ARG2NODE;
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
			TREEPTR_.ARG1NODE;
			ALCINREG(.RA,.BSYREGS,.FREGCT);
		END

		ELSE
		%(***IF ARG1 IS EVALUATED BEFORE ARG2***)%
		BEGIN
			TREEPTR_.ARG1NODE;
			IF .ARG2NODE[COMPLEXITY] GTR (.FREGCT-1)
				OR .PAIRPROBLEM

			THEN
			%(***IF WILL NEED TO USE RA IN COMPUTING ARG2***)%
			BEGIN
				ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
				TREEPTR_.ARG2NODE;
				IF .ARG2NODE[COMPLEXITY] EQL .FREGCT
				THEN
				ALCINREG(AFREEREG(CLRBIT(.BSYREGS,.RA),FALSE,.ARG2NODE[DBLFLG]),.BSYREGS,.FREGCT)
				ELSE
				ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
			END

			ELSE
			%(***IF CAN COMPUTE ARG2 WITHOUT CLOBBERRING RA***)%
			BEGIN
				ALCINREG(.RA,.BSYREGS,.FREGCT);

				%(***DETERMINE WHICH (IF ANY) REG MUST BE SAVED WHILE COMPUTING
					ARG2 BECAUSE IT HOLDS EITHER THE VAL OR A PTR TO THE
					VAL OF ARG1****)%
				RSV_RGTOSAVE(.ARG1NODE);
				IF .RSV NEQ -1
				THEN
				BEGIN
					BSYRG1_CLRBIT(.BSYREGS,.RSV);
					FRGCT1_.FREGCT-1;
				END
				ELSE
				BEGIN
					BSYRG1_.BSYREGS;
					FRGCT1_.FREGCT;
				END;

				TREEPTR_.ARG2NODE;
				ALCINREG(AFREEREG(CLRBIT(.BSYRG1,.RA),FALSE,.ARG2NODE[DBLFLG]),.BSYRG1,.FRGCT1);
			END;

		END;
	END;

END;


GLOBAL ROUTINE ALCVBOOL(RA,BSYREGS,FREGCT)=
%(***************************************************************************
	TO PERFORM REGISTER ALLOCATION TO COMPUTE THE VALUE OF A BOOLEAN.
***************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:ARG1NODE;
	LOCAL RV;				!REG INTO WHICH THE VAL OF THE BOOLEAN
						! WILL BE CALCULATED.

	%(****EQV AND XOR ARE HANDLED LIKE ARITHMETICS***)%
	IF .TREEPTR[BOOLCLS] NEQ ANDORCLS THEN ALCA(.RA,.BSYREGS,.FREGCT)

	ELSE
	%(***IF THIS EXPRESSION HAS VALTYPE "CONTROL" (BOTH ARGS ARE RELATIONALS
		OR BOOLEANS OF TYPE CONTROL), WILL ONLY COMPUTE A VAL FOR THE
		TOP LEVEL BOOLEAN NODE*****)%
	IF .TREEPTR[VALTYPE] EQL CONTROL THEN ALCCNB(.RA,.BSYREGS,.FREGCT)


	ELSE
	%(***IF ONE OF THE ARGS UNDER THIS NODE HAS TYPE CONTROL AND THE OTHER DOES NOT,
		THEN ARG2 WILL BE THE CONTROL ARG (COMPLEXITY  HAS SET THIS UP)
		IF NEITHER ARG HAS TYPE CONTROL, WILL HANDLE LIKE ARITHMETIC*****)%
	IF (OWN PEXPRNODE ARG2NODE;  ARG2NODE_.TREEPTR[ARG2PTR]; .ARG2NODE[VALTYPE] NEQ CONTROL)
	THEN ALCA(.RA,.BSYREGS,.FREGCT)


	ELSE
	%(****IF ARG1 IS A MASK (IE A NON-CONTROL EXPRESSION) AND ARG2 IS A CONTROL EXPR*****)%

	%(***IF HAVE ALREADY DETERMINED THAT VAL IS TO BE COMPUTED TO FN-RET-REG, THEN
		SIMPLY ALLOCATE THE 2 ARGS****)%
	IF .TREEPTR[ALCRETREGFLG] THEN ALCARGS(.RA,.BSYREGS,.FREGCT)


	ELSE
	%(****IF CANNOT COMPUTE THE WHOLE EXPRESSION ENTIRELY IN REGS, COMPUTE THE VAL
		OF THE BOOLEAN IN A TEMPORARY****)%
	IF .TREEPTR[COMPLEXITY] GTR .FREGCT THEN ALCTVBOOL(NXTTMP(),.BSYREGS,.FREGCT)

	ELSE
	%(***FOR A BOOLEAN WHERE ARG2 IS OF TYPE CONTROL, ARG1 IS A MASK.
		WILL COMPUTE ARG1 FIRST AND THEN USE THE REG CONTAINING ARG1 AS
		THE REG FOR THE VAL OF THE BOOLEAN*****)%
	BEGIN
		CNODE_.TREEPTR;
		ARG1NODE_.TREEPTR[ARG1PTR];

		%(***IF ARG1 IS A LEAF OR A COMMON SUBEXPR, GET A REG FOR COMP
			OF PARENT****)%
		IF .CNODE[A1VALFLG] THEN
		BEGIN
			IF (RV_REGCONTAINING(.ARG1NODE)) GEQ 0	!IF ARG1 WAS LEFT IN A REG BY A PREV STMNT
				AND .CNODE[A1NGNTFLGS] EQL 0
			THEN
			BEGIN
				IF BITSET(.BSYREGS,.RV)	!IF ITS OK TO CLOBBER RV WHILE
							! PROCESSING THIS STMNT
				THEN CNODE[A1SAMEFLG]_1	!DONT RELOAD IT
				ELSE
				 RV_REGTOUSE(.CNODE,.ARG1NODE,.CNODE[ARG2PTR],.RA,.BSYREGS)
			END
			ELSE
			 RV_REGTOUSE(.CNODE,.ARG1NODE,.CNODE[ARG2PTR],.RA,.BSYREGS)
		END

		%(***OTHERWISE, USE THE REG INTO WHICH ARG1 WAS COMPUTED***)%
		ELSE
		BEGIN
			TREEPTR_.ARG1NODE;
			ALCINREG(.RA,.BSYREGS,.FREGCT);
			IF .ARG1NODE[INREGFLG] AND NOT .ARG1NODE[ALCRETREGFLG]
			THEN
			BEGIN
				RV_.ARG1NODE[TARGTAC];
				CNODE[A1SAMEFLG]_1;
			END
			ELSE RV_REGTOUSE(.CNODE,.ARG1NODE,.CNODE[ARG2PTR],.RA,.BSYREGS);
		END;


		%(***PERFORM ALLOCATION FOR THE CONTROL ARG
			DO NOT USE REG THAT HOLDS VAL OF PARENT IN COMP OF ARG***)%
		TREEPTR_.CNODE[ARG2PTR];
		ALCNARG(CLRBIT(.BSYREGS,.RV),.FREGCT-1);

		SETTARGINREG(.CNODE,.RV);
	END;
END;



GLOBAL ROUTINE ALCCNB(RA,BSYREGS,FREGCT) =
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR A CONTROL-TYPE BOOLEAN
***************************************************************************)%
BEGIN
	EXTERNAL NOBBREGSLOAD;	!GLOBAL FLAG INDICATING THAT CODE FOR THE
					! NODES BEING PROCESSED WILL NOT ALWAYS
					! BE EXECUTED AND HENCE THAT THE BB ALLOCATOR
					! CANNOT ASSUME THAT REGS LOADED CONTAIN GIVEN VALS
	LOCAL SAVNOBBREGS;	!TO SAVE THE VAL THAT "NOBBREGSLOAD" HAD ON ENTERING THIS ROUTINE

	SAVNOBBREGS_.NOBBREGSLOAD;

	NOBBREGSLOAD_TRUE;	!SET FLAG TO TELL BB ALLOC THAT CODE NOT ALWAYS EXECUTED
	IF .TREEPTR[ALCRETREGFLG]
	THEN
	BEGIN
		ALCCNT(.BSYREGS,.FREGCT);
		RETURN;
	END;

	IF .TREEPTR[COMPLEXITY] LEQ .FREGCT
	THEN
	%(***IF VAL CAN BE COMPUTED IN A REG***)%
	BEGIN
		SETTARGINREG(.TREEPTR,.RA);
		ALCCNT(CLRBIT(.BSYREGS,.RA),.FREGCT-1)
	END

	ELSE
	%(***IF NUMBER OF REGS NECESSARY TO COMPUTE VAL OF THIS NODE IS GREATER THAN NO AVAILABLE*)%
	BEGIN
		TREEPTR[TARGTMEM]_NXTTMP(FALSE);
		ALCCNT(.BSYREGS,.FREGCT);
	END;

	NOBBREGSLOAD_.SAVNOBBREGS;	!RESTORE FLAG FOR CODE NOT ALWAYS EXECUTED
					! TO ITS STATE UPON ENTRY TO THIS ROUTINE
END;

GLOBAL ROUTINE ALCCNT(BSYREGS,FREGCT) =

%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR A CONTROL-TYPE
	BOOLEAN.
	THE VALUES OF SUBNODES OF SUCH A NODE ARE NEVER ACTUALLY COMPUTED.
	CALLED WITH THE GLOBAL "TREEPTR" POINTING TO THE NODE TO BE
	PROCESSED, WITH THE ARG "BSYREGS" INDICATING WHICH REGS ARE 
	AVAILABLE.
***************************************************************************)%

BEGIN
	LOCAL PEXPRNODE CNODE;

	CNODE_.TREEPTR;

	%(*********FOR THE 1ST ARG****************************)%

	TREEPTR_.CNODE[ARG1PTR];
	ALCNARG(.BSYREGS,.FREGCT);

	%(*********FOR THE 2ND ARG************************)%
	TREEPTR_.CNODE[ARG2PTR];
	ALCNARG(.BSYREGS,.FREGCT);

END;




GLOBAL ROUTINE RGTOSAVE(CNODE)=
%(***************************************************************************
	ROUTINE TO DETERMINE WHICH REGISTER MUST BE PRESERVED SO THAT THE
	VAL CORRESPONDING TO A GIVEN EXPRESSION NODE WILL BE PRESERVED.
	IF THE EXPRESSION NODE IS AN ARRAYREF, THEN NEED TO PRESERVE THE REG 
	HOLDING AN INDEX INTO THE ARRAY, OTHERWISE MAY NEED TO PRESERVE
	A REG HOLDING THE VALUE OF AN EXPRESSION.
	THIS ROUTINE RETURNS THE REG TO BE PRESERVED (FOR A DOUBLE-PREC
	NODE IT RETURNS THE EVEN REG OF THE EVEN-ODD PAIR TO BE PRESERVED),
	-1 IF NO REG NEEDS TO BE PRESERVED.
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNODE;
	OWN SVAC;

	IF .CNODE[OPRCLS] EQL DATAOPR OR .CNODE[OPRCLS] EQL CMNSUB
	THEN
	RETURN -1;

	%(***IF THE VAL WAS LEFT IN THE FN RETURN REG, THEN HAVE NO
		REGS FROM THE USUAL POOL TO PRESERVE***)%
	IF .CNODE[ALCRETREGFLG] THEN RETURN -1;


	!WE NEED TO CONSIDER THE CASE OF A TYPE CONVERSION
	! NODE ABOVE AN ARRAY REFERENCE WHEN THE TYPE CONVERSION
	! NODE ACQUIRES A TARGXF VALUE - TREAT IT JUST LIKE AN
	! ARRAY REFERENCE NODE, AND RESTRUCTURE THIS ROUTINE.
	! THE THREE CASES BELOW ARE:
	! 	1. WE HAVE A REAL TARGET (IN TARGTAC)
	! 	2. NO REGISTER IN USE AT ALL
	! 	3. TARGXF FIELD IN USE (ARRAY REF, TYPE CONVERSION,
	! 		AND POSSIBLY OTHERS)
	IF .CNODE[INREGFLG]
	THEN RETURN .CNODE[TARGTAC]
	ELSE	IF .CNODE[TARGXF] EQL 0
		THEN RETURN -1
		ELSE
		BEGIN
			 SVAC_.CNODE[TARGXF];
			IF .CNODE[DBLFLG]	!IF THE ARRAYREF WAS DOUBLE-PREC
			THEN			! WILL NEED TO PRESERVE THE EVEN-ODD PAIR
			SVAC_(.SVAC/2)*2;	! IF THE INDEX IS IN AN ODD REG
						! (INSERTED 11-5-73 TO FIX BUG IN BB0402.FTP
						! WITH -R*DP(I) WHEN R HAD BEEN
						! LEFT IN A REG )
			RETURN .SVAC
		END
END;

GLOBAL ROUTINE ALCNARG(BSYREGS,FREGCT) =
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR ONE OF THE ARGS OF
	A CONTROL-TYPE BOOLEAN.
	SUCH AN ARG CAN ONLY BE EITHER A RELATIONAL OR ANOTHER CONTROL-TYPE
	BOOLEAN (BY DEFINITION).
	THE VALUE OF SUCH AN ARG WILL NEVER BE EXPLICITLY COMPUTED, HENCE
	"LOC OF VALUE" FIELD WILL ALWAYS BE LEFT EMPTY
***************************************************************************)%
BEGIN

	EXTERNAL NOBBREGSLOAD;	! DON'T SAVE WHO'S IN REGS FLAG
	LOCAL SAVNOBBREGS;	! SAVE NOBBREGSLOAD

	IF .TREEPTR[OPRCLS] EQL RELATIONAL
	THEN
	%(*****IF THIS ARG IS A RELATIONAL******************)%
	%(***PERFORM REGISTER ALLOCATION FOR THE COMPARISON***)%
	ALCRL1(.BSYREGS,.FREGCT)
	ELSE

	IF .TREEPTR[OPRCLS] EQL BOOLEAN
	THEN
	%(*****IF THIS ARG IS A BOOLEAN************)%
	BEGIN
		SAVNOBBREGS_.NOBBREGSLOAD;	! SAVE CURRENT FLAG
		NOBBREGSLOAD_TRUE;	! DON'T REMEMBER VALUES WHICH
					! MAY NOT GET CALCULATED
		ALCCNT(.BSYREGS,.FREGCT);
		NOBBREGSLOAD_.SAVNOBBREGS;
	END

	ELSE
	%(*****AN ARG OF A CONTROL-TYPE BOOLEAN CAN ONLY BE A RELATIONAL
		OR A CONTROL-TYPE BOOLEAN (BY DEFINITION) *****)%
	CGERR(6);

END;






GLOBAL ROUTINE ALCFNCALL(BSYREGS,FREGCT)=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALLOCATION FOR A FUNCTION CALL.
	CALLED WITH "TREEPTR" POINTING TO THE FUNCTION CALL NODE
***************************************************************************)%
BEGIN
	EXTERNAL CLOBBCOMEQV;	!ROUTINE TO ASSUME THAT ALL VARS IN COMMON ARE CLOBBERED
	LOCAL PEXPRNODE CNODE;

	CNODE_.TREEPTR;

	%(***EVALUATE ALL ARGS INTO TMPS OR VARS***)%
	TREEPTR_.TREEPTR[ARG2PTR];
	ALCFNARGS(.BSYREGS,.FREGCT,.CNODE[DBLFLG]);

	REGCLOBB(0);	!THE CONTENTS OF REG 0 WILL BE CLOBBERED BY
			! EVAL OF THIS NODE
	REGCLOBB(1);	!THE CONTENTS OF REG 1 MIGHT BE CLOBBERED

	%(***FOR A NON-LIBRARY FN, MUST ASSUME THAT THE VALS OF ALL VARS THAT
		ARE PARAMS ARE CLOBBERED***)%
	IF .CNODE[OPERSP] NEQ LIBARY THEN
	BEGIN
		CLOBBCOMEQV();	!MUST ASSUME THAT ALL VARS IN COMMON
				! ARE CLOBBERED (ALSO ALL VARS EQUIVALENCED
				! TO ANYTHING
		IF .CNODE[ARG2PTR] NEQ 0 THEN
		BEGIN
			REGISTER ARGUMENTLIST ARGLST;	!PTR TO THE ARG LIST
			ARGLST_.CNODE[ARG2PTR];
			INCR CT FROM 1 TO .ARGLST[ARGCOUNT]	!LOOK AT EACH PARAM
			DO VARCLOBB(.ARGLST[.CT,ARGNPTR]);
		END;
	END;
END;


GLOBAL ROUTINE ALCFNARGS(BSYREGS,FREGCT,PARDBLFLG)=
%(***************************************************************************
	PERFORM REGISTER/TEMPORARY ALLOCATION FOR ALL ARGUMENTS OF
	A FUNCTION CALL.
	"PARDBLFLG" IS TRUE IFF THE FUNCTION-CALL NODE HAD A DOUBLE-WD
	VALTYPE (IF THE PARENT WAS A SUBROUTINE, PARDBLFLG IS ALWAYS
	FALSE).
	ALL ARGS MUST BE MATERIALIZED BEFORE THE FN IS CALLED.
	CALLED WITH THE GLOBAL TREEPTR POINTING TO THE ARGUMENT LIST
***************************************************************************)%
BEGIN
	LOCAL ARGUMENTLIST ARGLST;
	LOCAL FRGCT1,BSYRG1;

	%(***ARGLIST PTR IS 0 IF THERE ARE NO ARGS***)%
	IF .TREEPTR EQL 0 THEN RETURN;

	%(***GET A LOCAL PTR TO THE ARG LIST (TREEPTR WILL BE CLOBBERRED AS WALK DOWN)***)%
	ARGLST_.TREEPTR;

	%(***REPEAT THE FOLLOWING FOR EACH ARGUMENT***)%
	INCR CT FROM 1 TO .ARGLST[ARGCOUNT] BY 1
	DO
	BEGIN
		%(***GET PTR TO EXPRESSION NODE FOR THIS ARG***)%
		TREEPTR_.ARGLST[.CT,ARGNPTR];

		%(***IF THIS ARG INVOLVES A DOUBLE-PREC OR COMPLEX COMPUTATION,
			AND ARE NOT ALREADY ALLOCATING IN "DOUBLE-WD MODE",
			MUST CONVERT SET OF AVAILABLE REGS***)%
		IF .TREEPTR[DBLFLG] AND NOT .PARDBLFLG
		THEN
		BSYRG1_DPBSYREGS(.BSYREGS)

		%(***IF ARE OPERATING IN "DOUBLE-WD MODE" AND THIS ARG
			IS SINGLE-WD, CONVERT SET OF AVAILABLE REGS***)%
		ELSE
		IF .PARDBLFLG AND NOT .TREEPTR[DBLFLG]
		THEN BSYRG1_SPBSYREGS(.BSYREGS)

		ELSE
		BSYRG1_.BSYREGS;

		%(SETUP COUNT OF REGISTERS FREE IN BSYRG1)%
		FRGCT1_ONESCOUNT(.BSYRG1);

		%(***FOR A COMMON SUBEXPR- THE VAL MUST BE STORED IN A TEMP***)%
		IF .TREEPTR[OPRCLS] EQL CMNSUB 
		THEN
		BEGIN
			IF .TREEPTR[INREGFLG] AND NOT .TREEPTR[STOREFLG]
			THEN
			BEGIN
				TREEPTR[STOREFLG]_1;
				TREEPTR[TARGTMEM]_NXTTMP(.TREEPTR[DBLFLG]);
			END
		END

		ELSE
		IF .ARGLST[.CT,AVALFLG]
		THEN BEGIN END

		%(***FOR AN ARRAYREF, MUST GET PTR TO ELEM INTO A TMP***)%
		ELSE
		IF .TREEPTR[OPRCLS] EQL ARRAYREF
		THEN
		BEGIN
			%(***IF SUBSCRIPTS ARE ALL CONSTANTS, CAN SIMPLY PUT PTR TO ELEM
				INTO ARGLIST***)%
			IF .TREEPTR[ARG2PTR] NEQ 0
			%(******IF NOT, INSERT A "STORE-ADDRESS" NODE UNDER THE ARG-PTR,
				ABOVE THE ARRAYREF***)%
			THEN ARGLST[.CT,ARGNPTR]_ ALCTARY(.BSYRG1,.FRGCT1)
		END


		ELSE
		%(***PERFORM REG/TMP ALLOCATION FOR THIS ARG - TO GET ITS VAL
			INTO A TEMPORARY****)%
		ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYRG1,.FRGCT1);


	END;	!END OF INCR LOOP TO GO THRU ALL ARGS


END;	!END OF "ALCFNARGS"





GLOBAL ROUTINE ALCARRAY(BSYREGS,FREGCT)=
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR AN ARRAY REFERENCE
	FOR A FORMAL PARAM, THE ADDRESS WILL BE COMPUTED ENTIRELY INTO SOME REG
	FOR OTHER ARRAYS, THE OFFSET WILL BE COMPUTED INTO SOME REG AND
	THE BASE WILL BE RETRIEVED FROM THE SYMBOL TABLE BY THE OUTPUT MODULE
	CALLED WITH THE GLOBAL TREEPTR POINTING TO THE EXPRESSION NODE
	FOR THE ARRAY REFFERENCE
	RA IS A REGISTER TO USE TO HALD THE OFFSET IF ONE IS NEEDED
***************************************************************************)%
BEGIN
	REGISTER PEXPRNODE CNODE:ADDRNODE;
	LOCAL RA;	!REG TO USE TO HOLD INDEX
	OWN RB;
	LOCAL FRGCT1,BSYRG1;


	ROUTINE USESOMEREG(RA,BSYREGS)=
	%(************
		ROUTINE TO PICK A REG FROM BSYREGS TO USE TO HOLD THE INDEX
		AND SET UP FIELDS INDICATING THAT THAT REG IS TO BE USED
	**************)%
	BEGIN
		RA_RGTOU1(.CNODE,.ADDRNODE,.RA,CLRBIT(.BSYREGS,0));	!PICK A REG TO USE
		CNODE[TARGXF]_.RA;			!SET "INDEX" FIELD IN NODE TO INDICATE THE
								! REG TO INDEX OFF OF
		REGCLOBB(.RA);	!MUST ASSUME THAT THE PREVIOUS CONTENTS OF THE
						! REG USED ARE NOW CLOBBERED
	END;

	CNODE_.TREEPTR;
	ADDRNODE_.CNODE[ARG2PTR];		!2ND ARG UNDER AN ARRAYREF NODE IS
						! A PTR TO THE ADDRESS CALC TO BE PERFORMED

	%(***IF THE SS CALC IS ENTIRELY A CONSTANT (WHICH HAS ALREADY BEEN FOLDED INTO THE
		TARGET WD) - SIMPLY RETURN****)%
	IF .ADDRNODE EQL 0 THEN RETURN;

	%(***IF THIS ARRAY HAS DOUBLE-WD ENTRIES, THEN TO PERFORM THE ADDRESS ARITHMETIC WILL
		GO DOWN FROM DOUBLE-WD COMPUTATIONS TO SINGLE-WD COMPUTATIONS****)%
	IF .TREEPTR[DBLFLG]
	THEN
	BEGIN
		%(***ADJUST SET OF AVAILABLE REGS TO ONCE AGAIN INCLUDE ODD REGS
			(EXCEPT FOR THOSE ODD REGS HOLDING THE 2ND HALF OF A DP VAL)***)%
		BSYRG1_SPBSYREGS(.BSYREGS);
		FRGCT1_ONESCOUNT(.BSYRG1);
	END
	ELSE
	BEGIN
		BSYRG1_.BSYREGS;
		FRGCT1_.FREGCT;
	END;


	RA_AFREEREG(CLRBIT(.BSYRG1,0),.CNODE[SAVREGFLG],FALSE);	!GET A REG TO USE TO
							! HOLD THE VAR PART OF THE ADDRESS (AND
							! BE INDEXED FROM)



	%(***PERFORM REGISTER ALLOCATION FOR THE ADDRESS CALCULATION***)%
	IF NOT .CNODE[A2VALFLG] 
	THEN
	BEGIN
		TREEPTR_.CNODE[ARG2PTR];
		ALCINREG(.RA,.BSYRG1,.FRGCT1);
	END;


	%(***DETERMINE WHICH REG TO USE AS AN INDEX**************)%
	IF .ADDRNODE[OPRCLS] EQL DATAOPR	!IF ADDRESS IS A SIMPLE VARIABLE
	THEN
	BEGIN
		IF (RB_REGCONTAINING(.ADDRNODE)) GTR 0	!IF VAR WAS LEFT IN A
						! REG OTHER THAN 0  BY A PREVIOUS STMNT
			AND .CNODE[A2NGNTFLGS] EQL 0	!AND NEED NOT BE NEGATED OR COMPLEMENTED
		THEN
		BEGIN
			CNODE[TARGXF]_.RB;	!THEN USE THAT REG
			CNODE[A2SAMEFLG]_1	! AND DONT RELOAD IT
		END
		ELSE
		USESOMEREG(.RA,.BSYREGS);	!OTHERWISE LOAD THE INDEX INTO SOME REG

		IF .CNODE[SAVREGFLG]	!IF THE VAR WILL BE USEFUL TO HAVE IN REG
					! IN SOME FURTURE STMNT
			AND .CNODE[A2NGNTFLGS] EQL 0	! AND WAS NOT PICKED UP BY "MOVN"
		THEN SAVEREG(.CNODE[TARGXF],	!REMEMBER THAT THE REG USED AS INDEX
			.ADDRNODE,0,.CNODE[TARGXF]);	!CONTAINS THAT VAR
	END

	ELSE

	%(***IF HAVE ALREADY DETERMINED THAT THE INDEX SHOULD BE LEFT IN THE FN-RET
		REG, (IF SOME REG OTHER THAN 0 IS USED FOR FN-RET) THEN DONT
		CHANGE IT***)%
	IF .CNODE[ALCRETREGFLG]
	THEN BEGIN END

	ELSE
	%(***IF THE VARIABLE PART OF THE ADDR WAS CALCULATED INTO A
		REG OTHER THAN 0 AND OTHER THAN THE FN-RET REG, USE THAT REG
		AS THE INDEX***)%
	IF .ADDRNODE[INREGFLG] AND (.ADDRNODE[TARGTAC] NEQ 0) AND ( NOT .ADDRNODE[ALCRETREGFLG])
		AND NOT (.CNODE[A2VALFLG] AND .CNODE[A2NGNTFLGS] NEQ 0)	!IF ADDR WAS A COMMON SUB OR A REGCONTENTS
									! CANNOT USE THE REG IF VAL IN IT MUST
									! BE NEGATED OR COMPLEMENTED
	THEN
	BEGIN
		CNODE[TARGXF]_.ADDRNODE[TARGTAC];	!USE THE REG CONTAINING FOR THE ADDRESS
		CNODE[A2SAMEFLG]_1;			!DONT RELOAD THE REG
	END

	%(***OTHERWISE, PICK A REG TO USE***)%
	ELSE
	USESOMEREG(.RA,.BSYREGS);
END;





GLOBAL ROUTINE ALCTPCNV(RT,BSYREGS,FREGCT,TMPFLG)=
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR A TYPE CONVERSION NODE.

	THIS ROUTINE IS USED BOTH FOR ALLOCATING RESULT TO A REG AND FOR ALLOCATING
	IT TO A TEMPORARY.
	THE FLAG "TMPFLG" IS TRUE IF RESULT IS TO BE ALLOCATED TO A TEMP.
	THE ARG RT IS A REG IF ALLOCATING TOA REG, A TEMP IF ALLOCATING TO 
	A TEMP.

	IF ARE GOING FROM DOUBLE-WD COMPUTATIONS DOWN TO SINGLE WD
	COMPUTATIONS, ODD REGISTERS CAN NOW BE ASSIGNED (EXCEPT OF COURSE FOR
	THOSE WHOSE PRECEEDING EVEN REG WAS ASSIGNED TO SOME DOUBLE-WD
	RESULT.
	IF ARE GOING FROM SINGLE-WD COMPUTATIONS DOWN TO DOUBLE-WD COMPUTATIONS
	(ONLY OCCURS WHEN EXPLICITLY INVOKED BY PROGRAM), ODD REGISTERS
	CAN NO LONGER BE ASSIGNED, NOR CAN EVEN REGS WHICH ARE  FOLLOWED
	BY AN ODD REG THAT IS IN USE.

	IN THIS ROUTINE, WE USE THE LOCALS BSYRG1 AND FRGCT1 TO INDICATE WHICH
	REGISTERS ARE AVAILABLE FOR USE IN THE COMPUTATION OF THE ARG UNDER
	THE TYPE-CONVERSION NODE. THE ARGS BSYREGS AND FREGCT INDICATE WHICH REGS
	ARE AVAILABLE FOR THE COMPUTATION OF THIS TYPE-CONVERSION NODE ITSELF.

	THE LOCAL RA INDICATES THE REG TO BE USED FOR COMPUTATION OF THE TYPE-CONVERSION,
	CALLED WITH THE GLOBAL TREEPTR POINTING TO THE TYPE CONVERSION NODE.
***************************************************************************)%
BEGIN
	LOCAL RA,RB;			!REG TO BE USED
	LOCAL ARGREG;		!REG IN WHICH THE ARG WAS COMPUTED
	LOCAL PEXPRNODE ARGNODE;
	REGISTER PEXPRNODE CNODE;
	LOCAL BSYRG1;
	LOCAL FRGCT1;

	CNODE_.TREEPTR;
	ARGNODE_.CNODE[ARG2PTR];



	%(***INIT SET OF AVAILABLE REGS TO THOSE THAT WERE AVAILABLE ABOVE THIS NODE***)%
	BSYRG1_.BSYREGS;

	%(***IF CONVERSION IS FROM DOUBLE-WD TO SINGLE-WD AND HENCE ARE GOING
		DOWN FROM SINGLE-WD COMPUTATIONS TO DOUBLE-WD COMPUTATIONS****)%
	IF .CNODE[SDBLFLG] AND NOT .CNODE[DBLFLG]
	THEN
	%(**ADJUST SET OF AVAILABLE REGISTERS TO INCLUDE ONLY EVEN REGS***)%
	BSYRG1_DPBSYREGS(.BSYRG1);


	%(***IF CONVERSION IS FROM SINGLE-WD TO DOUBLE-WD AND ARE HENCE
		GOING DOWN FROM DOUBLE-WD COMPUTATIONS TO SINGLE-WD COMPUTATIONS****)%
	IF NOT .CNODE[SDBLFLG] AND .CNODE[DBLFLG]
	THEN
	%(***ADJUST SET OF AVAILABLE REGS TO INCLUDE ODD REGS AGAIN (EXCEPT
		FOR THOSE ODD REGS CONTAININD THE 2ND HALF OF A DP VAL TO BE SAVED)***)%
	BSYRG1_SPBSYREGS(.BSYRG1);

	%(***DETERMINE NUMBER OF REGS NOW AVAILABLE FOR USE***)%
	FRGCT1_ONESCOUNT(.BSYRG1);

	%(***SET RA TO INDICATE THE REG IN WHICH THE COMPUTATION
		OF THE TYPE CONVERSION  WILL TAKE
		PLACE (IF ARE ALLOCATING TO A REG IT WILL BE THAT REG IF POSSIBLE) ***)%
	IF .TMPFLG
	THEN
	RA_AFREEREG(.BSYREGS AND .BSYRG1,FALSE,.CNODE[SDBLFLG] OR .CNODE[DBLFLG]) !IF ARE ALLOCATING TO A TMP, USE THE
						! FIRST REG THAT IS LEGAL FOR BOTH THE
						! OLD AND NEW VALUE TYPES
	ELSE
	IF BITSET(.BSYRG1,.RT)		!IF THE SPECIFIED DESTIN REG FOR
						! THE PARENT IS ALSO LEGAL FOR THE OLD
						! VALUE-TYPE, THEN USE THAT REG
	THEN
	RA_.RT
	ELSE
	RA_AFREEREG(.BSYREGS AND .BSYRG1,FALSE,.CNODE[SDBLFLG] OR .CNODE[DBLFLG]); !OTHERWISE USE THE 1ST REG 
						! THAT IS LEGAL FOR BOTH THE OLD AND NEW
						! VALTYPES





	%(****PERFORM REGISTER ALLOCATION FOR NODES BELOW THIS NODE***)%

	TREEPTR_.ARGNODE;

	%(****IF NO ACTUAL CODE NEEDS TO BE GENERATED FOR THIS TYPE-CONVERSION (IE THE
		TYPE-CONVERSION NODE IS PRESENT ONLY TO KEEP TRACK OF THE WAY IN WHICH
		THE VALUE CORRESPONDING TO THE NODES BELOW IS TO BE USED),
		THEN THE "CONVERTED" VALUE SHOULD BE ACCESSED IN THE SAME
		WAY AS THE UNCONVERTED VALUE
	********)%
	IF NOCNV(CNODE)
	THEN
	BEGIN
		IF .CNODE[A2VALFLG] 
		THEN
		BEGIN
			%(***IF SUBNODE IS A SCALAR VARIABLE, THE ADDRESS FOR THE "CONVERTED"
				VARIABLE IS IDENTICAL TO THE ADDRESS OF THE ORIGINAL VAR***)%
			IF .ARGNODE[OPRCLS] EQL DATAOPR
			THEN
			CNODE[TARGADDR]_.ARGNODE[IDADDR]

			%(***IF SUBNODE IS A COMMON SUBEXPR, THE "CONVERTED" VALUE IS ACCESSED
				IN THE SAME WAY AS THE ORIGINAL VALUE***)%
			ELSE
			CNODE[TARGET]_.ARGNODE[TARGET];
		END

		%(***IF THE VALUE OF THE ARG MUST BE COMPUTED,  PERFORM REGISTER ALLOCATION FOR
			THAT COMPUTATION. THE ADDRESS CORRESPONDING TO THE "CONVERTED"
			VALUE IS IDENTICAL TO THE ADDRESS CORRESPONDING TO THE UNCONVERTED ONE***)%
		ELSE
		BEGIN
			IF .TMPFLG
			THEN
			ALCINTMP(.RT,.BSYRG1,.FRGCT1)
			ELSE
			BEGIN
				%(***IF THE ARGNODE WAS ALLOCATED TO THE FN RETURN REG,
					AND WE THEN FOUND THAT THAT REG WOULD BE CLOBBERED
					BEFORE THE RESULT WAS USED (AND HENCE DEALLOCATED THE
					CONVERTED VAL FROM THE RETREG), DEALLOCATE
					THE ARGNODE FROM THE RETREG ALSO***)%
				IF NOT .CNODE[ALCRETREGFLG] AND .ARGNODE[ALCRETREGFLG]
				THEN
				BEGIN
					ARGNODE[A1SAMEFLG]_0;
					ARGNODE[A2SAMEFLG]_0;
					ARGNODE[ALCRETREGFLG]_0;
					ARGNODE[INREGFLG]_0;
				END;
				ALCINREG(.RA,.BSYRG1,.FRGCT1);
			END;
			!ALCINTMP MAY HAVE INSERTED A STORE CLASS NODE BETWEEN
			! A TYPE CONVERSION AND AN ARRAYREF NODE - IN THIS CASE,
			! ARGNODE NEEDS TO BE UPDATED TO PREVENT A MOVE-MOVEM
			! PAIR FROM AND TO THE SAME LOCATION!
			ARGNODE_.CNODE[ARG2PTR];
			CNODE[TARGET]_.ARGNODE[TARGET];
		END;
	END


	%(****IF CODE MUST BE GENERATED TO PERFORM THE CONVERSION, THEN THE "UNCONVERTED"
		VALUE WILL HAVE TO BE LOADED INTO A REG TO CONVERT IT****)%
	ELSE
	BEGIN


		%(***IF ARG REQUIRES COMPUTATION, COMPUTE IT INTO RA IF POSSIBLE****)%
		IF NOT .CNODE[A2VALFLG]
		THEN
		BEGIN
			ALCINREG(.RA,.BSYRG1,.FRGCT1);

			%(***IF POSSIBLE, USE THE REG IN WHICH ARG WAS LEFT AS THE
				REG FOR COMPUTATION OF THE TYPE-CONVERSION***)%
			IF (.ARGNODE[INREGFLG]) AND (NOT .ARGNODE[ALCRETREGFLG])
			THEN
			RA_.ARGNODE[TARGTAC];

		END;


		%(***IF HAVE PREVIOUSLY ALLOCATED THE TYPE-CONVERSION TO BE DONE IN
			THE FN-RETURN REG, ARE DONE******)%
		IF NOT .CNODE[ALCRETREGFLG]
		THEN
		BEGIN
			%(**IF ARG IS A VAR WHOSE VAL WAS LEFT IN A REG BY A PREVIOUS STMNT, USE
				THAT REG IF POSSIBLE**)%
			IF (RB_REGCONTAINING(.ARGNODE)) GEQ 0		!IF ARG WAS LEFT IN A REG
			THEN
			BEGIN
				IF BITSET(.BSYRG1 AND .BSYREGS, .RB)	!IF THIS REG IS LEGAL FOR
									! THE PRECISION OF BOTH THE
									! SOURCE AND RESULT TYPES
				THEN
				BEGIN
					 SETTAC(.CNODE,.RB);	!USE RB FOR THE TYPE CONV
					CNODE[A2SAMEFLG]_1;	!DONT RELOAD THE REG

				END
				ELSE
				BEGIN
					RA_RGTOU1(.CNODE,.ARGNODE,.RA,(.BSYREGS AND .BSYRG1));	!USE SOME OTHER FREE RG
					SETTAC(.CNODE,.RA)
				END
			END
			ELSE
			BEGIN
				%(***SET REG FOR COMPUTATION OF THE TYPE-CONVERSION TO RA IF 
					RA IS LEGAL TO USE, OTHERWISE TO SOME OTHER LEGAL REG***)%
				RA_RGTOU1(.CNODE,.ARGNODE,.RA,(.BSYREGS AND .BSYRG1));
				SETTAC(.CNODE,.RA);
	
				%(***IF THE TYPE CONVERSION IS BEING COMPUTED IN THE SAME REG AS ITS ARG***)%
				IF (.CNODE[TARGTAC] EQL .ARGNODE[TARGTAC]) AND .ARGNODE[INREGFLG]
				THEN CNODE[A2SAMEFLG]_1;
			END;

			%(***IF ARE ALLOCATING TO A TEMPORARY, SET "STOREFLG" TO INDICATE
				THAT THE VAL COMPUTED MUST BE STORED; SET LOC FOR VAL TO THE TMP****)%
			IF .TMPFLG
			THEN
			BEGIN
				CNODE[TARGTMEM]_.RT;
				CNODE[STOREFLG]_1;
			END

			%(***IF ARE ALLOCATING TO A REG, SET MEMREF FIELD TO INDICATE THAT
				THAT IS THE LOC OF THE VAL****)%
			ELSE
			BEGIN
				CNODE[TARGADDR]_.CNODE[TARGTAC];
				CNODE[INREGFLG]_1;
			END;
		END;

	END;
END;	!END OF ALCTPCNV







GLOBAL ROUTINE ALCNEGNOT(RA,BSYREGS,FREGCT)=
%(***************************************************************************
	TO PERFORM REG ALLOC FOR A NEG/NOT NODE
***************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:ARGNODE;
	LOCAL RB;

	CNODE_.TREEPTR;
	ARGNODE_.TREEPTR[ARG2PTR];


	IF .CNODE[A2VALFLG]
	THEN
	BEGIN
		RA_RGTOU1(.CNODE,.ARGNODE,.RA,.BSYREGS);
		SETTARGINREG(.CNODE,.RA);
	END
	ELSE
	BEGIN
		TREEPTR_.CNODE[ARG2PTR];
		ALCINREG(.RA,.BSYREGS,.FREGCT);

		%(***DECIDE WHAT REG TO COMPUTE THE NEG/NOT IN***)%

		IF .CNODE[ALCRETREGFLG]
		%(***IF HAVE ALREADY DECIDED TO COMPUTE THE NEG/NOT IN THE FN-RET REG
			DONT CHANGE IT***)%
		THEN BEGIN END

		ELSE
		%(***IF THE ARG WAS LEFT IN A REG OTHER THAN THE FN-RET REG, USE THAT REG***)%
		IF .ARGNODE[INREGFLG] AND NOT .ARGNODE[ALCRETREGFLG]
		THEN
		BEGIN
			CNODE[TARGET]_.ARGNODE[TARGET];
			CNODE[A2SAMEFLG]_1;
		END
		ELSE
		IF (RB_REGCONTAINING(.ARGNODE)) GEQ 0	!IF ARG IS A VAR WHOSE VAL WAS LEFT
							! IN A REG BY ANOTHER STMNT
		THEN
		BEGIN
			IF BITSET(.BSYREGS,.RB)		!IF IT'S LEGAL TO CLOBBER THAT REG
							! IN THIS STMNT
			THEN
			BEGIN
				CNODE[TARGTAC]_.RB;	!USE THAT REG
				CNODE[A2SAMEFLG]_1;	!DONT RELOAD THE REG
			END
			ELSE
			BEGIN		!OTHERWISE, USE SOME FREE REG
				RA_RGTOU1(.CNODE,.ARGNODE,.RA,.BSYREGS);
				SETTARGINREG(.CNODE,.RA)
			END
		END
		ELSE
		BEGIN
			RA_RGTOU1(.CNODE,.ARGNODE,.RA,.BSYREGS);
			SETTARGINREG(.CNODE,.RA)
		END
	END
END;


GLOBAL ROUTINE ALCSPECOP(RA,BSYREGS,FREGCT)=
%(***************************************************************************
	PERFORM REGISTER ALLOCATION FOR THE SPECIAL OPERATIONS INTRODUCED
	BY PHASE 2 SKELETON.
	FOR P2MUL (POWER OF 2 MULTIPLY),P2DIV, AND EXPCIOP WHEN THE POWER IS A POWER OF 2
	 ALLOCATE ARG TO BE COMPUTED INTO REG TO BE USED FOR FINAL RESULT.
	FOR  P2PL1MUL	 ("POWER OF 2 PLUS 1" MULTIPLY)
	 AND EXPCIOP FOR POWER OTHER THEN A POWER OF 2
	 ALLOCATE ARG TO BE COMPUTED INTO
	SOME OTHER REG.
	CALLED WITH THE ARGS
		RA - REG INTO WHICH SHOULD ATTEMPT TO COMPUTE RESULT
		BSYREGS - INDICATES WHICH REGS ARE AVAILABLE
		FREGCT - CT OF AVAILABLE REGS
	CALLED WITH THE GLOBAL TREEPTR POINTING TO THE EXPRESSION NODE
		FOR WHICH ALLOCATION IS TO BE PERFORMED
***************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:ARGNODE;
	LOCAL RB;

	CNODE_.TREEPTR;
	ARGNODE_.CNODE[ARG1PTR];

	IF .CNODE[A1VALFLG]	!IF ARG REQUIRES NO COMPUTATION
	THEN
	BEGIN
		IF (RB_REGCONTAINING(.ARGNODE)) GEQ 0	!IF ARG IS A VAR WHOSE VAL WAS LEFT IN A REG
		THEN
		BEGIN
			IF BITSET(.BSYREGS,.RB)	!IF ITS OK TO CLOBBER THAT REG
			THEN
			BEGIN
				SETTARGINREG(.CNODE,.RB);	!USE THAT REG
				CNODE[A1SAMEFLG]_1;	!DONT RELOAD THE REG
			END
			ELSE	!OTHERWISE USE RA TO COMPUTE THE OP
			SETTARGINREG(.CNODE,.RA)
		END
		ELSE	!OTHERWISE USE RA TO COMPUTE THE OP
		SETTARGINREG(.CNODE,.RA)
	END
	ELSE
	%(***IF ARG MUST BE CALCULATED, PERFORM REGISTER ALLOCATION FOR THAT CALCULATION***)%
	BEGIN
		TREEPTR_.ARGNODE;
		IF .CNODE[OPERSP] EQL P2PL1OP
			OR 
			(.CNODE[OPERSP] EQL EXPCIOP AND NOT POWOF2(.CNODE[ARG2PTR]) )
		THEN
		%(***FOR MULTIPLICATION BY POWER OF 2 PLUS 1 OR TO RAISE A VAL TO POWER 
			THAT IS NOT A POWER OF 2***)%
		BEGIN
			REGISTER BSYRG1;
			IF .FREGCT GTR 1	!IF HAVE MORE FREE REGS THAN JUST "RA"
			THEN			! THEN DONT COMPUTE THE ARG INTO RA
			BEGIN
				RB_AFREEREG(CLRBIT(.BSYREGS,.RA),FALSE,.ARGNODE[DBLFLG]);
				ALCINREG(.RB,.BSYREGS,.FREGCT);
			END
			ELSE ALCINREG(.RA,.BSYREGS,.FREGCT);


			%(***PICK OUT A REG TO USE FOR COMP OF VAL OF PARENT***)%
				IF (RB_RGTOSAVE(.ARGNODE)) GEQ 0	!IF SOME REG MUST BE SAVED TO
							! REFERENCE THE VAL OF THE ARG
			THEN BSYRG1_CLRBIT(.BSYREGS,.RB)	!CANNOT USE THAT REG TO COMPUTE
							! THE PARENT
			ELSE BSYRG1_.BSYREGS;

			RA_RGTOU1(.CNODE,.ARGNODE,.RA,.BSYRG1);

			SETTARGINREG(.CNODE,.RA)
		END

		ELSE
		%(***FOR P2MUL,P2DIV, OR EXPCIOP WHEN THE POWER IS
			A POWER OF 2(AND HENCE A COPY OF THE ARG IS NOT NEEDED)**)%
		BEGIN
			ALCINREG(.RA,.BSYREGS,.FREGCT);

			%(***IF HAVE ALREADY DECIDED TO COMPUTE THE P2MUL IN THE FN-RET
				REG, DONT CHANGE IT***)%
			IF .CNODE[ALCRETREGFLG]
			THEN BEGIN END

			ELSE
			%(***WANT TO COMPUTE VAL OF PARENT IN SAME REG AS ARG WAS
				COMPUTED IN IF POSSIBLE***)%
			IF .ARGNODE[INREGFLG] AND NOT .ARGNODE[ALCRETREGFLG]
			THEN
			BEGIN
				CNODE[TARGET]_.ARGNODE[TARGET];
				CNODE[A1SAMEFLG]_1;
			END
			ELSE
			BEGIN
				RA_RGTOU1(.CNODE,.ARGNODE,.RA,.BSYREGS);
				SETTARGINREG(.CNODE,.RA)
			END;
		END
	END
END;



GLOBAL ROUTINE ALCILF(RA,BSYREGS,FREGCT)=
%(***************************************************************************
	TO PERFORM REGISTER FOR AN "IN-LINE-FN" NODE.
	FOR ALL EXCEPT ABS AND IABS, USE ALCA.
	RVRSFLG IS NEVER SET IN THIS NODE..
***************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:ARG1NODE;

	IF (.TREEPTR[OPERSP] EQL ABSFN)
	THEN
	BEGIN
		CNODE_.TREEPTR;
		ARG1NODE_.CNODE[ARG1PTR];
		IF NOT .CNODE[A1VALFLG]	!IF ARG MUST BE COMPUTED
		THEN
		BEGIN
			TREEPTR_.ARG1NODE;
			ALCINREG(.RA,.BSYREGS,.FREGCT);


			%(***IF HAVE DETERMINED (IN COMPLEXITY PASS) THAT SHOULD LEAVE
				VALUE OF THIS NODE IN THE FN-RET REG, DONT CHANGE IT***)%
			IF .CNODE[ALCRETREGFLG]
			THEN BEGIN END

			ELSE
			%(***IF  ARG1 WAS LEFT IN A REG OTHER THAN FN-RET REG
				 COMPUTE CNODE IN THAT REG***)%
			IF .ARG1NODE[INREGFLG] AND NOT .ARG1NODE[ALCRETREGFLG]
			THEN
			BEGIN
				CNODE[TARGTAC]_.ARG1NODE[TARGTAC];
				CNODE[TARGADDR]_.ARG1NODE[TARGTAC];
				CNODE[INREGFLG]_1;
				CNODE[A1SAMEFLG]_1;
			END
			ELSE
			BEGIN
				RA_RGTOU1(.CNODE,.ARG1NODE,.RA,.BSYREGS);
				SETTARGINREG(.CNODE,.RA)
			END;
		END
		ELSE	!IF ARG IS A VAR,COMMON SUB, OR REGCONTENTS
		BEGIN
			RA_RGTOU1(.CNODE,.ARG1NODE,.RA,.BSYREGS);
			SETTARGINREG(.CNODE,.RA)
		END;
	END
	ELSE
	ALCA(.RA,.BSYREGS,.FREGCT);
END;


GLOBAL ROUTINE ALCINTMP(TA,BSYREGS,FREGCT) =
%(***************************************************************************
	PERFORM REGISTER/TEMPORARY ALLOCATION FOR SUBNODES OF THE NODE POINTED TO BY
	THE GLOBAL "TREEPTR" SUCH THAT THE VALUE OF THAT NODE
	WILL BE LEFT IN THE MOMORY LOCATION INDICATED BY THE MEMREF FIELD  "TA"
	THE OTHER ARGS FOR THIS ROUTINE ARE:
	 "BSYREGS" -  HAS BITS 0-15 REPRESENTING THE 16 ACS
		THE BIT FOR A GIVEN AC IS 1 IF THAT AC IS AVAILABLE FOR USE
	"FREGCT" - NUMBER OF REGS AVAILABLE FOR USE
***************************************************************************)%

BEGIN
	LOCAL RB;
	LOCAL PEXPRNODE CNODE:ARGNODE;
	LOCAL SAVNOBBREGS;
	EXTERNAL NOBBREGSLOAD;	! FLAG TO NOT REMEMBER WHO'S IN REG
	EXTERNAL CLOBBCOMEQV;	!ROUTINE IN BASIC BLOCK ALLOCATOR THAT
				! ASSUMES THAT VARS IN COMMON HAVE BEEN CLOBBERED


	CNODE_.TREEPTR;


	CASE .TREEPTR[OPRCLS] OF SET

	%(****FOR A BOOLEAN OPERATOR***************)%
	BEGIN
		%(***EQV AND XOR ARE TREATED LIKE ARITH***)%
		IF .TREEPTR[BOOLCLS] NEQ ANDORCLS
		THEN
		ALCTA(.TA,.BSYREGS,.FREGCT)

		ELSE
		%(***FOR CONTROL-TYPE BOOLEANS, ALLOCATE VAL TO TA. ALLOC
			THE CONTROL PART IN SAME WAY AS DO WHEN VAL GOES TO REG***)%
		IF .TREEPTR[VALTYPE] EQL CONTROL
		THEN
		BEGIN
			SAVNOBBREGS_.NOBBREGSLOAD;	! SAVE CURRENT ONE
			NOBBREGSLOAD_TRUE;	! DON'T SAVE REGS WHICH
						! MAY NOT GET LOADED
			ALCCNT(.BSYREGS,.FREGCT);
			CNODE[TARGTMEM]_.TA;
			NOBBREGSLOAD_.SAVNOBBREGS;
		END

		ELSE
		BEGIN
			ARGNODE_.TREEPTR[ARG2PTR];

			%(***IF THE 2ND ARG IS NOT OF TYPE CONTROL, THEN NEITHER ARG IS.
				TREAT LIKE ARITHMETIC. ***)%
			IF .ARGNODE[VALTYPE] NEQ CONTROL
			THEN ALCTA(.TA,.BSYREGS,.FREGCT)

			%(***IF 1ST ARG IS A MASK, 2ND ARG OF TYPE CONTROL***)%
			ELSE ALCTVBOOL(.TA,.BSYREGS,.FREGCT);
		END;

	END;

	%(****FOR A DATA REFERENCE - SHOULD RARELY GET HERE*****)%
	BEGIN END;

	%(****FOR RELATIONALS***************************************)%
	BEGIN

		%(****PERFORM REGISTER ALLOCATION FOR THE COMPARISON****)%
		ALCRL1(.BSYREGS,.FREGCT);
		CNODE[TARGTMEM]_.TA;
	END;


	%(*****FOR FUNCTION CALLS********************************)%
	BEGIN
		TREEPTR[TARGTMEM]_.TA;
		TREEPTR[STOREFLG]_1;
		TREEPTR[TARGTAC]_RETREG;
		TREEPTR[INREGFLG]_0;
		ALCFNCALL(.BSYREGS,.FREGCT);
	END;


	%(*****FOR ARITHMETIC EXPRESSIONS************************)%
	ALCTA(.TA,.BSYREGS,.FREGCT);

	%(*****FOR TYPE CONVERSION******************************)%
	BEGIN
		CNODE_.TREEPTR;
		ALCTPCNV(.TA,.BSYREGS,.FREGCT,TRUE);

		%(***IF THE VAL COULD BE ALLOCATED DIRECTLY TO A TMP, STORE IT IN TA***)%
		IF .CNODE[INREGFLG]
		THEN
		BEGIN
			CNODE[INREGFLG]_0;
			CNODE[STOREFLG]_1;
			CNODE[TARGTMEM]_.TA;
		END;
	END;

	%(******FOR AN ARRAY REFERENCE*******************)%
	%(********MUST INSERT A "STORE" NODE ABOVE THE ARRYAREF NODE, TO HOLD THE
		ADDRESS TA - SINCE THE TARGTMEM FIELD OF THE ARRAYREF NODE MUST
		HOLD THE ARRAY OFFSET**********)%
	BEGIN
		OWN PEXPRNODE PARNODE:STORENODE;
		PARNODE_.TREEPTR[PARENT];

		%(***IN THE CASE WHERE THE ARRAY IS DOUBLE-WD (IE DP OR COMPLEX) AND THERE
			IS ONLY ONE REG PAIR LEFT WE WONT HAVE ENOUGH REGS
			TO HAVE THE INDEX IN A REG AND PICK UP THE 2 WDS OF THE ARRAY ELEMENT. 
			(SINCE WE CANNOT PICK UP A DOUBLE-WD VAL INTO THE SAME REG USED FOR INDEXING)
			IN THIS CASE, SAVE A PTR TO THE ELEMENT INSTEAD.
		*********)%
		IF .TREEPTR[DBLFLG] AND (.TREEPTR[ARG2PTR] NEQ 0) AND .FREGCT LSS 2
		THEN
		BEGIN
			(IF .PARNODE[ARG1PTR] EQL .TREEPTR THEN PARNODE[ARG1PTR] ELSE PARNODE[ARG2PTR])_
				ALCTARY(.BSYREGS,.FREGCT)
		END
		ELSE
		%(***OTHERWISE, STORE THE VALUE OF THE ARRAY ELEMENT IN THE TEMP**)%
		BEGIN
			STORENODE_MAKPR1(.PARNODE,STORECLS,STARVAL,.TREEPTR[VALTYPE],0,.TREEPTR);
			STORENODE[TARGTMEM]_.TA;
			(IF .PARNODE[ARG1PTR] EQL .TREEPTR THEN PARNODE[ARG1PTR]
				ELSE PARNODE[ARG2PTR]) _ .STORENODE;
			ALCARRAY(.BSYREGS,.FREGCT);
			SETTAC(.STORENODE,
				RGTOU1(.STORENODE,.STORENODE[ARG2PTR],
					AFREEREG(.BSYREGS,FALSE,FALSE),.BSYREGS));
		END
	END;

	%(*****FOR COMMON SUBEXPRS - DONT WALK DOWN ON THEM***)%
	BEGIN END;

	%(****FOR NEG/NOT***************************************)%
	BEGIN
		ARGNODE_.CNODE[ARG2PTR];

		RB_AFREEREG(.BSYREGS,FALSE,.ARGNODE[DBLFLG]);

		%(***IF ARG UNDER THIS NODE IS COMPUTED INTO A REG, USE THAT REG, 
			OTHERWISE USE RB******)%
		IF .CNODE[A2VALFLG]
		THEN
		%(***FOR ARG A VARIABLE OR COMMON-SUBEXPR***)%
		SETTAC(.CNODE,.RB)
		ELSE
		BEGIN
			TREEPTR_.ARGNODE;
			ALCINREG(.RB,.BSYREGS,.FREGCT);
			IF .ARGNODE[INREGFLG]
			THEN
			BEGIN
				CNODE[TARGTAC]_.ARGNODE[TARGTAC];
				CNODE[A2SAMEFLG]_1;
			END
			ELSE
			BEGIN
				RB_RGTOU1(.CNODE,.ARGNODE,.RB,.BSYREGS);
				SETTAC(.CNODE,.RB)
			END
		END;

		%(***STORE THE VALUE INTO THE TMP*************)%
		CNODE[INREGFLG]_0;
		CNODE[TARGTMEM]_.TA;
		CNODE[STOREFLG]_1;
	END;

	%(***FOR SPECIAL OPS -
		 P2MUL,P2DIV,SQUARE,CUBE,... -  COMPUTE THE VALUE IN A REG, THEN STORE***)%
	BEGIN
		ALCINREG(AFREEREG(.BSYREGS,FALSE,.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
		CNODE[INREGFLG]_0;
		CNODE[TARGTMEM]_.TA;
		CNODE[STOREFLG]_1;
	END;


	CGERR();				!FIELD-REF, NOT IN RELEASE 1
	CGERR();				!STORECLS: SHOULD NOT EXIST PRIOR TO
						! THIS PASS OVER THE TREE
	BEGIN  END;				!REGCONTENTS: SHOULD RARELY WALK DOWN HERE
	CGERR();				!LABOP: SHOULD NEVER WALK DOWN ON ONE
	CGERR();				!STATEMENT: SHOULD NOT OCCUR UNDER
						! AN EXPRESSION
	CGERR();				!IOLSCLS: SHOULD NOT OCCUR


	%(****FOR AN IN-LINE-FN:  COMPUTE THE VAL IN A REG, THEN STORE*****)%
	BEGIN
		ALCILF(AFREEREG(.BSYREGS,FALSE,.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
		CNODE[INREGFLG]_0;
		CNODE[TARGTMEM]_.TA;
		CNODE[STOREFLG]_1;
	END;

	TES;

END;



GLOBAL ROUTINE ALCTVBOOL(TA,BSYREGS,FREGCT)=
%(***************************************************************************
	ROUTINE TO PERFORM REGISTER ALOCATION FOR  AN "AND" OR "OR" NODE  WHOSE VALUE IS TO BE
	COMPUTED INTO THE MEMORY LOCATION "TA", AND WHICH IS KNOWN TO HAVE ARG2
	OF TYPE CONTROL, AND ARG1 NOT OF TYPE CONTROL.
	THE VALUE OF ARG1 WILL BE COMPUTED AND STORED INTO TA, THEN ARG2 WILL BE EVALUATED
	AND IN THE CASE OF "AND", 0 WILL BE STORED INTO TA IF ARG2 IS FALSE,
	IN THE CASE OF "OR", 1 WILL BE STORED IF ARG2 IS TRUE
	TREEPTR POINTS TO THE PARENT NODE.
***************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:ARG1NODE;
	LABEL ALLARG1;
	LOCAL RA;

	%(***DEFINE MACRO TO USE SOME LEGAL REGISTER***)%
MACRO	USESOMEREG=
BEGIN
	RA_RGTOU1(.CNODE,.ARG1NODE,AFREEREG(.BSYREGS,FALSE,FALSE),.BSYREGS);
	SETTAC(.CNODE,.RA);
END$;


	%(***DEFINE MACRO TO USE THE REG INTO WHICH ARG1 WAS COMPUTED (AND THEN
		STORE VAL INTO TA)***)%
MACRO	USEA1REG=
BEGIN
	CNODE[TARGTAC]_.ARG1NODE[TARGTAC];
	CNODE[A1SAMEFLG]_1;
END$;

	CNODE_.TREEPTR;
	ARG1NODE_.TREEPTR[ARG1PTR];

	%(***PERFORM REG ALLOC FOR ARG1******)%
	IF .CNODE[A1VALFLG] 
	THEN
	BEGIN
		%(***IF ARG IS A COMMON SUBEXPR OR REGCONTENTS, WILL JUST STORE IT INTO TA)%
		IF .ARG1NODE[INREGFLG]
		THEN
%[1064]%	CNODE[TARGTAC]_.ARG1NODE[TARGTAC]
		%(***IF ARG IS IN MEMORY, WILL LOAD IT AND STORE IT INTO TA***)%
		ELSE
		USESOMEREG
	END
	ELSE
ALLARG1:BEGIN
		TREEPTR_.ARG1NODE;
		!IF THE AND NODE (OR NODE) HAS A1NOTFLG SET, MUST BE
		! VERY CAREFUL ABOUT TARGETING BOTH ARG1NODE AND CNODE
		! SO THAT ARG1NODE GOES TO A REG WHILE CNODE GOES TO MEMORY
		IF .CNODE[A1NOTFLG]
		THEN
		BEGIN
			RA_AFREEREG(.BSYREGS,FALSE,FALSE);
			ALCINREG(.RA,.BSYREGS,.FREGCT);
			!IF THE PRECEDING CALL TO ALCINREG DOES NOT REALLY ALLOCATE
			! THE REGISTER THAT WAS EXPECTED, THEN WE NEED TO CALL 
			! SETTAC TO SET TARGET IN CNODE.
	![672] IF THE PRECEDING CALL TO ALCINREG DOES NOT REALLY ALLOCATE
	![672] THE REGISTER THAT WAS EXPECTED, THEN WE NEED TO CALL 
	![672] SETTAC TO SET TARGET IN CNODE.
	%[672]%		IF .ARG1NODE[INREGFLG] THEN 
	%[672]%		CNODE[A1SAMEFLG]_0
	%[672]%		ELSE USESOMEREG;

			LEAVE ALLARG1
		END;
		ALCINTMP(.TA,.BSYREGS,.FREGCT);
		IF .ARG1NODE[TARGTMEM] EQL .TA
		%(***IF ARG1 WAS COMPUTED INTO TA, WILL NOT NEED TO LOAD IT***)%
		THEN CNODE[A1SAMEFLG]_1
		ELSE
		%(**IF ARG1 WAS LEFT IN A REG, WILL STORE IT IN TA; IF NOT LOAD
			IT INTO A REG AND STORE IT INTO TA***)%
		IF  .ARG1NODE[INREGFLG]
		THEN
		USEA1REG
		ELSE
		USESOMEREG
	END;

	CNODE[TARGTMEM]_.TA;
	!IF THE COMPLEXITY PASS ALLOCATED THIS NODE TO BE COMPUTED
	! IN FUNCTION RETURN REGISTER, UNDO THAT DECISION
	IF .CNODE[ALCRETREGFLG] THEN
		BEGIN
			CNODE[ALCRETREGFLG]_0;
			CNODE[INREGFLG]_0
		END;

	%(***PERFORM ALLOCATION FOR THE CONTROL-TYPE ARG***)%
	TREEPTR_.CNODE[ARG2PTR];
	ALCNARG(.BSYREGS,.FREGCT);
END;


GLOBAL ROUTINE ALCTA(TA,BSYREGS,FREGCT) = 
%(***************************************************************************
	PERFORM REGISTER/TEMPORARY ALLOCATION FOR A BINARY NODE POINTED TO
	BY THE GLOBAL TREEPTR
	THE OPERATOR ON THIS NODE IS ARITHMETIC OR BOOLEAN AND IS ALWAYS
	ONE THAT CAN BE PERFORMED TO MEMORY, ***EXCEPT*** FOR KI10 DOUBLE-WD OPERATIONS
	CALLED WITH THE ARGS
		TA - TEMPORARY INTO WHICH THE RESULT SHOULD BE COMPUTED
		BSYREGS - BITS 0-15 OF THIS WD REPRESENT THE 16 REGS,
			A BIT IS 1 IFF THE CORRESP REG IS AVAIL FOR USE
***************************************************************************)%

BEGIN
	FORWARD USEARGREG;
	REGISTER PEXPRNODE CNODE;
	REGISTER PEXPRNODE ARG1NODE;
	LOCAL PEXPRNODE ARG2NODE;
	LOCAL RA;					!REGISTER TO BE USED IN THE
							!COMPUTATION OF THE VAL OF THIS NODE

	OWN CMPLX1,CMPLX2;				!NUMBER OF REGS NECESSARY TO
							! EVALUATE ARG1, ARG2




	ROUTINE USESOMEREG(BSYREGS)=
	%(******************************
		LOCAL ROUTINE TO USE SOME LEGAL REGISTER.
		DETERMINE REG TO USE AND THEN SET TARGET AC TO THAT REG 
	********************************)%
	BEGIN
		OWN RA;

		%(***IF FN-RET REG WAS ALREADY ASSIGNED, DONT DO ANYTHING***)%
		IF .CNODE[ALCRETREGFLG]
		THEN BEGIN END
		ELSE
		BEGIN
			%(***GET A REG THAT CAN BE USED***)%
			RA_REGTOUSE(.CNODE,.ARG1NODE,.CNODE[ARG2PTR],
						AFREEREG(.BSYREGS,FALSE,.CNODE[DBLFLG]),.BSYREGS);

			%(***SET REG FOR COMP OF CNODE TO RA***)%
			SETTAC(.CNODE,.RA);
		END
	END;

	ROUTINE USEARGREG(RA,BSYREGS)=
	%(**********************************************************
		LOCAL ROUTINE TO SET THE REG FOR COMPUTATION OF CNODE
		TO THE REG INTO WHICH ARG1 WAS COMPUTED IF POSSIBLE.
	***********************************************************)%
	BEGIN
		%(***IF THIS NODE WAS ALREADY ALLOCATED TO FN RET REG, DO NOT CHANGE IT***)%
		IF .CNODE[ALCRETREGFLG]
		THEN RETURN;


		%(***IF CAN USE THE REG CONTAINING ARG1, DO SO***)%
		IF .ARG1NODE[INREGFLG] AND NOT .ARG1NODE[ALCRETREGFLG]
		THEN
		RA_.ARG1NODE[TARGTAC];

		%(***USE RA IF ITS LEGAL FOR THIS OPERATION, IF NOT USE SOME OTHER LEGAL REG***)%
		RA_REGTOUSE(.CNODE,.CNODE[ARG1PTR],.CNODE[ARG2PTR],.RA,.BSYREGS);
		SETTAC(.CNODE,.RA);

		%(***IF WERE ABLE TO USE THE REG IN WHICH ARG1 WAS LEFT, SET A1SAMEFLG***)%
		IF (.CNODE[TARGTAC] EQL .ARG1NODE[TARGTAC]) AND .ARG1NODE[INREGFLG]
		THEN CNODE[A1SAMEFLG]_1;

	END;



	CNODE_.TREEPTR;
	RA_AFREEREG(.BSYREGS,FALSE,.CNODE[DBLFLG]);




	%(****IF THE VALUE OF THIS NODE CAN BE COMPUTED IN THE NUMBER OF REGS AVAILABLE, DO
		SO AND THEN STORE THE VALUE INTO TA
		ALSO - FOR DOUBLE WD OPS ON THE KI10, COMPUTE AND THEN STORE****)%
	IF .CNODE[COMPLEXITY] LEQ .FREGCT
		OR (.CNODE[VALTYPE] EQL DOUBLPREC)
		OR (.CNODE[OPERSP] EQL EXPONOP)
	THEN
	BEGIN
		ALCA(.RA,.BSYREGS,.FREGCT);
		CNODE[INREGFLG]_0;
		CNODE[STOREFLG]_1;
		CNODE[TARGTMEM]_.TA;
		RETURN
	END;


	ARG1NODE_.CNODE[ARG1PTR];
	ARG2NODE_.CNODE[ARG2PTR];


	%(****WANT TO PERFORM THE OPERATION ON THIS NODE TO MEMORY - THEREFORE ARG2 SHOULD
		BE COMPUTED INTO TA, ARG1 INTO RA. *****)%



	%(***IF ARG2 NEEDS NO EVALUATION, SIMPLY EVAL ARG1 INTO RA***)%
	%(****THEN COMPUTE VAL OF PARENT IN RA AND STORE IN TA**********)%
	IF .CNODE[A2VALFLG]
	THEN
	BEGIN
		TREEPTR_.ARG1NODE;
		ALCINREG(.RA,.BSYREGS,.FREGCT);

		%(***SET REG FOR COMP OF CNODE TO REG WHERE VAL OF ARG1 WAS LEFT***)%
		USEARGREG(.RA,.BSYREGS);

		CNODE[STOREFLG]_1;
	END

	ELSE
	%(***IF ARG1 NEEDS NO EVALUATION, EVALUATE ARG2 INTO TA****)%
	IF .CNODE[A1VALFLG]
	THEN
	BEGIN
		TREEPTR_.ARG2NODE;
		ALCINTMP(.TA,.BSYREGS,.FREGCT);

		%(***GET A REG FOR COMP OF THIS NODE***)%
		USESOMEREG(.BSYREGS);
	END



	ELSE
	%(****IF BOTH SUBNODES REQUIRE COMPUTATION, PERFORM REGISTER ALLOCATION FOR THE
		2 COMPUTATIONS.
		IF THE FIRST SUBNODE COMPUTED HAS ITS VAL LEFT IN A REGISTER, THEN THAT
		REGISTER CANNOT BE USED IN COMPUTATION OF THE OTHER SUBNODE.
		(NOTE THAT EVEN IF A SUBNODE HAS BEEN DESIGNATED AS COMPUTED INTO "FN
		RETURN REG", MUST STILL DO ALLOCATION FOR SOME OF ITS SUBNODES)
	*************)%

	IF .CNODE[RVRSFLG]
	THEN
	%(****IF ARG2 IS COMPUTED BEFORE ARG1****)%
	BEGIN
		TREEPTR_.ARG2NODE;
		ALCINTMP(.TA,.BSYREGS,.FREGCT);
		!THE CALL TO ALCINTMP (ONE LINE UP) MAY CAUSE A STORE
		! CLASS NODE TO BE INSERTED BETWEEN CNODE AND ARG2NODE.
		! WE NEED TO ADJUST ARG2NODE IN THIS CASE SO THAT THE
		! TEST AGAINST ARG2NODE[TARGTMEM] LATER ON WILL SUCCEED
		ARG2NODE_.CNODE[ARG2PTR];
		TREEPTR_.ARG1NODE;
		ALCINREG(.RA,.BSYREGS,.FREGCT);

		%(***SET REG FOR COMP OF CNODE TO REG WHERE VAL OF ARG1 WAS LEFT (IF CAN)***)%
		USEARGREG(.RA,.BSYREGS);
	END

	ELSE
	%(***IF ARG1 IS EVALUATED BEFORE ARG2***)%
	BEGIN
		TREEPTR_.ARG1NODE;
		IF .ARG2NODE[COMPLEXITY] GTR (.FREGCT-1)
		THEN
		%(***IF WILL NEED TO USE RA IN COMPUTING ARG2***)%
		BEGIN
			ALCINTMP(NXTTMP(.TREEPTR[DBLFLG]),.BSYREGS,.FREGCT);
			TREEPTR_.ARG2NODE;
			IF .ARG2NODE[COMPLEXITY] EQL .FREGCT
			THEN
			BEGIN
				ALCINREG(AFREEREG(CLRBIT(.BSYREGS,.RA),FALSE,.ARG2NODE[DBLFLG]),.BSYREGS,.FREGCT);
				CNODE[STOREFLG]_1;
			END

			ELSE
			ALCINTMP(.TA,.BSYREGS,.FREGCT);

			USESOMEREG(.BSYREGS)
		END

		ELSE
		%(***IF CAN COMPUTE ARG2 WITHOUT CLOBBERRING RA***)%
		BEGIN
			LOCAL BSYRG1;
			ALCINREG(.RA,.BSYREGS,.FREGCT);

			%(***IF ARG1 WAS LEFT IN A REG, DO NOT USE THAT REG IN THE COMP OF ARG2**)%
			IF .ARG1NODE[INREGFLG]
			THEN
			BSYRG1_CLRBIT(.BSYREGS,.ARG1NODE[TARGTAC])
			ELSE
			BSYRG1_.BSYREGS;

			TREEPTR_.ARG2NODE;
			ALCINREG(AFREEREG(.BSYRG1,FALSE,.ARG2NODE[DBLFLG]),.BSYRG1,ONESCOUNT(.BSYRG1));

			%(***SET REG FOR COMP OF CNODE TO REG WHERE VAL OF ARG1 WAS LEFT (IF CAN)***)%
			USEARGREG(.RA,.BSYREGS);
			CNODE[STOREFLG]_1;
		END;

	END;


	IF .ARG2NODE[TARGTMEM] EQL .TA
	THEN
	BEGIN
		CNODE[A2SAMEFLG]_1;
		CNODE[MEMCMPFLG]_1;
	END;

	CNODE[TARGTMEM]_.TA;
	RETURN;


END;


GLOBAL ROUTINE ALCTARY(BSYREGS,FREGCT)=
%(***************************************************************************
	ROUTINE TO ALLOCATE AN ARRAYREF NODE SO THAT THE ADDRESS WILL
	BE COMPUTED AND STORED IN A TEMPORARY (WHICH WILL LATER BE USED AS
	A PTR).
	THIS ROUTINE WILL INTRODUCE A "STARADDR" (OPRCLS=STORECLS, OPERSP=STARADDR)
	NODE INTO THE TREE ABOVE THE ARRAYREF NODE, HOWEVER IT WILL NOT ACTUALLY 
	LINK THE NEW NODE IN UNDER THE PARENT OF THE ARRAYREF. INSTEAD IT WILL
	RETURN A PTR TO THE NEW NODE AND THE LINKING MUST BE COMPLETED BY THE
	ROUTINE THAT CALLED IT. (THIS IS NECESSARY BECAUSE IN SOME CASES
	THE ARRAYREF WAS IN AN ARGUMENT LIST OR AN IOLIST).

	THE INDIRECT BIT WILL BE SET IN THE TARGET WORD OF THE STOREADDR
	NODE SO THAT REFERENCES TO THIS ELEMENT WILL BE MADE INDIRECT.
***************************************************************************)%
BEGIN
	LOCAL PEXPRNODE CNODE:STORENODE;
	LOCAL RA;		!REG TO USE IN GETTING THE ADDR


	CNODE_.TREEPTR;

	%(***PERFORM REGISTER ALLOCATION FOR THE ARRAYREF NODE***)%
	ALCARRAY(.BSYREGS,.FREGCT);

	%(***IF THE ADDRESS IS A COMPILE-TIME CONSTANT (AND HENCE REFERENCING IT DOES
		NOT DEPEND ON THE CONTENTS OF SOME REG BEING PRESERVED), NEED NOT DO ANYTHING SPECIAL***)%
	IF .CNODE[TARGXF] EQL 0
	THEN
	RETURN .CNODE;


	%(***PUT A "STARADDR" NODE ABOVE THE ARRAYREF NODE***)%
	STORENODE_MAKPR1(.CNODE[PARENT],STORECLS,STARADDR,.CNODE[VALTYPE],0,.CNODE);

	%(***DETERMINE WHAT REG TO USE TO LOAD THE ADDR - USE THE SAME REG THAT
		HOLDS THE PARTIAL ADDR (WITHOUT CONSTANT OFFSET) IF POSSIBLE***)%
	RA_.CNODE[TARGXF];
	IF NOT BITSET(.BSYREGS,.RA) THEN  RA_AFREEREG(.BSYREGS,FALSE,FALSE);
	SETTAC(.STORENODE,.RA);

	%(***IF THERE IS NO CONSTANT PORTION OF THE ADDRESS TO ADD IN TO THE
		VARIABLE PORTION, SET A2SAMEFLG ****)%
	IF (.CNODE[TARGADDR] EQL 0) AND (.CNODE[TARGXF] EQL .STORENODE[TARGTAC])
		AND (.CNODE[FORMLFLG])		!UNLESS THE ARRAY IS A FORMAL, WILL
						! HAVE TO  ADD IN THE BASE EVEN IF
						! ITS **REALTIVE** ADDRESS IS 0
	THEN
	STORENODE[A2SAMEFLG]_1;

	%(***SET UP TARGET WD OF THE STOREADDR NODE - WILL REFERENCE THIS
		ITEM INDIRECT THRU A TEMPORARY THAT HOLDS THE PTR***)%
	STORENODE[TARGADDR]_NXTTMP(FALSE);
	STORENODE[TARGIF]_1;

	RETURN .STORENODE;

END;


GLOBAL ROUTINE ALCTVARR(BSYREGS,FREGCT)=
%(***************************************************************************
	ALLOCATES AN ARRAY REF SO THAT THE VALUE OF THE ARRAY ELEM
	WILL BE STORED IN A TEMPORARY. FOR A DP OR COMPLEX ARRAY,
	THIS ROUTINE MUST BE CALLED WITH AT LEAST 2 REG (PAIRS) AVAILABLE,
	SINCE THE REG INDEXED OFF OF CANNOT BE LOADED INTO FOR KA10.
	  THIS ROUTINE WILL INTRODUCE A "STARVAL" (OPRCLS=STORECLS, OPERSP=STARVAL)
	INTO THE TREE ABOVE THE ARRAYREF NODE, HOWEVER IT WILL NOT
	LINK THAT NODE IN UNDER THE PARENT OF THE ARRAYREF. INSTEAD
	IT WILL RETURN A PTR TO THE NEW NODE AND THE LINKING MUST BE DONE
	BY THE ROUTINE THAT CALLED IT. THIS ROUTINE IS CALLED WHEN
	THE ARRAYREF IS A UNIT OR RECORD NUMBER, OR IS UNDER AN OPEN/CLOSE.
	TREEPTR POINTS TO THE ARRAYREF.
***************************************************************************)%
BEGIN
	REGISTER PEXPRNODE STORENODE;
	STORENODE_MAKPR1(.TREEPTR[PARENT],STORECLS,STARVAL,.TREEPTR[VALTYPE],0,.TREEPTR);
	STORENODE[TARGTMEM]_NXTTMP(.TREEPTR[DBLFLG]);
	ALCARRAY(.BSYREGS,.FREGCT);
	SETTAC(.STORENODE,
		RGTOU1(.STORENODE,.STORENODE[ARG2PTR],AFREEREG(.BSYREGS,FALSE,FALSE),.BSYREGS));
	RETURN .STORENODE
END; 	!END OF ROUTINE "ALCTVARR"


GLOBAL ROUTINE REGTOUSE(PNODE,ARG1NODE,ARG2NODE,RA,BSYREGS)=
%(***************************************************************************
	ROUTINE TO DECIDE WHICH REGISTER TO USE FOR COMPUTATION OF
	A BINARY NODE WHEN DO NOT HAVE THE 1ST ARG IN A REG THAT CAN BE USED.
	IF POSSIBLE WILL WANT TO USE THE REG RA (BECAUSE IT IS THE REG TO WHICH
	THE COMPUTATION WAS "TARGETED") - BUT CANNOT USE RA IF
		1.ARG2 WAS LEFT IN RA
		2.ARG1 IS A DOUBLE-PRECISION ARRAYREF AND THE INDEX WAS LEFT
			IN RA
		3.IF THE OPERATION CLOBBERS THE REGISTER AFTER THE ONE IN WHICH
			IT IS BEING PERFORMED AND THE REG AFTER RA CONTAINS
			A VALUE THAT NEEDS TO BE PRESERVED
	WE PREFER TO NOT USE RA IF IT IS IN THE SET OF REGS TO BE PRESERVED
	BY THE BB ALLOCATOR.
***************************************************************************)%
BEGIN
	EXTERNAL BLOCKBSYREGS;	!BIT PATTERN IN WHICH 0'S INDICATE REGS THAT
				! THE BASIC BLOCK ALLOCATOR WOULD LIKE TO
				! PRESERVE (1'S ARE REGS IT DOESNT CARE ABOUT)
	MAP PEXPRNODE PNODE:ARG1NODE:ARG2NODE;
	OWN BSYRG1;				!SET OF REGS THAT CAN BE
						! USED FOR PERFORMING THIS OPERATION
	OWN RB;

	%(***WHEN IN DEBUG MODE- CHECK THAT BSYREGS IS NON-ZERO***)%
	IF DEBUGFLG
	THEN
	(IF .BSYREGS EQL 0 THEN CGERR());


	BSYRG1_.BSYREGS;
	%(***IF ARG1 IS ACCESSED OFF OF AN INDEX REGISTER (IT COULD BE EITHER
		AN ARRAYREF NODE OR A TYPE-CONVERSION NODE THAT DOESNT DO ANYTHING),
		THEN CAN'T USE THE INDEX REGISTER FOR THE FETCH ON A KA10,
		SINCE 2 MOVE-TYPE INSTRUCTIONS ARE GENERATED.  THIS ALSO
		APPLIES TO A NEGATED COMPLEX FETCH ON A KI OR KL, SINCE
		THAT CASE GENERATES TWO CONSECUTIVE MOVN'S.  WE WON'T
		ALLOW THE AC'S TO BE THE SAME FOR ANY COMPLEX FETCHES,
		SINCE NEGFLG'S CAN FLOAT IN LATER (IN FORTG)***)%
	IF .ARG1NODE[TARGXF] NEQ 0
	THEN
		IF.ARG1NODE[VALTYPE] EQL COMPLEX
		THEN BSYRG1_CLRBIT(.BSYRG1,.ARG1NODE[TARGXF] );


	%(***IF NEED TO PRESERVE SOME REG TO ACCESS THE VAL OF ARG2, MUST NOT USE
		THAT REG***)%
	IF (RB_RGTOSAVE(.ARG2NODE)) NEQ -1
	THEN BSYRG1_CLRBIT(.BSYRG1,.RB);

	%(***IF RA IS NOW NOT IN THE SET OF REGS AVAILABLE FOR USE
		OR IF IT IS ONE OF THE REGS TO BE PRESERVED FOR THE BB ALLOCATOR, GET A NEW REG
		TO USE***)%
	IF NOT BITSET(.BSYRG1 AND .BLOCKBSYREGS,.RA) THEN   RA_AFREEREG(.BSYRG1,FALSE,.PNODE[DBLFLG]);

	%(***IF THIS OPERATION CLOBBERS THE NEXT REG AFTER THE ONE USED, CHECK
		THAT THE REG AFTER RA IS FREE (NOTE HOWEVER THAT THE REG AFTER
		RA DOES NOT HAVE THE SAME RESTRICTIONS ON IT AS RA DOES -HENCE
		CAN COMPARE WITH "BSYREGS" RATHER THAN "BSYRG1"***)%
	IF CLOBBNX(.PNODE) AND (NOT NXREGFREE(.BSYREGS,.RA))
	THEN RA_GETRGPR(.RA,.BSYRG1);

	RETURN .RA
END;



GLOBAL ROUTINE RGTOU1(PNODE,ARGNODE,RA,BSYREGS)=
%(***************************************************************************
	ROUTINE TO DECIDE WHICH REGISTER TO USE FOR A UNARY NODE WHEN THE
	ARG WAS NOT LEFT IN A REG THAT CAN BE USED FOR COMPUTATION OF THE
	PARENT. IF POSSIBLE WANT TO USE THE REG "RA".
	IF RA IS IN THE SET OF REGS TO BE PRESERVED FOR THE BB ALLOCATOR,
	THEN IF POSSIBLE USE SOME OTHER REG.
***************************************************************************)%
BEGIN
	EXTERNAL BLOCKBSYREGS;	!BIT PATTERN IN WHICH 0'S REPRESENT REGS THAT THE BB ALLOCATOR
				! WANTS TO PRESERVE. 1'S REPRESENT REGS IT DOESNT CARE ABOUT
	MAP PEXPRNODE PNODE:ARGNODE;
	OWN BSYRG1,RB;

	%(***WHEN IN DEBUG MODE- CHECK THAT BSYREGS IS NON-ZERO***)%
	IF DEBUGFLG
	THEN
	(IF .BSYREGS EQL 0 THEN CGERR());

	%(**FIRST, MUST CHECK THAT RA IS IN THE SET OF REGS INDICATED BY BSYREGS (ALCTPCNV
		COUNTS ON THIS BEING DONE HERE)***)%
	IF NOT BITSET (.BSYREGS AND .BLOCKBSYREGS,.RA) THEN RA_AFREEREG(.BSYREGS,.PNODE[SAVREGFLG],.PNODE[DBLFLG]);


	BSYRG1_.BSYREGS;



	%(***IF THE ARG IS ACCESSED BY USING AN INDEX REGISTER AND IT IS DOUBLE-WD
		THEN THAT INDEX REG CANNOT BE USED FOR COMPUTATION OF THE PARENT NODE***)%
	IF (.ARGNODE[DBLFLG]) AND (.ARGNODE[TARGXF] NEQ 0)
	THEN
	BEGIN
		BSYRG1_CLRBIT(.BSYRG1,(RB_.ARGNODE[TARGXF]));
		IF .RA EQL .RB
		THEN
		BEGIN
			IF .BSYRG1 EQL 0 THEN CGERR();
			RA_AFREEREG(.BSYRG1,.PNODE[SAVREGFLG],.PNODE[DBLFLG]);
		END;
	END;

	%(***IF THIS OP CLOBBERS THE REG AFTER THE ONE ON WHICH IT IS PERFORMED***)%
	IF CLOBBNX(.PNODE) AND NOT NXREGFREE(.BSYREGS,.RA) THEN RA_GETRGPR(.RA,.BSYRG1);

	RETURN .RA
END;



GLOBAL ROUTINE SETTARGINREG(CNODE,RA)=
%(***************************************************************************
	TO SET THE TARGET OF A NODE TO INDICATE THAT THE VALUE WILL
	LIVE IN THE REGISTER "RA"
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNODE;
	CNODE[TARGTAC]_.RA;	!SET FIELD IN NODE TO INDICATE THAT THIS REG
					! SHOULD BE USED FOR THE COMPUTATION OF THE NODE

	CNODE[TARGADDR]_.CNODE[TARGTAC];	!SET FIELD INDICATING THAT THE "MEMORY" LOCATION
						! FOR THE VAL OF THE NODE IS THE REG THAT
						! WAS USED TO COMPUTE THE VAL
	CNODE[INREGFLG]_1;	!SET FLAG INDICATING VAL IS IN A REG


	REGCLOBB(.CNODE[TARGTAC]);	!MUST ASSUME THAT THE PREVIOUS CONTENTS OF
					! THE REG USED WILL BE CLOBBERED (MUST
					! CLEAR ENTRIES FOR THAT REG IN BASIC-BLOCK ALLOC TABLES)
	IF CLOBBNX(.CNODE)		!IF THIS OPERATION WILL CLOBBER THE REG
		OR .CNODE[DBLFLG]	! FOLLOWING RA, MUST ALSO ASSUME THAT
	THEN				! THE PREVIOUS CONTENTS OF THAT REG
	REGCLOBB(.CNODE[TARGTAC]+1);	! ARE CLOBBERED
END;


GLOBAL ROUTINE SETTAC(CNODE,RA)=
%(***************************************************************************
	TO SET THE TARGET AC FIELD OF A NODE TO THE REG RA (WHEN
	THE "TARGADDR" WILL BE SOME OTHER LOC)
***************************************************************************)%
BEGIN
	MAP PEXPRNODE CNODE;
	CNODE[TARGTAC]_.RA;	!SET FIELD IN NODE TO INDICATE THAT OPERATION
					! SHOULD BE CALCULATED IN REG "RA"

	REGCLOBB(.RA);	!MUST ASSUME THAT THE PREVIOUS CONTENTS OF THAT
					! REG WILL BE CLOBBERED BY CALC OF THIS NODE
					! CLEAR THE BASIC-BLOCK ALLOCATOR TABLE ENTRIES FOR
					! THAT REG
	IF CLOBBNX(.CNODE)	!IF THE EVAL OF THIS NODE WILL CLOBBER THE REG FOLLOWING RA
		OR .CNODE[DBLFLG]
		OR ((.CNODE[OPRCLS] EQL TYPECNV)	! CHECK FOR TYPE CONVERSION
			AND .CNODE[SDBLFLG])	! FROM DOUBLE TO SINGLE
	THEN			! THEN CLEAR THE BASIC-BLOCK ALLOCATOR TABLE ENTRIES
	REGCLOBB(.CNODE[TARGTAC]+1);	!FOR THAT REG AS WELL
END;


GLOBAL ROUTINE CLOBBNX(NODE)=
%(***************************************************************************
	ROUTINE TO TEST WHETHER AN OPERATION CLOBBERS THE
	REGISTER FOLLOWING THE REG IN WHICH IT IS PERFORMED.
	THIS TEST DOES NOT CHECK FOR DOUBLE-PREC OPERATIONS -
	WHEN ONE IS IN "DOUBLE-PREC MODE" ONE SIMPLY DOES NOT USE
	THE ODD REGS AT ALL
	NODE POINTS TO AN EXPRESSION NODE.
***************************************************************************)%
BEGIN
	MAP PEXPRNODE NODE;
	((.NODE[OPR1] EQL OPR1C(ARITHMETIC,DIVOP)	!FOR DIVIDE
		AND .NODE[VALTP1] EQL INTEG1)		! OF AN INTEGER,LOGICAL, OR INDEX VAR
	 OR (.NODE[OPR1] EQL MODFNFL))
END;
%[757]%GLOBAL ROUTINE STORAC( CNODE, BSYREGS )=
%[757](****************************************************************************
	ROUTINE TO STORE THE VALUE OF A NODE IN A TEMPORARY IF IT DEPENDS
	ON ANY AC (IE IF IT IS IN AN AC OR IF IT REQUIRES AN INDEXED 
	REFERENCE).

		CNODE - THE NODE WHOSE VALUE SHOULD BE STORED
		BSYREGS - THE ACS THAT CAN BE USED TO LOAD THE VALUE
			IF NECESSARY FOR AN ARRAYREF

	THIS ROUTINE RETURNS A POINTER TO THE NODE WHICH SHOULD
	REPLACE CNODE IN THE TREE. THIS MAY BE CNODE ITSELF
	OR IT MAY BE A STORECLS NODE. NOTE THAT THIS
	ROUTINE DOES NOT INSERT THE STORECLS NODE INTO THE TREE.
	THE CALLER MUST DO SO.
*****************************************************************************)%
%[757]%BEGIN
%[757]%	REGISTER TEMP;			! THE TEMPORARY TO BE USED
%[757]%	REGISTER PEXPRNODE STORENODE;	!"STORE CLASS" NODE BEING INSERTED
%[757]%					! IN THE TREE IF NEEDED
%[757]%
%[757]%	MAP PEXPRNODE CNODE;
%[757]%
%[757]%	! IF THE VALUE IS IN AN AC, MARK CNODE TO STORE THE VALUE
%[757]%	IF .CNODE[INREGFLG]
%[757]%	THEN
%[757]%	BEGIN
%[757]%		CNODE[INREGFLG] _ 0;	! TURN OFF FLAG FOR IN AC
%[757]%		CNODE[STOREFLG] _ 1;	! SET FLAG FOR STORE THE VALUE
%[757]%		CNODE[TARGTMEM] _ NXTTMP(.CNODE[DBLFLG]); ! USE THE NEXT 
%[757]%					!  AVAILABLE TEMPORARY
%[757]%
%[757]%		RETURN .CNODE
%[757]%	END
%[757]%
%[757]%	ELSE
%[757]%	! IF THE VALUE MUST BE ACCESSED BY INDEXING, INSERT A STORECLS
%[757]%	!  NODE INTO THE TREE TO STORE IT IN A TEMP
%[757]%
%[757]%	IF .CNODE[OPRCLS] EQL ARRAYREF AND .CNODE[TARGXF] NEQ 0
%[757]%	THEN
%[757]%	BEGIN
%[757]%
%[757]%		STORENODE _ MAKPR1( .CNODE[PARENT], STORECLS, STARVAL,
%[757]%			.CNODE[VALTYPE], 0, .CNODE );	!GET STORAGE
%[757]%					! FOR A NODE AND INIT SOME FIELDS
%[757]%		STORENODE[TARGTMEM] _ NXTTMP( .CNODE[DBLFLG] );  !USE NEXT
%[757]%					!  AVAILABLE TEMPORARY
%[757]%		CNODE[PARENT] _ .STORENODE;
%[757]%		SETTAC(.STORENODE,
%[757]%			RGTOU1(.STORENODE,.STORENODE[ARG2PTR],AFREEREG(.BSYREGS,FALSE,FALSE),.BSYREGS));
%[757]%		RETURN .STORENODE
%[757]%	END
%[757]%	ELSE
%[757]%		RETURN .CNODE;
%[757]%END;


END
ELUDOM