Google
 

Trailing-Edge - PDP-10 Archives - BB-D480C-SB_1981 - alcblo.bli
There are 12 other files named alcblo.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) 1973,1981 BY DIGITAL EQUIPMENT CORPORATION
!AUTHOR: S. MURPHY/SRM/JNG

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

GLOBAL BIND ALCBLV = 6^24 + 0^18 + 60;	! Version Date: 24-Jul-81

%(

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

55	-----	-----	MUST END A BASIC BLOCK ON AN IF THAT CONTAINS A CALL
56	-----	-----	WHEN INSERT AN ENTRY IN REGSTATE TABLE
			MUST CLEAR VARINREGFLG OF A POSSIBLE ENTRY
			BEING WRITTEN OVER. THIS CAN HAPPEN FOR:
				A=B
				C=B
			WHERE B IS GLOBALLY ALLOCATED TO A REG
57	-----	-----	MUST CHECK FOR A BASIC BLOCK
		TERMINATED BY THE NEXT STMNT HAVING A LABEL BEFORE
			CHECK FOR IT TERMINATED BY THE PREVIOUS STMNT
		A DO STMNT (SINCE IN THAT CASE WE STILL REMEMBER THE
		LP INDEX
58	632	24245	IN REGCLOBB, DON'T CLEAR VARINREGFLG FOR THE
			VARIABLE IN THE REGISTER IF THE VARIABLE IS
			ALSO IN ANOTHER REGISTER. THIS CAN HAPPEN IF
			A VAR IS LIVING IN 0, MOVED TO 2 FOR INDEXING,
			THEN 0 IS REGLOBB'ED BY A FUNCTION CALL., (JNG)
59	652	NONE	EDIT 632 NEEDS TO CARE ABOUT DOUBLE WORD VARS, (DCE)

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

60	1024	SRM	21-Nov-80	NONE
	Fixed REGCLOBB to work for REAL='literal' when
	compiling /gfloating. REGCLOBB had assumed that
	if a literal was in an AC the 2nd half must be
	in an adjacent AC. This was always true because
	we did a "type conversion" on the literal and
	created a constant of type REAL that contained
	the bits from the literal. When compiling
	/gfloating we dont do this "conversion".

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

)%

FORWARD ALCBLOCK(0),AFREEREG(3),REGCONTAINING(1),VARCLOBB(1),CLOBBCOMEQV,
	CLOBBEQV,CLRRGSTATE,
	INIRGSTATE,SAVEREG(5),FREEPAIRS(1);

EXTERNAL CGERR;		!ROUTINE TO GIVE MESSAGE WHEN INTERNAL COMPILER ERROR
			! IS DETECTED


	!REQUIRE OF "FIRST.BLI" AND "TABLES.BLI" - DONT LIST THEM
	SWITCHES NOLIST;

	REQUIRE FIRST.BLI;
	REQUIRE TABLES.BLI;

	SWITCHES LIST;
BIND RGSENTSIZE=2;	!NUMBER OF WDS IN EACH ENTRY OF THE REGSTATE TABLE

OWN REGSTATE[RGSENTSIZE*16];	!THIS TABLE HAS AN ENTRY FOR EACH OF THE 16 ACS 
				! EACH ENTRY INDICATES WHICH VARS/CONSTS ARE IN EACH REG


OWN BLKISN;	!SEQ NUMBER WITHIN THIS BLOCK OF THE STMNT CURRENTLY BEING PROCESSED



GLOBAL ROUTINE ALCBLOCK=
%(**********
	THE TOP LEVEL ROUTINE FOR THE SECOND PASS OF THE BASIC BLOCK REGISTER ALLOCATOR.
	THIS ROUTINE CAUSES LOCAL REGISTER ALLOCATION TO BE PERFORMED FOR EVERY
	STATEMENT IN A BASIC BLOCK.
	A BASIC BLOCK IS TERMINATED BY
		1.  A LABEL WHICH IS REFERENCED OTHER THAN AS A FORMAT
		2.  A DO STATEMENT
		3.  FOR PURPOSES OF REGISTER ALLOCATION, A CALL STATEMENT (SINCE SUBROUTINES ARE
		    ASSUMED TO CLOBBER ALL REGISTERS)
		4. AN ENTRY POINT
	THIS ROUTINE IS CALLED WITH THE GLOBAL CSTMNT POINTING TO THE FIRST STATEMENT OF
	A BASIC BLOCK.  IT RETURNS WITH CSTMNT POINTING TO THE FIRST STATEMENT OF
	THE NEXT BASIC BLOCK.  IF THE END OF THE PROGRAM HAS BEEN REACHED IT
	RETURNS CSTMNT=0.
	THIS ROUTINE CLEARS THE REGSTATE TABLE WHEN IT HAS COMPLETED THE PASS OVER A
	BASIC BLOCK.  IF THE LAST STATEMENT OF THE BLOCK WAS A DO STATEMENT THEN IF THAT 
	DO STATEMENT HAS THE FLAGS "SAVEREGFLG" AND "NEDSMATRLZ" BOTH SET, IT SETS
	UP A REGSTATE TABLE ENTRY FOR THE DO LOOP INDEX SO THAT THE REGISTER CONTAINING
	THE INDEX CAN BE USED IN THE NEXT BASIC BLOCK.
	IT IS ASSUMED THAT WHEN THIS ROUTINE IS CALLED FOR A GIVEN BASIC BLOCK, THE
	REGSTATE TABLE IS IN THE STATE IN WHICH THIS ROUTINE LEFT IT AFTER
	PROCESSING THE PRECEEDING BASIC BLOCK.
**********)%
BEGIN
	REGISTER BASE PRVSTMNT;	!THE STMNT JUST PROCESSED
	EXTERNAL CSTMNT;			!POINTER TO CURRENT STATEMENT BEING PROCESSED
	MAP BASE CSTMNT;
	EXTERNAL ISN;		!INTERNAL SEQ NUMBER OF THE STMNT BEING PROCESSED
				! (THIS IS USED FOR ERROR MESSAGES)
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL CLRRGSTATE;			!ROUTINE TO CLEAR THE REGSTATE TABLE
	EXTERNAL SAVEREG;			!ROUTINE TO SET UP A REGSTATE TABLE ENTRY FOR A REGISTER
						!WHOSE VALUE SHOULD BE PRESERVED
	EXTERNAL ALCSTMN;			!ROUTINE TO PERFORM LOCAL REGISTER ALLOCATION
						!FOR A GIVEN STATEMENT

	EXTERNAL GBSYREGS;	!BIT PATTERN REPRESENTING THE REGS LEFT FREE BY THE
				! GLOBAL ALLOCATOR (A ONE REPRESENTS A FREE REG, A ZERO A BUSY ONE)
	EXTERNAL GBSYCT;	!NUMBER OF FREE REGS IN GBSYREGS
	EXTERNAL STBSYR;	!BIT PATTERN REPRESENTING THE REGS AVAILABLE FOR
				! USE WITHIN A GIVEN STMNT
	EXTERNAL STRGCT;	!NUMBER OF FREE REGS IN STBSYR
	EXTERNAL FRSTLNK;	!POINT TO THE FIRST TEMPORARY ON THE LINKED LIST
				! OF TEMPORARIES THAT HAVE HAD TO BE CREAETED
	EXTERNAL FTEMP;		!POINTER TO THE  TEMPORARY ON THE LINKED LIST
				! OF TEMPS THAT SHOULD BE USED NEXT
				! ZERO IF NONE IS AVAILABLE (AND HENCE A NEW ONE
				! MUST BE ADDED TO THE LIST)
	OWN PEXPRNODE STLABEL;			!POINTER TO THE LABEL TABLE ENTRY FOR THE LABEL ON THIS STATEMENT (IF ANY)

	EXTERNAL OLDGBSYREGS;	!BIT PATTERN SET UP BY THE GLOBAL OPTIMIZER TO
				! INDICATE REGS AVAILABLE OUTSIDE THE CURRENT DO LOOP
				! WHEN THE CURRENT LOOP WAS GLOBALLY ALLOCATED

	BLKISN_1;	!1ST STMNT IN BASIC BLOCK HAS BLOCK INTERNAL SEQ NO. 1
	%(***WALK THRU ALL STATEMENTS IN THE BLOCK***)%
	UNTIL .CSTMNT EQL 0			!UNTIL REACH THE END OF THE PROGRAM
	DO
	BEGIN
		ISN_.CSTMNT[SRCISN];	!GET INTERNAL SEQ NUMB OF THE STMNT TO BE PROCESSED NEXT
		STBSYR_.GBSYREGS;	!INIT SET OF REGS AVAILABLE FOR USE
					! IN THIS STMNT
		STRGCT_.GBSYCT;

		FTEMP_.FRSTLNK;	!INIT PTR TO NEXT TEMPORARY TO BE USED SO
					! THAT WILL REUSE THE TEMPORARIES THAT
					! WERE CREATED FOR PREVIOUS STMNTS
		ALCSTMN();			!PERFORM LOCAL REGISTER ALLOCATION FOR THIS STATEMENT

		IF .CSTMNT[SRCID] EQL CALLID	!IF THIS STATEMENT WAS A CALL STATEMENT, 
			OR .CSTMNT[SRCID] EQL SFNID	! OR A STMNT FN, THEN
			OR (IF .CSTMNT[SRCID] EQL IFLID	! OR A LOG IF
				THEN
				BEGIN
					REGISTER BASE SUBSTMNT;
					SUBSTMNT_.CSTMNT[LIFSTATE];
					IF .SUBSTMNT[SRCID] EQL CALLID	!THAT CONTAINS A CALL
					THEN TRUE
					ELSE FALSE
				END
				ELSE FALSE
			)
		THEN				!IT TERMINATES A BASIC BLOCK
		BEGIN
			CLRRGSTATE();		!CLEAR THE REGSTATE TABLE
			CSTMNT_.CSTMNT[SRCLINK]; !AND RETURN WITH CSTMNT POINTING TO THE
			RETURN			!STATEMENT AFTER THE CALL STATEMENT
		END;

	PRVSTMNT_.CSTMNT;
		CSTMNT_.CSTMNT[SRCLINK];	!GO ON TO THE NEXT STMNT


		IF .CSTMNT NEQ 0		!UNLESS THE END OF THE PROGRAM HAS BEEN REACHED
		THEN
		BEGIN
			IF .CSTMNT[SRCID] EQL ENTRID	!IF THE NEXT STMNT IS AN ENTRY
				OR .CSTMNT[SRCID] EQL SFNID	! OR A STMNT FN
							! IT WILL START A NEW BASIC BLOCK

			THEN 
			BEGIN
				CLRRGSTATE();	!CLEAR TABLE INDICATING VALS IN REGS
				RETURN;		! RETURN WITH CSTMNT POINTING TO THE ENTRY STMNT
			END

			ELSE
			IF (STLABEL_.CSTMNT[SRCLBL]) NEQ 0 !IF THE NEXT STATEMENT HAS A LABEL
			THEN
			BEGIN
				IF .STLABEL[SNREFNO] GTR 1 !WHICH IS REFERENCED OTHER THAN AS A FORMAT
				THEN		!(THE COUNT IN "SNREFNO" INCLUDES THE DEFINITION OF THE
				BEGIN		!LABEL AS A REFERENCE-DOES NOT INCLUDE FORMAT NEFS)
					IF .STLABEL[SNREFNO]-1 !IF THE NUMBER OF REFERENCES TO THIS LABEL
						GTR .STLABEL[SNDOLVL] !IS LARGER THAN THE NUMBER OF DO LOOPS IT TERMINATES
						!(I.E. IF THIS LABEL IS REFERENCED OTHER THAN AS A DO LOOP
						!TERMINATOR)-THEN THE STATEMENT PRECEEDING
						!IT TERMINATED A BASIC BLOCK
					THEN
					BEGIN
						CLRRGSTATE(); !CLEAR THE REGSTATE TABLE
						RETURN	      !AND RETURN WITH CSTMNT POINTING TO THE
              						      !STMNT WITH THE LABEL THAT IS REFERENCED OTHER
							      !THAN AS A FORMAT OR A LOOP TERMINATOR
					END
				END
			END
		END;



		IF .PRVSTMNT[SRCID] EQL DOID	!IF  STATEMENT JUST
					! PROCESSED  WAS A DO STATEMENT,
		THEN				!THEN IT TERMINATES A BASIC BLOCK
		BEGIN
			CLRRGSTATE();		!CLEAR THE REGSTATE TABLE (I.E. CAN NO LONGER ASSUME ANY
						!PREVIOUS VALUES IN REGISTERS)
			IF .PRVSTMNT[NEDSMATRLZ]  !IF THE LOOP INDEX HAS NOT BEEN REPLACED THRUOUT THE
				AND .PRVSTMNT[SAVREGFLG] !LOOP BY REGCONTENTS NODES, BUT THE VALUE OF THE
						!INDEX SHOULD BE LEFT IN A REG ACROSS THE
						!FIRST BASIC BLOCK OF THE LOOP
			THEN
			BEGIN
				REGISTER PEXPRNODE DOIX;	!PTR TO SYMBOL TABLE ENTRY FOR INDEX
				DOIX_.PRVSTMNT[DOSYM];
				IF .DOIX[DBLFLG]	!IF LOOP INDEX IS DP OR COMPLEX
				THEN BEGIN END		! DONT BOTHER (ON KA10, VAL WONT BE IN A REG)
				ELSE
				SAVEREG(.PRVSTMNT[DOIREG], !SET UP A REGSTATE TABLE ENTRY FOR THE REG
					.PRVSTMNT[DOSYM],0, !CONTAINING THE LOOP INDEX
					.PRVSTMNT[SRCSONNXTUSE]);

				%(***IF THE LOOP CONST WAS IN "AOBJN" FORM, MUST CHANGE IT
					SO THAT THE INITIAL VAL FOR THE LOOP INDEX WILL
					BE PICKED UP IN A REG BY ITSELF***)%
				IF .PRVSTMNT[FLCWD]	!IF CTL CONST HAD COUNT IN LEFT HALF
				THEN			! VAR IN RIGHT HALF
				BEGIN
					REGISTER CT;
					REGISTER PEXPRNODE AOBJNCNST;
					AOBJNCNST_.PRVSTMNT[DOLPCTL];	!PTR TO CONST TABLE ENTRY
								! FOR THE CONST THAT HAS NEG CT IN LEFT HALF
					CT_.AOBJNCNST[CONST2]^(-18)	!THE NEG  NUMBER OF ITERATIONS
						OR #777777000000;

					PRVSTMNT[DOLPCTL]_	!SET LOOP CTL CONST TO BE
						MAKECNST(INTEGER,0,-.CT);	!THE POS NUMBER OF ITERATIONS
					PRVSTMNT[CTLNEG]_1;	!SET FLAGS INDICATING THAT CT SHOULD
					PRVSTMNT[CTLIMMED]_1;	! BE PICKED UP WITH "MOVNI" INSTR

					PRVSTMNT[INITLIMMED]_1;	!SET FLAG INDICATING THAT INIT VAL
								! SHOULD BE PICKED UP WITH "MOVEI"
					PRVSTMNT[FLCWD]_0;	!TURN OFF FLAG FOR "USE AOBJN FORM"
					PRVSTMNT[SSIZONE]_1;	! AND IN ITS PLACE, LEAVE FLAG FOR
								! "STEP SIZE IS 1"

					PRVSTMNT[DOCREG]_		!PICK A FREE REG TO USE FOR THE CT
						AFREEREG(CLRBIT(.STBSYR,.PRVSTMNT[DOIREG]),FALSE,FALSE);
				END
			END;

			RETURN			!POINTING TO THE STATEMENT AFTER THE DO STATEMENT
		END;


		BLKISN_.BLKISN+1;	!INCR VAL OF "BLOCK INTERNAL SEQ NUMBER"
	END;					!END OF WALK THRU STMNTS
END;						!END OF ROUTINE "ALC BLOCK"

GLOBAL ROUTINE AFREEREG (BSYREGS,BLKFLG,DOUBLFLG)=
%(**********
	ROUTINE TO RETURN A REGISTER (OR REGISTER PAIR) TO BE USED FOR A GIVEN COMPUTATION.
	THE PARAMETERS FOR THIS ROUTINE ARE:
		1.  BSYREGS-SPECIFIES REGISTERS THAT IT IS POSSIBLE TO USE.  THAT IS, REGISTERS THAT
		    ARE NOT EITHER:
			A.  HOLDING INTERMEDIATE RESULTS IN THIS STATEMENT
			B.  ALLOCATED BY THE GLOBAL REGISTER ALLOCATOR
		    THE BITS IN BSYREGS EACH REPRESENT A REGISTER.  IF A BIT IS ZERO THE CORRESPONDING
		    REGISTER IS NOT AVAILABLE. 
		2.  BLKFLG-IF THIS FLAG IS "TRUE," THE REGISTER TO BE RETURNED WILL BE USED TO
		    HOLD A VALUE THAT WILL BE PRESERVED OVER SUCCEEDING STATEMENTS IN THIS BASIC BLOCK
		3.  DOUBLFLG-SPECIFIES WHETHER A SINGLE REGISTER OR A REGISTER PAIR IS REQUIRED

	THIS ROUTINE USES THE GLOBAL "BLOCKBSYREGS" WHICH SPECIFIES REGISTERS THAT WE PREFER TO
	NOT USE BECAUSE THEIR CONTENTS WILL BE NEEDED LATER IN THIS BASIC BLOCK.  THE
	FORMAT OF "BLOCKBSYREGS" IS SIMILAR TO THAT OF "BSYREGS" (I.E. IF A BIT IS ZERO, THE
	CORRESPONDING REGISTER SHOULD PREFERABLY NOT BE USED).

	WHEN ALL REGISTERS ARE BUSY AND HENCE SOME REGISTER FROM "BLOCKBSYREGS" MUST
	BE USED, WE SELECT THE REGISTER WHOSE NEXT USE IS THE FURTHEST IN THE
	FUTURE.  THE "REGSTATE" TABLE CONTAINS THE INTERNAL SEQUENCE NUMBER
	OF THE NEXT USE OF EACH REGISTER THAT BLOCKBSYREGS INDICATES SHOULD BE PRESERVED.
**********)%
BEGIN
	EXTERNAL BLOCKBSYREGS;			!SPECIFIES REGISTERS WHOSE CONTENTS WILL BE NEEDED LATER
						!IN THIS BASIC BLOCK.
	REGISTER BESTREGS;			!REGISTERS THAT ARE AVAILABLE ACCORDING TO "BSYREGS" AND
						!NOT OF FUTURE USE IN THIS BASIC BLOCK
	OWN RGTOUSE;				!REGISTER WHOSE NEXT USE IS FURTHEST IN THE FUTURE

	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	ROUTINE PAIRREGS(BSYRG1)=
	%(**********
		GIVEN A BIT PATTERN "BSYRG1" IN WHICH ZEROES REPRESENT REGISTERS THAT ARE
		BUSY AND ONES REPRESENT REGISTERS THAT ARE FREE, THIS ROUTINE RETURNS
		A BIT PATTERN IN WHICH ZEROES REPRESENT REGISTERS FOR WHICH THE OTHER
		HALF OF THEIR EVEN-ODD PAIR IS BUSY AND ONES REPRESENT REGISTERS
		FOR WHICH THE OTHER HALF OF THEIR EVEN-ODD PAIR IS FREE.

		FOR BOTTOMMOST FUNCTIONS, BIT 0 OF EACH BIT PATTERN REPRESENTS REGISTER 2
		BIT 1 REPRESENTS REGISTER 3, ETC. FOR NON-BOTTOMMOST FUNCTIONS, BIT
		0 REPRESENTS REGISTER 15, BIT 1 REGISTER 14, ETC.

		HENCE FOR BOTH NON-BOTTOMMOST FUNCTIONS AND BOTTOMMOST FUNCTIONS,
		THE BIT PAIRS 0-1, 2-3, 4-5, ETC CORRESPOND TO THE REGISTER
		PAIRS 2-3 (OR 14-15), 4-5 (OR 12-13), ETC
	**********)%
	(
		((.BSYRG1 AND #525252525252)^(-1)) !THE ODD REGS CORRESP TO FREE EVEN REGS;
	OR
		((.BSYRG1 AND #252525252525)^1) !THE EVEN REGS CORRESPTO FREE ODD REGS;
	);

	%(***DETERMINE WHICH REGISTERS ARE FREE**)%
	BESTREGS_(IF .DOUBLFLG			!FOR DOUBLE-PRECISION, MUST
			THEN (.BSYREGS AND DPBSYREGS(.BLOCKBSYREGS)) !CONVERT BLOCKBSYREGS TO DP MODE
			ELSE (.BSYREGS AND .BLOCKBSYREGS));

	IF .BESTREGS NEQ 0
	THEN
	%(****IF THERE ARE SOME FREE REGISTERS****)%
	BEGIN
		IF .DOUBLFLG			!IF ARE CONSIDERING REGISTER PAIRS ALREADY,
		THEN RETURN FIRSTONE(.BESTREGS) !SIMPLY RETURN THE FIRST AVAILABLE PAIR
		ELSE
		%(***IF A SINGLE REGISTER IS BEING USED, TRY TO USE SINGLE REGISTERS WHOSE
			ADJACENT REGISTERS ARE ALREADY IN USE***)%
		BEGIN
			REGISTER VERYBESTREGS;

			IF .BLKFLG		!IF THIS REGISTER IS TO BE PRESERVED ACROSS SOME FUTURE
			THEN			!STATEMENTS
			BEGIN
				VERYBESTREGS_.BESTREGS AND !IF THERE ARE ANY FREE REGISTERS FOR WHICH THE
					NOT PAIRREGS(.BLOCKBSYREGS); !OTHER HALF OF THEIR EVEN-ODD PAIR IS ALREADY
				IF .VERYBESTREGS NEQ 0 !HOLDING A VALUE FOR FUTURE STATEMENTS, USE ONE OF THEM
				THEN
				BESTREGS_.VERYBESTREGS
			END;

			VERYBESTREGS_.BESTREGS AND !IF THERE ARE ANY FREE REGISTERS FOR WHICH THE OTHER
				NOT PAIRREGS(.BSYREGS); !HALF OF THEIR EVEN-ODD PAIR IS ALREADY HOLDING
			IF .VERYBESTREGS NEQ 0	!A VALUE ACROSS THIS STATEMENT, USE ONE OF THEM
			THEN
			BESTREGS_.VERYBESTREGS;

			RETURN FIRSTONE(.BESTREGS)
		END
	END

	ELSE

	%(***IF THERE ARE NO FREE REGISTERS, THEN MUST USE ONE OF THE REGISTERS THAT HOLDS A
		VALUE OF FUTURE USE (I.E. A REGISTER IN BLOCKBSYREGS).  PICK THE REGISTERS WHOSE
		NEXT USE IS FURTHEST AWAY
	****)%
	BEGIN
		REGISTER MAXNXUSE;
		IF .DOUBLFLG
		THEN
		%(***IF NEED TO GET A REGISTER PAIR***)%
		BEGIN
			REGISTER NXPAIRUSE;	!THE ISN OF THE NEXT STATEMENT AT WHICH EITHER REG IN A PAIR IS USED
			%(***WALK THRU THE REGISTER-STATE TABLE TO FIND THE REGISTER PAIR WHOSE NEXT USE
				IS THE FURTHEST AWAY***)%
			MAXNXUSE_0;
			INCR REG FROM #2 TO #14 BY 2
			DO
			BEGIN
				IF .REGSTATE[.REG,RGNXUSE] LSS .BLKISN	!IF THE "NEXT USE" OF THIS
					AND .REGSTATE[.REG+1,RGNXUSE] LSS .BLKISN	! REG HAS ALREADY
								! BEEN PASSED
					AND BITSET(.BSYREGS,.REG)	!THEN IF THIS REG IS
							!LEGAL TO USE, USE IT
				THEN RETURN .REG;

				NXPAIRUSE_(IF .REGSTATE[.REG,RGNXUSE] EQL 0 !IF THE EVEN REGISTER HAS NO FUTURE USE, THEN
					THEN .REGSTATE[.REG+1,RGNXUSE]  !THE NEXT USE IS THE NEXT USE FOR THE ODD REG
					ELSE IF .REGSTATE[.REG+1,RGNXUSE]EQL 0 !IF THE ODD REGISTER HAS NO FUTURE USE,
					THEN .REGSTATE[.REG,RGNXUSE] !THE NEXT USE IS THE NEXT USE FOR THE EVEN REG
					ELSE IF .REGSTATE[.REG,RGNXUSE] !IF THE NEXT USE OF THE EVEN REGISTER IS
						LEQ .REGSTATE[.REG+1,RGNXUSE] !SOONER THAN THE NEXT USE OF THE ODD REGISTER
					THEN .REGSTATE[.REG,RGNXUSE] !THE NEXT USE FOR THE PAIR IS THE NEXT USE FOR THE EVEN REG
					ELSE .REGSTATE[.REG+1,RGNXUSE]); !OTHERWISE, IT'S THE NEXT USE FOR THE ODD REG

				IF .NXPAIRUSE GTR .MAXNXUSE !IF THE NEXT USE OF THIS PAIR IS
				THEN		!FURTHER AWAY THAN THE BEST PAIR FOUND
				BEGIN		!SO FAR,
					IF BITSET(.BSYREGS,.REG) !AND THIS PAIR IS A LEGAL ONE TO USE
					THEN
					BEGIN
						MAXNXUSE_.NXPAIRUSE; !THEN USE THIS PAIR
						RGTOUSE_.REG
					END;
				END
			END			!END OF WALK THRU REGSTATE TABLE FOR PAIRS

		END				!END OF BLOCK TO FIND A REGISTER PAIR

		ELSE
		%(***IF NEED A SINGLE REGISTER***)%
		BEGIN
			%(***WALK THRU THE REGISTER STATE TABLE TO FIND THE REGISTER WHOSE NEXT USE
				IS FURTHEST AWAY***)%
			MAXNXUSE_0;
			INCR REG FROM #2 TO #15 BY 1
			DO
			BEGIN
				IF .REGSTATE[.REG,RGNXUSE] LSS .BLKISN	!IF THE "NEXT USE" OF THIS
						! REG HAS ALREADY BEEN PASSED
					AND BITSET(.BSYREGS,.REG)	!THEN IF THIS REG IS LEGAL TO USE
				THEN RETURN .REG;	!THEN USE THIS REG

				IF .REGSTATE[.REG,RGNXUSE] !IF THE NEXT USE OF THIS REG
					GTR .MAXNXUSE	 !IS GREATER THAN THE MAXIMUN FOUND FOR
				THEN			!ANY REG
				BEGIN
					IF BITSET(.BSYREGS,.REG) !AND THIS REG IS A LEGAL ONE TO USE
					THEN
					BEGIN
						MAXNXUSE_.REGSTATE[.REG,RGNXUSE]; !USE THIS REG
						RGTOUSE_.REG
					END
				END
			END
		END;				!END OF BLOCK TO FIND A SINGLE REG

		IF .MAXNXUSE EQL 0 THEN CGERR(); !IF CAN'T FIND A REG TO USE THAT'S CURRENTLY
						!HOLDING A BASIC BLOCK VARIABLE
		RETURN .RGTOUSE
	END
END;						!END OF ROUTINE "AFREEREG"

GLOBAL ROUTINE REGCONTAINING(SYMPTR)=
%(**********
	THIS ROUTINE DETERMINES WHETHER THE VALUE OF THE VARIABLE/CONSTANT INDICATED
	BY "SYMPTR" IS ALREADY IN SOME REGISTER.  IF SO, IT RETURNS THE REGISTER,
	IF NOT, IT RETURNS MINUS ONE.
	"SYMPTR" POINTS TO THE SYMBOL TABLE OR CONSTANT TABLE ENTRY FOR THE VARIABLE/CONSTANT
**********)%
BEGIN
	MAP PEXPRNODE SYMPTR;
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS


	IF .SYMPTR[OPRCLS] NEQ DATAOPR		!IF ARE NOT LOOKING AT A VARIABLE OR CONSTANT
	THEN RETURN -1;

	IF NOT .SYMPTR[VARINREGFLG]		!FLAG IN SYMBOL/CONSTENT TABLE ENTRIES INDICATING
	THEN RETURN -1;				!THAT VALUE IS IN A REGISTER

	INCR REG FROM 0 TO #15			!IF VALUE IS IN A REGISTER, SEARCH THE REGISTER
	DO					!STATE TABLE TO DETERMINE WHICH REGISTER-FOR
	BEGIN					!AN EVEN-ODD PAIR WILL FIND THE EVEN REG FIRST
		IF .REGSTATE[.REG,RGVAR1] EQL .SYMPTR !IF EITHER OF THE TWO POSSIBLE VARIABLES WHOSE
		THEN RETURN .REG;		!VALUES ARE IN THIS REG ARE IDENTICAL
		IF .REGSTATE[.REG,RGVAR2] EQL .SYMPTR !TO SYMPTR, THEN THIS
		THEN RETURN .REG;		!IS THE ENTRY DESIRED
	END;

	CGERR();				!IF THE "VARINREGFLG" WAS SET IN THE SYMBOL TABLE ENTRY, BUT
						!THE VARIABLE COULDN'T BE FOUND IN THE REGSTATE TABLE, HAVE A
						!COMPILER ERROR
END;						!END OF "REGCONTAINING"

GLOBAL ROUTINE VARCLOBB(SYMPTR)=
%(**********
	THIS ROUTINE IS CALLED WHEN THE VALUE OF A VARIABLE IS MODIFIED.
	IF SOME REGISTER HAS BEEN ASSUMED TO CONTAIN THE VALUE OF THAT VARIABLE,
	THEN THAT ASSUMPTION CAN NO LONGER BE MADE.
	IF THE VARIABLE IS EQUIVALENCED THEN ALL VARIABLES THAT ARE EQUIVALENCED OR IN
	COMMON MUST BE ASSUMED TO BE CLOBBERED
**********)%
BEGIN
	MAP PEXPRNODE SYMPTR;
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL BLOCKBSYREGS;			!GLOBAL VARIABLE INDICATING WHICH REGS CONTAIN VALUES THAT
						!SHOULD BE PRESERVED


	IF .SYMPTR[OPRCLS] EQL ARRAYREF	!IF AN ARRAY ELEMENT IS BEING CLOBBERED
	THEN
	BEGIN
		REGISTER PEXPRNODE ARRAYNM;	!PTR TO SYM TAB ENTRY FOR THE ARRAY NAME
		ARRAYNM_.SYMPTR[ARG1PTR];

		IF .ARRAYNM[IDATTRIBUT(INEQV)]	!IF THE ARRAY IS IN AN EQUIVALENCE STMNT
		THEN CLOBBCOMEQV()		!MUST ASSUME THAT ALL VARS IN EQUIVALENCE OR
						! IN COMMON ARE CLOBBERED

		ELSE IF .ARRAYNM[IDATTRIBUT(INCOM)]	!IF THE VAR IS IN COMMON
		THEN CLOBBEQV()			! MUST ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS
						! ARE CLOBBERED
	END

	ELSE
	IF .SYMPTR[OPRCLS] EQL DATAOPR	!IF ITS A SIMPLE VAR THAT'S BEING CLOBBERED
		AND .SYMPTR[OPR1] NEQ CONSTFL
	THEN
	BEGIN
	


		IF .SYMPTR[IDATTRIBUT(INEQV)]		!IF THIS VAN IS EQUIVALENCED
		THEN CLOBBCOMEQV()			!ASSUME THAT ALL VARS IN EQUIVALENCE OR COMMON
							!STMNTS HAVE BEEN CLOBBERED
		ELSE
		IF .SYMPTR[VARINREGFLG]		!IF SOME REG IS ASSUMED TO CONTAIN THE VAL OF
		THEN					!THIS VARIABLE
		BEGIN
			SYMPTR[VARINREGFLG]_0;	!CAN NO LONGER ASSUME THAT THIS VAR IS IN A REG

			%(***SEARCH THE REGSTATE TABLE FOR THE ENTRY FOR THIS VARIABLE AND CLEAR THAT ENTRY**)%
			INCR REG FROM 0 TO #15
			DO
			BEGIN
				IF .REGSTATE[.REG,RGVAR1] EQL .SYMPTR !IF THIS IS THE REG THAT CONTAINED "SYMPTR"
				THEN			!CLEAR ITS ENTRY IN THE REGSTATE TABLE
				BEGIN
					REGSTATE[.REG,RGVAR1]_0;
					IF .REGSTATE[.REG,RGVAR2] EQL 0 !IF "SYMPTR" WAS THE ONLY VARIABLE
					THEN		!IN THIS REG, THEN RETURN THIS
					BEGIN		!REG TO THE SET OF FREE REGISTERS
						REGSTATE[.REG,RGNXUSE]_0;
						BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
					END;

				END;

				IF .REGSTATE[.REG,RGVAR2] EQL .SYMPTR !IF THIS IS THE REG THAT CONTAINED "SYMPTR"
				THEN			!CLEAR ITS ENTRY
				BEGIN
					REGSTATE[.REG,RGVAR2]_0;
					IF .REGSTATE[.REG,RGVAR1] EQL 0 !IF "SYMPTR" WAS THE ONLY VARIABLE
					THEN		!IN THIS REG, THEN RETURN THIS
					BEGIN		!REG TO THE SET OF FREE REGISTERS
						REGSTATE[.REG,RGNXUSE]_0;
						BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
					END;
				END;

			END;				!END OF INCR LOOP
		END;	!END OF BLOCK FOR SYMPTR KNOWN TO BE IN A REG

		IF .SYMPTR[IDATTRIBUT(INCOM)]	!IF SYMPTR IS IN COMMON
		THEN CLOBBEQV();		! MUST ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS
						! ARE CLOBBERED

	END	!END OF BLOCK FOR "SYMPTR" A SIMPLE VARIABLE
END;						!END OF ROUTINE "VARCLOBB"


GLOBAL ROUTINE CLOBBCOMEQV=
%(**********
	ROUTINE TO ASSUME THAT ALL VARIABLES IN COMMON AND ALL VARIABLES
	THAT ARE EQUIVALENCED TO ANYTHING HAVE HAD THEIR VALUES MODIFIED.
	REMOVES FROM THE REGSTATE TABLE ALL VARIABLES WHICH ARE IN COMMON OR HAVE
	BEEN EQUIVALENCED
**********)%
BEGIN
	REGISTER PEXPRNODE SYMENTRY;	!POINTER TO SYMBOL/CONSTANT TABLE ENTRY FOR
						!THE VARIABLE IN A GIVEN REGISTER
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL BLOCKBSYREGS;			!GLOBAL VARIABLE INDICATING WHICH REGS CONTAIN VALUES THAT
						!SHOULD BE PRESERVED
	ROUTINE COMOREQV=
	%(**********
		LOCAL ROUTINE TO TEST WHETHER "SYMENTRY" POINTS TO A SYMBOL
		TABLE ENTRY FOR A VARIABLE THAT OCCURS IN A COMMON OR
		EQUIVALENCE STATEMENT
	**********)%
	BEGIN
		IF .SYMENTRY[OPR1] EQL CONSTFL	!IF SYMENTRY IS NOT A SYMBOL TABLE ENTRY
		THEN FALSE			!(I.E. IS A CONSTANT TABLE ENTRY)

		ELSE
		(.SYMENTRY[IDATTRIBUT(INEQV)]	!FLAG FOR "VARIABLE IS IN AN EQUIVALENCE STMNT"
			OR
			.SYMENTRY[IDATTRIBUT(INCOM)] !FLAG FOR "VARIABLE IS IN A COMMON STMNT"
		)
	END;					!END OF "COMOREQV"


	INCR REG FROM 0 TO #15			!LOOK AT THE REGSTATE TABLE ENTRY FOR EACH REG
	DO
	BEGIN
		IF (SYMENTRY_.REGSTATE[.REG,RGVAR1]) NEQ 0 !ONE OF THE VARIABLES IN THIS REGISTER
		THEN
		BEGIN
			IF COMOREQV()		!IF VARIABLE IS IN COMMON OR IS EQUIVALENCED
			THEN
			BEGIN
				SYMENTRY[VARINREGFLG]_0;
				REGSTATE[.REG,RGVAR1]_0; !CLEAR ENTRY INDICATING THAT CONTAINS VAL OF THIS VAR
				IF .REGSTATE[.REG,RGVAR2] EQL 0 !IF THIS REG NO LONGER CONTAINS ANY VARIABLES,
				THEN		!RETURN IT TO THE SET OF AVAILABLE REGS
				BEGIN
					REGSTATE[.REG,RGNXUSE]_0;
					BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
				END
			END
		END;

		IF (SYMENTRY_.REGSTATE[.REG,RGVAR2]) NEQ 0 !POSSIBLY A SECOND VARIABLE WHOSE VALUE IS
		THEN				!IN "REG" (E.G. FOR A=B, FOTH A AND B
		BEGIN				!ARE IN THE SAME REG)
			IF COMOREQV()		!IF VARIABLE IS IN COMMON OR IS EQUIVALENCED
			THEN
			BEGIN
				SYMENTRY[VARINREGFLG]_0;
				REGSTATE[.REG,RGVAR2]_0; !CLEAR ENTRY INDICATING THAT "REG" CONTAINS VAL OF THIS VARIABLE
				IF .REGSTATE[.REG,RGVAR1] EQL 0 !IF THIS REG NO LONGER CONTAINS ANY VARIABLES
				THEN		!RETURN IT TO THE SET OF AVAILABLE REGS
				BEGIN
					REGSTATE[.REG,RGNXUSE]_0;
					BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
				END
			END
		END
	END
END;						!END OF "CLOBBCOMEQV"


GLOBAL ROUTINE CLOBBEQV=
%(***************************************************************************
	ROUTINE TO ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS ARE CLOBBERED.
	REMOVES FROM THE REGSTATE TABLE ALL VARS THAT ARE IN EQUIVALENCE STMNTS;
***************************************************************************)%
BEGIN
	REGISTER PEXPRNODE SYMENTRY;	!PTR TO SYMBOL/CONST TABLE ENTRY FOR THE
					! VAR IN A GIVEN REG
	MAP RGSTBL REGSTATE;	!TABLE INDICATING WHICH VARS ARE IN WHICH REGS
	EXTERNAL BLOCKBSYREGS;	!BIT PATTERN INDICATING WHICH REGS ARE IN USE
				! BY THE BASIC BLOCK ALLOCATOR

	INCR REG FROM 0 TO #15	!LOOK AT THE ENTRY FOR EACH REG
	DO
	BEGIN
		IF (SYMENTRY_.REGSTATE[.REG,RGVAR1]) NEQ 0	!ONE OF THE VARS IN THIS REG
		THEN
		BEGIN
			IF .SYMENTRY[OPR1] NEQ CONSTFL
				AND .SYMENTRY[IDATTRIBUT(INEQV)]	!IF THIS VAR IS IN AN EQUIVALENCE
			THEN
			(SYMENTRY[VARINREGFLG]_0; REGSTATE[.REG,RGVAR1]_0);	!CAN NO LONGER ASSUME THAT ITS VAL
										! IS IN REG
		END;

		IF (SYMENTRY_.REGSTATE[.REG,RGVAR2]) NEQ 0	!A 2ND VAR IN THIS REG
		THEN
		BEGIN
			IF .SYMENTRY[OPR1] NEQ CONSTFL
				AND .SYMENTRY[IDATTRIBUT(INEQV)]	!IF THIS VAR IS IN EQUIVALENCE
			THEN
			(SYMENTRY[VARINREGFLG]_0; REGSTATE[.REG,RGVAR2]_0);	!REMOVE ITS VAL FROM REG
		END;


		IF .REGSTATE[.REG,RGVAR1] EQL 0 AND .REGSTATE[.REG,RGVAR2] EQL 0	!IF THIS REG NOW
										! CONTAINS NO KNOWN VALS
		THEN
		(REGSTATE[.REG,RGNXUSE]_0; BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG));	!RETURN IT TO SET
										! OF FREE REGISTERS
	END	!END OF INCR LOOP
END;	!END OF ROUTINE CLOBBEQV



GLOBAL ROUTINE REGCLOBB(REG)=
%(**********
	THIS ROUTINE IS CALLED WHENEVER THE CONTENTS OF A REGISTER ARE CLOBBERED.
	THIS ROUTINE CLEARS THE REGSTATE TABLE ENTRY FOR THE REGISTER "REG".
	IF ANY VARIABLES HAVE BEEN ASSUMED TO BE IN REG IT CLEARS THE "VARINREGFLG"
	FOR THOSE VARIABLES
	IT ALSO SETS THE BIT CORRESPONDING TO THE REGISTER CLOBBERED
	IN THE GLOBAL "CLOBBREGS" WHICH IS USED TO DETERMINE WHICH REGS
	TO SAVE AND RESTORE IN A FUNCTION
**********)%
BEGIN
	REGISTER PEXPRNODE SYMPTR;		!POINTER TO SYMBOL TABLE OR CONSTANT TABLE ENTRY FOR
						!VARIABLE/CONSTANT WHOSE VALUE IS IN REG
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL BLOCKBSYREGS;			!GLOBAL VARIABLE INDICATING REGS THAT SHOULD
						!BE PRESERVED IF POSSIBLE
	EXTERNAL CLOBBREGS;	!GLOBAL IN WHICH THE BIT CORRESPONDING TO
				! EACH REG CLOBBERED BY A GIVEN SUBPROGRAM
				! IS SET (USED TO DETERMINE WHICH REGS TO SAVE/RESTORE)


	ROUTINE CLRVAR1FIELD(RG)=
	%(**********
		ROUTINE TO CLEAR THE "RGVAR1" FIELD OF A REGSTATE TABLE
		ENTRY AND IF THE "RGVAR2" FIELD IS ALSO 0, TO RETURN THE
		REGISTER TO THE SET OF FREE REGS
	***********)%
	BEGIN
		REGSTATE[.RG,RGVAR1]_0;
		IF .REGSTATE[.RG,RGVAR2] EQL 0	!IF THERE IS NOT ANOTHER VAR IN THIS REG
		THEN
		BEGIN
			REGSTATE[.RG,RGNXUSE]_0;	!"LOC OF NEXT USE"
			BLOCKBSYREGS_	!RETURN "RG" TO SET OF FREE REGS
				SETBIT(.BLOCKBSYREGS,.RG)
		END
	END;

	ROUTINE CLRVAR2FIELD(RG)=
	%(**********
		ROUTINE TO CLEAR THE "RGVAR2" FIELD OF A REGSTATE TABLE
		ENTRY AND IF THE "RGVAR1" FIELD IS ALSO 0, TO RETURN THE
		REGISTER TO THE SET OF FREE REGS
	***********)%
	BEGIN
		REGSTATE[.RG,RGVAR2]_0;
		IF .REGSTATE[.RG,RGVAR1] EQL 0	!IF THERE IS NOT ANOTHER VAR IN THIS REG
		THEN
		BEGIN
			REGSTATE[.RG,RGNXUSE]_0;	!"LOC OF NEXT USE"
			BLOCKBSYREGS_	!RETURN "RG" TO SET OF FREE REGS
				SETBIT(.BLOCKBSYREGS,.RG)
		END
	END;


%[632]%	ROUTINE CHKOTHREGS(SYM,RG)=
%[632]%	%(***********
[632]		ROUTINE TO CLEAR THE VARINREGFLG FOR SYM IFF SYM IS
[632]		ONLY IN REGISTER RG. THIS KEEPS VARINREGFLG SET IF
[632]		SOME REG CONTAINING SYM IS CLOBBERED, BUT SYM IS
[632]		STILL IN OTHER REG(S).
[632]	************)%
%[632]%	BEGIN
%[632]%
%[632]%		MAP PEXPRNODE SYM;	!THE VAR IN REGISTER RG
%[632]%		MAP RGSTBL REGSTATE;	!THE REG STATE TABLE
%[632]%
%[632]%		REGISTER REGX;		!INDEX FOR LOOP BELOW
%[632]%
%[632]%		SYM[VARINREGFLG]_0;	!ASSUME NOT IN ANY OTHER REG
%[632]%
%[632]%		REGX_0;
%[632]%		WHILE (.REGX LEQ #15) AND NOT .SYM[VARINREGFLG]
%[632]%		DO
%[632]%		BEGIN
%[632]%			IF .REGX NEQ .RG
%[632]%			THEN
%[632]%				IF    .REGSTATE[.REGX,RGVAR1] EQL .SYM
%[632]%				   OR .REGSTATE[.REGX,RGVAR2] EQL .SYM
![652] MUST BE CAREFUL IF THE VARIABLE WAS DOUBLE WORD IN WHICH
![652] CASE WE NEED TO FIND A REG FAR AWAY (MORE THAN 1)
%[652]%				THEN IF NOT .SYM[DBLFLG] THEN SYM[VARINREGFLG]_1
%[652]%					ELSE IF (.REGX+1 NEQ .RG) AND (.REGX-1 NEQ .RG)
%[652]%					THEN SYM[VARINREGFLG]_1;
%[632]%			REGX_.REGX+1
%[632]%		END
%[632]%	END;


	IF .REG GEQ 2	!UNLESS THE REG IS 0 OR 1 (WHICH ARE NEVER SAVE/RESTORED ACROSS A FN)
	THEN		! SET THE BIT CORRESPONDING TO THAT REG IN THE GLOBAL USED TO KEEP
	CLOBBREGS_	! TRACK OF ALL REGS THAT MUST BE SAVE/RESTORED
		SETBIT(.CLOBBREGS,.REG);



	IF (SYMPTR_.REGSTATE[.REG,RGVAR1]) NEQ 0 !IF SOME VARIABLE IS ASSUMED TO
	THEN					!BE IN "REG"
	BEGIN
%[632]%		CHKOTHREGS(.SYMPTR,.REG);		!CLEAR VARINREGFLG IF NECESSARY
		IF .SYMPTR[DBLFLG]	!IF THE VAR IS DP OR COMPLEX
		THEN	!MUST CLEAR THE ENTRY FOR THE OTHER HALF OF THE VAR
		BEGIN	!WHICH IS IN A REG ADJACENT TO "REG"
			IF .REGSTATE[.REG+1,RGVAR1] EQL .SYMPTR	!IF "REG" WAS THE 1ST HALF
			THEN CLRVAR1FIELD(.REG+1)	!CLEAR ENTRY IN NEXT REG
			ELSE
			IF .REGSTATE[.REG-1,RGVAR1] EQL .SYMPTR	!IF "REG" WAS THE 2ND HALF
			THEN CLRVAR1FIELD(.REG-1)	!CLEAR ENTRY IN PREVIOUS REG
			ELSE	!(IF "RGVAR1" FIELD WAS USED FOR A GIVEN VAR
				! IN ONE REG, CAN ASSUME THAT "RGVAR1" FIELD WILL
				! ALSO BE USED FOR THE OTHER HALF OF THE VAR)
			CGERR()	!IF CANT FIND ENTRY FOR THE OTHER HALF OF THE VAR
		END
	END;
	IF (SYMPTR_.REGSTATE[.REG,RGVAR2]) NEQ 0 !IF SOME SECOND VARIABLE IS ASSUMED
	THEN					!TO BE IN "REG" (E.G. IF HAD "A=B")
	BEGIN
%[632]%		CHKOTHREGS(.SYMPTR,.REG);		!CLEAR VARINREGFLG IF NEEDED
		IF .SYMPTR[DBLFLG]	!IF THE VAR IS DP OR COMPLEX
		THEN	!MUST CLEAR THE ENTRY FOR THE OTHER HALF OF THE VAR
		BEGIN	!WHICH IS IN A REG ADJACENT TO "REG"
			IF .REGSTATE[.REG+1,RGVAR2] EQL .SYMPTR	!IF "REG" WAS THE 1ST HALF
			THEN CLRVAR2FIELD(.REG+1)	!CLEAR ENTRY IN NEXT REG
			ELSE
			IF .REGSTATE[.REG-1,RGVAR2] EQL .SYMPTR	!IF "REG" WAS THE 2ND HALF
			THEN CLRVAR2FIELD(.REG-1)	!CLEAR ENTRY IN PREVIOUS REG
			ELSE	!(IF "RGVAR2" FIELD WAS USED FOR A GIVEN VAR
				! IN ONE REG, CAN ASSUME THAT "RGVAR2" FIELD WILL
				! ALSO BE USED FOR THE OTHER HALF OF THE VAR)
%[1024]%			IF .SYMPTR[VALTYPE] NEQ LITERAL	! IF THE "VAR" IS
%[1024]%						! A LITERAL THAT WAS ASSIGNED TO
%[1024]%						! A REAL, ONLY THE 1ST WORD WILL
%[1024]%						! BE IN AN AC
%[1024]%			THEN			!OTHERWISE, WE SHOULD HAVE FOUND
						! AC THAT CONTAINED THE OTHER WORD
			CGERR()	!IF CANT FIND ENTRY FOR THE OTHER HALF OF THE VAR
		END
	END;

	BLOCKBSYREGS_				!RETURN "REG" TO THE SET
		SETBIT(.BLOCKBSYREGS,.REG);	!OF FREE REGISTERS

	REGSTATE[.REG,RGVAR1]_0;		!CLEAR REGSTATE TABLE
	REGSTATE[.REG,RGVAR2]_0;		!ENTRY FOR REG
	REGSTATE[.REG,RGNXUSE]_0;
END;

GLOBAL ROUTINE CLRRGSTATE=
%(**********
	THIS ROUTINE CLEARS THE REGSTATE TABLE. IT IS CALLED AT THE END OF REGISTER ALLOCATION
	FOR A BASIC BLOCK (WHEN ALL ASSUMPTIONS ABOUT THE CONTENTS OF REGISTERS
	MUST BE DISCARDED)
**********)%
BEGIN
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL BLOCKBSYREGS;			!THIS WORD CONTAINS A BIT PATTERN IN WHICH ONES REPRESENT
						!REGISTERS THAT ARE FREE, ZEROES REPRESENT REGISTERS WHOSE
						!CONTENTS WILL BE NEEDED LATER IN THIS BASIC BLOCK
	REGISTER PEXPRNODE SYMPTR;		!POINTER TO SYMBOL/CONSTANT TABLE ENTRY FOR A VARIABLE/CONSTANT
						!WHICH IS ASSUMED TO HAVE BEEN LEFT IN SOME REGISTER

	DECR REG FROM #15 TO 0			!WALK THRU THE REGSTATE TABLE
	DO
	BEGIN
		IF (SYMPTR_.REGSTATE[.REG,RGVAR1]) NEQ 0 !A VARIABLE WHOSE VALUE IS ASSUMED TO BE IN "REG"
		THEN
		BEGIN
			SYMPTR[VARINREGFLG]_0;	!CAN NO LONGER ASSUME THAT THAT VAR IS IN A REG
			REGSTATE[.REG,RGVAR1]_0;
		END;

		IF (SYMPTR_.REGSTATE[.REG,RGVAR2]) NEQ 0 !A SECOND VARIABLE WHOSE VALUE IS ASSUMED TO BE IN "REG"
		THEN
		BEGIN
			SYMPTR[VARINREGFLG]_0;	!CAN NO LONGER ASSUME THAT THAT VAR IS IN A REG
			REGSTATE[.REG,RGVAR2]_0;
		END;

		REGSTATE[.REG,RGNXUSE]_0;	!ISN OF NEXT USE OF THES REG SET TO 0 (MEANING
	END;	!END OF DECR LOOP		!NO FUTURE USE)

	BLOCKBSYREGS_-1;			!ALL REGS ARE NOW AVAILABLE
END;						!END OF CLRRGSTATE


GLOBAL ROUTINE INIRGSTATE=
%(**********
	THIS ROUTINE INITS THE REGISTER STATE TABLE BY ZEROING ALL
	ENTRIES.
*********)%
BEGIN
	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL BLOCKBSYREGS;	!GLOBAL INDICATING WHICH REGS CONTAIN VALS OF
				! FUTURE USE IN THIS BASIC BLOCK (AND HENCE
				! HAVE ENTRIES IN THE REGSTATE TABLE)

	DECR REG FROM #15 TO 0	!CLEAR THE ENTRY FOR EACH REG
	DO
	BEGIN
		REGSTATE[.REG,RGVAR1]_0;	!CLEAR ALL FIELDS OF THE ENTRY
		REGSTATE[.REG,RGVAR2]_0;
		REGSTATE[.REG,RGNXUSE]_0;	
	END;

	BLOCKBSYREGS_-1;	!THIS WORD WILL HAVE THE BIT CORRESPONDING TO EACH
				! BUSY REG SET TO 0. INIT IT TO HAVE
				! NO BITS SET TO 0
END;	!END OF INIRGSTATE


GLOBAL ROUTINE SAVEREG(REG,SYMENT1,SYMENT2,USEISN)=
%(**********
	THIS ROUTINE IS CALLED WHEN IT IS DETERMINED THAT THE REGISTER "REG"
	SHOULD BE PRESERVED OVER FUTURE STATEMENTS IN THE CURRENT BASIC BLOCK.
	SYMENT1 IS A POINTER TO THE SYMBOL/CONSTANT TABLE ENTRY FOR THE VARIABLE/CONSTANT
	WHOSE VALUE IS IN REG.  SYMENT2 IS A POINTER TO A POSSIBLE SECOND SYMBOL/CONSTANT
	TABLE ENTRY.  USEISN IS  THE ISN OF THE NEXT USE OF THE VALUE IN REG.
********)%
BEGIN
	MAP PEXPRNODE SYMENT1;
	MAP PEXPRNODE SYMENT2;

	MAP RGSTBL REGSTATE;			!TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS

	EXTERNAL BLOCKBSYREGS;			!BIT PATTERN IN WHICH ZEROES REPRESENT REGISTERS
						!WHOSE VALUES ARE TO BE PRESERVED
	EXTERNAL NOBBREGSLOAD;		!FLAG INDICATING THE BB ALLOCATOR CANNOT ASSUME
					! THAT THE CODE FOR THE EXPRESSION CURRENTLY BEING
					! PROCESSED WILL ALWAYS BE EXECUTED AND
					! HENCE THAT WE CANNOT ASSUME THAT REGS LOADED
					! IN PROCESSING THIS EXPR HAVE THE VALS INDICATED
					! (E.G. THIS FLAG IS SET WHEN PROCESSING A LOG IF)

	IF .NOBBREGSLOAD	!IF CANNOT ASSUME THAT THE CODE FOR THIS EXPR WILL
	THEN			! ALWAYS BE EXECUTED, THEN CANNOT KEEP THIS VAL IN THIS REG
	RETURN;

	IF .SYMENT2 EQL 0	!IF ARE ONLY TRYING TO REMEMBER 1 VAR
		AND (.REGSTATE[.REG,RGVAR1] EQL .SYMENT1	! AND WE ALREADY KNEW THAT THIS
			OR .REGSTATE[.REG,RGVAR2] EQL .SYMENT1)	! VAR WAS IN THIS REG
	THEN
	BEGIN
		REGSTATE[.REG,RGNXUSE]_.USEISN;	!UPDATE VAL FOR "NEXT USE"
		IF .SYMENT1[DBLFLG]		!IF ARE SAVING  A REG  PAIR
		THEN REGSTATE[.REG+1,RGNXUSE]_.USEISN;	!UPDATE "NXT USE"FOR 2ND HALF
	END
	ELSE
	BEGIN
		REGCLOBB(.REG);		!IF THIS ENTRY ALREADY CONTAINED
				! VARS FORGET ABOUT THEM
		REGSTATE[.REG,RGVAR1]_.SYMENT1;		!SET UP THE REGSTATE TABLE ENTRY FOR THIS REG
		REGSTATE[.REG,RGVAR2]_.SYMENT2;
		REGSTATE[.REG,RGNXUSE]_.USEISN;

		IF .SYMENT1[DBLFLG]			!IF THE VALUE TO BE PRESERVED IS DOUBLE PREC OR COMPLEX
		THEN
		BEGIN
			REGSTATE[.REG+1,RGVAR1]_.SYMENT1; !SET UP REGSTATE TABLE ENTRY FOR THE REG FOLLOWING THIS REG
			REGSTATE[.REG+1,RGVAR2]_.SYMENT2;
			REGSTATE[.REG+1,RGNXUSE]_.USEISN;
		END;
	END;

	BLOCKBSYREGS_CLRBIT(.BLOCKBSYREGS,.REG); !TURN OFF BIT IN BLOCKBSYREGS CORRESPONDING
						!TO THIS REG TO INDICATE IT SHOULD
						!BE PRESERVED
	IF  .SYMENT1[DBLFLG]	!IF ARE SAVING A REG PAIR

	THEN
		BLOCKBSYREGS_CLRBIT(.BLOCKBSYREGS,.REG+1); !CLEAR BIT IN BLOCKBSYREGS TO INDICATE
						!THAT REG AFTER "REG" MUST BE
						!PRESERVED

	SYMENT1[VARINREGFLG]_1;			!SET FLAG IN SYMBOL/CONST TABLE ENTRY INDICATING THAT THIS
						!VAR IS IN SOME REG
	IF .SYMENT2 NEQ 0			!IF A SECOND VARIABLE IS ALSO IN THIS REG (EG FOR A=B)
	THEN
	SYMENT2[VARINREGFLG]_1;			!SET FLAG IN ITS SYMBOL TABLE ENTRY AS WELL
END;	!END OF ROUTINE SAVEREG


GLOBAL ROUTINE FREEPAIRS(BSYREGS)=
%(***************************************************************************
	GIVEN A BIT PATTERN "BSYREGS" IN WHICH 0'S INDICATE BUSY REGS AND
	1'S INDICATE FREE REGS, THIS ROUTINE RETURNS THE NUMBER
	OF EVEN-ODD REG PAIRS THAT ARE FREE
***************************************************************************)%
BEGIN
	RETURN ONESCOUNT(
		(.BSYREGS AND #525252525252)^(-1)	!BITS FOR FREE EVEN REGISTERS
						! SHIFTED RIGHT TO INDICATE ODD REG FOLLOWING EACH
		AND
		(.BSYREGS AND #252525252525)	!BITS FOR FREE ODD REGISTERS
		)
END;
						!END OF "SAVEREG"