Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-04 - 43,50325/tnbind.bli
There are no other files named tnbind.bli in the archive.
! File:   TNBIND.BLI
!
!    This work was supported by the Advanced Research
!    Projects Agency of the Office of the Secretary of
!    Defense (F44620-73-C-0074) and is monitored by the
!    Air Force Office of Scientific Research.

MODULE TNBIND(TIMER=EXTERNAL(SIX12))=
BEGIN
!
!
!
!
!			TNBIND    MODULE
!			----------------
!
!
!					AUGUST 1972
!					BILL WULF
!					RICHARD JOHNSSON
!
!					LATER ADDITIONS
!					PAUL KNUEVEN
!					BRUCE LEVERETT
!
!
!	THIS MODULE ASSIGN SYMBOLIC 'TEMPORARY NAMES' TO HOLD THE
!	RESULTS OF EXPRESSIONS - THEN BINDS THESE NAMES TO REGISTERS
!	AND/OR MEMORY LOCATIONS. THE MODULE CONSISTS OF THREE
!	DISTINCT SEQUENTIALLY EXECUTED PHASES: TN-ASSIGNMENT, RANKING,
!	AND PACKING.
!
!	ASSIGNMENT: IN THIS PHASE A TREE-WALK (IN EXECUTION ORDER)
!	IS MADE. A SEPARATE ROUTINE IS CALLED FOR EACH TYPE OF 
!	NODE (+,*,IF, ETC.). GENERALLY THE FUNCTIONS OF THESE ROUTINES
!	ARE TO:
!		1) ASSIGN TEMP-NAMES AND/OR LABELS IN SUCH A WAY 
!		   THAT ,IF POSSIBLE, THE SAME NAME
!		   IS USED FOR THE ENTIRE EVALUATION OF AN EXPRESSION.
!		   AN ATTEMPT IS MADE TO 'TARGET' THE VALUES OF SOME
!		   (SEVERAL) EXPRESSIONS TO THE SAME NAME.
!		2) COMPUTE THE RELATIVE 'IMPORTANCE' OF A PARTICULAR
!		   TEMP-NAME BY EXAMINING THE WAY AND NUMBER OF
!		   TIMES IT IS USED.
!		3) DETERMINE THE 'LIFE' OF A TEMP NAME -- THAT IS, THE
!		   SPAN OF PROGRAM OVER WHICH THE NAME MUST OCCUPY
!		   A SINGLE LOCATION.
!
!	RANKING: USING THE 'IMPORTANCE' MEASURE COMPUTED IN THE FIRST
!	PHASE, THE RANKING PHASE ORDERS THE TEMP-NAMES SO THAT THE
!	PACKING PHASE MAY ALLOCATE THE MOST IMPORTANT FIRST.
!	THIS INSURES THAT THE MOST IMPORTANT TEMP-NAMES WILL BE BOUND
!	TO THE MOST DESIRABLE LOCATIONS -- GENERALLY REGISTERS.
!
!	PACKING: THE FINAL PHASE PROCESSES TEMP-NAMES IN THE ORDER
!	DEFINED BY THE RANKING PHASE. USING THE 'LIFE-SPAN' INFORMATION
!	THIS PHASE ATTEMPTS TO 'FIT' OR 'PACK' THE TEMP-NAMES INTO
!	THE VARIOUS POSSIBLE LOCATIONS. ROUGHLY, THE ORDER OF PREFERENCE
!	FOR VARIOUS LOCATIONS IS:
!
!		1) AN 'OPEN' REGISTER -- THIS IS A REGISTER WHICH HAS ALREADY
!		   BEEN USED (AND THUS ITS CONTENTS NEED NOT BE SAVED).
!		2) AN 'OPEN LOCAL' -- AT LEAST IF THE COST OF USING
!		   A LOCAL FOR THIS TEMP IS LESS THAN OPENING A NEW
!		   REGISTER.
!		3) A 'CLOSED REGISTER'
!		4) AN 'OPEN LOCAL'
!		5) A 'CLOSED LOCAL'.
!
!
!	THIS BRIEF DESCRIPTION HARDLY DOES JUSTICE TO THE ALGORITHMS,
!	BUT IT SHOULD GIVE AN OVERVIEW OF WHATS GOING ON. DETAILS 
!	WILL BE FOUND BELOW. ALSO, NOTE THE OUTLINE OF THE ORGANIZATION
!	OF THE CODE GIVEN BELOW!
!
!
!
!
!


SWITCHES NOLIST;
REQUIRE COMMON.BEG;
REQUIRE PREDEF.BEG;
REQUIRE GTST.BEG;
REQUIRE ST.BEG;
REQUIRE GTX.BEG;
REQUIRE FLOW.BEG;
REQUIRE LDSF.BEG;
SWITCHES LIST;
REQUIRE DTC.BEG;
REQUIRE TN.BEG;
BEGIN
REQUIRE TRY.BEG;



! OUTLINE OF THE TNBIND MODULE
!------------------------------
!
!
!
! I. - GENERAL UTILITIES FOR TNBIND
!   A. - FOR MANIPULATING STACKS OF LISTS
!   B. - FOR ACCESSING TN REPRESENTATIVES
!   C. - FOR PERFORMING AN ACTION ON A LIST OF TN'S
!   D. - ROUTINES FROM THE LOWSEGMENT
!   E. - MISCELLANEOUS
! II. - TEMP NAME AND LABEL ASSIGNMENT
!   A. - UTILITIES
!   B. - SPECIFIC ROUTINES
!   C. - DRIVER FOR TEMP NAME/LABEL ASSIGNMENT
! III. - RANKING TEMP NAMES
!   A. - UTILITIES
!   B. - SORTING OF TEMP NAMES
!   C. - DRIVER FOR RANKING
! IV. - PACKING
!   A. - UTILITIES
!	1. - PREFERENCES
!	2. - FITTING	!
!	3. - OPENING	!
!   B. - REGISTERS	! FOR THESE FIVE, SEE TRY.BLI
!   C. - STATIC TEMPS	!
!   D. - DYNAMIC TEMPS	!
!   E. - DRIVER FOR PACKING
!   F. - MARKING OF TNS AFTER PACKING
! V. - DRIVER FOR TNBIND MODULE

! EXTERNALS, FORWARDS, AND BINDS
! -------------------------------------------------

    EXTERNAL
!	TNREP,		! FROM LOW SEGMENT
	RELTNREPLST,	! FROM LOW SEGMENT
	GETTN,		! FROM LOW SEGMENT
	DELINK,		! FROM LSTPKG
	PULSELIST,	! FROM LSTPKG
	EQLPOSSIZE,	! FROM DELAY

	TRYFIT,		! THE NEXT FEW ARE FROM TRY.BLI
	OPENLIST,
	CLOSELIST,
	REOPEN,
	ISREGLST,
	TRYSPREG,
	TRYOPREG,
	TRYCLREG,
	TRYOPSTEMPS,
	TRYCLSTEMPS,
	TRYSPDYTEMP,
	OPENDYTEMP,
	CLOSEDYTEMPS,
	TRYDYTEMPS,
	MUSTBETOP,

!	LON,		! LINEAR ORDER NUMBER
!	FON,		! FLOW ORDER NUMBER
	MAXLOCALS,	! NUMBER OF LOCALS IN 'MAXLOCALS' AREA
	STATICSIZE,	! NUMBER OF LOCALS IN 'STATIC LOCALS' AREA
!	SRLST,		! HEAD OF SPECIFIC REGISTER LIST
!	ARLST,		! HEAD OF ANY REGISTER LIST
!	SLLST,		! HEAD OF SPECIFIC LOCAL LIST
	ULST,		! BASE OF VECTOR OF "USUAL" LISTS
!	LOOPDEPTH,	! CURRENT LOOPDEPTH
	MAXKOST,	! MAXIMUM VALUE OF XUSECOMPLEXITY FIELD
	MAXFONSPAN,	! MAX FONLU-FONFU
	CALLSTK,	! BASE OF STACK OF TN'S IN CALLS
!	LOOPSTK,	! BASE OF STACK FOR TN'S IN LOOPS
	FONSTK,		! STACK OF FON VALUES AT CONTROL NODES
	LOOPLFSTK,	! STACK OF LOOP BEGINNING LON/FON VALUES
	DTDSTK;		! STACK OF DY-TEMP-DEPTH AT CONTROL NODES
!	PREFLST;	! HEAD OF PREFERENCE LIST
!	STEMPS,		! HEAD OF LIST OF STATIC TEMPS
!	DTEMPS,		! HEAD OF LIST OF DYNAMIC TEMPS
!	REGS,		! HEAD OF REGISTER LIST
!	TNCHAIN;	! HEAD OF LIST OF ALL TEMP NAMES

BIND ESTIM=FONSTK;	! RE-USE OF GLOBAL

    BIND ULSZ=4,	! SIZE OF USUAL LIST VECTOR
	 VREGNUM=0,	! NUMBER OF THE VALUE REGISTER
	MAGIC3=3,	! CAN "IF" RESULT REG BE USED AS TARGET?
	MAGIC2=5;	! IS TOS OK FOR TARGET?




! I. - GENERAL UTILITIES FOR TNBIND
! ------------------------------------------------

!   A. - FOR MANIPULATING STACKS OF LISTS
! ------------------------------------------------
!	
!	THE FOLLOWING STRUCTURES/MACROS/AND ROUTINES DEFINE
!	A SYSTEM OF STACKS OF LISTS -- THAT IS, EACK STACK
!	ELEMENT IS THE HEADER OF A DOUBLY LINKED CIRCULAR
!	LIST. THESE STACKS ARE USED, IN GENERAL, WHERE SEVERAL
!	PIECES OF INFORMATION MUST BE RECORDED AT A SINGLE
!	LEVEL OF (OBJECT PROGRAM) CONTROL. THE TYPICAL ENTRIES
!	ARE 'TN-REPRESENTATIVES' -- TWO WORD CELLS WHICH
!	POINT TO A TN CELL.
!
!




    STRUCTURE LSTSTK[I,J,K,L]= [I+1]
	CASE .I OF
	  SET
	  (.LSTSTK + .J - 1)<0,36>;
	  ([email protected])<.K,.L>;
	  .(.([email protected])<0,18>)<.K,.L>;
	  .(.([email protected])<18,18>)<.K,.L>;
	  (.LSTSTK+1+.J)<.K,.L>
	  TES;

    MAP PLSTSTK CALLSTK;

    STRUCTURE LLSTSTK[I,J,K,L]=
	CASE .I OF
	SET
	  (.LLSTSTK + .J)<.K,.L>;
	  GT[.(.LLSTSTK)<0,18>,.J,.K,.L];
	  GT[.(.LLSTSTK)<18,18>,.J,.K,.L];
	TES;

    MACRO ADDTOTOS(STK,Z)=BEGIN MAP PLSTSTK STK; LINK((Z),STK[TOS]) END$;

    MACRO INITSTK(STK)= BEGIN MAP PLSTSTK STK;
			STK_GETSPACE(GT,STKSIZE+2);
			STK[CURD]_-1;
			STK[MAXD]_-1 END$;

!   B. - FOR ACCESSING TN REPRESENTATIVES
! ------------------------------------------------
!
!
!	THIS SECTION DEFINES ACCESSING OF 'TN-REPRESENTATIVES'.
!	IN THE PROCESS OF TNBINDING IT IS NECESSARY TO
!	INCLUDE THE TN'S ON SEVERAL LISTS SIMULTANEOUSLY.
!	RATHER THAN ALLOW SPACE IN THE TN-CELL FOR ALL POSSIBLE
!	SUCH LINKINGS, A 'REPRESENTATIVE' OF THE TN-CELL IS
!	PLACED ON THE APPROPRIATE LISTS.  THE STRUCTURE OF
!	TN-REPS IS DEFINED SO THAT FIELDS IN THE TNCELL MAY
!	BE ACCESSED ,BY NAME, INDIRECTLY.
!
!


    MACRO RELTNREP(A)=RELEASESPACE(GT,(A),2)$;

!   C. - FOR PERFORMING AN ACTION ON A LIST OF TN'S
! ------------------------------------------------
!
!
!   D. - ROUTINES FROM THE LOWSEGMENT
! ------------------------------------------------

%%%<
    ROUTINE TNREP(TN)=
	BEGIN
	LOCAL TNREPR T;
	T_GETSPACE(GT,2);
	T[TNPTR]_.TN;
	T[RLINK]_T[LLINK]_.T
	END;

    ROUTINE RELTNREPLST(LST)=
	BEGIN MAP TNLSTHDR LST;
	UNTIL EMPTY(.LST) DO RELEASESPACE(GT,DELINK(.LST[RLINK]),2)
	END;

    BIND TNSIZE=6;	! SIZE OF TEMP NAME CELL

    ROUTINE GETTN=
	BEGIN LOCAL GTVEC T;
	T_GETSPACE(GT,TNSIZE);
	T[TYPEF]_TEMPNAMET;
	T[LONFU]_T[FONFU]_-1;
	LINK(TNREP(.T),TNCHAIN);
	.T
	END;
>%%%

!   E. - MISCELLANEOUS
! ------------------------------------------------

    FORWARD TLA,WANTPREF;

    EXTERNAL FIXLIST;

    STRUCTURE TNWORD[I,J]=.TNWORD<.I,.J>;

    MACRO CONTINUE=EXITBLOCK$,
	  DUMMYBLOCK=BIND ZQZQZQZQ=437$,
	  FILLTX=(IF .TX EQL 0 THEN TX_GETTN())$,
	  ISRELOP(NODE)=ONEOF(.GT[.NODE,NODEX],
					   (BMSKX(SGTROP,6) OR
					    BMSKX(SGTRUOP,6) OR
					    BMSK(SBITOP)))$,
	  ISDESTROYABLE(LEX)=(BIND LEXEME QQ=LEX; .QQ[IDTF])$,
	  LASTOPERAND=OPERAND(.NODE[NODESIZEF]-1)$,
	  LOG2(N)=(REGISTER QQ; IF (QQ_FIRSTONE(N)) GTR 0 THEN 36-.QQ ELSE 0)$,
	  MIN(A,B)=(IF (A) LSS (B) THEN (A) ELSE (B))$,
	  RESREQ=(.NODE[NSRFF] NEQ RFNONE)$;




!   F. STRUCTURE/MACROS/ROUTINES FOR LIST-IMPLEMENTED STACKS
! ------------------------------------------------

    STRUCTURE LSTACK[I,J,K,L]=
	CASE .I OF
	    SET
	    (.LSTACK)<0,36>;
	    (.LSTACK + .J)<.K,.L>;
	    (.(.LSTACK)<0,18>+.J)<.K,.L>
	    TES;


    MAP LSTACK FONSTK:LOOPLFSTK:DTDSTK;


    MACRO
	SWRD= 2,1,0,36$,
	MFON= 2,1,18,18$,  ! MAXIMUM FON
	LFON= 2,1,0,18$,   ! LAST FON
	LEFON= 2,1,0,18$,  ! LEAST FON
	LELON= 2,1,18,18$, ! LEAST LON
	LDTD= 2,1,0,36$,   ! LAST DYTEMPS DEPTH
	MDTD=2,2,0,36$;    ! MINIMUM DYTEMPS DEPTH



    MACRO PUSHLS(STK,ZVAL)=
		BEGIN
		REGISTER ITEM ZQ;
		ZQ_GETSPACE(GT,3);
		ZQ[LLINK]_ZQ[RLINK]_.ZQ[BASE];
		LINK(.ZQ,STK);
		STK[SWRD]_ZVAL
		END$,
	  POPLS(STK)= RELEASESPACE(GT,DELINK(.STK[RLINK]),3)$,
	  INITLS(STK)=NULLLST(STK)$;


! II. - TEMP NAME AND LABEL ASSIGNMENT
! ------------------------------------------------
!
!
!	THIS SECTION CONTAINS THE CODE TO DO PHASE 1: ASSIGNMENT
!	OF TEMP NAMES AND LABELS. SEE BELOW FOR DETAILS.
!
!
!   A. - UTILITIES
! ------------------------------------------------


!	COST COMPUTATIONS: THESE UTILITIES DEFINE THE COST OF
!	USING A PARTICULAR TEMP NAME. TWO COSTS ARE COMPUTED:
!	1) A 'MAX' COST -- WHICH RESULTS IF THE TEMP WERE
!	ASSIGNED TO A MEMORY LOCATION, AND 2) A 'MIN' COST
!	-- WHICH RESULTS IF A REGISTER IS USED. IN BOTH CASES
!	THE COST IS A FUNCTION OF THE OPERATOR, TYPE OF USE, AND CURRENT LOOPDEPTH.
!
!

    STRUCTURE CONSTVECTOR[I]=.CONSTVECTOR<0,36>;

    BIND VECTOR KOPND=PLIT(0,1,1,2,1,2,2,3); ! INDEXED BY ADDRESSING MODES 0-7
    BIND VECTOR KOPNDX=PLIT(1,2,7,9,7,9,7,8);

COMMENT ! UPDATE
!
! FUNCTION:
!	INCREMENT THE MIN AND MAX USE COMPLEXITY FIELDS OF THE TEMP NAME
!	POINTED TO BY 'NODE' (A GT NODE OR SYMBOL TABLE ENTRY) BY 'MN' & 'MX'
!	RESPECTIVELY. ALSO UPDATE 'MAXKOST' IF ANY LARGER ONE COMES THRU.
!
ROUTINE UPDATE(NODE,MN,MX)=
    BEGIN MAP GTVEC NODE;
	BIND LEXEME LEX=NODE;
	LOCAL GTVEC TN;
	IF .LEX[LTYPF] NEQ LITTYP THEN
	IF (TN_.NODE[REGF]) GEQ 8 THEN
	IF .TN[TYPEF] EQL TEMPNAMET THEN
	  IF NOT .TN[TNLITBIT] THEN
	    BEGIN LOCAL GTVEC Z;
	    Z_.TN[REGF]; IF .Z GEQ 8 THEN	! TAKING ACCOUNT OF BINDSTORE
		(IF .Z[TYPEF] EQL TEMPNAMET THEN RETURN UPDATE(.TN,.MN,.MX)
					    ELSE RETURN UPDATE(.Z,.MN,.MX)  );
	    TN[USECOMPLEXITY]_.TN[USECOMPLEXITY]+.MN*(.LOOPDEPTH+1);
	    Z_TN[XUSECOMPLEXITY]_.TN[XUSECOMPLEXITY]+.MX*(.LOOPDEPTH+1);
	    IF .Z GTR .MAXKOST THEN MAXKOST_.Z
	    END
    END;

COMMENT ! K
!
! FUNCTION:
!	COST OF ACCESSING NODE 'N' IF IT'S IN A REGISTER.
!
MACRO K(N)=(MAP GTVEC N; BIND LEXEME LN=N;
	    IF .LN[LTYPF] EQL LITTYP THEN 1 ELSE .KOPND[.N[MODE]])$;
COMMENT ! KX
!
! FUNCTION:
!	COST OF ACCESSING NODE 'N' IF IT'S IN MEMORY.
!
MACRO KX(N)=(MAP GTVEC N; BIND LEXEME LN=N;
	    IF .LN[LTYPF] EQL LITTYP THEN 1 ELSE .KOPNDX[.N[MODE]])$;
MACRO CLITVALUE(OP)=(BIND LEXEME LOP=OP;IF .LOP[LTYPF] EQL LITTYP
			  THEN LITVALUE(.LOP) ELSE .OP[OFFSETF])$;

COMMENT ! SHIFTKOST
!
! FUNCTION:
!	COMPUTE THE APPROXIMATE NUMBER OF ACCESSES TO A WORD
!	REQUIRED TO SHIFT A FIELD OF SIZE 'SIZE' A DISTANCE
!	OF 'DIST' BITS.
!
ROUTINE SHIFTKOST(DIST,SIZE)=
	BEGIN
	DIST_ ABS(.DIST);
	IF .DIST GTR 12 THEN DIST_17-.DIST;
	IF .DIST GTR 7 THEN DIST_.DIST-7;
	IF .SIZE EQL 1 THEN DIST_2;
	.DIST
	END;

COMMENT ! KOSTOFTEMP
!
! FUNCTION:
!	COMPUTE THE NUMBER OF ACCESSES TO A WORD REQUIRED TO MAKE IT
!	DESTROYABLE AND/OR SHIFT THE REQUIRED FIELD TO THE RIGHT END
!	OF THE WORD.
!
ROUTINE KOSTOFTEMP(NODE)=
	BEGIN LOCAL Z;
	MAP GTVEC NODE; BIND LEXEME LEX=NODE;
	IF .LEX[LTYPF] NEQ GTTYP THEN RETURN;
	Z_1 - ISDESTROYABLE(NODE);
	IF NOT .Z THEN IF .NODE[SIZEF] NEQ 16 THEN
	    Z_.Z+1+SHIFTKOST(-.NODE[POSF],.NODE[SIZEF]);
	.Z
	END;

COMMENT ! KKMOV
!
! FUNCTION:
!	COMPUTE THE NUMBER OF ACCESSES TO 'NODE2' REQUIRED
!	TO GENERATE A MOVE FROM 'NODE1' TO 'NODE2'.
!
ROUTINE KKMOV(NODE1,NODE2)=
	BEGIN MAP GTVEC NODE1:NODE2;
	BIND LEXEME LEX=NODE1:LEX2=NODE2;
	IF .LEX2[LTYPF] EQL LITTYP THEN 1 ELSE
	IF .LEX[LTYPF] NEQ GTTYP THEN 1 ELSE
	    (.NODE1[REGF] NEQ .NODE2[REGF])+
	    SHIFTKOST(.NODE2[POSF]-.NODE1[POSF],.NODE1[SIZEF])+
	    (.NODE2[SIZEF] NEQ 16)
	END;

COMMENT ! KUNOP
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR TYPICAL UNARY OPERATOR NODES.
!
ROUTINE KUNOP(NODE,UOPST,KOP)=
	BEGIN MAP GTVEC NODE:UOPST;
	LOCAL KMOV;
	KMOV_KKMOV(.UOPST,.NODE);
	UPDATE(.UOPST,(.KMOV NEQ 0)*K(UOPST),(.KMOV NEQ 0)*KX(UOPST));
	UPDATE(.NODE,(.KMOV+.KOP)*K(NODE),(.KMOV+.KOP)*KX(NODE))
	END;

COMMENT ! KBINOP
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR TYPICAL BINARY OPERATOR NODES.
!
ROUTINE KBINOP(NODE,LOPST,ROPST,KOP)=
	BEGIN MAP GTVEC NODE:LOPST:ROPST;
	LOCAL KMOV;
	IF .NODE[TPATH] THEN (KMOV_.LOPST;LOPST_.ROPST;ROPST_.KMOV);
	KMOV_KKMOV(.LOPST,.NODE);
	UPDATE(.ROPST,.KOP*K(ROPST),.KOP*KX(ROPST));
	UPDATE(.LOPST,(.KMOV NEQ 0)*K(LOPST),(.KMOV NEQ 0)*KX(LOPST));
	UPDATE(.NODE,(.KMOV+.KOP)*K(NODE),(.KMOV+.KOP)*KX(NODE))
	END;

COMMENT ! KASOP
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR +,- NODES.
!
ROUTINE KASOP(NODE,LOPST,ROPST)=
	BEGIN MAP GTVEC NODE:LOPST:ROPST;
	BIND LEXEME LOP=LOPST;
	LOCAL Z;
	IF .NODE[NIMMF] THEN
	    IF .NODE[MODE] GTR GENREG+DEFERRED
		THEN NODE[MODE]_GENREG;
	IF .NODE[TPATH] THEN (Z_.LOPST;LOPST_.ROPST;ROPST_.Z);
	Z_SUMBITS(.NODE[RCBITS]);
	IF .NODE[RCMTF] THEN Z_.Z-1+KKMOV(.LOPST,.NODE);
	UPDATE(.NODE,.Z*K(NODE),.Z*KX(NODE));
	Z_IF .NODE[RCMTF] THEN
	    IF .LOP[LTYPF] EQL GTTYP THEN
	      (.NODE[REGF] NEQ .LOPST[REGF]);
	UPDATE(.LOPST,.Z*K(LOPST),.Z*KX(LOPST));
	Z_.NODE[RCOPTF]*(1+KOSTOFTEMP(.ROPST));
	UPDATE(.ROPST,.Z*K(ROPST),.Z*KX(ROPST))
	END;

COMMENT ! KSHFTOP
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR A ^ NODE.
!
ROUTINE KSHFTOP(NODE,LOPST,NUM)=
	BEGIN LOCAL KMIN,KMAX,KMOV;
	MAP GTVEC NODE:LOPST;
	KMIN_KMAX_0;
	IF .NUM GEQ 8 THEN (KMIN_KMAX_1; NUM_.NUM-8);
	IF .NUM EQL 7 THEN KMIN_KMAX_.KMAX+4 ELSE
	(KMIN_KMAX_.KMAX+ABS(.NUM); IF .NUM LEQ -8 THEN KMAX_.KMIN+5);
	IF .NODE[NIMMF] THEN		% TAKING ACCT. OF DISTRIB. MULTIPY. %
	    IF .NODE[MODE] GTR GENREG+DEFERRED
		THEN NODE[MODE]_GENREG;
	KMOV_KKMOV(.LOPST,.NODE);
	UPDATE(.NODE,(.KMOV+.KMIN)*K(NODE),(.KMOV+.KMAX)*KX(NODE));
	UPDATE(.LOPST,(.KMOV NEQ 0)*K(LOPST),(.KMOV NEQ 0)*KX(LOPST))
	END;

COMMENT ! KRELOP
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR RELATIONAL OPERATOR NODES.
!
ROUTINE KRELOP(NODE,LOPST,ROPST)=
	BEGIN
	MAP GTVEC NODE;
	UPDATE(.LOPST,K(LOPST),KX(LOPST));
	UPDATE(.ROPST,K(ROPST),KX(ROPST));
	IF .NODE[NSRFRF] THEN UPDATE(.NODE,2*K(NODE),2*KX(NODE))
	END;

COMMENT ! LOADANALYSIS
!
! FUNCTION:
!	COMPUTE NUMBER OF ACCESSES TO THE TEMP OF A LOAD NODE.
!
MACRO LOADANALYSIS=(1+.NODE[RCNTF]+.NODE[RCCF]+2*.NODE[NIMMF])$;

COMMENT ! CTRLKOST
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR ANY CONTROL NODE WHICH HAS
!	A DEFAULT VALUE RETURNED, E.G. -1 FOR A LOOP, ETC.
!
MACRO CTRLKOST=(UPDATE(.NODE,K(NODE),KX(NODE)))$;

COMMENT ! IDKOST
!
! FUNCTION:
!	DRIVER FOR COST UPDATING FOR INCR/DECR NODES.
!
ROUTINE IDKOST(NODE)=
	BEGIN
	MAP GTVEC NODE;
	LOCAL O1,O3,O4;
	O1_.NODE[OPR1];O3_.NODE[OPR3];O4_.NODE[OPR4];
	LOOPDEPTH_.LOOPDEPTH+1;
	UPDATE(.O1,2*K(O1),2*KX(O1));
	UPDATE(.O3,K(O3),KX(O3));
	UPDATE(.O4,K(O4),KX(O4));
	LOOPDEPTH_.LOOPDEPTH-1;
	KUNOP(.O1,.NODE[OPR2],0)
	END;

COMMENT ! KOST
!
! FUNCTION:
!	MAIN COST CONTROL ROUTINE. CALLED BY TLA FOR COST UPDATING OF
!	THE CURRENT NODE. SWITCHES TO THE NODE-SPECIFIC COST UPDATING
!	ROUTINES.
!
ROUTINE KOST(NODE)=
	BEGIN MAP GTVEC NODE;
	LOCAL GTVEC LOPST:ROPST;
	BIND KLABEL=2,	! EST. AVG. NUMBER OF LEAVES TO ANY LABEL
	     MUSTBEREG=20;
	MACRO KAS=KASOP(.NODE,.LOPST,.ROPST)$,
	      KUN(C)=KUNOP(.NODE,.LOPST,(C))$,
	      KSHFT=KSHFTOP(.NODE,.LOPST,EXTEND(CLITVALUE(ROPST)))$,
	      KREL=KRELOP(.NODE,.LOPST,.ROPST)$,
	      KBIN(C)=KBINOP(.NODE,.LOPST,.ROPST,(C))$;
	IF NOT .NODE[MUSTGENCODE] THEN RETURN;
	IF .NODE[NODEX] GTR MAXOPERATOR THEN
	    BEGIN
		SELECT .NODE[NODEX] OF
		 NSET
	SYNWDO: CTRLKOST;
	SYNUDO: CTRLKOST;
	SYNDOW: CTRLKOST;
	SYNDOU: CTRLKOST;

	SSTOROP: BEGIN
		LOPST_IF .NODE[TPATH] THEN .NODE[OPR2] ELSE .NODE[OPR1];
		ROPST_IF .NODE[TPATH] THEN .NODE[OPR1] ELSE .NODE[OPR2];
		IF RESREQ THEN (KUNOP(.NODE,.ROPST,0);KUNOP(.LOPST,.NODE,0))
			  ELSE KUNOP(.LOPST,.ROPST,0)
		END;

	SYNIF: BEGIN
		LOCAL O2; O2_.NODE[OPR2];
		IF RESREQ THEN
		(KUNOP(.NODE,.NODE[OPR3],0);
		KUNOP(.NODE,.NODE[OPR4],0));
		UPDATE(.O2,K(O2),KX(O2))
		END;
	SYNCASE: BEGIN
		LOCAL O2; O2_.NODE[OPR2];
		UPDATE(.O2,MUSTBEREG*K(O2),MUSTBEREG*KX(O2));
		IF RESREQ THEN
		INCR I FROM 2 TO .NODE[NODESIZEF]-2 DO
		    KUNOP(.NODE,.NODE[OPERAND(.I)],0)
		END;
	SYNSEL: BEGIN
		MACRO OPND(I)=NODE[OPERAND(I)]$,
		      LAST(I)=NODE[OPERAND(.NODE[NODESIZEF]-I)]$;
		LOCAL FO,LAS2;
		LOPST_.OPND(0);
		IF RESREQ THEN IF NOT .NODE[ROTHER] THEN CTRLKOST;
		IF (FO_LITVALUE(.LAST(1))) NEQ 0
		    THEN (LAS2_.LAST(2); UPDATE(.LAS2,K(LAS2),KX(LAS2)));
		INCR I FROM 1 TO .NODE[NODESIZEF]-4 BY 2 DO
		   BEGIN
			IF .I LEQ .FO THEN UPDATE(.LAS2,K(LAS2),KX(LAS2));
			IF (ROPST_.OPND(.I)) NEQ LEXALWAYS
			 THEN IF .ROPST NEQ LEXOTHERWISE
			  THEN (UPDATE(.LOPST,K(LOPST),KX(LOPST));
				UPDATE(.ROPST,K(ROPST),KX(ROPST)));
			IF RESREQ THEN KUNOP(.NODE,.OPND(.I+1),0)
			END
		END;

	SYNINCR: IDKOST(.NODE);
	SYNDECR: IDKOST(.NODE);

	SFPARM:	BEGIN
		LOPST_.NODE[OPR1];
		KUN(LOADANALYSIS);
		END;

	SYNLABEL: IF RESREQ THEN
			KUNOP(.NODE,.NODE[OPR1],IF .GT[.NODE[OPR2],LEFTBIT]
						   THEN KLABEL
						   ELSE 1)
		 TESN
	    END

	ELSE BEGIN
		IF NOT RESREQ THEN RETURN;
		LOPST_.NODE[OPR1];
		IF .NODE[NODESIZEF] GEQ 2 THEN ROPST_.NODE[OPR2];
		IF ISRELOP(NODE) THEN KREL ELSE
		SELECT .NODE[NODEX] OF
	    NSET
	SADDOP: KAS;
	SSWABOP: KUN(1);
	SMINOP: KAS;
	SPLUSOP: KUN(LOADANALYSIS);
	SANDOP: KBIN(2);
	SOROP: KBIN(2);
	SXOROP: KBIN(4);
	SEQVOP: KBIN(4);
	SMAXOP: KBIN(2);
	SMINNOP: KBIN(2);
	SSHIFTOP: KSHFT;
	SROTOP: (LOCAL X; X_EXTEND(CLITVALUE(ROPST));X_ABS(.X);
		    KUN(IF .X GTR 8 THEN 17-.X ELSE .X));
	OTHERWISE: 0
	    TESN
	     END
	END;



!	THE FOLLOWING ROUTINES,ETC., ARE CONCERNED
!	WITH DETERMINING THE LIFE 'SPAN' OF A TEMP NAME.
!	THE 'SPAN' IS DEFINED IN TERMS OF TWO QUANTITIES,
!	THE 'LON' AND 'FON'. (SEE THE TNBIND DOCUMENTATION
!	FOR THE DEFINITION AND USE OF THESE).
!
!	THE PROCESS OF DETERMINING THE 'SPAN' IS ACCOMPLISHED
!	BY A SINGLE ROUTINE 'SPAN' AND A NUMBER OF NODE-SPECIFIC
!	DRIVERS FOR SPAN. FOR EXAMPLE, ALL BINARY OPERATORS
!	INVOKE THE ROUTINE 'SPANBINARY' WHICH, IN TURN,, 
!	MAKES SEVERAL CALLS ON SPAN.
!
!

    MACRO NEXTLON=(LON_.LON+1)$,
	  NEXTFON=(FON_.FON+1)$,
	  SAVDTD=(PUSHLS(DTDSTK,.DTEMPS[CURD]); DTDSTK[MDTD]_#777777)$,
	  POPDTD=(POPLS(DTDSTK))$;
COMMENT ! RESETDTD
!
! FUNCTION:
!	USED AFTER EACH BRANCH OF A FORK. KEEPS TRACK (IN MDTD) OF THE
!	LOWEST LEVEL TO WHICH ANY BRANCH RAISED DTEMPS[CURD] (THE
!	DYNAMIC TEMPS STACK DEPTH). ALSO RESETS THE DYTEMP STACK TO
!	WHATEVER IT WAS BEFORE THE BRANCH.
!
MACRO	RESETDTD=(IF .DTEMPS[CURD]LSS.DTDSTK[MDTD]THEN DTDSTK[MDTD]_
		   .DTEMPS[CURD]; CLOSEDYTEMPS(.DTDSTK[LDTD]))$;
COMMENT ! MINDTD
!
! FUNCTION:
!	USED AFTER AN ENTIRE FORK. CUTS BACK THE DYTEMPS STACK
!	TO THE MINIMUM HEIGHT, KEPT TRACK OF AS NOTED ABOVE.
!
MACRO	MINDTD=(IF .DTEMPS[CURD] LSS .DTDSTK[MDTD]
		  THEN DTDSTK[MDTD]_.DTEMPS[CURD];
		CLOSEDYTEMPS(.DTDSTK[MDTD]))$;
MACRO	NOTEDTD=NODE[DTDELETE]_-1  %(.DTEMPS[CURD]+1)*2% $,

	  SAVFON= PUSHLS(FONSTK,(.FON^18+.FON))$,
	  RESETFON=(IF .FON GTR .FONSTK[MFON]
			THEN FONSTK[MFON]_.FON;
		    FON_.FONSTK[LFON])$,
	  MAXFON=(IF .FONSTK[MFON] GTR .FON
		    THEN FON_.FONSTK[MFON];
		  POPLS(FONSTK))$;

    MACRO UPDATELONFON=(NODE[LONF]_NEXTLON; NODE[FONF]_NEXTFON)$,
	  LABELWORD(Z1,Z2)=((Z1)^18 OR ((Z2) AND #777777))$,
	  ASSIGNLABELS=
		IF .LABS NEQ 0 THEN
		IF LABSNEEDED THEN
		    BEGIN
		    LOCAL GTVEC T;
		    NODE[LABELW]_.LABS;
		    IF (T_.LABS[LTF]) NEQ 0 THEN T[LABELREQDF]_1;
		    IF (T_.LABS[LFF]) NEQ 0 THEN T[LABELREQDF]_1;
		    END$;
    MACRO TNF=0,18$,
	  LTF=18,18$,
	  LFF=0,18$;

    MACRO NOTELOOP(Z,LD)=(LINK(TNREP(Z),LOOPSTK[LSELEM(LD)]))$;

    MACRO
	ISGTLEX(X)=(BIND LEXEME L=(X); .L[LTYPF] EQL GTTYP)$,
	LABSNEEDED=(.NODE[NSRFFF])$,
	FLOWRES=(.NODE[NSRFF] EQL RFFLOW)$,
	TNNEEDED=(.NODE[NSRFRF])$;

    MACRO SETNOTFPARM=
	(LOCAL A;
	 A_.DTEMPS[CURD]+1;
	 IF .A GTR .DTEMPS[MAXD] THEN EXITBLOCK;
	 REOPEN(DTEMPS[LSELEM(.A)],.LON,.FON);
	 CLOSELIST(DTEMPS[LSELEM(.A)],.LON)   )$;

    COMMENT ! KILLPDTEMPS
    !
    ! FUNCTION:
    !	    MAKES SURE THAT CODE WILL BE GENERATED TO CLEAN UP THE STACK
    !	    DOWN TO LEVEL 'NUM', AFTER CODING OF 'NODE'.
    !
    ROUTINE KILLPDTEMPS(NODE,NUM)=
	BEGIN
	MAP GTVEC NODE;
	BIND LEXEME LEX=NODE;
	IF .LEX[LTYPF] NEQ GTTYP THEN RETURN;
	CLOSEDYTEMPS(.NUM);
	NODE[DTDELETE]_(.NUM+1)*2;

	END;

    COMMENT ! KLCLEANUP
    !
    ! FUNCTION: EXIT ROUTINE FOR KILLDYTEMPS AND KILLFORKDYTEMPS
    !	MAKES SURE APPROPRIATE SUBNODES PUT OUT STACK CLEANUP
    !	CODE IF NECESSARY (I.E. IF THEY ARE LIKELY TO CAUSE
    !	BRANCHES TO LABELS PAST THE NODE'S STACK CLEANUP CODE)
    !
    ROUTINE KCLEANUP(ROUT,NODE)=
    BEGIN
	MAP GTVEC NODE;
	IF .NODE[NODEX] EQL SYNCOMP
	  THEN RETURN (.ROUT)(.NODE[LASTOPERAND]);
	IF NOT FLOWRES THEN
	  IF NOT (IF ISRELOP(NODE)
		    THEN .GT[.NODE[OPR1],NODEX] EQL SBITOP
			OR .GT[.NODE[OPR2],NODEX] EQL SBITOP)
	    THEN RETURN;
	IF .NODE[NODEX] EQL SYNIF
	  THEN ((.ROUT)(.NODE[OPR3]);
		(.ROUT)(.NODE[OPR4]);
		RETURN);
	IF .NODE[NODEX] EQL SYNCASE
	  THEN (INCR I FROM 2 TO .NODE[NODESIZEF]-2 DO
		  (.ROUT)(.NODE[OPERAND(.I)]);
		RETURN);
	% AT THIS POINT, NODE MUST BE AND, OR, OR NOT %
	(.ROUT)(.NODE[OPR1]);
	IF .NODE[NODESIZEF] EQL 2
	  THEN (.ROUT)(.NODE[OPR2]);
	END;


    COMMENT ! KILLFORKDYTEMPS
    !
    ! FUNCTION:
    !	    USED ON EACH BRANCH OF A FORK AFTER MINDTD. MAKES SURE THAT
    !	    CODE TO CLEAN UP THE STACK IS GENERATED AFTER EACH BRANCH.
    !
    ROUTINE KILLFORKDYTEMPS(NODE)=
	BEGIN
	MAP GTVEC NODE;
	BIND LEXEME LEX=NODE;
	IF .LEX[LTYPF] NEQ GTTYP THEN RETURN NOVALUE;
	NODE[DTDELETE]_(.DTDSTK[MDTD]+1)*2;
	KCLEANUP(KILLFORKDYTEMPS,.NODE);
	RETURN NOVALUE
	END;


    ROUTINE KILLDYTEMPS(NODE)=
	BEGIN
	MAP GTVEC NODE;
	BIND LEXEME LEX=NODE;
	IF .LEX[LTYPF] NEQ GTTYP THEN RETURN NOVALUE;
	CLOSEDYTEMPS(.DTDSTK[LDTD]);
	NODE[DTDELETE]_(.DTDSTK[LDTD]+1)*2;
	KCLEANUP(KILLDYTEMPS,.NODE);
	RETURN NOVALUE
	END;



    MACRO TNSPAN(XTN)=(IF .XTN GTR 8 THEN (XTN[LONLU]_.LON;XTN[FONLU]_.FON))$,
	  INITTNSPAN(XTN)=(IF .XTN GTR 8 THEN
		(XTN[FONFU]_XTN[FONLU]_.FON;XTN[LONFU]_XTN[LONLU]_.LON))$;


    ROUTINE SPAN(NODE,INC)=
	BEGIN
	MAP GTVEC NODE; BIND LEXEME NLEX=NODE;
	LOCAL GTVEC TN,FFU,FLU,LD;
	IF .NLEX[LTYPF] EQL BNDVAR THEN
	    (IF NOT ONEOF(.NODE[TYPEF],BIT3(REGT,LOCALT,FORMALT))
	      THEN RETURN NOVALUE)
	  ELSE IF .NLEX[LTYPF] NEQ GTTYP THEN RETURN NOVALUE ELSE
	IF .NODE[NODEX] EQL SYNCOMP THEN SPAN(.NODE[LASTOPERAND],.INC);
	IF (TN_.NODE[REGF]) GTR 8 THEN
	    BEGIN
	    IF .TN[TNLITBIT] THEN RETURN NOVALUE;
	    IF .TN[LONLU] LSS .LON THEN TN[LONLU]_.LON-.INC;
	    IF (FLU_.TN[FONLU]) LSS .FON THEN FLU_TN[FONLU]_.FON-.INC;
	    IF .TN[LONFU] GTR .LON THEN TN[LONFU]_.LON;
	    IF (FFU_.TN[FONFU]) GTR .FON THEN FFU_TN[FONFU]_.FON;
	    IF .NLEX[LTYPF] EQL GTTYP
		THEN LD_MIN(.TN[LDF],.NODE[GTLDF])
		ELSE LD_.TN[LDF];
	    IF .LD LSS .LOOPDEPTH THEN NOTELOOP(.TN,.LD);
	    IF ONEOF(.TN[REQD],BIT3(NOREQDB,DECREQDB,RFREQDB)) THEN
		IF .MAXFONSPAN LSS .FLU-.FFU THEN MAXFONSPAN_.FLU-.FFU;
	    SELECT .TN[REQD] OF
		NSET
		MEMREQDB: EXITSELECT NODE_.TN[REGF];
		RFREQDB:  EXITSELECT NODE_.TN[OFFSETF];
		ALWAYS: RETURN NOVALUE
		TESN;
	    SELECT .NODE[TYPEF] OF
		NSET
		TEMPNAMET: RETURN NOVALUE;
		GRAPHT: RETURN SPAN(FASTLEXOUT(GTTYP,.NODE),.INC);
		OTHERWISE: RETURN SPAN(FASTLEXOUT(BNDVAR,.NODE),.INC)
		TESN
	    END;
	NOVALUE
	END;




    ROUTINE SPANBINARY(NODE)=
	BEGIN MAP GTVEC NODE;
	LOCAL LEXEME TN;
	MACRO SPC=(.TN[SSPF] NEQ PFE1)$;
	SPAN(.NODE,0);
	IF .NODE[TPATH]
	    THEN (TN_.NODE[OPR2]; SPAN(.NODE[OPR1],0))
	    ELSE (TN_.NODE[OPR1]; SPAN(.NODE[OPR2],0));
	SPAN(.TN,SPC)
	END;

    ROUTINE AOSPAN(NODE)=
	BEGIN
	MAP GTVEC NODE;
	IF NOT FLOWRES THEN SPANBINARY(.NODE)
	END;

    ROUTINE SPANBXNARY(NODE)=
	BEGIN MAP GTVEC NODE;
	SPAN(.NODE,0);
	SPAN(.NODE[OPR1],0);
	SPAN(.NODE[OPR2],0)
	END;

    ROUTINE SPANSTORE(NODE)=
	BEGIN MAP GTVEC NODE;
	LOCAL LEXEME L; BIND GTVEC LST=L;
	MACRO SC=IF NOT RESREQ THEN 0 ELSE
		   IF .L[LTYPF] NEQ GTTYP THEN 1 ELSE
			IF .LST[NODEX] LEQ MAXOPERATOR
			    THEN (.L[SSPF] NEQ PFE1)$;
	SPAN(.NODE,0);
	IF .NODE[TPATH]
	    THEN (L_.NODE[OPR1]; SPAN(.NODE[OPR2],0))
	    ELSE (L_.NODE[OPR2]; SPAN(.NODE[OPR1],0));
	SPAN(.L,SC)
	END;

    ROUTINE SPANUNARY(NODE)=
	BEGIN MAP GTVEC NODE;
	SPAN(.NODE,0);
	SPAN(.NODE[OPR1],1)
	END;

    ROUTINE SPANUXNARY(NODE)=
	BEGIN MAP GTVEC NODE;
	SPAN(.NODE,0);
	SPAN(.NODE[OPR1],0)
	END;

    ROUTINE SPANUX(NODE)=
	BEGIN MAP GTVEC NODE;
	SPAN(.NODE,0)
	END;

    ROUTINE SPANLOADNODE(NODE)=
	BEGIN
	REGISTER LEXEME OP;
	MAP GTVEC NODE;
	SPAN(.NODE,0);
	OP_.NODE[OPR1];
	IF .OP[LTYPF] EQL BNDVAR THEN SPAN(.OP,0) ELSE
	IF .OP[SSPF] EQL PFE1 THEN SPAN(.OP,0);
	NOVALUE
	END;

    ROUTINE SPANID(NODE)=
	BEGIN
	MAP GTVEC NODE;
	SPAN(.NODE,0);
	SPAN(.NODE[OPR1],1);
	SPAN(.NODE[OPR3],1);
	SPAN(.NODE[OPR4],1)
	END;



    MACRO
 	INITLOOP=(INITSTK(LOOPSTK);INITLS(LOOPLFSTK))$,
	RELEASELOOP=RELEASESPACE(GT,.LOOPSTK,STKSIZE)$;

    ROUTINE ENTLOOP=(PUSHSTK(LOOPSTK); NEXTLON; NEXTFON;
		 PUSHLS(LOOPLFSTK,.LON^18+.FON); LOOPDEPTH_.LOOPDEPTH+1);

    ROUTINE XITLOOP=
	BEGIN LOCAL L,GTVEC T;
	FORALLTN(T,LOOPSTK[TOS],
	    BEGIN
	    IF .T[FONFU] GTR .LOOPLFSTK[LEFON] 
		THEN T[FONFU]_.LOOPLFSTK[LEFON];
	    IF .T[LONFU] GTR .LOOPLFSTK[LELON]
		THEN T[LONFU]_.LOOPLFSTK[LELON];
	    IF .T[FONLU] LSS .FON THEN T[FONLU]_.FON;
	    IF ONEOF(.T[REQD],BIT3(NOREQDB,DECREQDB,RFREQDB)) THEN
		(L_.T[FONLU]-.T[FONFU];
		 IF .L GTR .MAXFONSPAN THEN MAXFONSPAN_.L);
	    IF .T[LONLU] LSS .LON THEN T[LONLU]_.LON
	    END);
	LOOPDEPTH_.LOOPDEPTH-1;
	POPSTK(LOOPSTK);
	POPLS(LOOPLFSTK);
	NOVALUE
	END;

    COMMENT ! BINDUSES
    !
    ! FUNCTION:
    !	    'NODE' IS A CSE. ASSIGN THE SAME TN TO
    !	    ALL THE OCCURRENCES OF THE CSE.
    !
    ROUTINE BINDUSES(NODE)=
	BEGIN
	MAP GTVEC NODE;
	REGISTER GTVEC PNODE:T;
	PNODE_.NODE[CSPARENT];
	PNODE[BOUND]_1;		! SAVES SOME TROUBLE FOR BOGUS NODES
	IF (T_.NODE[REGF]) LSS 8 THEN RETURN;
	IF .T[REQD] EQL 0 THEN
	    T[REQD]_DECREQDB;	! TREAT CSE'S LIKE DECLARED TN'S
	DO (IF .PNODE[NSRFF] NEQ RFNONE
	      THEN PNODE[REGF]_.T;
	    IF NOT (.PNODE[DELAYED] AND .PNODE[MUSTGENCODE])
	      THEN PNODE[BOUND]_1)
	  UNTIL (PNODE_.PNODE[CSTHREAD]) EQL 0;
	NOVALUE
	END;

!   B. - SPECIFIC ROUTINES
! ------------------------------------------------
!
!
!	THIS SECTION CONTAINS THE NODE-SPECIFIC TN ASSIGNMENT
!	ROUTINES. THE FLOW WITHIN THESE ROUTINES IS A BIT
!	INVOLUTED - A BIT OF EXPLANATION IS PROBABLY IN ORDER:
!
!	1) ASSIGNMENT IS DONE IN AN EXECUTION-ORDER TREE WALK.
!	EACH ROUTINE TENDS TO DO A BIT OF WORK AT A NODE THEN
!	CALL OTHER BINDERS TO WORK ON ITS SUBNODES, AND FINALLY
!	DOES A BIT MORE AT ITS OWN NODE BEFORE RETURNING.
!	
!	2) SINCE EACH TYPE OF NODE HAS A ROUTINE TO HANDLE
!	IT, THE ROUTINE 'TLA' ACTS AS A SWITCH TO CALL THE
!	APPROPRIATE ONE. THAT IS, EACH NODE CALLS 'TLA' ON ITS 
!	SUBNODES, AND TLA PROMPTLY SWITCHES OFF TO THE
!	SPECIFIC ROUTINE.
!
!	3) SINCE MANY OF THE ACTIONS OF BINDING ARE COMMON TO
!	EACH OF THE SPECIFIC ROUTINES, A SINGLE ROUTINE,
!	'TLCOMMON', HANDLES THESE IN MOST CASES. IN THESE
!	CASES, TLCOMMON CALLS ANOTHER ROUTINE TO PERFORM THE
!	NODE-SPECIFIC ACTIONS.  TLCOMMON ALSO CALLS THE SPAN ROUTINE
!	WHICH IS APPROPRIATE FOR THE SPECIFIC NODE.
!
!	THE MACRO 'TLRDEF' IS USED TO DEFINE A TN ASSIGNMENT
!	ROUTINE CALLED BY 'TLA'.  THE MACRO 'NDRDEF' IS USED
!	TO DEFINE A NODE-SPECIFIC ROUTINE CALLED BY TLCOMMON.
!
!
!

%<  ROUTINE TNWALK(NODE)=
	BEGIN
	MAP GTVEC NODE;
	LOCAL GTVEC N;
	BIND LEXEME L=N;
	INCR I FROM 0 TO .NODE[NODESIZEF]-1 DO
	    BEGIN
	    N_.NODE[OPERAND(.I)];
	    IF .L[LTYPF] EQL GTTYP THEN
		IF .N[MUSTGENCODE]
		    THEN TLA(.N,0,0)
		    ELSE TNWALK(.N)
	    END;
	NOVALUE
	END;
>%

FORWARD TLCOMMON;

MACRO SETBOUND=NODE[BOUND]_1$;


    ROUTINE TLLIST(NODE,P)=
	BEGIN
	MAP GTVEC NODE;
	LOCAL L;
	L_.NODE[MUSTGENCODE];
	NODE[MUSTGENCODE]_1;
	TLA(.NODE,0,0);
	BINDUSES(.NODE);
	NODE[MUSTGENCODE]_.L;
	NOVALUE
	END;

    ROUTINE LOOPTLLIST(NODE,P)=
	(MAP GTVEC NODE;
	 TLLIST(.NODE,.P);
	 IF (NODE_.NODE[REGF]) GEQ 8
	   THEN IF .NODE[LDF] GTR .LOOPDEPTH
		  THEN NODE[LDF]_.LOOPDEPTH;
	 NOVALUE);

    ROUTINE BINDLST(N)=(PULSELIST(TLLIST<0,0>,.N,0); FIXLIST(.N));

    ROUTINE LPBINDLST(N)=(PULSELIST(LOOPTLLIST<0,0>,.N,0); FIXLIST(.N));

    MACRO TLRDEF(NAME,BODY)=
	ROUTINE ID(TL)NAME(NODE,TX,LABS)=
	    ( MAP GTVEC NODE, TNWORD TX:LABS; BODY)$;

    MACRO NDRDEF(NAME,BODY)=
	ROUTINE ID(ND)NAME(NODE,TX,LABS)=
	    ( MAP GTVEC NODE, TNWORD TX:LABS; BODY)$;

    TLRDEF(NULL,(NOTEDTD; 0));


    NDRDEF(B,(
	BEGIN LOCAL LOP,ROP,OP1;
	BIND TEMP=LABS;
	LOP_ROP_0;
	IF .NODE[TPATH] THEN (ROP_.TX;OP1_.NODE[OPR2])
			ELSE (LOP_.TX;OP1_.NODE[OPR1]);
	LOP_TLA(.NODE[OPR1],.LOP,0);
	ROP_TLA(.NODE[OPR2],.ROP,0);
	IF .NODE[TPATH] THEN LOP_.ROP;
	IF NOT RESREQ THEN RETURN .LOP;
	TEMP_0;
	IF .TX EQL 0 THEN
	    IF ISDESTROYABLE(OP1) THEN TX_.LOP ELSE TEMP_.LOP;
	IF TNNEEDED THEN (FILLTX; WANTPREF(.TX,.TEMP));
	.TX
	END));


    NDRDEF(U,TLA(.NODE[OPR1],.TX,.LABS));

    ROUTINE ISBIT(LEX)=
	BEGIN
	MAP LEXEME LEX;
	BIND GTVEC NODE=LEX;
	IF .LEX[LTYPF] EQL GTTYP
	    THEN IF .NODE[NODEX] EQL SBITOP
		THEN (TNNEEDED)^1 + 1
	END;

    NDRDEF(REL,(
	BEGIN
	LOCAL LOP,ROP,LB1,LB2;
	BIND BITLEFT =ISBIT(.NODE[OPR1]),
	     BITRIGHT=ISBIT(.NODE[OPR2]);
	IF TNNEEDED OR (BITLEFT OR BITRIGHT)^(-1) THEN FILLTX ELSE TX_0;
	LOP_ROP_LB1_LB2_0;
	IF BITLEFT THEN (LOP_.TX; LB1_.LABS) ELSE
	IF BITRIGHT THEN (ROP_.TX; LB2_.LABS);
	LOP_TLA(.NODE[OPR1],.LOP,.LB1);
	ROP_TLA(.NODE[OPR2],.ROP,.LB2);
	IF BITLEFT THEN WANTPREF(.TX,.LOP) ELSE
	IF BITRIGHT THEN WANTPREF(.TX,.ROP);
	.TX
	END));

    NDRDEF(FSTO,(
	BEGIN LOCAL UOP;
	UOP_TLA(.NODE[OPR1],0,0);
	IF RESREQ THEN (FILLTX; WANTPREF(.TX,.UOP));
	.TX
	END));

    NDRDEF(SWAB,(
	BEGIN LOCAL UOP;
	UOP_TLA(.NODE[OPR1],.TX,0);
	IF RESREQ THEN
	  IF ISDESTROYABLE(NODE[OPR1])
	    THEN TX_.UOP
	    ELSE (FILLTX; WANTPREF(.TX,.UOP));
	.TX
	END));



    NDRDEF(FPAR,(
	BEGIN
	LOCAL GTVEC UOP:PARM;
	BIND LEXEME PARMLEX=PARM;
	UOP_TLA(PARM_.NODE[OPR1],0,0);
	IF .NODE[CSCOMPL] LEQ MAGIC2 THEN
	  IF .UOP GTR 8 THEN
	  IF .UOP[REQD] EQL 0 THEN
	  IF .PARMLEX[LTYPF] EQL GTTYP THEN
	  IF ISDESTROYABLE(PARM) THEN
	  IF .PARM[MODE] EQL GENREG THEN
	    EXITBLOCK .UOP;
	TX_GETTN();
	WANTPREF(.TX,.UOP);
	.TX
	END));

    MACRO ISNCSE(TN) = (IF TN GEQ 8 THEN
			  .GT[TN,BNDTYP] EQL BNDNCSE) $,
	  FIXLDF(TN) = (GT[TN,LDF]_.LOOPDEPTH) $;

    NDRDEF(LOADNODE,(
	BEGIN LOCAL UOP,LEXEME OP1;
	OP1_.NODE[OPR1];
	UOP_TLA(.OP1,0,0);
	IF ISNCSE(.NODE[REGF])
	  THEN FIXLDF(.NODE[REGF]);
	IF RESREQ THEN (FILLTX;
			IF .OP1[LTYPF] NEQ BNDVAR
			  THEN WANTPREF(.TX,.UOP));
	.TX
	END));


    NDRDEF(ADDSUB,(
	BEGIN LOCAL LOP,ROP,OP1,TN;
	BIND TEMP=LABS;
	LOP_ROP_0;
	IF .NODE[TPATH] THEN (ROP_.TX;OP1_.NODE[OPR2])
			ELSE (LOP_.TX;OP1_.NODE[OPR1]);
	LOP_TLA(.NODE[OPR1],.LOP,0);
	ROP_TLA(.NODE[OPR2],.ROP,0);
	IF .NODE[TPATH] THEN LOP_.ROP;
	IF NOT RESREQ THEN RETURN .LOP;
	TN_TEMP_0;
	IF ISDESTROYABLE(OP1) THEN TN_.LOP ELSE TEMP_.LOP;
	IF .TN GEQ 8 THEN TX_.TN ELSE
	    IF TNNEEDED THEN
		BEGIN
		IF NOT (.NODE[RCMTF] AND NOT .NODE[OLDRCMTF]) THEN
		  IF NOT .NODE[RCMOF] THEN
		    TX_.TEMP;
		FILLTX;
		WANTPREF(.TX,.TEMP);
		END;
	.TX
	END));

    TLRDEF(DOT,(
	BEGIN
	BIND LEXEME LEX=NODE;
	IF ISCSEUSE(NODE)
	    THEN BEGIN
		LOCAL GTVEC PAR;
		PAR_.NODE[CSPARENT];
		IF NOT .PAR[BOUND] THEN
		  (IF NOT .PAR[DELAYED]		! PAR IS A BOGUS NODE
		    THEN NONBOGUS(PAR);
		   IF .PAR NEQ .LEX[ADDRF] THEN
		     TLLIST(FASTLEXOUT(GTTYP,.PAR),0))
		END
	    ELSE BEGIN
		TX_TLA(.NODE[OPR1],.TX,.LABS);
		IF .NODE[REGF] EQL 0 THEN NODE[REGF]_.TX;
		IF ISCSECREATION(NODE) THEN BINDUSES(.NODE);
		END;
	NOTEDTD;
	UPDATELONFON;
	SETBOUND;
	ASSIGNLABELS;
	SPANUXNARY(.NODE);
	.NODE[REGF]
	END));

    ROUTINE BINDSTORE(LOP,ROP)=
	BEGIN MAP GTVEC LOP:ROP;
	BIND LEXEME LLOP=LOP;
	LOCAL SVLON,SVFON;
	IF .ROP LEQ 7 THEN RETURN NOVALUE;
	IF .ROP[REQD] NEQ 0 THEN RETURN NOVALUE;
	ROP[REQD]_MEMREQDB;
	IF .LLOP[LTYPF] EQL LITTYP
	  THEN BEGIN
		ROP[TNLITBIT]_1;
		ROP[TNLITLEX]_.LOP;
		ROP[BNDTYP]_0;
		RETURN NOVALUE
		END;
	ROP[REGF]_.LOP;
	UPDATE(.LOP,.ROP[USECOMPLEXITY]/(.LOOPDEPTH+1),.ROP[XUSECOMPLEXITY]/(.LOOPDEPTH+1));
	SVLON_.LON; SVFON_.FON;
	LON_.ROP[LONFU]; FON_.ROP[FONFU];
	SPAN(.LOP,0);
	LON_.SVLON; FON_.SVFON;
	NOVALUE
	END;

    ROUTINE FINDLEX(LEX,TREE)=
	BEGIN
	MAP LEXEME LEX, GTVEC TREE;
	BIND LEXEME TLEX=TREE;
	MACRO FINDNCSE(NODE)=
		(MAP GTVEC NODE;
		 IF .NODE[REGF] LEQ 7 THEN RETURN 0 ELSE
		 IF .GT[.NODE[REGF],BNDTYP] NEQ BNDNCSE THEN RETURN 0 ELSE
		 NODE_.GT[.NODE[REGF],OFFSETF];
		 IF .NODE[TYPEF] EQL GRAPHT THEN RETURN 0;
		 NODE<LTYPF>_BNDVAR)$;

	IF .LEX[LTYPF] EQL GTTYP THEN FINDNCSE(LEX);
	IF .TLEX[LEXPART] EQL .LEX[LEXPART] THEN RETURN 1;
	IF .TLEX[LTYPF] EQL GTTYP THEN
	  IF .TREE[NODEX] EQL SYNNULL THEN (FINDNCSE(TREE); RETURN FINDLEX(.LEX,.TREE))
				      ELSE
	    INCR I FROM 0 TO .TREE[NODESIZEF]-1 DO
		IF FINDLEX(.LEX,.TREE[OPERAND(.I)]) THEN RETURN 1;
	0
	END;

    ROUTINE FINDLEFT(LN,RN)=
	BEGIN LOCAL X,Y;
	MAP GTVEC LN:RN; BIND LEXEME LRN=RN;
	IF .LRN[LTYPF] NEQ GTTYP THEN RETURN 0;
	IF .RN[NODEX] EQL SDOTOP THEN RETURN (.RN[OPR1] EQL .LN);
	IF NOT (ONEOF(.RN[NODEX],BIT5(SADDOP,SMINOP,SANDOP,SOROP,SSWABOP))
		OR ONEOF(.RN[NODEX]-2,BIT6(SSHIFTOP-2,SROTOP-2,
					   SMAXOP-2,SMINNOP-2,SEQVOP-2,SXOROP-2)))
	  THEN RETURN 0;
	IF .RN[TPATH] THEN (X_.RN[OPR2];Y_.RN[OPR1])
		      ELSE (Y_.RN[OPR2];X_.RN[OPR1]);
	IF .RN[NODESIZEF] EQL 2 THEN
	  IF FINDLEX(.LN,.Y) THEN RETURN 0;
	IF (Y_FINDLEFT(.LN,.X)) NEQ 0 THEN .Y+1 ELSE 0
	END;

    ROUTINE ISNEGNOT(LN,RN)=
	BEGIN
	MAP GTVEC LN:RN;
	LOCAL GTVEC LRN:LLRN;
	BIND LEXEME LNLEX=LN:RNLEX=RN:LRNLEX=LRN:LLRNLEX=LLRN;
	IF .RNLEX[LTYPF] NEQ GTTYP THEN RETURN 0;
	IF .RN[NODEX] NEQ SNEGOP THEN
	    IF .RN[NODEX] NEQ SNOTOP THEN RETURN 0;
	LRN_.RN[OPR1];
	IF .LRNLEX[LTYPF] NEQ GTTYP THEN RETURN 0;
	IF .LRN[NODEX] NEQ SDOTOP THEN RETURN 0;
	LLRN_.LRN[OPR1];
	IF EQLPOSSIZE(.LN,.LLRN) THEN RETURN 1;
	0
	END;


    ROUTINE SIMPLESTORE(LN,RN)=
	BEGIN
	!
	! A "SIMPLE" STORE IS, BY DEFINITION, ONE WHICH DOES NOT
	! NEED A SPECIAL TEMPORARY FOR THE RHS.
	!
	! VALUE RETURNED:
	!	-1 :: WE HAVE A STORE OF THE FORM
	!		(EXPR1) _ .(EXPR1) OP (EXPR2),
	!	      OR (EXPR1) _ NOT .(EXPR1)
	!	      OR (EXPR1) _ - .(EXPR2);
	!		THE 'RCMTF' BIT OF THE 'OP' (OR 'NOT' OR '-') NODE
	!		SHOULD BE TURNED OFF.
	!	 1 :: WE HAVE SOME OTHER KIND OF SIMPLE STORE, E.G.
	!		VAR1 _ .VAR2 + 3;
	!		THE 'RCMTF' BIT OF THE 'OP' NODE SHOULD BE LEFT AS IS.
	!	 0 :: THE STORE WE ARE DEALING WITH IS NOT SIMPLE.
	!
	MACRO
	    ADDORSUB=ONEOF(.RN[NODEX],BIT2(SADDOP,SMINOP))$,
	    ANDORIOR=ONEOF(.RN[NODEX],BIT2(SANDOP,SOROP))$,
	SPECIALCASES=
	    NOT ONEOF(.RN[NODEX],(BIT3(SPLUSOP,SXOROP,SEQVOP) OR
				  BMSKX(SGTROP,6) OR
				  BMSKX(SGTRUOP,6)))$;
	MAP GTVEC LN:RN;
	LOCAL GTVEC LRN:LLRN, RRN;
	BIND LEXEME LNLEX=LN:RNLEX=RN:LRNLEX=LRN:LLRNLEX=LLRN;
	BIND SIMPLEVAL=3;
	ROUTINE SIMPLOP(NODE)= (MAP GTVEC NODE;
			IF .NODE[NODEX] LEQ MAXOPERATOR THEN 1 ELSE
			IF .NODE[NODEX] EQL SYNNULL THEN 1 ELSE
			IF .NODE[NODEX] EQL SSTOROP THEN
			    SIMPLOP(IF .NODE[TPATH] THEN .NODE[OPR1] ELSE .NODE[OPR2]));

	ROUTINE ISPSOK(LN,RN)=
	    BEGIN
	    MAP GTVEC LN:RN;
	    BIND LEXEME LNLEX=LN:RNLEX=RN;
	    LOCAL SSP;
	    MACRO ISBISORBIC=
		(IF ANDORIOR THEN
		   (LOCAL LEXEME RRN:LRN;
		    IF .RN[TPATH]
		      THEN (LRN_.RN[OPR2]; RRN_.RN[OPR1])
		      ELSE (LRN_.RN[OPR1]; RRN_.RN[OPR2]);
		    (1 AND (.RRN[KNOTF] EQV (.RN[NODEX] EQL SANDOP)))
		    + .LRN[KNOTF]*2  ))$;
	    MACRO ISINCORDEC=
		(IF ADDORSUB THEN
		   IF ABS(EXTEND(.RN[OFFSETF])) EQL 1 THEN
		     (.RN[RCAF] OR .RN[RCSF]))$;
	    MACRO ISCOMORNEG=
		(IF .RN[NODEX] EQL SPLUSOP THEN
		   (.RN[RCCF] OR .RN[RCNTF]))$;

	    SSP_.LNLEX[SSPF];
	    IF .SSP LEQ PF016
		THEN TRUE
	    ELSE IF .SSP LEQ PF08
		THEN (IF ISINCORDEC THEN TRUE
		      ELSE IF ISCOMORNEG THEN TRUE
		      ELSE ISBISORBIC)
	    ELSE (ISBISORBIC EQL 1)
	    END;

	IF .RNLEX[LTYPF] NEQ GTTYP THEN RETURN 0;
	IF .LNLEX[LTYPF] EQL GTTYP THEN
	    BEGIN MACRO PROCEED=EXITBLOCK$;
	    IF .LN[NODEX] EQL SYNPOI THEN
		IF ISPSOK(.LN,.RN) THEN PROCEED;
	    IF NOT SIMPLOP(.LN) THEN RETURN 0
	    END;
	IF .LNLEX[LTYPF] EQL BNDVAR THEN
	    BEGIN LOCAL X;
	    IF .LNLEX[LEXPART] EQL .PCREG THEN RETURN 0;
		! LATER THIS WILL BE EXTENDED TO ALL
		! VOLATILE LOCATIONS.
	    IF NOT ISPSOK(.LN,.RN) THEN RETURN 0;
	    IF (X_FINDLEFT(.LN,.RN)) NEQ 0
		THEN IF .X LEQ (SIMPLEVAL+1)/(1+(.LN[MODE] NEQ GENREG)) THEN RETURN -1
	    END;
	IF .RN[NODEX] EQL SPLUSOP THEN
	    RETURN
		IF .RN[OCCF] EQL 1
		    THEN IF .RN[CSCOMPL] EQL 0 THEN 1 ELSE
			 IF ISNEGNOT(.LN,.RN[OPR1]) THEN -1;
	IF .RN[NODEX] EQL SFSTORE THEN RETURN 1;
	IF .RN[NODEX] LEQ MAXOPERATOR THEN
	    IF .RN[NODEX] EQL SDOTOP THEN RETURN 0 ELSE
	    IF .RN[NODEX] EQL SSWABOP THEN RETURN 1 ELSE
		IF .RN[NODESIZEF] EQL 2 THEN
		    BEGIN
		    MACRO PROCEED=EXITBLOCK$;
		    IF .RN[TPATH]
			THEN (LRN_.RN[OPR2]; RRN_.RN[OPR1])
			ELSE (LRN_.RN[OPR1]; RRN_.RN[OPR2]);
		    IF .RN[REGF] EQL .LRN[REGF] THEN
			IF .RN[CSCOMPL] GTR SIMPLEVAL THEN PROCEED;
		    IF FINDLEX(.LN,.LRN) THEN
			IF SPECIALCASES THEN PROCEED ELSE RETURN 0;
		    IF .LNLEX[SSPF] GTR PF016 THEN PROCEED;
		    IF .LRNLEX[LTYPF] EQL GTTYP THEN
		      IF .LRN[NODEX] EQL SFSTORE THEN RETURN 0;
		    RETURN 1 - FINDLEX(.LN,.RRN)
		    END;
	IF BEGIN
	   MACRO TRUNC(X)=(X-MAXOPERATOR)$;;
	   ONEOF(TRUNC(.RN[NODEX]),BIT4(TRUNC(SYNIF),TRUNC(SYNCASE),
					TRUNC(SYNSEL),TRUNC(SYNLABEL)))
	   END
	  THEN RETURN 1
	  ELSE IF .RN[NODEX] LEQ MAXOPERATOR THEN
	    BEGIN
	    LRN_IF .RN[TPATH] THEN .RN[OPR2] ELSE .RN[OPR1];
	    IF .LRNLEX[LTYPF] NEQ GTTYP THEN RETURN 0;
	    IF .LRN[NODEX] EQL SDOTOP THEN
		BEGIN
		LLRN_.LRN[OPR1];
		IF .LLRN EQL .LN THEN RETURN -(SPECIALCASES)
		  ELSE IF EQLPOSSIZE(.LLRN,.LN)
			 THEN IF SPECIALCASES
				THEN (LRN[CODED]_1;
				      LRN[MODE]_0;
				      LRN[REGF]_.RN[REGF];
				      RETURN -1);
		END;
	    END;
	0
	END;

    ROUTINE TRYSIMPLESTORE(NODE,LN,RN)=
	BEGIN
	MAP GTVEC NODE:LN:RN;
	BIND LEXEME LNLEX=LN:RNLEX=RN;
	WHILE 1 DO
	    BEGIN
	    MACRO DOBIND=(LOCAL SMPL;
			  SMPL_SIMPLESTORE(.LN,.RN);
			  IF .SMPL THEN
			     (BINDSTORE(.LN,.RN[REGF]);
			      IF .SMPL LSS 0 THEN RN[RCMTF]_FALSE;
			      TRUE)   )$;
	    IF .RNLEX[LTYPF] NEQ GTTYP THEN RETURN NOVALUE;
	    IF .RN[NODEX] LEQ MAXOPERATOR THEN RETURN DOBIND;
	    SELECT .RN[NODEX] OF
	      NSET
		SYNIF:
		    BEGIN
		    IF DOBIND THEN
		    (TRYSIMPLESTORE(.NODE,.LN,.RN[OPR3]);
		     TRYSIMPLESTORE(.NODE,.LN,.RN[OPR4]) );
		    RETURN NOVALUE
		    END;

		SYNCASE:
		    BEGIN
		    IF DOBIND THEN
		      INCR I FROM 2 TO .RN[NODESIZEF]-2 DO
			TRYSIMPLESTORE(.NODE,.LN,.RN[OPERAND(.I)]);
		    RETURN NOVALUE
		    END;

		SYNSEL:
		    BEGIN
		    IF DOBIND THEN
		      INCR I FROM 2 TO .RN[NODESIZEF]-3 BY 2 DO
			TRYSIMPLESTORE(.NODE,.LN,.RN[OPERAND(.I)]);
		    RETURN NOVALUE
		    END;

		SYNCOMP:
		    CONTINUE RN_.RN[OPERAND(.RN[NODESIZEF]-1)];

		SYNLABEL:
		    (DOBIND; RETURN NOVALUE);

		SFSTORE:
		    DOBIND;

		ALWAYS:
		    RETURN NOVALUE
	      TESN;
	    END;
	NOVALUE
	END;

    NDRDEF(STORE,(
	BEGIN
	BIND TEMP=LABS;
	LOCAL LEXEME LOP:ROP;
	IF .NODE[TPATH]
	  THEN (LOP_.NODE[OPR2]; ROP_.NODE[OPR1])
	  ELSE (LOP_.NODE[OPR1]; ROP_.NODE[OPR2]);
	IF .TX LSS 8
	  THEN
	    (IF RESREQ THEN
		IF NOT .NODE[COPIED] THEN
		    NODE[REGF]_TX_GETTN())
	  ELSE
	    BEGIN
	    MAP GTVEC TX;
	    IF .TX[REQD] EQL MEMREQDB
	      THEN IF .TX[REGF] EQL .ROP[ADDRF]
		THEN TX_0
	    END;
	IF NOT RESREQ THEN TX_0;
	IF .NODE[TPATH] THEN TEMP_TLA(.ROP,.TX,0);
	TLA(.LOP,0,0);
	IF NOT .NODE[TPATH] THEN TEMP_TLA(.ROP,.TX,0);
	WANTPREF(.NODE[REGF],.TEMP);

	IF .TX EQL 0 THEN TRYSIMPLESTORE(.NODE,.LOP,.ROP);

	.TX
	END));




    MACRO INITPARMDESC=(LNKGD_.LNAME[LNKGDESCF]; PARMNO_0)$,
	  NEXTPARMDESC=
	    BEGIN
	    IF (PARMNO_.PARMNO+1) GTR .LNKGD[LNKGSIZEF]
		THEN PT_STACKPARM
		ELSE
		    (PT_.LNKGD[PARMTYPE(.PARMNO)];
		     PL_.LNKGD[PARMLOC(.PARMNO)])
	    END$;



    ROUTINE SPANPARMS=
	BEGIN
	LOCAL GTVEC T;
	DECR I FROM .CALLSTK[CURD] TO 0 DO
	    FORALLTN(T,CALLSTK[LSELEM(.I)],
		(IF .T[LONLU] LSS .LON THEN T[LONLU]_.LON;
		 IF .T[FONLU] LSS .FON THEN T[FONLU]_.FON));
	NOVALUE
	END;

    MACRO
	INITCALL=INITSTK(CALLSTK)$,
	PUSHCALL=PUSHSTK(CALLSTK)$,
	NOTECALL=ADDTOTOS(CALLSTK,TNREP(.SUBNODE[REGF]))$,
	POPCALL=POPSTK(CALLSTK)$,
	RELEASECALL=RELEASESPACE(GT,.CALLSTK,STKSIZE)$;

    TLRDEF(CALL,(
	BEGIN
	BIND STVEC LNAME=NODE[OPR1];
	LOCAL GTVEC SUBNODE:TN:LNKGD, OLON,OFON,N,PARMNO,PT,PL,FSP,Z;

	! 1ST, BIND THE ROUTINE NAME
	TLA(.NODE[OPR2],0,0);

	INITPARMDESC;

	FSP_1;
	IF .NODE[NODESIZEF] GTR 2 THEN
		BEGIN
		PUSHCALL;
		INCR I FROM 2 TO .NODE[NODESIZEF]-1 DO
		    BEGIN
		    NEXTPARMDESC;
		    SUBNODE_.NODE[OPERAND(.I)];
		    OLON_.LON+1; OFON_.FON+1;
		    TN_TLA(.SUBNODE,0,0);
		    SPAN(.SUBNODE,0);
		    NOTECALL;
		    SPANPARMS();
		    CASE .PT OF
			SET

			%0: STACK PARM %
				BEGIN
				IF .FSP THEN
				    BEGIN LOCAL D;
				    FSP_0; D_.DTDSTK[LDTD];
				    N_.DTEMPS[CURD];
				    SAVDTD;
				    IF ((.DTEMPS[CURD] NEQ .D)
					OR (.NODE[NODESIZEF] EQL 3)
					OR (.NODE[NODESIZEF] EQL 5)) THEN
				    IF TRYSPDYTEMP(.TN,.N) THEN
					EXITCASE (TN[REQD]_MEMREQDB)
				    END;
				IF NOT TRYSPDYTEMP(.TN,N_.N+1)
				    THEN OPENDYTEMP(.TN,.OLON,.OFON);
				DTDSTK[LDTD]_.N;
				TN[REQD]_MEMREQDB
				END;

			%1: SPECIFIC REGISTER %
				BEGIN
				LOCAL LEXEME SUBSUB,TTN;
				SUBSUB_.SUBNODE[OPR1];
				IF .SUBSUB[LTYPF] EQL GTTYP THEN
				  (TTN_.GT[.SUBSUB,REGF];
				   IF .TTN GEQ 8 THEN
				      TN[TNPERMIT]_.TTN);
				TNSRREQD(.TN,.PL);
				END;

			%2: (LITERAL) MEMORY %
				BEGIN
				TN[TNLITBIT]_TRUE;
				TN[TNLITLEX]_LITLEXEME(.PL);
				TN[REQD]_MEMREQDB
				END;

			%3: (NAMED) MEMORY %
				BEGIN
				TN[REGF]_.PL;
				TN[REQD]_MEMREQDB
				END

			TES;
		    IF NOT .FSP THEN KILLPDTEMPS(.SUBNODE,
				(IF .DTEMPS[CURD] EQL .N OR .I EQL .NODE[NODESIZEF]-1 THEN .N ELSE .N+1))
		    END;
		POPCALL
		END;
	NOTEDTD;
	IF NOT .FSP THEN POPDTD;
	IF .DTEMPS[CURD] GEQ (STKSIZE-.MAXPARMS) THEN KILLDYTEMPS(.NODE);

	! GET A NEW TN FOR THE VALUE OF THE CALL AND MAKE IT THE VALUE REGISTER
	IF .LNAME[LNKGTF] NEQ INTRRPTLNKGT
	  THEN
	    BEGIN
	    NODE[REGF]_TN_Z_GETTN();
	    IF .NODE[XOPR2] EQL .LXHALT
		THEN BINDSTORE(LITLEXEME(#177570),.TN)
		ELSE TNSRREQD(.TN,VREGNUM);
	    END
	  ELSE
	    TN_Z_0;
	UPDATELONFON;
	SETBOUND;
	ASSIGNLABELS;
	SPAN(.NODE,0); 
	SPAN(.NODE[OPR2],1);
	.Z
	END));

    ROUTINE LOADR0(NODE)=
	BEGIN
	MAP GTVEC NODE;
	LOCAL GTVEC TX;
	NODE[REGF]_TX_GETTN();
	TX[BNDTYP]_BNDREG;
	TX[REQD]_SRREQDB;
	TX[REGF]_VREGNUM;
	TX[BNDLSTHDR]_REGS[VREGNUM];
	IF EMPTY(.REGS[VREGNUM])
	    THEN OPENREG(VREGNUM);
	.TX
	END;


    TLRDEF(ROUTINE,(
	BEGIN
	LOCAL STVEC RNAME:LNAME:LDESC, GTVEC TN:TL;
	RNAME_.NODE[OPR2];
	RNAME[RETLAB]_.NODE;
	LDESC_.GT[LNAME_.RNAME[LNKGNMF],LNKGDESCF];
	IF NOT .ANYENAB
	    THEN BEGIN
	DECR I FROM 5 TO 0 DO NULLLST(REGS[.I]);
	INCR I FROM 1 TO .LDESC[LNKGSIZEF] DO
	    IF .LDESC[PARMTYPE(.I)] EQL REGPARM
		THEN OPENREG(.LDESC[PARMLOC(.I)]);
	    END;
	IF NOT EMPTY(.RNAME[REGFORMLST]) THEN
	    BEGIN
	    LOCAL LSTHDR L,ITEM I;
	    I_L_.RNAME[REGFORMLST];
	    UNTIL (I_.I[RLINK]) EQL .L DO
		BEGIN
		TL_GETTN();
		TL[BNDLSTHDR]_REGS[.I[LDATITEM(1)]];
		TL[REQD]_MEMREQDB;
		TL[REGF]_.I[LDATITEM(1)];
		WANTPREF(.TL,.GT[.I[RDATITEM(1)],REGF]);
		UPDATE(.I[RDATITEM(1)],1,2)
		END
	    END;

	IF .LNAME[LNKGTF] NEQ INTRRPTLNKGT
	  THEN TN_LOADR0(.NODE)
	  ELSE TN_0;
	TL_TLA(.NODE[OPR1],0,0);
	UPDATELONFON;
	SPANUNARY(.NODE);
	WANTPREF(.TL,.TN);
	NODE[REGF]_.TN
	END));


    NDRDEF(AND,(
	BEGIN LOCAL LOP,ROP,OP1,L;
	BIND TEMP=LABS;
	BIND LEXEME LEX2=NODE[OPR2];
	L_LABELWORD(.NODE[OPR2],.LABS[LFF]);
	IF .LEX2[LTYPF] EQL LITTYP THEN
	    IF LITVALUE(.LEX2)
		THEN L_.LABS
		ELSE L_LABELWORD(.LABS[LFF],.LABS[LFF]);
	LOP_ROP_0;
	IF .NODE[TPATH] THEN (ROP_.TX;OP1_.NODE[OPR2])
			ELSE (LOP_.TX;OP1_.NODE[OPR1]);
	LOP_TLA(.NODE[OPR1],.LOP,.L);
	IF FLOWRES THEN SAVDTD;
	ROP_TLA(.NODE[OPR2],.ROP,.LABS);
	IF .NODE[TPATH] THEN LOP_.ROP;
	IF FLOWRES THEN
	  BEGIN
	  IF .DTEMPS[CURD] NEQ .DTDSTK[LDTD]
	    THEN (KILLDYTEMPS(.NODE[OPR2]);
		  SETNOTFPARM);
	  POPDTD;
	  RETURN 0;
	  END;
	IF NOT RESREQ THEN RETURN .LOP;
	TEMP_0;
	IF .TX EQL 0 THEN
	    IF ISDESTROYABLE(OP1) THEN TX_.LOP ELSE TEMP_.LOP;
	FILLTX; WANTPREF(.TX,.TEMP);
	.TX
	END));


    NDRDEF(OR,(
	BEGIN LOCAL LOP,ROP,OP1,L;
	BIND TEMP=LABS;
	BIND LEXEME LEX2=NODE[OPR2];
	L_LABELWORD(.LABS[LTF],.NODE[OPR2]);
	IF .LEX2[LTYPF] EQL LITTYP THEN
	    IF LITVALUE(.LEX2)
		THEN L_LABELWORD(.LABS[LTF],.LABS[LTF])
		ELSE L_.LABS;
	LOP_ROP_0;
	IF .NODE[TPATH] THEN (ROP_.TX;OP1_.NODE[OPR2])
			ELSE (LOP_.TX;OP1_.NODE[OPR1]);
	LOP_TLA(.NODE[OPR1],.LOP,.L);
	IF FLOWRES THEN SAVDTD;
	ROP_TLA(.NODE[OPR2],.ROP,.LABS);
	IF .NODE[TPATH] THEN LOP_.ROP;
	IF FLOWRES THEN
	  BEGIN
	  IF .DTEMPS[CURD] NEQ .DTDSTK[LDTD]
	    THEN (KILLDYTEMPS(.NODE[OPR2]);
		  SETNOTFPARM);
	  POPDTD;
	  RETURN 0;
	  END;
	IF NOT RESREQ THEN RETURN .LOP;
	TEMP_0;
	IF .TX EQL 0 THEN
	    IF ISDESTROYABLE(OP1) THEN TX_.LOP ELSE TEMP_.LOP;
	FILLTX; WANTPREF(.TX,.TEMP);
	.TX
	END));


    TLRDEF(NOT,TLCOMMON(.NODE,.TX,LABELWORD(.LABS[LFF],.LABS[LTF])));

    NDRDEF(COMP,(
	BEGIN
	INCR I FROM 0 TO .NODE[NODESIZEF]-2 DO
		TLA(.NODE[OPERAND(.I)],0,0);
	TX_TLA(.NODE[LASTOPERAND],.TX,.LABS);
	IF RESREQ THEN .TX ELSE 0
	END));


    NDRDEF(IF,(
	BEGIN
	LOCAL DTUNEVEN,TT3,TT4, GTVEC TTHEN:TELSE;
	BINDLST(.NODE[OPR1]);
	TLA(.NODE[OPR2],0,LABELWORD(.NODE[OPR3],.NODE[OPR4]));
	SAVFON; SAVDTD;
	IF RESREQ THEN FILLTX;
	TTHEN_.NODE[OPR3]; TT3_(.TTHEN[CSCOMPL] LEQ MAGIC3);
	TELSE_.NODE[OPR4]; TT4_(.TELSE[CSCOMPL] LEQ MAGIC3);
	TTHEN_TLA(.TTHEN,IF .TT3 AND .TT4 THEN .TX,.LABS);
	RESETFON; RESETDTD;
	TELSE_TLA(.TELSE,IF .TT4 THEN .TX,.LABS);
	MAXFON;
	DTUNEVEN_(.DTEMPS[CURD] NEQ .DTDSTK[MDTD]);
	MINDTD;
	IF .DTUNEVEN THEN
	    BEGIN
	    KILLFORKDYTEMPS(.NODE[OPR3]);
	    KILLFORKDYTEMPS(.NODE[OPR4]);
	    SETNOTFPARM
	    END;
	POPDTD;
	IF RESREQ THEN (WANTPREF(.TX,.TTHEN); WANTPREF(.TX,.TELSE));
	BINDLST(.NODE[OPR5]);
	.TX
	END));

    NDRDEF(CASE,(
	BEGIN
	LOCAL T,RES,DTUNEVEN,GTVEC SUBNODE;
	DTUNEVEN_0;
	BINDLST(.NODE[OPR1]);
	TLA(.NODE[OPR2],0,0);
	IF (RES_RESREQ) THEN FILLTX ELSE TX_0;
	SAVFON;	SAVDTD;
	INCR I FROM 2 TO .NODE[NODESIZEF]-2 DO
	    BEGIN
	    SUBNODE_.NODE[OPERAND(.I)];
	    T_TLA(.SUBNODE,0,.LABS);
	    IF .RES THEN WANTPREF(.T,.TX);
	    IF .I GEQ 3 THEN IF .DTEMPS[CURD] NEQ .DTDSTK[MDTD] THEN DTUNEVEN_1;
	    IF .I NEQ .NODE[NODESIZEF]-2 THEN RESETDTD ELSE MINDTD;
	    RESETFON
	    END;
	IF .DTUNEVEN THEN
	    BEGIN
	    INCR I FROM 2 TO .NODE[NODESIZEF]-2 DO
		KILLFORKDYTEMPS(.NODE[OPERAND(.I)]);
		SETNOTFPARM
		END;
	POPDTD;
	MAXFON;
	BINDLST(.NODE[OPERAND(.NODE[NODESIZEF]-1)]);
	.TX
	END));

    ROUTINE FLOOP(NODE,TX,LABS,TYPE)=
	BEGIN
	! TLA FOR WHILE-DO, UNTIL-DO, DO-WHILE, AND DO-UNTIL
	! CASES 0 THROUGH 3 OF TYPE
	MAP GTVEC NODE, TNWORD TX:LABS;
	LOCAL L1,L2;
	LPBINDLST(.NODE[OPR1]);
	LPBINDLST(.NODE[OPR2]);
	L1_CASE .TYPE OF
	    SET
	    %WD% LABELWORD(.NODE[OPR4],.NODE[OPR5]);
	    %UD% LABELWORD(.NODE[OPR5],.NODE[OPR4]);
	    %DW% 0;
	    %DU% 0
	    TES;
	L2_CASE .TYPE OF
	    SET
	    %WD% 0;
	    %UD% 0;
	    %DW% LABELWORD(.NODE[OPR3],.NODE[OPR5]);
	    %DU% LABELWORD(.NODE[OPR5],.NODE[OPR3])
	    TES;
	SAVDTD;
	ENTLOOP();
	TLA(.NODE[OPR3],0,.L1);
	IF (NOT .TYPE^(-1))
	OR (BIND LEXEME OP4=NODE[OPR4];
	    IF .OP4[LTYPF] NEQ GTTYP THEN TRUE
	    ELSE IF .GT[.OP4,NSRFF] EQL RFFLOW THEN TRUE
	    ELSE ISRELOP(OP4) )
	  THEN (RESETDTD; KILLDYTEMPS(.NODE[OPR3]));
	TLA(.NODE[OPR4],0,.L2);
	RESETDTD; XITLOOP();
	KILLDYTEMPS(.NODE[OPR4]);
	KILLDYTEMPS(.NODE);
	POPDTD;
	IF TNNEEDED THEN FILLTX;
	.TX
	END;

    NDRDEF(WD,FLOOP(.NODE,.TX,.LABS,0));

    NDRDEF(UD,FLOOP(.NODE,.TX,.LABS,1));

    NDRDEF(DW,FLOOP(.NODE,.TX,.LABS,2));

    NDRDEF(DU,FLOOP(.NODE,.TX,.LABS,3));

    NDRDEF(IDLOOP,(
	BEGIN
	LOCAL L, GTVEC CV;
	L_TLA(.NODE[OPR2],0,0);
	TLA(.NODE[OPR3],0,0);
	TLA(.NODE[OPR4],0,0);
	LPBINDLST(.NODE[OPR5]);
	LPBINDLST(.NODE[OPR6]);
	SPAN(.NODE[OPR2],0);
	NEXTLON; NEXTFON;
	SPAN(.NODE[OPR1],0);
	CV_.NODE[OPR1];
	WANTPREF(.L,.CV[REGF]);
	SAVDTD;
	ENTLOOP();
	TLA(.NODE[OPR7],0,0);
	RESETDTD; XITLOOP();
	KILLDYTEMPS(.NODE[OPR7]);
	POPDTD;
	IF TNNEEDED THEN FILLTX;
	.TX
	END));

    TLRDEF(LABEL,(
	BEGIN
	IF RESREQ THEN (IF .TX LSS 8 THEN TX_GETTN()) ELSE TX_0;
	NODE[REGF]_.TX;
	WANTPREF(TLCOMMON(.NODE,0,.LABS),.TX);
	KILLPDTEMPS(.NODE,.DTEMPS[CURD]);
	SETNOTFPARM;
	.TX
	END));

    TLRDEF(LEAVE,(
	BEGIN
	LOCAL GTVEC N;
	N_.ST[.NODE[OPR2],LINKFLD];
	TX_TLA(.NODE[OPR1],0,.LABS);
	WANTPREF(.N[REGF],.TX);
	NOTEDTD;
	.TX
	END));

    TLRDEF(RLEAVE,(
	BEGIN
	LOCAL GTVEC RNTN;
!	SWAP(LON,RLON); SWAP(FON,RFON);
	RNTN_.NODE[OPR2]; RNTN_.RNTN[RETLAB];
	WANTPREF(TLA(.NODE[OPR1],0,.LABS),.RNTN[REGF]);
	NOTEDTD;
	UPDATELONFON;
!	SWAP(LON,RLON); SWAP(FON,RFON);
	NODE[REGF]_0
	END));

    TLRDEF(SYNNULL,(
	BEGIN
	LOCAL GTVEC PAR; PAR_.NODE[CSPARENT];
	IF NOT .PAR[BOUND] THEN
	  (IF NOT .PAR[DELAYED] THEN NONBOGUS(PAR);
	   IF .PAR NEQ .NODE<ADDRF> THEN
	     TLLIST(FASTLEXOUT(GTTYP,.PAR),0));
	NOTEDTD;
	UPDATELONFON;
	ASSIGNLABELS;
	SPAN(.NODE,0);
	.NODE[REGF]
	END));


    NDRDEF(SELECT,(
	BEGIN
	MAP GTVEC TX;
	LOCAL OTHEREND,DTUNEVEN,SAVDTC, LEXEME L, GTVEC OTHERTN;
	DTUNEVEN_0;
	IF RESREQ THEN FILLTX ELSE TX_0;
	INITTNSPAN(TX);
	OTHEREND_LITVALUE(.NODE[LASTOPERAND]);
	IF .OTHEREND EQL 0
	    THEN OTHERTN_0
	    ELSE NODE[OPERAND(.NODE[NODESIZEF]-2)]_LEXOUT(TNTYP,OTHERTN_GETTN());
	TLA(.NODE[OPR1],0,0);
	INITTNSPAN(OTHERTN);
	INCR I FROM 1 TO .NODE[NODESIZEF]-3 DO
	    BEGIN
	    L_.NODE[OPERAND(.I)];
	    IF .I
		THEN !LEFT PART
		    (IF .L[LTYPF] NEQ SELTYP THEN (TLA(.L,0,0);SPAN(.NODE[OPR1],0)))
		ELSE !RIGHT PART
		    BEGIN
		    IF .I EQL 2 THEN SAVDTC_.DTEMPS[CURD];
		    SAVDTD;
		    TLA(.L,.TX,0);
		    IF .DTEMPS[CURD] NEQ .SAVDTC THEN DTUNEVEN_1;
		    RESETDTD;
		    KILLDYTEMPS(.L);
		    POPDTD;
		    END;
	    IF .I LEQ .OTHEREND THEN TNSPAN(OTHERTN)
	    END;
	IF .OTHERTN NEQ 0 THEN
	   IF (L_.OTHERTN[FONLU]-.OTHERTN[FONFU]) GTR .MAXFONSPAN
	     THEN MAXFONSPAN_.L;
	IF .DTUNEVEN THEN SETNOTFPARM
		     ELSE
	    INCR I FROM 2 TO .NODE[NODESIZEF]-3 BY 2 DO
		BEGIN
		LOCAL LEXEME OP;
		BIND GTVEC SUBNODE=OP;
		OP_.NODE[OPERAND(.I)];
		IF .OP[LTYPF] EQL GTTYP
		   THEN SUBNODE[DTDELETE]_DTDONTCARE
		END;
	.TX
	END));

    TLRDEF(ENABLE,(
	BEGIN
	SETBOUND;
	LOADR0(.NODE);
	NOTEDTD;
	UPDATELONFON;
	SPANUX(.NODE);
	TLA(.NODE[OPR1],0,0);
	.NODE[REGF]
	END));


    NDRDEF(SIGNAL,(
	BEGIN
	LOCAL GTVEC TL;
	MAP GTVEC TX;
	TL_TLA(.NODE[OPR1],0,0);
	TX_LOADR0(.NODE);
	TX[REQD]_IGREQDB;
	WANTPREF(.TL,.TX);
	.TX
	END));






!   C. - DRIVER FOR TEMP NAME/LABEL ASSIGNMENT
! ------------------------------------------------
!
!
!	THIS PLIT IS USED TO SWITCH TO SPECIFIC ROUTINES TO DO
!	TLA PROCESSING FOR A NODE, NODE-SPECIFIC PROCESSING FOR
!	NODES WHICH USE TLCOMMON AS THEIR TLA ROUTINE, AND
!	SPANNING FOR NODES WHICH USE TLCOMMON.
!
!


BIND
	TLAR=0,		!INDEX FOR NODE'S TLA ROUTINE
	NODER=1,	!INDEX FOR "COMMON" NODE'S NODE-SPECIFIC ROUTINE
	SPANR=2;	!INDEX FOR "COMMON" NODE'S SPAN ROUTINE

STRUCTURE TNSWITCH[I,J]= (.TNSWITCH+3*.J+.I)<0,18>;

BIND TNSWITCH TLPLIT=PLIT(
	TLCOMMON,	NDADDSUB,	SPANBINARY,	! +
	TLCOMMON,	NDSWAB,		SPANUNARY,	! SWAB
	TLCOMMON,	NDB,		SPANBINARY,	! /
	TLDOT,		0,		0,		! .
	TLCOMMON,	NDADDSUB,	SPANBINARY,	! - (BINARY)
	TLCOMMON,	NDB,		SPANBINARY,	! MOD
	TLCOMMON,	NDB,		SPANBINARY,	! *
	TLCOMMON,	NDU,		SPANUNARY,	! - (UNARY)
	TLCOMMON,	NDLOADNODE,	SPANLOADNODE,	! + (UNARY)
	TLCOMMON,	NDB,		SPANBINARY,	! ^
	TLCOMMON,	NDREL,		SPANBXNARY,	! BIT
	TLCOMMON,	NDREL,		SPANBXNARY,	! GTR
	TLCOMMON,	NDREL,		SPANBXNARY,	! LEQ
	TLCOMMON,	NDREL,		SPANBXNARY,	! LSS
	TLCOMMON,	NDREL,		SPANBXNARY,	! GEQ
	TLCOMMON,	NDREL,		SPANBXNARY,	! EQL
	TLCOMMON,	NDREL,		SPANBXNARY,	! NEQ
	TLNOT,		NDU,		SPANUNARY,	! NOT
	TLCOMMON,	NDB,		SPANBINARY,	! EQV
	TLCOMMON,	NDAND,		AOSPAN,		! AND
	TLCOMMON,	NDOR,		AOSPAN,		! OR
	TLCOMMON,	NDB,		SPANBINARY,	! XOR
	0,		0,		0,		! FADR
	0,		0,		0,		! FDVR
	0,		0,		0,		! FIX
	0,		0,		0,		! FLOAT
	0,		0,		0,		! FMPR
	0,		0,		0,		! FNEG
	0,		0,		0,		! FSBR
	TLCOMMON,	NDREL,		SPANBXNARY,	! GTRU
	TLCOMMON,	NDREL,		SPANBXNARY,	! LEQU
	TLCOMMON,	NDREL,		SPANBXNARY,	! LSSU
	TLCOMMON,	NDREL,		SPANBXNARY,	! GEQU
	TLCOMMON,	NDREL,		SPANBXNARY,	! EQLU
	TLCOMMON,	NDREL,		SPANBXNARY,	! NEQU
	TLCOMMON,	NDB,		SPANBINARY,	! ROT
	TLCOMMON,	NDB,		SPANBINARY,	! MAX
	TLCOMMON,	NDB,		SPANBINARY,	! MIN
	TLCOMMON,	PUNT,		SPANUNARY,	! CARRY
	TLCOMMON,	PUNT,		SPANUNARY,	! OVERFLOW
	TLCOMMON,	NDSTORE,	SPANSTORE,	! _
	0,		0,		0,		! ERROR OPERATOR
	TLCOMMON,	NDCASE,		SPANUX,		! CASE
	TLCOMMON,	NDFSTO,		SPANUX,		! CALL-PARM
	TLCOMMON,	NDFSTO,		SPANUX,		! CALL-STORE
	TLCOMMON,	NDWD,		SPANUX,		! WHILE-DO
	TLCOMMON,	NDUD,		SPANUX,		! UNTIL-DO
	TLROUTINE,	0,		0,		! ROUTINE DEFN
	TLCOMMON,	NDCOMP,		SPANUX,		! COMPOUND
	TLCOMMON,	NDIDLOOP,	SPANID,		! INCR
	TLCOMMON,	NDIDLOOP,	SPANID,		! DECR
	TLCOMMON,	NDIF,		SPANUX,		! IF
	TLCOMMON,	NDDW,		SPANUX,		! D0-WHILE
	TLCOMMON,	NDDU,		SPANUX,		! DO-UNTIL
	0,		0,		0,		! CREATE
	0,		0,		0,		! EXCHJ
	TLCOMMON,	NDSELECT,	SPANUX,		! SELECT
	0,		0,		0,		! EXITLOOP
	TLLABEL,	NDU,		SPANUNARY,	! LABEL PLACEMENT
	0,		0,		0,		! MODULE
	0,		0,		0,		! PLIT
	TLCALL,		0,		0,		! CALL
	TLDOT,		0,		0,		! POINTER
	0,		0,		0,		! [
	TLLEAVE,	0,		0,		! LEAVE
	TLRLEAVE,	0,		0,		! RETURN
	TLSYNNULL,	0,		0,		! NULL
	TLNULL,		0,		0,		! INLINE
	TLENABLE,	0,		0,		! ENABLE
	TLCOMMON,	NDSIGNAL,	SPANUNARY,	! SIGNAL
	TLCOMMON,	NDU,		SPANUXNARY,	! MFPI, ETC.
	0,0,0,0,0,0);


    TLRDEF(COMMON,(
	BEGIN
	!
	! THIS IS THE COMMON ROUTINE WHICH PERFORMS TN ASSIGNMENT
	! FOR MOST BINARY (ARITHMETIC) OPERATORS.
	!
	LOCAL TN,LOP,ROP,TEMP;
	IF ISCSEUSE(NODE) THEN
		BEGIN LOCAL GTVEC PAR;
		PAR_.NODE[CSPARENT];
		IF NOT .PAR[BOUND] THEN
		  (IF NOT .PAR[DELAYED] THEN NONBOGUS(PAR);
		   IF .PAR NEQ .NODE<ADDRF> THEN
		     TLLIST(FASTLEXOUT(GTTYP,.PAR),0)  )
		END
			  ELSE
	IF NOT .NODE[BOUND] THEN
	    BEGIN
	    SETBOUND;
	    IF (TN_.NODE[REGF]) LSS 8 THEN TN_0;
	    IF .TN EQL 0 THEN
		IF NOT ISCSECREATION(NODE) THEN TN_.TX[TNF];
	    TN_(.TLPLIT[NODER,.NODE[NODEX]])(.NODE,.TN,.LABS);
	    IF .NODE[REGF] EQL 0 THEN NODE[REGF]_.TN;
	    IF ISCSECREATION(NODE) THEN BINDUSES(.NODE)
	    END;
	NOTEDTD;
	UPDATELONFON;
	ASSIGNLABELS;
	(.TLPLIT[SPANR,.NODE[NODEX]])(.NODE);
	.NODE[REGF]
	END));


    ROUTINE TLA(NODE,TN,LABS)=
	BEGIN
	! THIS ROUTINE IS THE COMMON DRIVER THROUGH WHICH ALL
	! TEMP-LABEL-ASSIGNMENT ROUTINES ARE CALLED.
	!
	MAP GTVEC NODE; BIND LEXEME LEX=NODE;
	IF .LEX[LTYPF] EQL LITTYP THEN RETURN 0;
	IF ONEOF(.NODE[TYPEF],BIT3(LOCALT,REGT,FORMALT))
	  THEN IF .NODE[REGF] GTR 7
	    THEN RETURN .NODE[REGF];
	IF .NODE[TYPEF] NEQ GRAPHT THEN RETURN 0;
	TN_(.TLPLIT[TLAR,.NODE[NODEX]])(.NODE,.TN,.LABS);
	KOST(.NODE);
	NODE[LABELF]_0;
	.TN
	END;





! II.(A)  ESTIMATING NUMBER OF TEMPS NEEDED
! -----------------------------------------
!
!
!  THIS CODE DOES A LINEAR SCAN OVER THE (UNRANKED) TEMP NAMES AND
!  ATTEMPS TO GET A ROUGH ESTIMATE OF THE NUMBER OF ACTUAL TEMP
!  LOCATIONS THAT WILL BE REQUIRED.
!
!


 ROUTINE ESTIMATE=
    BEGIN
    MACRO
	UPMD=	(MD_.MD+1)$,
	SETFU=	FU_.T[LONFU]$,
	SETLU=	LU_.T[LONLU]$,
	SETBOTH=(SETFU;SETLU)$,
	NEWNEST=(IF .MD GTR .MDS THEN MDS_.MD;MD_1;SETBOTH)$,
	TFU=	.T[LONFU]$,
	TLU=	.T[LONLU]$,

	C1=	NEWNEST$,
	C2=	(UPMD;SETLU)$,
	C3=	(UPMD;SETBOTH)$,
	C4=	(UPMD;SETFU)$,
	C5=	NEWNEST$,
	C6=	UPMD$;

	LOCAL MD,MDS; REGISTER TNREPR R, GTVEC T; LOCAL FU,LU;
	MD_MDS_0; LU_0; FU_#777777; R_TNCHAIN<0,0>;
	WHILE (R_.R[LLINK]) NEQ TNCHAIN<0,0> DO
		BEGIN
		DUMMYBLOCK;
		T_.R[TNPTR];
		IF TFU GEQ TLU THEN CONTINUE;
		IF ONEOF(.T[REQD],BIT3(MEMREQDB,SLREQDB,IGREQDB))
		  THEN CONTINUE;
		IF TFU LSS .FU
		    THEN (IF TLU LSS .FU THEN C1
					 ELSE IF TLU GTR .LU THEN C6 ELSE C2)
		    ELSE IF TFU GTR .LU THEN C5 ELSE
			 IF TLU LSS .LU THEN C3 ELSE C4;
		END;
	IF .MD GTR .MDS THEN .MD ELSE .MDS
    END;


! III. - RANKING TEMP NAMES
! ------------------------------------------------
!
!
!	THE ACTION OF RANKING IS STRAIGHT-FORWARD AND SHOULD
!	PRESENT NO PROBLEMS. NOTE, HOWEVER:
!
!	1) RANKING IS BASED ON THE 'MAX' COST -- THIS IS DONE
!	SO THAT THE WORST CASE COST IS MINIMIZED.
!
!	2) CERTAIN TN'S MUST BE IN A REGISTER, OR IN A SPECIFIC
!	REGISTER, IN A LOCAL, ETC. THESE TN'S ARE SEGREGATED
!	ONTO SEPERATE LISTS AT THIS POINT. IN THE PACKING
!	ALGORITHM THESE TN'S ARE TREATED FIRST IN ORDER
!	TO INSURE THAT THEIR NEEDS ARE SATISFIED.
!
!
!   A. - UTILITIES
! ------------------------------------------------

    MACRO INITRANK=
	BEGIN
	MAXFONSPAN_LOG2(.MAXFONSPAN);
	NULLLST(SRLST); NULLLST(ARLST); NULLLST(SLLST);
	DECR I FROM ULSZ-1 TO 0 DO NULLLST(ULST[.I])
	END$;

!   B. - SORTING OF TEMP NAMES
! ------------------------------------------------

    ROUTINE TNSORTENTER(TN)=
	BEGIN
	MAP GTVEC TN;
	MACRO
	    KXY=.TN[XUSECOMPLEXITY]$,
	    FS=(.MAXFONSPAN-LOG2(.TN[FONLU]-.TN[FONFU])+1)$,
	    SZ=ULSZ$,
	    MAX=(.MAXKOST*(.MAXFONSPAN+1)+1)$;
	LOCAL GTVEC T, TNLSTHDR L;
	LOCAL LCOST,LMAX;
	LCOST_(KXY*FS)*SZ; LMAX_MAX;
	TN[USECOMPLEXITY]_.TN[XUSECOMPLEXITY]-.TN[USECOMPLEXITY];
	L_.ULST[.LCOST/.LMAX];
	TN[XUSECOMPLEXITY]_.LCOST MOD .LMAX;
	FORALLTN(T,L,
	    IF .T[XUSECOMPLEXITY] LSS .TN[XUSECOMPLEXITY]
		THEN RETURN LINK(TNREP(.TN),.TR[LLINK]));
	LINK(TNREP(.TN),.L[LLINK])
	END;

    ROUTINE LONORDER(TN,L)=
	BEGIN
	MAP GTVEC TN, TNLSTHDR L; LOCAL GTVEC T,TNREPR TF;
	[email protected];
	TF_TNREP(.TN);
	IF .TN[LONFU] NEQ .TN[FONFU] THEN RETURN LINK(.TF,.L[RLINK]);
	FORALLTN(T,L, IF .T[LONFU] EQL .T[FONFU] THEN
			IF .T[LONFU] GTR .TN[LONFU] THEN
				RETURN LINK(.TF,.TR[LLINK]));
	LINK(.TF,.L[LLINK])
	END;


!   C. - DRIVER FOR RANKING
! ------------------------------------------------

    ROUTINE TRANK=
	BEGIN LOCAL GTVEC T;
	INITRANK;
	FORALLTN(T,TNCHAIN,
	    BEGIN
	    IF .T[LONFU] LEQ .T[LONLU] THEN
	    CASE .T[REQD] OF
	      SET
	      % 0 % TNSORTENTER(.T);		! USUAL CASE
	      % 1 % 0;				! ALREADY BOUND
	      % 2 % LONORDER(.T,SLLST);		! MUST BE STATIC LOCAL (ADDR USED)
	      % 3 % LINK(TNREP(.T),ARLST);	! ANY REGISTER
	      % 4 % LINK(TNREP(.T),SRLST);	! SPECIFIC REGISTER
	      % 5 % 0;				! IGNORE DUMMY ENTRIES
	      % 6 % TNSORTENTER(.T);		! DECLARED LOCALS
	      % 7 % TNSORTENTER(.T)		! REGISTER OR FORGET IT
	      TES
	    END);
	NOVALUE
	END;




! IV. - PACKING
! ------------------------------------------------
!
!
!	THIS, THE LAST PHASE, TAKES THE ORDERED LIST OF TN'S
!	AND ATTEMPTS A 'BEST-FIT' PACKING INTO THE AVAILABLE
!	REGISTERS, LOCALS, ETC. THE UTILITIES DEFINE VARIOUS
!	PRIMITIVES. THE MAIN WORK, AND THE IMPLEMENTATION
!	OF THE PACKING POLICY, IS CONTAINED IN THE ROUTINE 'TPACK'.
!
!
!   A. - UTILITIES
! ------------------------------------------------

!	0. - REPACKING (ALREADY!)

		REQUIRE RESHUF.RTN;

!	1. - PREFERENCES
!
!		IN A FEW CASES WE 'PREFER' THAT TWO TEMP NAMES
!		BE PACKED INTO THE SAME LOCATION. THIS SECTION
!		PROVIDES THE MECHANISM FOR DOING THIS. THE 'TL'
!		ROUTINES ARE CHARGED WITH THE RESPONSIBILITY
!		OF NOTING THAT SUCH BINDING IS DESIRABLE.
!

	    MACRO INITPREF=PREFLST_0$,
		  PRFLST=1,1,0,18$,
		  PRFTHREAD=1,1,18,18$;

	    ROUTINE PREFLINK(T)=
		BEGIN
		! PUT A PREFREP ON THE PREFCHAIN
		MAP GTVEC T;
		LOCAL TNREPR TR;
		TR_T[PREFF]_TNREP(.T);
		TR[PRFTHREAD]_.PREFLST[BASE];
		PREFLST[BASE]_.TR
		END;

	    ROUTINE WANTPREF(T,TW)=
		BEGIN
		MAP GTVEC T:TW;
		LOCAL TNREPR P:P1;
		IF .TW LSS 8 THEN RETURN;
		IF .T LSS 8 THEN RETURN;
		IF .T EQL .TW THEN RETURN;
		IF (P_.TW[PREFF]) EQL 0 THEN
		    P_PREFLINK(.TW);
		IF (P1_.T[PREFF]) EQL 0 THEN
		    P1_PREFLINK(.T);
		LINK(.P,.P1)
		END;

	    ROUTINE TRYPREF(TN)=
		BEGIN
		MAP GTVEC TN;
		MACRO OK=(TN[REGF]_.T; TN[REQD]_MEMREQDB; TN[BNDTYP]_BNDPREF; SUCCESS)$;
		LOCAL OPENED,TRIED,REG,TEMP,GTVEC T;
		IF .TN[PREFF] NEQ 0 THEN
		    BEGIN
		    FORALLTN(T,.TN[PREFF],
			(BEGIN
			IF ISREGLST(REG_.T[BNDLSTHDR]) THEN
			    IF TRYFIT(.TN,.REG) THEN OK ELSE
			      IF SLOW THEN
				BEGIN LOCAL C[SRCHWIDTH],CNT;
				TEMP_.T[REQD];T[REQD]_SRREQDB;
				IF (CNT_COUNTCONFLICTS(.TN,.REG,C)) LEQ SRCHWIDTH THEN
				    IF TRYALT(.TN,.CNT,.REG,C,SRCHDEPTH)
					THEN (T[REQD]_.TEMP; OK);
				T[REQD]_.TEMP
				END
			END));
		    IF FAST THEN EXITCOMPOUND;
		    OPENED_0; TRIED_.RESERVED;
		    FORALLTN(T,.TN[PREFF],
			(BEGIN
			IF ISREGLST(REG_.T[BNDLSTHDR]) THEN
			  IF NOT .TRIED<.REG-REGS<0,0>,1> THEN
			    BEGIN LOCAL C[SRCHWIDTH],CNT;
			    TRIED<.REG-REGS<0,0>,1>_1;
			    TEMP_.T[REQD];T[REQD]_SRREQDB;
			    IF (CNT_COUNTCONFLICTS(.TN,.REG,C)) LEQ SRCHWIDTH THEN
				BEGIN
				IF NOT .OPENED THEN
				  INCR I FROM 0 TO 5 DO
				    IF EMPTY(.REGS[.I]) THEN
					(OPENREG(.I); OPENED_1; EXITLOOP);
				IF NOT .OPENED THEN (T[REQD]_.TEMP; EXITLOOP);
				IF TRYALT(.TN,.CNT,.REG,C,SRCHDEPTH)
				    THEN (T[REQD]_.TEMP; OK)
				END;
			    T[REQD]_.TEMP
			    END
			END));
		    IF .TN[REQD] EQL RFREQDB THEN FAIL;
		    IF .TN[USECOMPLEXITY] GTR 6 THEN FAIL;
		    FORALLTN(T,.TN[PREFF],
			(IF MUSTBETOP(.TN,.T[BNDLSTHDR]) THEN
			    IF TRYFIT(.TN,.T[BNDLSTHDR]) THEN OK));
		    FORALLTN(T,.TN[PREFF],
			BEGIN
			IF .T[BNDLSTHDR] NEQ 0 THEN
			    IF TRYFIT(.TN,.T[BNDLSTHDR]) THEN OK
			END);
		    END;
		FAIL
		END;





!	NOW LOOK AT TRY.BLI FOR THE REST OF THE "PACKING" ROUTINES



!   E. - DRIVER FOR PACKING
! ------------------------------------------------
!
!
!
!	THE FOLLOWING ROUTINE, 'TPACK', DEFINES THE POLICY
!	BY WHICH TEMP NAMES ARE BOUND TO LOCATIONS. THAT POLICY
!	IS:
!
!	1) BIND THOSE TN'S WHICH MUST BE IN A SPECIFIC REGISTER.
!	2) BIND THOSE TN'S THAT MUST BE IN SOME REGISTER.
!	3) BIND THOSE TN'S THAT MUST BE IN SOME LOCAL.
!	4) BIND THE REMAINDER OF THE TN'S  - IN ORDER OF THEIR IMPORTANCE -.
!
!	WITHIN 4) THE ALGORITHM IS:
!
!	4A) TRY TO USE THE TN'S 'PREFERENCE', IF ANY.
!	4B) TRY AN OPEN REGISTER.
!	4C) IF THE DIFFERENCE BETWEEN THE TN'S MAX AND MIN COSTS
!		IS SUFFICIENTLY SMALL, THEN TRY AN OPEN LOCAL.
!	4D) TRY A CLOSED REGISTER.
!	4E) IF THE DIFFERENCE BETWEEN THE TN'S MAX AND MIN COSTS
!		PREVENTED THE ATTEMPT IN 4C), THEN TRY THE
!		OPEN LOCALS NOW.
!	4F) USE A CLOSED LOCAL ( THIS WILL ALWAYS WORK AS
!		A LAST RESORT).
!
!	NOTE THAT THE TN-REP LISTS ARE RELEASED AS WE GO
!	THROUGH ALL THIS.
!
!

    BIND NOTENUFREGS = 98;	! COPIED FROM ERROR.BEG
    EXTERNAL WARNEM;

    ROUTINE TPACK=
	BEGIN
	LOCAL GTVEC T;
	INITSTEMPS;
	FORALLTN(T,SRLST,TRYSPREG(.T,.T[REGF]));
	RELTNREPLST(SRLST);
	FORALLTN(T,ARLST,
	    IF NOT TRYREGSEARCH(.T,SRCHDEPTH) THEN
		IF NOT(TRYCLREG(.T)) THEN 
			(WARNEM (0,NOTENUFREGS);
			 T[BNDLSTHDR]_REGS[5]<0,0>;
			 MARKTN(T,BNDREG);
			 T[REGF]_5));
	RELTNREPLST(ARLST);

	IF .ESTIM GTR 1 THEN
	    BEGIN
	    IF .ESTIM GTR 6 THEN ESTIM_6;
	    IF .ESTIM GTR 2 THEN ESTIM_.ESTIM-1;
	    IF .DTDSTK[MAXD] GEQ 0 THEN ESTIM_.ESTIM-1;
	    DECR I FROM 5 TO 0 DO
		(IF .RESERVED[.I,1] THEN OPENREG(.I) ELSE
		   IF ISOPEN(.REGS[.I]) THEN ESTIM_.ESTIM-1);
	    IF .ESTIM GTR 0 THEN
		INCR I FROM 0 TO 5 DO
		    IF EMPTY(.REGS[.I]) THEN
			IF (ESTIM_.ESTIM-1) GEQ 0
			  THEN OPENREG(.I)
			  ELSE EXITLOOP;
	    END;

	DECR I FROM (ULSZ-1) TO 0 DO
	    BEGIN
	    FORALLTN(T,ULST[.I],
	      BEGIN
		BEGIN
		DUMMYBLOCK;
		IF .T[PREFF] NEQ 0 THEN IF TRYPREF(.T) THEN CONTINUE;
		IF TRYREGSEARCH(.T,SRCHDEPTH) THEN CONTINUE;
		IF TRYCLREG(.T) THEN CONTINUE;
		IF .T[REQD] EQL RFREQDB THEN
		    BEGIN
		    T[REQD]_MEMREQDB;
		    T[REGF]_.T[OFFSETF];
		    T[OFFSETF]_0;
		    CONTINUE
		    END;
		IF TRYDYTEMPS(.T) THEN CONTINUE;
		LONORDER(.T,SLLST)
		END;
	      END);
	    RELTNREPLST(ULST[.I])
	    END;
	FORALLTN(T,SLLST,
	    IF NOT(TRYOPSTEMP(.T)) THEN TRYCLSTEMP(.T));
	RELTNREPLST(SLLST);
	BEGIN
	MAP TNREPR T;
	REGISTER TEMP;
	T[BASE]_.PREFLST[BASE];
	WHILE .T[BASE] NEQ 0 DO
	    BEGIN
	    TEMP_.T[PRFTHREAD];
	    RELTNREP(.T[BASE]);
	    T[BASE]_.TEMP
	    END
	END;
	NOVALUE
	END;



!   F. - MARKING OF TNS AFTER PACKING

    ROUTINE TMARK=
	BEGIN
	MACRO CHKPREF=DUMMYBLOCK; IF .T[BNDTYP] EQL BNDPREF THEN CONTINUE$;
	LOCAL GTVEC T;
	DECR I FROM 5 TO 0 DO
	    FORALLTN(T,REGS[.I],(CHKPREF; MARKTN(T,BNDREG); T[REGF]_.I));
	STATICSIZE_(.STEMPS[MAXD]+1)*2;
	DECR I FROM .STEMPS[MAXD] TO 0 DO
	    FORALLTN(T,STEMPS[LSELEM(.I)],(CHKPREF; MARKTN(T,BNDLOCAL); T[REGF]_SP;
			T[MODE]_INDEXED; T[OFFSETF]_-(.MAXLOCALS+(.I+1)*2)));
	DECR I FROM .DTEMPS[MAXD] TO 0 DO
	    FORALLTN(T,DTEMPS[LSELEM(.I)],
		(CHKPREF;
		 IF .T[BNDTYP] EQL 0 THEN MARKTN(T,BNDPUSH % USED TO BE BNDLOCAL -- BWL %);
		 T[REGF]_SP; T[MODE]_INDEXED;
		 T[OFFSETF]_-(.MAXLOCALS+.STATICSIZE+(.I+1)*2)));
	NOVALUE
	END;

    ROUTINE MARKSYMBOLS=
	BEGIN
	REGISTER STVEC STE;
	STE_.PURGED;
	UNTIL .STE EQL 0 DO
	  BEGIN
	  REGISTER REG,GTVEC NODE;
	  SELECT .STE[TYPEF] OF
	      NSET
	   REGT:    NODE_.STE;
	   LOCALT:  NODE_.STE;
	   MBINDT: (NODE_.STE[BINDLEXF];
		    IF .NODE<LTYPF> NEQ GTTYP THEN EXITBLOCK STE_.STE[THREAD]);
	   OTHERWISE: EXITBLOCK STE_.STE[THREAD]
	      TESN;
	  UNTIL (REG_.NODE[REGF]) LEQ 7
	    DO (NODE_.REG);
	  IF .REG EQL SP
	    THEN STE[OFFSETF]_.NODE[OFFSETF];
	  STE[SREGF]_.REG;
	  STE_.STE[THREAD]
	  END;
	NOVALUE
	END;


! V. - DRIVER FOR TNBIND MODULE



    ROUTINE INITPDTNS=
	BEGIN
	MACRO MAKEREG(NAME,REGNUM,IGNORE)=
	BEGIN
	MAP GTVEC NAME;
	REGISTER GTVEC L;
	L_NAME[REGF]_GETTN();
	L[REGF]_(REGNUM);
	IF IGNORE THEN L[REQD]_IGREQDB ELSE L[REQD]_SRREQDB;
	L[BNDTYP]_BNDREG;
	END$;
	BIND Z=0;
	MAKEREG(PCREG,PC,1);
	MAKEREG(SPREG,SP,1);
	MAKEREG(VVREG,VR,1);
	MAKEREG(RR0,0,0);
	MAKEREG(RR1,1,0);
	MAKEREG(RR2,2,0);
	MAKEREG(RR3,3,0);
	MAKEREG(RR4,4,0);
	MAKEREG(RR5,5,0);
	END;


    GLOBAL ROUTINE TNBIND(NODE)=
	BEGIN
	MAP GTVEC NODE;
	INITPDTNS();
	INITPREF;
	INITDYTEMPS;
	INITLOOP;
	INITCALL;
	INITLS(FONSTK);
	INITLS(DTDSTK);
	IF (.NODE[NODEX] NEQ DCROUTINE) OR .ANYENAB THEN INITREGS;
	LON_FON_1;
	MAXFONSPAN_MAXKOST_0;
	SAVDTD;
	TLA(.NODE,0,0);
	POPDTD;
	RELEASELOOP;
	RELEASECALL;
	ESTIM_ESTIMATE();
	TRANK();
	TPACK();
	TMARK();
	IF .DEBFLG THEN MARKSYMBOLS();
	NOVALUE
	END;

END
END
ELUDOM