Google
 

Trailing-Edge - PDP-10 Archives - BB-H138A-BM - 3a-sources/h2regi.bli
There are 18 other files named h2regi.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BEUSED
!  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!
!COPYRIGHT (C) 1977,1978 BY DIGITAL EQUIPMENT CORPORATION
!FILENAME:	H2REGI.BLI
!DATE:		7 JUNE 1973		MGM/FLD


! REVISION HISTORY::
!  1-20-78 ROUTINE GLR,GLAR ARE MODIFIED TO FIX BUG#4. REGISTER
!	   DECLARATIONS WITHIN GLOBAL ROUTINES.
!
!  10-19-77 ROUTINE DUMPREG IS MODIFIED TO FIX A BUG RELATED TO MOD FUNCTION.
!           CLEAR ALL REGISTER REFERENCES IF A REGISTER IS DUMPED ONTO
!           A STACK.
!
!  9-27-77 ROUTINE ACQUIRE AND REGINIT ARE MODIFIED TO FIX BUG#48,
!          NESTED ROUTINES WITH INCR OR DECR LOOP EXPRESSIONS.
!          SAVABLE TEMPS ARE NOT PRESERVED ACROSS THE ROUTINES.
!          A GLOBAL VARIABLE REGTEMP IS ADDED AND USED IN DE3N AND
!          IN THIS MODULE IN ROUTINE ACQUIRE.
!  9-19-77 ROUTINE COPYTRCT,RESRT,RESTORERESULT ARE MODIFIED TO
!          FIX BUG=#36.
!          ROUTINE CODEN IS MODIFIED TO FIX  BUG#39.
!
GLOBAL BIND LOREV=2;
GLOBAL REGTEMP;			%9-27-77%
EXTERNAL MODFLAG;

! REVISION HISTORY
!
!
!
!			GENERAL DOCUMENTATION FOR REGIST.BLI
!	
!	
!		THE SET OF 16 ACCUMULATORS ARE PUT INTO FOUR SETS BY THE BLISS
!	MACHINE USING THE FOLLOWING STRATEGY:
!	
!		1. FIRST THE REGISTERS DECLARED IN THE MODULE HEAD AS "RESERVED"
!		   ARE SET ASIDE AND NOT USED IN THE REMAINING THREE SUBSETS.
!	
!		2. THEN THE FOUR RUN-TIME REGISTERS SREG,BREG,FREG, AND VREG ARE
!		   DEFINED.  IN THE ABSENCE OF USER SPECIFICATION THESE ARE
!		   GENERALLY THE LOWEST FOUR AVAILABLE REGISTERS.
!	
!		3. THE REMAINING REGISTERS ARE BROKEN INTO TWO CLASSES: DECLARABLE
!		   (SAVABLE) AND TEMPORARY.  THE NUMBER OF DECLARABLE IS EITHER
!		   SET BY THE USER (DREGS=) OR IS DEFAULTED TO FIVE.  THESE
!		   SAVABLE REGISTERS ARE SAVED IN ROUTINE PROLOGS AND
!		   RESTORED IN THE EPILOGS.  THE TEMPORARIES ARE SAVED
!		   AT CALL SITES OF ROUTINES IF THEIR VALUES MUST BE PRESERVED.
!	
!		THE INITIALIZATION OF THE NAMES SREG, ... ,VREG AND THE DEFINITION
!	OF THEIR ADDRESSES, ETC. IS DONE IN THE ROUTINE RGINIT(H3REGIST).
!	
!	
!		THE ALLOCATION OF REGISTERS IS CONTROLLED BY TWO TABLES: ART AND
!	RT.  THEIR FORMAT IS SPECIFIED BELOW.  THE ART TABLE MAINTAINS A "MAP"
!	OF AVAILABLE SPACE AND THE RT TABLE MAINTAINS THE "NAME" OF INTERMEDIATE
!	RESULTS.  REFERENCES TO INTERMEDIATE RESULTS FROM LEXEMES ALWAYS REFER
!	TO THE RT TABLE SO THAT IF A REGISTER MUST BE SAVED ON THE STACK, SUBSEQUENT
!	CODE GENERATION FOR THAT RESULT WILL BE AWARE THAT THE RESULT IS NO
!	LONGER IN A REGISTER.
!	
!	    ART[0:19]
!	
!............................................................................................................
!                 !                 !\  \  \ !              !  !\  \  \  \  \  \  \  \  \  \ !              !
!                 !                 ! \  \  \!              ! F! \  \  \  \  \  \  \  \  \  \!              !
!                 !                 !  \  \  !              ! R!  \  \  \  \  \  \  \  \  \  !              !
!     FCHAINF     !     BCHAINF     !\  \  \ !     RTEF     ! E!\  \  \  \  \  \  \  \  \  \ !     LRTEF    !
!                 !                 ! \  \  \!              ! E! \  \  \  \  \  \  \  \  \  \!              !
!                 !                 !  \  \  !              ! F!  \  \  \  \  \  \  \  \  \  !              !
!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!
!                30                24                18                12                 6
!		THE ART TABLE CONTAINS TWO DOUBLY LINKED CHAINS: ONE FOR THE
!	TEMPORARY REGISTERS AND ONE FOR THE SAVABLE REGISTERS.  THE RUN-TIME
!	REGISTERS AND THE RESERVED REGISTERS ARE NOT LINKED INTO EITHER CHAIN.
!	THE TEMPORARY REGISTER ARE ALLOCATED IN ROUND-ROBIN FASHION TO PROLONG
!	THE LIFE OF VALUES IN REGISTERS.  THE SAVABLE REGISTERS ARE ALLOCATED
!	AS A STACK TO MINIMIZE THE SAVING AND RESTORING.  THE ROUTINE REGINIT
!	INITIALIZES THE ART (AND RT) TABLE.
!	
!		THE ENTRIES A[0] THROUGH A[15] CORRESPOND TO THE ACTUAL
!	REGISTERS 0 THROUGH 15:  A[I] CONTAINING INFORMATION RELATING TO REGISTER I.
!	
!		A[16]: TAIL OF TEMPORARY  CHAIN
!		A[17]: TAIL OF SAVABLE CHAIN
!		A[18]: HEAD OF TEMPORARY CHAIN
!		A[19]: HEAD OF SAVABLE CHAIN
!	
!		THE FIELDS ARE INTERPRETED AS FOLLOWS:
!	
!		FCHAINF: INDEX IF NEXT REGISTER IN CHAIN
!		BCHAINF: INDEX OF PREVIOUS REGISTER IN CHAIN
!		RTEF:    INDEX OF "NAME" IN RT TABLE
!		FREEF:   BIT INDICATING REGISTER IS ALLOCATABLE
!		LRTEF:   INDEX OF MOST RECENT "NAME" IN RT TABLE.  (AT ONE POINT
!			  IN THE IMPLEMENTATION THIS FIELD WAS NECESSARY BUT NOW
!			  SERVES MAINLY AS A CONVENIENCE WHEN OBTAINING A NEW NAME.)
!	    RT-TABLE
!	
!		RT[0]: NOT USED, SET TO 0
!		RT[1]: BIT-MASK OF AVAILABLE, SAVABLE REGISTERS
!		RT[2:3]: NOT USED, SET TO -1
!		RT[4]: LINK TO THE PREVIOUS VERSION OF ART AND RT TABLE(SEE SAVRT)

!	
!		RT[5:15]
!	
!............................................................................................................
!           !  !\ !           !                       !\  \ !  !                                            !
!           ! H! \!           !                       ! \  \!  !                                            !
!           ! O!  !           !                       !  \  ! R!                                            !
!   ARTEF   ! L!\ ! BLOCKSIZEF!          USEF         !\  \ ! S!                  S T E F                   !
!           ! Y! \!           !                       ! \  \! F!                                            !
!           ! F!  !           !                       !  \  !  !                                            !
!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!
!                30                24                18                12                 6
!	
!	
!		THIS PORTION OF THE RT TABLE IS USED TO NAME: (1) DECLARED
!	REGISTERS; (2) RUN-TIME REGISTERS; AND (3) RESERVED REGISTERS.  THUS
!	WHENEVER A LEXEME IS CREATEED WHICH REFERS TO THE VALUE OF A REGISTER FROM
!	ONE OF THE ABOVE THREE CLASSES, ITS RTEF IS AN INDEX IN THE RANGE 5 TO 15.
!	
!	
!		FIELDS:
!	
!		ARTEF:  REGISTER ADDRESS (INDEX INTO ART)
!		HOLYF:  SET TO 1 (IGNORED)
!		BLOCKSIZEF: # OF REGISTERS ALLOCATED IN SAME CHUNK WITH THIS
!			    ONE:  E.G. REGISTER R[3];
!		USEF: SET TO 1 (IGNORED)
!		LSF: SET TO 1
!		STEF: IF THE REGISTER IS EXPLICITLY DECLARED THEN THE ST-INDEX
!		      OF THE SYMBOL.  ZERO OTHERWISE (E.G. 4<>_ ...)
!	    RT[16:31]
!	
!............................................................................................................
!           !  !\  \  \  \  \ !                       !\  \ !  !                                            !
!           ! H! \  \  \  \  \!                       ! \  \!  !                                            !
!           ! O!  \  \  \  \  !                       !  \  ! R!                                            !
!   ARTEF   ! L!\  \  \  \  \ !          USEF         !\  \ ! S!                 NEXTF/STEF                 !
!           ! Y! \  \  \  \  \!                       ! \  \! F!                                            !
!           ! F!  \  \  \  \  !                       !  \  !  !                                            !
!!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!
!		                30                24                18                12                 6
!	
!	
!		THIS PORTION OF THE TABLE IS USED TO NAME TEMPORARY RESULTS (INCLUDING
!	VREG WHEN IS CONTAINS THE RESULT OF A CONTROL EXPRRESSION OR ROUTINE).
!	NAMES IN THIS RANGE CAN REFER BOTH TO ACTUAL REGISTERS AND TEMPORARY LOCALS
!	(I.E. REGISTERS SAVED ON THE STACK).
!	
!		FIELDS:
!	
!		ARTEF: REGISTER ADDRESS (INDEX INTO ART).  NOTE: REGISTER 0 IS
!		       NEVER USED AS A TEMPORARY.
!		HOLYF: WHEN SET IT INDICATES THAT ONE OF THE OPERATOR ROUTINES HAS
!		       TESTED ONE OF ITS OPERAND LEXEMES AND HAS FOUND ITS
!		       RTEF REFERENCING A REAL REGISTER.  HENCE THIS BIT BEING
!		       SET PREVENTS A REGISTER FROM BEING SAVED ON THE STACK
!		       UNTIL IT IS USED IN AN INSTRUCTION.
!		USEF: A COUNT OF THE NUMBER OF TIMES THIS TEMPORARY RESULT
!		      WILL BE USED IN COMPILING THE PRESENT EXPRESSION.
!		RSF: 0 IF THIS NAME REFERENCES A REAL REGISTER. 1 IF IT REFERENCES
!		     A TEMPORARY VALUE WHICH IS NOW A LOCAL.
!		NEXTF/STEF: IF RSF IS 0 THEN THIS IS THE INDEX OF THE HEADER OF A
!		            DOUBLY LINKED LIST OF LEXEMES WHICH: (1) DEPEND UPON THIS
!			    TEMPORARY VALUE (GRAPH-TABLE LEXEMES) OR (2) REPRESENT VALUES IN THIS
!			    REGISTER (ORDINARY LEXEMES).   IF RSF IS 1  THEN THIS IS THE INDEX OF A
!			    GENSYMS (GENERATED-SYMBOL) ENTRY IN THE SYMBOL TABLE.
!	GLOBALS USED BY REGIST.BLI:
!		HITREGM:	TEMPORARY REGISTER MASK
!		MODREGM:	(4-RUN-TIME REGS) OR RESREGM
!		NOSVR:		NUMBER OF SAVABLE REGISTERS
!		RESREGM:	RESERVED REGISTER MASK
!		SVREGM:		SAVABLE REGISTER MASK
!		CODEPROP:	SET TO 1 WHEN CODEN PRODUCES INST.
!		GENSYMS:	SEE GENLOCAL BELOW
!		VTARGET:	IF >0 THEN USE VREG AS A TEMP





FORWARD ACQUIRE,CHGNG,CHGNGF,CLEARONE,CODEN,CTRCTH;
FORWARD DUA,DUM,DUAN,DUMPREG,ENTER;
FORWARD FREERN,GENLOCAL,GETAR,GETMIN,GETRN,GLAR,GLR,GLTR;
FORWARD INCRUSEN,MATCH,MOVEREG,OPENSPACE,RELREG;
FORWARD RMALL,RMFRLST,SAVEWORTHY,SWAP,TRCTSEARCH;
FORWARD UNUSEOLDNAMP;
GLOBAL ROUTINE GLR(X,F,N)=

!	PRIMARY ROUTINE TO GENERATE CODE TO LOAD A REGISTER WITH THE LEXEME X.
!	CALLED BY THE FOUR ROUTINES:
!	
!		(1) GLTR (GENERATE-LOAD-TEMP-REGISTER)
!			N=1, F=0
!	
!		(2) GLTR2 (GENERATE-LOAD-TWO-ADJACENT-REGISTERS)
!			N=2, F=0
!	
!		(3) GLPR (GENERATE-LOAD-PARTICULAR-REGISTER)
!			N=ADDRESS OF REG, F=2
!	
!		(4) GOLTR (GENERATE-LOAD-TEMP-REGISTER---BUT ONLY NEGATE
!			   IF YOU GET IT FOR FREE, E.G. MOVN)
!			N=1 OR 2, F=1
!	
!	GLOBAL VARIABLES USED BY GLR:
!		OPTTOREGADDR:
!			SET BY GOTM FOR EXPRESSIONS OF THE FORM
!			REG_.REG OP EXP.  IF NOT -1, THEN IT CONTAINS
!			THE ADDRESS OF REG.
!
!		LOADECREG:
!			IF F=2 (GLPR CASE), THEN LOADECREG IS SET TO
!			.N BEFORE CALLING GMA SO THAT IF GMA MUST
!			LOAD A REGISTER IT WILL USE THE ONE POINTED TO
!			LOADECREG.
!

  BEGIN
    REGISTER R;
    MACRO NEGBIT=R<0,1>$,	! NEG-BIT SET IN X
	  NOTBIT=R<1,1>$,	! NOT-BIT SET IN X
	  FULLWORD=R<2,1>$,	! 36-BIT LOAD
	  HALFWORD=R<3,1>$,	! 18-BIT LOAD
	  RIGHTHLF=R<4,1>$,	! 18-BIT LOAD (RIGHT, I.E. <0,18>)
	  INDIRBIT=R<5,1>$,	! INDIRECT ADDRESSING (IF \ EVER HAPPENS)
	  ANDCASE=R<6,1>$,	! A BYTE WITH POSITION 0 CAN BE LOADED
				! BY "ANDING" A REGISTER WHICH NOW CONTAINS
				! .X<0,36>
	  SINGTEMPCASE=R<7,1>$; ! ONE, TEMPORARY TO BE LOADED

    REGISTER OPCODE;	! FUNCTION FOR LOAD INSTRUCTION

    LOCAL REG,		! ADDRESS OF LOADED REGISTER
	  COPFIELD,	! .X<COPF>
	  ADDRESS,	! CODE-3 FORMAT OF ADDRESS IN LOADING INSTRUCTION
	  VALUE,	! USED TO HOLD VALUE OF LITERAL
	  NGNTMASK,	! MASK : NEGM XOR NOTM XOR EMPTY
	  OLDX,		! A COPY OF THE INPUT LEXEME X
	  PSFIELD,	! POSN-SIZEFIELD OF X
	  ANDMASK,	! MASK TO BE ANDED FOR ANDCASE
	  ANDLEX;	! .X<0,36> USED IN ANDCASE
LOCAL STVEC TEMP;		%1-20-78%
! THE FOLLOWING 8 LINES ARE ADDED ON 1-20-78
IF .X<LSF> THEN
	BEGIN
	TEMP=.X<STEF>;
	IF .TEMP[0]<TYPEF> EQL REGT
		THEN ( X=.TEMP[1]<ADDRESSF>;
		       X<VEF>=1
		     );
	END;

!	THESE FIRST FOUR 'IF' STATEMENTS CHECK TO SEE IF THE LEXEME X
!	IS ALREADY IN A REGISTER AND  ALSO ('IF' #3) ADJUST THE INPUT
!	LEXEME TO A MORE STANDARD FORM.

    SINGTEMPCASE_.F NEQ 2 AND .N NEQ 2;
    IF REGP(.X AND NOT NGNTM) THEN IF .SINGTEMPCASE THEN
      IF .RT[.X<RTEF>]<ARTEF> EQL .OPTTOREGADDR THEN
	RETURN IF .X<NGNTF> NEQ 0 THEN GLPR(.X,.OPTTOREGADDR) ELSE .X;
    IF .X<COPF> NEQ 0 THEN
      IF (.X AND (POSNM OR SIZEM OR RTEM OR LSM OR VEM)) EQL VEM THEN
	X<POSNSIZEF>_LITV(.X<LSSTEF>)^(-24);
    IF .SINGTEMPCASE THEN
      IF TVRP(.X) THEN RETURN .X;
    IF .F NEQ 2 THEN
      (IF (REG_MATCH(.X,(.N-1)*2)) NEQ .X THEN RETURN .REG)
    ELSE REGSEARCH(X,0);

!	NOW WE LOAD X IF IT IS A LITERAL

    IF LITP(.X) THEN
      BEGIN
	VALUE_LITV(.X);
	IF .VALUE EQL 0 THEN (OPCODE_SETZ; ADDRESS_0) ELSE
	IF .VALUE EQL -1 THEN (OPCODE_SETO; ADDRESS_0) ELSE
	IF SMNEGLITVP(.VALUE) THEN (OPCODE_MOVNI; ADDRESS_-.VALUE) ELSE
	IF SMPOSLITVP(.VALUE) THEN (OPCODE_MOVEI; ADDRESS_.VALUE) ELSE
	IF .VALUE<RIGHTF> EQL 0 THEN (OPCODE_HRLZI;ADDRESS_.VALUE<LEFTF>) ELSE
	IF .VALUE<RIGHTF> EQL 1^18-1 THEN (OPCODE_HRLOI; ADDRESS_.VALUE<LEFTF>)
	ELSE (OPCODE_MOVE; ADDRESS_LITA(.X));
	CODEN(.OPCODE,
	      REG_IF .F EQL 2 THEN .N ELSE ACQUIRE(-1,.N),
	      .ADDRESS,3,.X);
	RETURN(LEXRA(.REG))
      END;
    COPFIELD_.X<COPF>;
    NEGBIT_.X<NEGF>;
    NOTBIT_.X<NOTF>;
    OLDX_.X;
    X_.X AND NOT (NEGM OR NOTM OR COPM);
    OPCODE_0;
    INDIRBIT_0;
    NGNTMASK_0;
    ANDCASE_0;

!	THIS MESSY IF-THEN-ELSE STATEMENT DETERMINES WHETHER
!	TO GENERATE A FULL OR HALF WORD LOAD AND IN THE CASE WHERE WE
!	HAVE A DOTTED LEXEME WITH A SIZE FIELD OF ZERO AND ITS
!	RTEF FIELD IS SET, WE MANIPULATE X SO THAT WHEN GMA IS CALLED
!	LATER IT CAN DO ITS THING CORRECTLY.  TO UNDERSTAND THIS
!	YOU MUST READ THROUGH GMA.

    IF .COPFIELD NEQ 0 THEN
      IF .X<SIZEF> EQL 0 AND .X<RTEF> NEQ 0 THEN
	BEGIN
	  OPCODE_CASE .COPFIELD OF SET
		   0;
		   (COPFIELD_0; LDB);
		   MOVE;
		   (COPFIELD_0; SESTOG_.SESTOG OR 2;
		    INDIRBIT_1; MOVE)
		 TES;
	  FULLWORD_1;
	  HALFWORD_0
	END
      ELSE
	BEGIN
	  PSFIELD_.X<POSNSIZEF>;
	  HALFWORD_(RIGHTHLF_.PSFIELD EQL 18) OR .PSFIELD EQL #2222;
	  FULLWORD_.PSFIELD EQL 36;
	  IF .PSFIELD NEQ 0 THEN
	    IF NOT .FULLWORD THEN IF .F NEQ 2 THEN
	      IF .RIGHTHLF OR ((.PSFIELD AND #77^6) EQL 0) THEN
		BEGIN
		  ANDLEX_(.X AND NOT (POSNM OR SIZEM)) OR (ZERO36 OR DOTM);
		  REG_MATCH(.ANDLEX,(.N-1)*2);
		  IF .REG NEQ .ANDLEX THEN
		    BEGIN
		      ANDCASE_1; REG_.RT[.REG<RTEF>]<ARTEF>;
		      ANDMASK_
		        IF .RIGHTHLF THEN RIGHTM ELSE 1^.PSFIELD-1;
		      OPCODE_ANDI-(.ANDMASK<LEFTF> NEQ 0);
		      CODEN(.OPCODE,.REG,
			    IF .OPCODE THEN .ANDMASK
			    ELSE LITA(LITLEXEME(.ANDMASK)),
			    3,.OLDX AND NOT NGNTM)
		    END
		END
	END
    ELSE
      BEGIN
	IF ZERONAMP(.X) THEN (OPCODE_MOVEI; COPFIELD_1);
	FULLWORD_1;
	HALFWORD_0
      END;
    LOADECREG_IF .F EQL 2 THEN .N ELSE -1;
    X<COPF>_.COPFIELD;
    ADDRESS_IF NOT .ANDCASE THEN IF .FULLWORD OR .HALFWORD THEN GMA(.X) ELSE GPA(.X);
    LOADECREG_-1;
    IF .OPCODE EQL 0 THEN
      IF .ADDRESS<RELOCF> NEQ 0 OR
	(IF .ADDRESS<IXYF> LEQ 15 THEN
	   IF .F EQL 2 THEN (.ADDRESS<IXYF> NEQ .N OR NOT .FULLWORD)
	   ELSE NOT ITRP(LEXRN(.ART[.ADDRESS<IXYF>]<RTEF>))
	 ELSE 1) THEN
	OPCODE_
	  CASE 2*.HALFWORD+.FULLWORD OF SET
	    LDB;
	    IF .NEGBIT THEN (NEGBIT_0;NGNTMASK_NEGM;MOVN) ELSE
	    IF .NOTBIT THEN (NOTBIT_0;NGNTMASK_NOTM; SETCM)
	    ELSE MOVE;
	    IF .RIGHTHLF THEN HRRZ ELSE HLRZ TES;
    IF NOT .ANDCASE THEN
      IF .OPCODE NEQ 0 THEN
        CODEN(.OPCODE,
	      REG_IF .F EQL 2 THEN .N ELSE ACQUIRE(-1,.N),
	      .ADDRESS OR .INDIRBIT^23,3,(.OLDX AND NOT NGNTM) OR .NGNTMASK)
      ELSE
        REG_
	  IF .F EQL 2 THEN .N ELSE
	  IF .N THEN .ADDRESS<RELRF>
	  ELSE ACQUIRE(.ADDRESS<RELRF>,2);
    IF .NOTBIT THEN CODE(SETCA,.REG,0,1) ELSE
    IF .NEGBIT AND NOT .F THEN CODE(MOVN,.REG,.REG,4);
    LEXRA(.REG) OR (IF .F AND .NEGBIT THEN NEGM)
  END;
GLOBAL ROUTINE GLTR(X)=GLR(.X,0,1);



GLOBAL ROUTINE GOLTR(X)=GLR(.X,1,1);



GLOBAL ROUTINE GLTR2(X)=GLR(.X,0,2);



GLOBAL ROUTINE GLPR(X,A)=GLR(.X,2,.A);



GLOBAL ROUTINE GLAR(X)=
  !(GENERATE-LOAD-ANY-REGISTER)
  !CALLED TO LOAD A VALUE INTO A (POTENTIALLY) READ ONLY REGISTER.  IT
  !FIRST ATTEMPTS TO FIND X INS SOME REGISTER (EVEN IF THAT REGISTER'S
  !USE IS GREATER THAN 1) AND FAILING THAT CALLS GLTR.

  BEGIN LOCAL R;
! THE FOLLOWING 9 LINES ARE ADDED ON 1-20-78
	LOCAL STVEC TEMP;
	IF .X<LSF> THEN
	BEGIN
	TEMP=.X<STEF>;
	IF .TEMP[0]<TYPEF> EQL REGT
	  THEN ( X=.TEMP[1]<ADDRESSF>;
		 X<VEF>=1
	       );
	END;
    IF DCRP(.X) THEN RETURN .X;
    IF (R_MATCH(.X,1)) NEQ .X THEN RETURN .R;
    GLTR(.X)
  END;
GLOBAL ROUTINE RELOADTEMP(ADDRESS,NAME)=
  !RELOADS TEMPORARY MEMORY INTO A REGISTER.  USED BY THE GCREATE
  !ROUTINES FOR THEIR TEMPORARY STACK AND BASE REGISTERS.  ALSO USED
  !BY GMA.  IF ADDRESS=0, THEN ANY REGISTER IS LOADED, OTHERWISE
  !THAT PARTICULAR REGISTER IS LOADED AFTER ITS CONTENTS (IF IN USE)
  !ARE DUMPED.  RETURNS THE ADDRESS OF THE REGISTER.  CARE IS TAKEN
  !NOT TO USE THE VREG SINCE WEIRD SIDE-EFFECTS ARE CAUSED AT THE
  !POPPING OF REGISTER TABLES.

  BEGIN REGISTER SAVVTARGET;
  ROUTINE FUNMARK(L)=
    IF .L<LEFTF> EQL GTLEX THEN MARKFUNNY(.L)
    ELSE SETFUNBIT(.L);

    IF NOT .RT[.NAME]<RSF> THEN RETURN .RT[.NAME]<ARTEF>;
    IF .ADDRESS NEQ 0 THEN
      BEGIN
	IF NOT .ART[.ADDRESS]<FREEF> THEN DUMPREG(.ADDRESS);
	RMFRLST(.ADDRESS)
      END
    ELSE (SAVVTARGET_.VTARGET; VTARGET_-1; ADDRESS_GETAR(-1,1); VTARGET_.SAVVTARGET);
    CODE(MOVE,.ADDRESS,GMA(LEXNPSD(.RT[.NAME]<LSSTEF>,0,36,1)),1);
    RT[.NAME]<LSSTEF>_.ST[.RT[.NAME]<NEXTF>,1]<LEFTF>;
    SCAN0(.RT[.NAME]<STEF>,FUNMARK);
    IF .RT[.ART[.ADDRESS]<LRTEF>]<ARTEF> EQL .ADDRESS THEN
      BEGIN
	RT[.ART[.ADDRESS]<LRTEF>]<LEFTF>_0;
	CLEARONE(RT[.ART[.ADDRESS]<LRTEF>])
      END;
    ART[.ADDRESS]<LRTEF>_ART[.ADDRESS]<RTEF>_.NAME;
    RT[.NAME]<ARTEF>_.ADDRESS
  END;
GLOBAL ROUTINE ACQUIRE(A,N)=
    !THIS ROUTINE ACQUIRES REGISTERS, BOTH TEMPORARY AND DECLARED.
    !PARAMETERS:
    !   DECLARED:    A=ST-INDEX + 16; N=BLOCKSIZE
    !   INCR-DECR:   A=-(ST-INDEX); N=1
    !   TEMPORARY:   A=-1; N=1 OR 2
    !   DIV/MOD:     -1<A<16; N=2
    !RETURNS THE ADDRESS OF THE FIRST OF THE N REGISTERS.  IN THE
    !DIV/MOD CASE, THE RETURNED REGISTER CONTAINS THE CONTENTS OF A.
  BEGIN LOCAL M,R;
    IF .A EQL -1 THEN
      BEGIN
        R_GETAR(-1,.N); GETRN(.R,0,0);
        IF .N EQL 2 THEN GETRN(.R+1,0,0)
      END ELSE
    IF .A LSS 0 THEN
      IF (R_.ART[19]<FCHAINF>) LSS 17 THEN (RMFRLST(.R);
                    IF (1^.R AND .SVREGM) NEQ 0 THEN REGTEMP=.REGTEMP OR 1^.R;   %9-27-77%
                         GETRN(.R,.N,-.A))       %9-27-77%
      ELSE
        BEGIN
          R_INCR I FROM 16 TO 31 DO
              IF (1^.RT[.I]<ARTEF> AND .SVREGM) NEQ 0 THEN
                IF NOT .RT[.I]<HOLYF> THEN BREAK(DUMPREG(.RT[.I]<ARTEF>));
          IF .R LSS 0 THEN RETURN(ERROR(.NSYM,#761))
          ELSE (IF (1^.R AND .SVREGM) NEQ 0 THEN REGTEMP=.REGTEMP OR 1^.R;GETRN(.R,.N,-.A))   %9-27-77%
        END ELSE
    IF .A GTR 15 THEN
      BEGIN
        M_(1^.N)-1;
        R_DECR I FROM 16-.N TO 0 DO
            IF (.RT[1]^(-.I) AND .M) EQL .M THEN BREAK(.I);
        IF .R LSS 0 THEN RETURN(ERROR(.NSYM,#762))
        ELSE INCR I FROM .R TO .R+.N-1 DO RMFRLST(.I);
        GETRN(.R,.N,.A-16)
      END
    ELSE
      BEGIN R_GETAR(.A,.N);GETRN(.R+1,0,0) END;
    .R
  END;
GLOBAL ROUTINE RMFRLST(R)=
    !THIS ROUTINE REMOVES THE REGISTER R FROM THE FREE LIST IN ART
    !(IF IT IS THERE).  IF R IS A SAVABLE TEMPORARY,THE
    !APPROPRIATE BIT IN RT[1] IS SET TO 0.
  BEGIN
    IF .ART[.R]<CHAINF> NEQ 0 THEN
      BEGIN
        ART[.ART[.R]<FCHAINF>]<BCHAINF>_.ART[.R]<BCHAINF>;
        ART[.ART[.R]<BCHAINF>]<FCHAINF>_.ART[.R]<FCHAINF>;
        ART[.R]<CHAINF>_0;
        REGUSE_.REGUSE OR 1^.R;
        ART[.R]<FREEF>_0;
        IF (1^.R AND .SVREGM) NEQ 0 THEN RT[1]<.R,1>_0
      END;
    .R
  END;
GLOBAL ROUTINE ENTFRLST(J)=

    !ENTERS REGISTER J IN THE FREE LIST OF ART AND IF J IS
    !A SAVABLE REGISTER SETS THE APPROPRIATE BIT IN RT[1]

  BEGIN REGISTER T;
  IF (1^.J AND .MODREGM) EQL 0 THEN
    BEGIN
    ART[.J]<15,6>_1;
    IF (1^.J AND .SVREGM) EQL 0 THEN
      BEGIN
        ART[T_.ART[16]<BCHAINF>]<FCHAINF>_.J;
        ART[16]<BCHAINF>_.J;
        ART[.J]<FCHAINF>_16;
        ART[.J]<BCHAINF>_.T
      END
    ELSE
      BEGIN
        ART[T_.ART[19]<FCHAINF>]<BCHAINF>_.J;
        ART[19]<FCHAINF>_.J;
        ART[.J]<FCHAINF>_.T;
        ART[.J]<BCHAINF>_19;
        RT[1]<.J,1>_1
      END
    END
  ELSE IF .J EQL .VREG THEN ART[.J]_0
  END;
GLOBAL ROUTINE TRYVREG=
  !A FIRST ATTEMPT AT TRYING TO OPTIMIZE MINI-ROUTINE AND MINI EXPRESSIONS
  !WHICH RESULT IN LOADING THE VALUE REGISTER FROM A TEMPORARY.  THIS
  !ALGORITHM SAYS THAT IF VTARGET IS GTR 0 THEN TRY TO USE VREG
  !RATHER THAN ANOTHER TEMP. VTARGET IS MANIPULATED BY THE SYNTAX ROUTINES
  !AND GENCODE AND IN A (CLEVER-KLUDGEY) WAY BY GREL.

  IF .VTARGET GTR 0 THEN
  BEGIN
    IF .ART[.VREG]<LRTEF> GEQ 16 THEN
      RETURN
	IF .RT[.ART[.VREG]<LRTEF>]<ARTEF> EQL .VREG THEN
	  .RT[.ART[.VREG]<LRTEF>]<USEF> EQL 0
	ELSE  .RT[.ART[.VREG]<LRTEF>]<ARTEF> EQL 0;
    .ART[.VREG]<LRTEF> EQL 0
  END;
GLOBAL ROUTINE GETAR(A,N)=
    !THIS ROUTINE IS CALLED BY ACQUIRE AND FINDS THE N(=1 OR 2)
    !TEMPORARY REGISTERS.  IT FIRST ATTEMPTS TO RETURN A HI-TEMP
    !FAILING THIS IT SELECTS A SAVABLE TEMP AND FAILING THIS IT
    !CALLS SWAP TO PUT TEMPORARY VALUES ON THE STACK. IF A IS NOT
    !-1, THEN A (AND A+1 IF N=2) ARE TO BE ACQUIRED.


  BEGIN LOCAL R;
    IF .A GEQ 0 THEN IF
      (IF .ART[.A+1]<RTEF> NEQ 0 THEN
	 IF .ART[.A+1]<DTF> THEN NOT .RT[.ART[.A+1]<RTEF>]<HOLYF>
	 ELSE 0
       ELSE (1^(.A+1) AND (.SVREGM OR .MODREGM)) EQL 0) THEN
      BEGIN
	IF NOT .ART[.A+1]<FREEF> THEN DUMPREG(.A+1);
	RMFRLST(.A+1); RETURN .A
      END;
    IF .N EQL 2 THEN
      BEGIN
        R_INCR I FROM 18 TO 19 DO
          BEGIN
            R_.ART[.I]<FCHAINF>;
            WHILE .R LSS (.I-2) DO
              IF .ART[.R+1]<FREEF> THEN EXITLOOP[2] .R
              ELSE R_.ART[.R]<FCHAINF>
          END;
        IF .R LSS 0 THEN A_SWAP(.A,2)
        ELSE
          BEGIN
            RMFRLST(.R);RMFRLST(.R+1);
            A_IF .A GEQ 0 THEN MOVEREG(.A,.R) ELSE .R
          END;
        RETURN .A
      END;
    IF TRYVREG() THEN RETURN RMFRLST(.VREG);
    IF (R_.ART[18]<FCHAINF>) LSS 16 THEN RMFRLST(.R) ELSE
    IF (R_.ART[19]<FCHAINF>) LSS 17 THEN RMFRLST(.R) 
    ELSE SWAP(.A,2)
  END;
GLOBAL ROUTINE GETRN(A,TDN,S)=

  %ACQUIRES A NAME FOR REGISTER A. IF TDN IS 0, THEN THE REGISTER
   IS TEMPORARY ELSE TDN IS THE NUMBER OF DECLARED REGISTERS IN A
   BLOCK AND S IS THEIR SYMBOL TABLE ENTRY%

  BEGIN 
    REGISTER T;
    IF .TDN GTR 0 THEN
    BEGIN
      INCR I FROM .A TO .A+.TDN -1 DO
	BEGIN
	  T_
	    INCR J FROM 5 TO 15 DO
	      IF .RT[.J]<ARTEF> EQL .I THEN EXITLOOP(.J);
	  IF .T LSS 0 THEN
	    T_
	      INCR J FROM 5 TO 15 DO
		IF .RT[.J]<LEFTF> EQL 0 THEN EXITLOOP(.J);
	  IF .T GTR 15 THEN RETURN(ERROR(.NSYM,#761));
	  IF .ART[.I]<LRTEF> GEQ 16 AND NOT .RT[.ART[.I]<LRTEF>]<RSF> THEN
	  BEGIN
	    RT[.ART[.I]<LRTEF>]<LEFTF>_0;
	    CLEARONE(RT[.ART[.I]<LRTEF>])
	  END;
	  RT[.T]<BLOCKSIZEF>_.TDN;
	  RT[.T]<ARTEF>_.I;
	  RT[.T]<USEF>_(RT[.T]<LSF>_1);
	  RT[.T]<STEF>_.S;
	  ART[.I]<RTEF>_ART[.I]<LRTEF>_.T;
	END;
      .ART[.A]<RTEF>
    END
    ELSE
      BEGIN
	IF UNUSEOLDNAMP(.A) OR
	   (.RT[.ART[.A]<LRTEF>]<ARTEF> EQL .A AND .ART[.A]<LRTEF> GEQ 16) THEN
	  T_.ART[.A]<LRTEF>
	ELSE
	BEGIN
          T_16;
          UNTIL .RT[.T]<LEFTF> EQL 0 AND NOT .RT[.T]<RSF>
            DO T_.T+1;
          IF .T GTR 31 THEN
		(T_16;
		UNTIL .RT[.T]<USEF> EQL 0 AND NOT .RT[.T]<RSF>
		    DO T_.T+1);
	IF .T GTR 31 THEN RETURN(ERROR(.NSYM,#760));
	  INCR I FROM 0 TO 15 DO
	    IF .ART[.I]<LRTEF> EQL .T THEN
	      BREAK(ART[.I]<LRTEF>_0)
	END;
        RT[.T]<ARTEF>_.A;
        RT[.T]<USEF>_1;
	CLEARONE(RT[.T]);
        ART[.A]<LRTEF>_ART[.A]<RTEF>_.T
      END
  END;
GLOBAL ROUTINE UNUSEOLDNAMP(A)=
    !PREDICATE TO SEE IF THE NAME REFERENCED BY .ART[.A]<LRTEF>
    !IS FREE TO BE USED.

  IF .ART[.A]<LRTEF> NEQ 0 AND NOT .RT[.ART[.A]<LRTEF>]<RSF>
    THEN .RT[.ART[.A]<LRTEF>]<LEFTF> EQL 0
  ELSE 0;


GLOBAL ROUTINE SWAP(A,N)=

  %MOVES N REGISTERS INTO TEMPORARY MEMORY AND REACQUIRES THEM.
   IF A IS NOT -1, THEN THE CONTENTS OF A WILL BE IN THE
   FIRST OF THE N REGISTERS%

  BEGIN LOCAL T;
    IF .A EQL -1 THEN OPENSPACE(0,.N) ELSE
    IF (T_OPENSPACE(.A+1,.N)) EQL .A THEN .A
    ELSE MOVEREG(.A,.T)
  END;



GLOBAL ROUTINE MOVEREG(A,R)=

  %MOVES REGISTER A TO REGISTER R AND ADJUSTS REGISTER TABLE%

  IF .A EQL .R THEN .A ELSE
  BEGIN
    CODE(MOVE,.R,.A,1);
    IF NOT UNUSEOLDNAMP(.R) AND .RT[.ART[.R]<LRTEF>]<ARTEF> EQL .R THEN
      CLEARONE(RT[.ART[.R]<LRTEF>]);
    RT[ART[.R]<LRTEF>_ART[.R]<RTEF>_.ART[.A]<RTEF>]<ARTEF>_.R;
    ART[.A]<LRTEF>_ART[.A]<RTEF>_0;
    IF .A NEQ .R+1 THEN ENTFRLST(.A);
    .R
  END;
GLOBAL ROUTINE OPENSPACE(A,N)=

  %FREES N(=1 OR 2) REGISTERS BY MOVING THE N 'LEAST USED' REGISTER(S)
   TO TEMPORARY MEMORY%

  BEGIN REGISTER R;
    R_GETMIN(.N);
    IF .N EQL 1 THEN (DUMPREG(.R); RMFRLST(.R)) 
    ELSE
      BEGIN
        IF .RT[.ART[.R]<RTEF>]<USEF> NEQ 0 AND .R NEQ (.A-1)
          THEN DUMPREG(.R);
        IF .N EQL 2 THEN
	  BEGIN
	    IF .RT[.ART[.R+1]<RTEF>]<USEF> NEQ 0 AND (.R+1) NEQ (.A-1)
              THEN DUMPREG(.R+1);
	    RMFRLST(.R+1)
	  END;
	RMFRLST(.R)
      END
  END;
GLOBAL ROUTINE DUMPREG(A)=

  %A IS THE ADDRESS OF A REGISTER DUE TO BE DUMPED IN TEMPORARY
   MEMORY. DUMPREG ACQUIRES LOCAL MEMORY; GENERATES THE DUMPING
   CODE AND SETS THE RT ENTRY%

  BEGIN LOCAL M; REGISTER N;
    N_.ART[.A]<RTEF>;
    M_GENLOCAL();
    GSTO(.M,LEXRN(.N));
    IF .MODFLAG THEN (CLEARONE(RT[.N]); MODFLAG = 0);
    ST[.M<NEXTF>,1]<LEFTF>_.RT[.N]<NEXTF>;
    RT[.N]<NEXTF>_.M;
    RT[.N]<RSF>_1;
    RT[.N]<ARTEF>_0;
    ENTFRLST(.A);
    .A
  END;
!		A GLOBAL COMMENT ON THE GENSYMS(GENERATED-SYMBOLS) LIST:
!	
!		GENSYMS IS A GLOBAL VARIABLE WHOSE VALUE IS THE INDEX OF THE
!	TOP ITEM ON A PUSHDOWN LIST OF TWO-WORD CELLS WHICH HAVE
!	THE FORMAT OF THE FIRST TWO WORDS OF A ST-ENTRY. 
!		THE LIST IS USED BY TWO ROUTINE:
!	
!		GENLOCAL:
!	
!		    THIS ROUTINE GENERATES LOCAL VARIABLES (1) FOR SAVING TEMPORARY
!		REGISTERS AT FUNCTION CALLS AND ACROSS CONTROL EXPRESSIONS,
!		(2) FOR USE IN CONTROL EXPRESSIONS TO HOLD
!		TEMPORARY VALUES (E.G. INCR-DECR COMPUTED TO-VALUES).
!	
!		GANL:
!	
!		    THIS ROUTINE GENERATES NEW NAMES FOR SYMBOLS WHICH RESULT
!		FROM ADDING CONSTANTS TO GLOBALS, OWNS, LOCALS, ETC.  FOR
!		MORE DETAILS SEE THE ROUTINE GANL (IN H2ARITH).
!	


GLOBAL ROUTINE GENLOCAL=

  %GENERATE A SINGLE UNNAMED LOCAL FOR THE CURRENT FUNCTION LEVEL
   AND BLOCK LEVEL AND LINK IT TO GENSYMS%

  BEGIN LOCAL I;
    I_GETSPACE(1);
    CT[.I,0]<BLF>_.BLOCKLEVEL;
    CT[.I,0]<FLF>_.FUNCTIONLEVEL;
    CT[.I,0]<TYPEF>_LOCALT;
    CT[.I,0]<LSF>_1;
    CT[.I,0]<LINKF>_.GENSYMS;
    GENSYMS_.I;
    CT[.I,1]<ADDRESSF>_.NEXTLOCAL;
    NEXTLOCAL_.NEXTLOCAL+1;
    IF .NEXTLOCAL GTR .MAXLOCAL THEN MAXLOCAL_.NEXTLOCAL;
    .I+(LSM OR ZERO36)
  END;
GLOBAL ROUTINE GETMIN(N)=

  %RETURNS THE ART INDEX OF THE FIRST REGISTER OF THE 'LEAST
   EXPENSIVE' BLOCK OF N REGISTERS.  N MUST BE 1 OR 2%

  BEGIN LOCAL I,J,M,S,T;
    T_1^13-1;
    CASE .N-1 OF SET
      INCR P FROM 0 TO 15 DO
	IF ((1^.P) AND .MODREGM) EQL 0 THEN
        IF .T GEQ (IF .RT[I_.ART[.P]<RTEF>]<RSF>
                     OR .RT[.I]<HOLYF> THEN S_1^12
                  ELSE S_.RT[.I]<USEF>)
        THEN (T_.S;M_.P);
      INCR P FROM 0 TO 14 DO
	IF ((3^.P) AND .MODREGM) EQL 0 THEN
        IF .T GEQ (IF .RT[I_.ART[.P]<RTEF>]<RSF> OR
                     .RT[J_.ART[.P+1]<RTEF>]<RSF> OR
                     .RT[.I]<HOLYF> OR
                     .RT[.J]<HOLYF> THEN S_1^12
                  ELSE S_(I_.RT[.I]<USEF>)*(J_.RT[.J]<USEF>)+.I+.J)
        THEN (T_.S;M_.P) TES;
    IF .T EQL 1^12 THEN RETURN(ERROR(.NSYM,#760)) ELSE .M
  END;



GLOBAL ROUTINE REACQUIRE(A,N)=

    !REMOVES THE REGISTER A (NAME N) FROM THE FREE LIST AND LINKS
    !IT TO NAME N.  CALLED WHEN A VALUE IS REFOUND IN  A REGISTER.

  BEGIN
    RMFRLST(.A);
    ART[.A]<RTEF>_.N;
    RT[.N]<USEF>_1;
    .A
  END;
GLOBAL ROUTINE MATCH(X,F)=

  %SEARCHES TRCT FOR AN EXACT MATCH WITH THE LEXEME X.  IF F IS ONE,
   THEN THE USE FIELD IS IGNORED.  OTHERWISE THE USE FIELD MUST BE
   0. ACQUIRE IS CALLED WITH N=2 IF F IS TWO ELSE REACQUIRE. IF
   SUCCESSFUL, THE LEXEME .R FOR THE APPROPRIATE REGISTER IS RETURNED
   IN PLACE OF X%

  BEGIN LOCAL A,C,N,R;
    C_.CODEPROP;CODEPROP_0;
    R_IF .X<RTEF> EQL 0 AND NOT .X<NOTF> THEN
        IF (N_TRCTSEARCH(.X)) GTR 0 THEN
          IF .F THEN INCRUSEN(.N) ELSE
	  IF .RT[.N]<USEF> NEQ 0 THEN .X
	  ELSE
	    BEGIN
	      A_.RT[.N]<ARTEF>;
	      REACQUIRE(.A,.N);
	      IF .F NEQ 0 THEN A_ACQUIRE(.A,2);
	      LEXRA(.A)
	    END
        ELSE .X
      ELSE .X;
    IF .R NEQ .X AND .CODEPROP EQL 0 THEN NORECVAL_.NORECVAL+1;
    CODEPROP_.CODEPROP OR .C;
    .R
  END;
GLOBAL ROUTINE TRCTSEARCH(X)=

  %TRCT IS SEARCHED FOR THE LEXEME X.  IF THE SEARCH IS SUCCESS-
   FUL, THE REGISTER NAME IS RETURNED AS THE VALUE, OTHERWISE -1%

  BEGIN REGISTER H,I,J;
    INCR K FROM 16 TO 31 DO
      IF .RT[.K]<LEFTF> NEQ 0 THEN IF NOT .RT[.K]<RSF> THEN
        BEGIN
          I_.CT[H_.RT[.K]<NEXTF>,1]<NEXTF>;
          UNTIL .I EQL .H DO
            (J_.CT[.I,0]<NEXTF>;
             IF .X EQL .CT[.I,1] THEN RETURN .K;
             I_.J)
        END
  END;
GLOBAL ROUTINE REGSEARCH(X,Y)=
  !CALLED TO SEE IF LEXEMES POINTED TO BY X AND Y ALREADY ARE IN
  !REGISTERS.  IF SO THE LEXEMES ARE REPLACED BY APPROPRIATE REGISTER
  !LEXEMES.
  BEGIN
    INCR I FROM -1 TO 0 DO
      BEGIN LOCAL R,COPY; BIND A=.Y[.I];
	IF A EQL 0 THEN EXITBLOCK;
	IF NOT SAVEWORTHY(.A) THEN EXITBLOCK;
	COPY_.A;
	IF FULLWORD(.COPY) AND (.COPY<COPF> NEQ 0) THEN
	  COPY<POSNSIZEF>_36;
	IF (R_MATCH(.COPY,1)) NEQ .COPY THEN A_.R
      END
  END;
GLOBAL ROUTINE SAVEWORTHY(L)=
    !PREDICATE TO CHECK IF LEXEME L IS TO BE PRESERVED IN A
    !TRCT (TEMPORARY-REGISTER-CONTENTS-LIST).  NOTE IN PARTICULAR
    !THAT THIS IMPLIES THAT WE DO NOT PRESERVE LEXEMES IN
    !THESE LISTS IF THEIR NOT-BIT IS SET NOR IF THEY ARE LEXEMES WITH
    !NON-ZERO REGISTER FIELDS.
    .L<RTEF> EQL 0 AND NOT .L<NOTF>;



GLOBAL ROUTINE GTUPDATE(REGNAME,LEXEME)=
  !CALLED FROM CODEN TO UPDATE THE GRAPH TABLE AND TRCT LIST
  !WHICH IS HANGING FROM RT[.REGNAME]
  BEGIN
    RMALL(.LEXEME);
    IF SAVEWORTHY(.LEXEME)
	AND .REGNAME GEQ 16 THEN ENTER(.REGNAME,.LEXEME);
    SETFUNBIT(.LEXEME);
    SESTOG_.SESTOG OR 1
  END;
!	WHENEVER CODEN IS CALLED IT PLANTS AN INSTRUCTION AT THE BOTTOM
!	OF THE LIST WHOSE HEADER IS PRESENTLY POINTED TO BY CODEPTR.
!	THE FORMAT OF ITS OUTPUT IS:
!
!
!............................................................................................................
!  !              !                                            !                                            !
!  !              !                                            !                                            !
!  !              !                                            !                                            !
! 0!    RELOCF    !                  P R E V F                 !                  N E X T F                 !
!  !              !                                            !                                            !
!  !              !                                            !                                            !
!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!
!                          !           !  !           !                                                     !
!                          !           !  !           !                                                     !
!                          !           !  !           !                                                     !
!             F            !     A     ! I!     X     !                          Y                          !
!                          !           !  !           !                                                     !
!                          !           !  !           !                                                     !
!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!..!
!                30                24                18                12                 6
!
!	THE RELOCF IS A CODE TO THE LOADER INTERFACE INDICATED THE KIND
!	OF RELOCATION (IF ANY) TO BE DONE ON THE Y FIELD.  F,A,I,X
!	CORRESPOND TO THE FIELDS OF A NORMAL PDP10 INSTRUCTION.


GLOBAL ROUTINE CODEN(F,A,M,U,L)=

  %CODEN PLANTS THE PDP10 INSTRUCTION CODE WITH FUNCTION F,
   ACCUMULATOR A, AND ADDRESS FIELD M(CODE-3 FORMAT (SEE FSA)).  U INDICATES THE UPDATE
   ROUTINE FOR TRCT AND L IS THE LEXEME(DEFAULT 0) INVOLVED IN
   THE UPDATE%

  BEGIN LOCAL R,T,Z; REGISTER I;
    CODEPROP_1;
    Z_CT[I_NEWBOT(.CODEPTR,1),1]_(.F AND 1^9-1)^27 OR
                                    (R_.A AND 1^4-1)^23 OR
                                    (.M AND 1^23-1);
    T_.ART[.R]<RTEF>;
    CT[.I,0]<RELOCF>_.M<RELOCF>;
    IF (I_.A<RELRF>) NEQ 0 THEN DUA(.I);
    IF (I_.M<RIGHTF>) LEQ 15 AND .M<RELOCF> EQL 0 THEN
       RT[.ART[.I]<RTEF>]<HOLYF>_0;
    IF (I_.M<INDXF>) NEQ 0 THEN
      (RT[.ART[.I]<RTEF>]<HOLYF>_0;
      IF .U EQL 2 AND .I NEQ .FREG THEN U_5
      ELSE IF .U EQL 3 AND .I NEQ .FREG THEN SESTOG_.SESTOG OR 2);
    IF (I_.M<RELRF>) NEQ 0 THEN DUA(.I);
    IF .L<RTEF> NEQ 0 THEN
      IF .RT[.L<RTEF>] NEQ .FREG THEN
      BEGIN
	IF (.F EQL DPB) AND REGP(.L AND NOT COPM)	%9-19-77%
			THEN U = 8			%9-19-77%
        ELSE
	BEGIN
	  IF .U EQL 2 THEN U_5 ELSE
	  IF .U EQL 3 THEN SESTOG_.SESTOG OR 2;
	  RT[.L<RTEF>]<HOLYF>_0
	END
      END;
    IF .T GEQ 16 OR .U GEQ 5 OR .U EQL 2 THEN
      BEGIN
        RT[.T]<HOLYF>_0;
        CASE .U OF SET
          !0: NO CHANGE
             0;
          !1: CLEAR TRCT ENTRY
	     CLEARONE(RT[.T]);
          !2: MOVEM,DPB,HALF-WORD TO MEMORY
		GTUPDATE(.T,.L);
          !3: MOVE,LDB,HALF-WORD TO ACCUMULATOR
	     (CLEARONE(RT[.T]);IF SAVEWORTHY(.L) THEN ENTER(.T,.L));
          !4: MOVN   T,T
             CHGNG(.T);
          !5: AN INDEXED ADDRESS WAS GENERATED
             SESTOG_.SESTOG OR 3;
          !6: OP-TO-M
		GTUPDATE(0,.L);
          !7: OP-TO-B
	     BEGIN
               CLEARONE(RT[.T]);
		GTUPDATE(.T,.L)
	     END;
	!8: CLEAR ALL TEMPORARY REGS. FOR DPB INST AND LEXEME IS A REGISTER
		(CLEARSOME();FIXSIDEEFFECTS())		%9-19-77%
               TES;
        FREERN(RT[.T]);
      END;
    .Z
  END;
!  THE FOLLOWING SHOULD BE A MACRO BUT THERE ARE TOO MANY FORMALS, ETC.
!  AROUND TO MAKE IT EASY TO CHANGE

GLOBAL ROUTINE CODE(F,A,M,U)=CODEN(.F,.A,.M,.U,0);



ROUTINE CHGNG(T)=

  %CHANGES THE NEG BITS OF ALL ENTRIES IN THE TRCT LIST OF REGISTER
   NAME T%

    SCAN0(CTRCTH(.T),CHGNGF);



ROUTINE CHGNGF(I)=
  !CALLED FROM CHGNG TO XOR THE NEG-BIT OF  ITEMS HANGING FROM RT[.I]

    IF .CT[.I,1]<LEFTF> EQL GTLEX THEN
      (GT[.CT[.I,1]<NEXTF>,0]<RESULTF>_0; ERASE(.I))
    ELSE CT[.I,1]_.CT[.I,1] XOR NEGM;


GLOBAL ROUTINE ENTER(T,L)=

  %ENTERS LEXEME L ON THE TRCT LIST OF REGISTER NAME T%

  CT[NEWBOT(CTRCTH(.T),1),1]_.L;



GLOBAL ROUTINE RMREFREG(REG)=

  ! REMOVES ALL REFERENCES TO CONTENTS OF REG IN TRCT

  BEGIN
    ROUTINE RMREGP(I,REG)=
      (.CT[.I,1] AND (DOTM OR LSSTEM)) EQL (.REG OR DOTM);

    INCR I FROM 16 TO 31 DO
      (SCAN(CTRCTH(.I),.REG,RMREGP,ERASE);
       FREERN(RT[.I]))
  END;
GLOBAL ROUTINE RMALL(L)=
  !REMOVES ALL OCCURENCES OF ITEMS IN TRCT WITH THE SAME STE AS L

  BEGIN
    ROUTINE RMALLP(I,X)=.X<LSSTEF> EQL .CT[.I,1]<LSSTEF>;

    INCR I FROM 16 TO 31 DO
      (SCAN(CTRCTH(.I),.L,RMALLP,ERASE); FREERN(RT[.I]))
  END;


GLOBAL ROUTINE CLEARONE(I)=
  !CALLED TO CLEAR TRCT LIST HANGING FROM .I
  BEGIN
    ROUTINE CLTRCT(I)=
      !(CLEAR-TEMPORARY-REGISTER-CONTENTS-LIST)
    
      BEGIN
        IF .CT[.I,1]<LEFTF> EQL GTLEX THEN

%3.4%	!THIS CHANGE FIXES A BUG WHICH RESULTED FROM THE FACT THAT
%3.4%	!WHEN A TEMP WAS RE-USED, GRAPH TABLE LEXEMES WHICH COUNTED ON THE
%3.4%	!OLD TEMP CONTENTS BUT DID NOT USE THE TEMP DIRECTLY DID NOT HAVE
%3.4%	!RESULT BITS TURNED OFF.  THE NEW ROUTINE GTORES CYCLES THROUGH
%3.4%	!THE GT TURNING OFF RESULT BITS IN ALL GT ENTRIES WHICH COUNT
%3.4%	!ON THE OLD CONTENTS OF THE REGISTER.

%3.4%	GTORES(.CT[.I,1]);

        ERASE(.I)
      END;
    
    IF .I<RIGHTF> GEQ RT[16]<0,0> THEN
    BEGIN
      SCAN0(IF NOT .(.I)<RSF> THEN .(.I)<NEXTF>
	    ELSE .ST[.(.I)<NEXTF>,1]<LEFTF>,CLTRCT);
      FREERN(.I)
    END
  END;
GLOBAL ROUTINE CLEARSOME=
    !CLEAR TRCT LIST OF EACH REGISTER WHOSE USE IS ZERO

  BEGIN 
    INCR I FROM RT[16] TO RT[31] DO
      IF .(.I)<USEF> EQL 0 THEN CLEARONE(.I)
  END;


GLOBAL ROUTINE CLEARTEMP=
    !CLEARS TRCT LIST OF EACH TEMPORARY LOCAL WHOSE USE IS ZERO

  BEGIN
  INCR I FROM RT[16] TO RT[31] DO
    IF .(.I)<USEF> EQL 0 THEN
    IF .(.I)<RSF> THEN CLEARONE(.I)
  END;



GLOBAL ROUTINE FREERN(I)=

  %FREES REG