Trailing-Edge
-
PDP-10 Archives
-
CFS_TSU04_19910205_1of1
-
update/ftncsr/alcblo.bli
There are 12 other files named alcblo.bli in the archive. Click here to see a list.
!COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1973, 1987
!ALL RIGHTS RESERVED.
!
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
!ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
!INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
!COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
!OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
!TRANSFERRED.
!
!THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
!AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
!CORPORATION.
!
!DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
!SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!AUTHOR: S. MURPHY/SRM/JNG/TFV/TJK
MODULE ALCBLO(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3))=
BEGIN
GLOBAL BIND ALCBLV = #11^24 + 0^18 + #2407; ! Version Date: 21-Jun-84
%(
***** Begin Revision History *****
55 ----- ----- MUST END A BASIC BLOCK ON AN IF THAT CONTAINS A CALL
56 ----- ----- WHEN INSERT AN ENTRY IN REGSTATE TABLE
MUST CLEAR VARINREGFLG OF A POSSIBLE ENTRY
BEING WRITTEN OVER. THIS CAN HAPPEN FOR:
A=B
C=B
WHERE B IS GLOBALLY ALLOCATED TO A REG
57 ----- ----- MUST CHECK FOR A BASIC BLOCK
TERMINATED BY THE NEXT STMNT HAVING A LABEL BEFORE
CHECK FOR IT TERMINATED BY THE PREVIOUS STMNT
A DO STMNT (SINCE IN THAT CASE WE STILL REMEMBER THE
LP INDEX
58 632 24245 IN REGCLOBB, DON'T CLEAR VARINREGFLG FOR THE
VARIABLE IN THE REGISTER IF THE VARIABLE IS
ALSO IN ANOTHER REGISTER. THIS CAN HAPPEN IF
A VAR IS LIVING IN 0, MOVED TO 2 FOR INDEXING,
THEN 0 IS REGLOBB'ED BY A FUNCTION CALL., (JNG)
59 652 NONE EDIT 632 NEEDS TO CARE ABOUT DOUBLE WORD VARS, (DCE)
***** Begin Version 6 *****
60 1024 SRM 21-Nov-80 NONE
Fixed REGCLOBB to work for REAL='literal' when
compiling /gfloating. REGCLOBB had assumed that
if a literal was in an AC the 2nd half must be
in an adjacent AC. This was always true because
we did a "type conversion" on the literal and
created a constant of type REAL that contained
the bits from the literal. When compiling
/gfloating we dont do this "conversion".
***** Begin Version 7 *****
61 1212 TFV 29-Apr-81 ------
Replace LITERAL with HOLLERITH.
62 1226 SRM 19-June-81
Change REGCONTAINING to look at ACs starting from 15
rather than starting from 0. That way, if have the value
in both AC 0 and another AC will get the non-0 AC.
This makes better code for the case:
SUBROUTINE S(I)
A(I)=0
B(I)=0
63 1231 CKS 23-Jun-81
Remove edit 62. It has slight side effect that a double word
quantity in N and N+1 is "found" in (N+1,N+2) instead of (N,N+1).
***** End V7 Development *****
2006 TJK 6-Oct-83
Add call to ENDSMZTRIP in ALCBLOCK to determine if the current
statement (pointed to by CSTMNT) should end a basic block by
virtue of ending at least one DO-loop with the MAYBEZTRIP flag
set.
***** Begin Version 10 *****
2214 TJK 26-Sep-83
Fix ALCBLOCK to correctly undo an AOBJN loop control word. It
now calls UNFLDO.
2227 TJK 21-Oct-83
Rewrite ALCBLOCK to have it call ENDSBBLOCK to determine where
a basic block ends. Also added external declaration for
ENDSBBLOCK, removed external declaration for ENDSMZTRIP (now
called only by ENDSBBLOCK), and fixed some comments.
2407 TJK 21-Jun-84
Have VARCLOBB check for SUBSTRING nodes.
***** End V10 Development *****
***** End Revision History *****
)%
SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;
FORWARD
ALCBLOCK(0),
AFREEREG(3),
REGCONTAINING(1),
VARCLOBB(1),
CLOBBCOMEQV,
CLOBBEQV,
REGCLOBB(1),
CLRRGSTATE,
INIRGSTATE,
SAVEREG(4),
FREEPAIRS(1);
EXTERNAL
ALCSTMN, ! ROUTINE TO PERFORM LOCAL REGISTER ALLOCATION
! FOR A GIVEN STATEMENT
BLOCKBSYREGS, ! SPECIFIES REGISTERS WHOSE CONTENTS WILL BE NEEDED LATER
! IN THIS BASIC BLOCK. The values SHOULD BE PRESERVED
! BIT PATTERN INDICATING WHICH REGS ARE IN USE
! BY THE BASIC BLOCK ALLOCATOR
! THIS WORD CONTAINS A BIT PATTERN IN WHICH ONES REPRESENT
! REGISTERS THAT ARE FREE, ZEROES REPRESENT REGISTERS WHOSE
! CONTENTS WILL BE NEEDED LATER IN THIS BASIC BLOCK
CGERR, ! ROUTINE TO GIVE MESSAGE WHEN INTERNAL COMPILER ERROR
! IS DETECTED
CLOBBREGS, ! GLOBAL IN WHICH THE BIT CORRESPONDING TO
! EACH REG CLOBBERED BY A GIVEN SUBPROGRAM
! IS SET (USED TO DETERMINE WHICH REGS TO SAVE/RESTORE)
BASE CSTMNT, ! POINTER TO CURRENT STATEMENT BEING PROCESSED
%2227% ENDSBBLOCK, ! Checks if the current statement (pointed to
! by CSTMNT) ends a basic block
GBSYCT, ! NUMBER OF FREE REGS IN GBSYREGS
GBSYREGS, ! BIT PATTERN REPRESENTING THE REGS LEFT FREE BY THE
! GLOBAL ALLOCATOR (A ONE REPRESENTS A FREE REG, A ZERO A BUSY ONE)
ISN, ! INTERNAL SEQ NUMBER OF THE STMNT BEING PROCESSED
! (THIS IS USED FOR ERROR MESSAGES)
%1274% LASTQ, ! Pointer to the last .Q used by the current statement
%1274% LASTSFNQ, ! Pointer to the last .Q used by statement
! functions
! The .Q variables between QANCHOR and LASTSFNQ can not
! be reused by other statements
NOBBREGSLOAD, ! FLAG INDICATING THE BB ALLOCATOR CANNOT ASSUME
! THAT THE CODE FOR THE EXPRESSION CURRENTLY BEING
! PROCESSED WILL ALWAYS BE EXECUTED AND
! HENCE THAT WE CANNOT ASSUME THAT REGS LOADED
! IN PROCESSING THIS EXPR HAVE THE VALS INDICATED
! (E.G. THIS FLAG IS SET WHEN PROCESSING A LOG IF)
OLDGBSYREGS, ! BIT PATTERN SET UP BY THE GLOBAL OPTIMIZER TO
! INDICATE REGS AVAILABLE OUTSIDE THE CURRENT DO LOOP
! WHEN THE CURRENT LOOP WAS GLOBALLY ALLOCATED
%2227% QLOC, ! Next location in .Q space to be used by the
! current statement
%1274% QSFNMAX, ! Maximum size of .Q space used by statement functions
STBSYR, ! BIT PATTERN REPRESENTING THE REGS AVAILABLE FOR
! USE WITHIN A GIVEN STMNT
STRGCT, ! NUMBER OF FREE REGS IN STBSYR
%2214% UNFLDO; ! ROUTINE TO UNDO AN AOBJN LOOP CONTROL WORD
BIND RGSENTSIZE=2; !NUMBER OF WDS IN EACH ENTRY OF THE REGSTATE TABLE
OWN
BLKISN, !SEQ NUMBER WITHIN THIS BLOCK OF THE STMNT CURRENTLY BEING PROCESSED
RGSTBL REGSTATE[RGSENTSIZE*16]; !THIS TABLE HAS AN ENTRY FOR EACH OF THE 16 ACS
! EACH ENTRY INDICATES WHICH VARS/CONSTS ARE IN EACH REG
GLOBAL ROUTINE ALCBLOCK = ![2227] Routine rewritten in this edit
!++
! FUNCTIONAL DESCRIPTION:
!
! This is the top level routine for the second pass of the basic
! block register allocator. It causes local register allocation
! to be performed for every statement in a basic block.
!
! This routine is called with CSTMNT pointing to the first
! statement of a basic block. It returns with CSTMNT pointing
! to the first statement of the next basic block. If the end of
! the program has been reached it returns with CSTMNT equal to
! zero. The REGSTATE table is cleared when it has completed the
! pass over a basic block.
!
! If the basic block is terminated by a DO statement, and if the
! following conditions hold:
!
! 1. The only reason for terminating the basic block is
! because of the DO statement
!
! 2. The DO statement has the flags NEDSMATRLZ and
! SAVREGFLG both set
!
! 3. The DO-variable is a single-word data type (i.e.,
! it doesn't have the DBLFLG flag set)
!
! then a REGSTATE table entry for the DO-variable is created so
! that the register containing the DO-variable can be used in
! the next basic block. In addition, if the loop is in AOBJN
! form it will be converted to non-AOBJN form.
!
! The REGSTATE table should be properly initialized for the
! first call to this routine. For subsequent calls, the
! REGSTATE table should be in the state in which this routine
! left it after processing the preceding basic block.
!
! FORMAL PARAMETERS:
!
! NONE
!
! IMPLICIT INPUTS:
!
! CSTMNT points to the first statement of the basic
! block to be processed.
!
! GBSYCT is the number of free registers indicated by
! GBSYREGS.
!
! GBSYREGS is the bit pattern representing the registers
! left free by the global allocator.
!
! LASTSFNQ points to the last .Qnnnn temporary used by
! the STATEMENT FUNCTION statements.
!
! QSFNMAX is the maximum size of the .Q space used by
! the STATEMENT FUNCTION statements.
!
! IMPLICIT OUTPUTS:
!
! BLKISN is the basic block internal sequence number of the
! current statement.
!
! CSTMNT points to the next statement to be processed. Upon
! return from this routine, CSTMNT points to the first
! statement of the next basic block to be processed
! (unless we just processed the last basic block of the
! current program unit, in which case CSTMNT is zero).
!
! ISN is the internal sequence number of the statement being
! processed (used for error messages).
!
! LASTQ points to the last .Qnnnn temporary used by the
! current statement.
!
! QLOC is the next location (offset) in .Q space to be used
! by the current statement.
!
! STBSYR is the bit pattern of registers available for use by
! the statement being processed.
!
! STRGCT is the number of free registers indicated by STBSYR.
!
! ROUTINE VALUE:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
LABEL BLOCK; ! Used to leave basic block processing loop
REGISTER ENDVAL; ! Used to save value returned by ENDSBBLOCK
BLKISN = 1; ! First statement in basic block has block ISN of 1
! Now perform register allocation for each statement in this
! basic block.
BLOCK: WHILE TRUE
DO
BEGIN ! For each statement in basic block
ISN = .CSTMNT[SRCISN]; ! ISN for the current statement
STBSYR = .GBSYREGS; ! Set of regs available for use
! in this statement
STRGCT = .GBSYCT; ! Number of free regs indicated
! by STBSYR
%1274% LASTQ = .LASTSFNQ; ! Init pointer to last .Qnnnn used
! by statement functions. These are
! not reused by other statements
%1274% QLOC = .QSFNMAX; ! Set location to allocate next .Qnnnn
! var to after the SFN .Q variables
ALCSTMN(); ! Do local reg allocation for current stmnt
! Check if the current statement is the last statement
! of the basic block by calling ENDSBBLOCK, and save
! the return value in ENDVAL. If it's 0, we continue
! the basic block. Otherwise we end the basic block
! by leaving BLOCK; ENDVAL will be 1 for a normal end
! of the basic block, and 2 if the basic block was
! ended for the sole reason that CSTMNT points to a DO
! statement.
IF (ENDVAL = ENDSBBLOCK()) NEQ 0 ! End of basic block?
THEN LEAVE BLOCK; ! Yes, leave the loop
! The current statement (pointed to by CSTMNT) isn't
! the last statement of the basic block.
CSTMNT = .CSTMNT[SRCLINK]; ! Move to next statement
BLKISN = .BLKISN+1; ! Bump basic block ISN
END; ! For each statement in basic block
! We're at the end of the basic block. The last statement of
! the basic block has had register allocation performed on it,
! and is pointed to by CSTMNT. Also, ENDVAL is either 1 or 2;
! 1 for a normal end of the basic block, and 2 if the basic
! block was ended for the sole reason that CSTMNT points to a
! DO statement.
CLRRGSTATE(); ! Clear the REGSTATE table (i.e. can no longer
! assume any previous values in registers)
! Check for special DO case
IF .ENDVAL EQL 2 ! Did BB end because of a DO?
THEN IF .CSTMNT[NEDSMATRLZ] ! And is the DO-variable materialized?
THEN IF .CSTMNT[SAVREGFLG] ! And should the DO-var stay in a reg?
THEN
BEGIN ! Special DO case
REGISTER PEXPRNODE DOVAR; ! DOVAR points to the symbol
DOVAR = .CSTMNT[DOSYM]; ! node for the DO-variable
! If the DO-variable is single-word, set up a REGSTATE
! entry, and un-AOBJN it if FLCWD is set.
IF NOT .DOVAR[DBLFLG] ! If the DO-variable is single-word
THEN
BEGIN ! Single-word DO-variable
! Set up a REGSTATE entry for the register
! containing the DO-variable.
SAVEREG(.CSTMNT[DOIREG],.DOVAR,0,
.CSTMNT[SRCSONNXTUSE]);
! If the loop is in AOBJN form, undo it so
! that the initial value for the DO-variable
! will be picked up in a register by itself.
IF .CSTMNT[FLCWD] ! Is the loop in AOBJN form?
THEN
BEGIN ! Loop is AOBJN
%2214% UNFLDO(.CSTMNT); ! Un-AOBJN the loop
CSTMNT[INITLIMMED] = 1;
! Choose a free register for the control word
CSTMNT[DOCREG] = AFREEREG(CLRBIT(.STBSYR,
.CSTMNT[DOIREG]),FALSE,FALSE);
END; ! Loop is AOBJN
END; ! Single-word DO-variable
END; ! Special DO case
CSTMNT = .CSTMNT[SRCLINK]; ! Have CSTMNT point to the next stmnt
! (i.e., the first stmnt of the next
! basic block)
END; ! of ALCBLOCK
ROUTINE PAIRREGS(BSYRG1)=
%(**********
GIVEN A BIT PATTERN "BSYRG1" IN WHICH ZEROES REPRESENT REGISTERS THAT ARE
BUSY AND ONES REPRESENT REGISTERS THAT ARE FREE, THIS ROUTINE RETURNS
A BIT PATTERN IN WHICH ZEROES REPRESENT REGISTERS FOR WHICH THE OTHER
HALF OF THEIR EVEN-ODD PAIR IS BUSY AND ONES REPRESENT REGISTERS
FOR WHICH THE OTHER HALF OF THEIR EVEN-ODD PAIR IS FREE.
FOR BOTTOMMOST FUNCTIONS, BIT 0 OF EACH BIT PATTERN REPRESENTS REGISTER 2
BIT 1 REPRESENTS REGISTER 3, ETC. FOR NON-BOTTOMMOST FUNCTIONS, BIT
0 REPRESENTS REGISTER 15, BIT 1 REGISTER 14, ETC.
HENCE FOR BOTH NON-BOTTOMMOST FUNCTIONS AND BOTTOMMOST FUNCTIONS,
THE BIT PAIRS 0-1, 2-3, 4-5, ETC CORRESPOND TO THE REGISTER
PAIRS 2-3 (OR 14-15), 4-5 (OR 12-13), ETC
**********)%
BEGIN
((.BSYRG1 AND #525252525252)^(-1)) !THE ODD REGS CORRESP TO FREE EVEN REGS;
OR
((.BSYRG1 AND #252525252525)^1) !THE EVEN REGS CORRESPTO FREE ODD REGS;
END; ! PAIRREGS
GLOBAL ROUTINE AFREEREG (BSYREGS,BLKFLG,DOUBLFLG)=
%(**********
ROUTINE TO RETURN A REGISTER (OR REGISTER PAIR) TO BE USED FOR A GIVEN COMPUTATION.
THE PARAMETERS FOR THIS ROUTINE ARE:
1. BSYREGS-SPECIFIES REGISTERS THAT IT IS POSSIBLE TO USE. THAT IS, REGISTERS THAT
ARE NOT EITHER:
A. HOLDING INTERMEDIATE RESULTS IN THIS STATEMENT
B. ALLOCATED BY THE GLOBAL REGISTER ALLOCATOR
THE BITS IN BSYREGS EACH REPRESENT A REGISTER. IF A BIT IS ZERO THE CORRESPONDING
REGISTER IS NOT AVAILABLE.
2. BLKFLG-IF THIS FLAG IS "TRUE," THE REGISTER TO BE RETURNED WILL BE USED TO
HOLD A VALUE THAT WILL BE PRESERVED OVER SUCCEEDING STATEMENTS IN THIS BASIC BLOCK
3. DOUBLFLG-SPECIFIES WHETHER A SINGLE REGISTER OR A REGISTER PAIR IS REQUIRED
THIS ROUTINE USES THE GLOBAL "BLOCKBSYREGS" WHICH SPECIFIES REGISTERS THAT WE PREFER TO
NOT USE BECAUSE THEIR CONTENTS WILL BE NEEDED LATER IN THIS BASIC BLOCK. THE
FORMAT OF "BLOCKBSYREGS" IS SIMILAR TO THAT OF "BSYREGS" (I.E. IF A BIT IS ZERO, THE
CORRESPONDING REGISTER SHOULD PREFERABLY NOT BE USED).
WHEN ALL REGISTERS ARE BUSY AND HENCE SOME REGISTER FROM "BLOCKBSYREGS" MUST
BE USED, WE SELECT THE REGISTER WHOSE NEXT USE IS THE FURTHEST IN THE
FUTURE. THE "REGSTATE" TABLE CONTAINS THE INTERNAL SEQUENCE NUMBER
OF THE NEXT USE OF EACH REGISTER THAT BLOCKBSYREGS INDICATES SHOULD BE PRESERVED.
**********)%
BEGIN
REGISTER BESTREGS; !REGISTERS THAT ARE AVAILABLE ACCORDING TO "BSYREGS" AND
!NOT OF FUTURE USE IN THIS BASIC BLOCK
OWN RGTOUSE; !REGISTER WHOSE NEXT USE IS FURTHEST IN THE FUTURE
%(***DETERMINE WHICH REGISTERS ARE FREE**)%
BESTREGS_(IF .DOUBLFLG !FOR DOUBLE-PRECISION, MUST
THEN (.BSYREGS AND DPBSYREGS(.BLOCKBSYREGS)) !CONVERT BLOCKBSYREGS TO DP MODE
ELSE (.BSYREGS AND .BLOCKBSYREGS));
IF .BESTREGS NEQ 0
THEN
%(****IF THERE ARE SOME FREE REGISTERS****)%
BEGIN
IF .DOUBLFLG !IF ARE CONSIDERING REGISTER PAIRS ALREADY,
THEN RETURN FIRSTONE(.BESTREGS) !SIMPLY RETURN THE FIRST AVAILABLE PAIR
ELSE
%(***IF A SINGLE REGISTER IS BEING USED, TRY TO USE SINGLE REGISTERS WHOSE
ADJACENT REGISTERS ARE ALREADY IN USE***)%
BEGIN
REGISTER VERYBESTREGS;
IF .BLKFLG !IF THIS REGISTER IS TO BE PRESERVED ACROSS SOME FUTURE
THEN !STATEMENTS
BEGIN
VERYBESTREGS_.BESTREGS AND !IF THERE ARE ANY FREE REGISTERS FOR WHICH THE
NOT PAIRREGS(.BLOCKBSYREGS); !OTHER HALF OF THEIR EVEN-ODD PAIR IS ALREADY
IF .VERYBESTREGS NEQ 0 !HOLDING A VALUE FOR FUTURE STATEMENTS, USE ONE OF THEM
THEN
BESTREGS_.VERYBESTREGS
END;
VERYBESTREGS_.BESTREGS AND !IF THERE ARE ANY FREE REGISTERS FOR WHICH THE OTHER
NOT PAIRREGS(.BSYREGS); !HALF OF THEIR EVEN-ODD PAIR IS ALREADY HOLDING
IF .VERYBESTREGS NEQ 0 !A VALUE ACROSS THIS STATEMENT, USE ONE OF THEM
THEN
BESTREGS_.VERYBESTREGS;
RETURN FIRSTONE(.BESTREGS)
END
END
ELSE
%(***IF THERE ARE NO FREE REGISTERS, THEN MUST USE ONE OF THE REGISTERS THAT HOLDS A
VALUE OF FUTURE USE (I.E. A REGISTER IN BLOCKBSYREGS). PICK THE REGISTERS WHOSE
NEXT USE IS FURTHEST AWAY
****)%
BEGIN
REGISTER MAXNXUSE;
IF .DOUBLFLG
THEN
%(***IF NEED TO GET A REGISTER PAIR***)%
BEGIN
REGISTER NXPAIRUSE; !THE ISN OF THE NEXT STATEMENT AT WHICH EITHER REG IN A PAIR IS USED
%(***WALK THRU THE REGISTER-STATE TABLE TO FIND THE REGISTER PAIR WHOSE NEXT USE
IS THE FURTHEST AWAY***)%
MAXNXUSE_0;
INCR REG FROM #2 TO #14 BY 2
DO
BEGIN
IF .REGSTATE[.REG,RGNXUSE] LSS .BLKISN !IF THE "NEXT USE" OF THIS
AND .REGSTATE[.REG+1,RGNXUSE] LSS .BLKISN ! REG HAS ALREADY
! BEEN PASSED
AND BITSET(.BSYREGS,.REG) !THEN IF THIS REG IS
!LEGAL TO USE, USE IT
THEN RETURN .REG;
NXPAIRUSE_(IF .REGSTATE[.REG,RGNXUSE] EQL 0 !IF THE EVEN REGISTER HAS NO FUTURE USE, THEN
THEN .REGSTATE[.REG+1,RGNXUSE] !THE NEXT USE IS THE NEXT USE FOR THE ODD REG
ELSE IF .REGSTATE[.REG+1,RGNXUSE]EQL 0 !IF THE ODD REGISTER HAS NO FUTURE USE,
THEN .REGSTATE[.REG,RGNXUSE] !THE NEXT USE IS THE NEXT USE FOR THE EVEN REG
ELSE IF .REGSTATE[.REG,RGNXUSE] !IF THE NEXT USE OF THE EVEN REGISTER IS
LEQ .REGSTATE[.REG+1,RGNXUSE] !SOONER THAN THE NEXT USE OF THE ODD REGISTER
THEN .REGSTATE[.REG,RGNXUSE] !THE NEXT USE FOR THE PAIR IS THE NEXT USE FOR THE EVEN REG
ELSE .REGSTATE[.REG+1,RGNXUSE]); !OTHERWISE, IT'S THE NEXT USE FOR THE ODD REG
IF .NXPAIRUSE GTR .MAXNXUSE !IF THE NEXT USE OF THIS PAIR IS
THEN !FURTHER AWAY THAN THE BEST PAIR FOUND
BEGIN !SO FAR,
IF BITSET(.BSYREGS,.REG) !AND THIS PAIR IS A LEGAL ONE TO USE
THEN
BEGIN
MAXNXUSE_.NXPAIRUSE; !THEN USE THIS PAIR
RGTOUSE_.REG
END;
END
END !END OF WALK THRU REGSTATE TABLE FOR PAIRS
END !END OF BLOCK TO FIND A REGISTER PAIR
ELSE
%(***IF NEED A SINGLE REGISTER***)%
BEGIN
%(***WALK THRU THE REGISTER STATE TABLE TO FIND THE REGISTER WHOSE NEXT USE
IS FURTHEST AWAY***)%
MAXNXUSE_0;
INCR REG FROM #2 TO #15 BY 1
DO
BEGIN
IF .REGSTATE[.REG,RGNXUSE] LSS .BLKISN !IF THE "NEXT USE" OF THIS
! REG HAS ALREADY BEEN PASSED
AND BITSET(.BSYREGS,.REG) !THEN IF THIS REG IS LEGAL TO USE
THEN RETURN .REG; !THEN USE THIS REG
IF .REGSTATE[.REG,RGNXUSE] !IF THE NEXT USE OF THIS REG
GTR .MAXNXUSE !IS GREATER THAN THE MAXIMUN FOUND FOR
THEN !ANY REG
BEGIN
IF BITSET(.BSYREGS,.REG) !AND THIS REG IS A LEGAL ONE TO USE
THEN
BEGIN
MAXNXUSE_.REGSTATE[.REG,RGNXUSE]; !USE THIS REG
RGTOUSE_.REG
END
END
END
END; !END OF BLOCK TO FIND A SINGLE REG
IF .MAXNXUSE EQL 0 THEN CGERR(); !IF CAN'T FIND A REG TO USE THAT'S CURRENTLY
!HOLDING A BASIC BLOCK VARIABLE
RETURN .RGTOUSE
END
END; ! AFREEREG
GLOBAL ROUTINE REGCONTAINING(SYMPTR)=
%(**********
THIS ROUTINE DETERMINES WHETHER THE VALUE OF THE VARIABLE/CONSTANT INDICATED
BY "SYMPTR" IS ALREADY IN SOME REGISTER. IF SO, IT RETURNS THE REGISTER,
IF NOT, IT RETURNS MINUS ONE.
"SYMPTR" POINTS TO THE SYMBOL TABLE OR CONSTANT TABLE ENTRY FOR THE VARIABLE/CONSTANT
**********)%
BEGIN
MAP PEXPRNODE SYMPTR;
IF .SYMPTR[OPRCLS] NEQ DATAOPR !IF ARE NOT LOOKING AT A VARIABLE OR CONSTANT
THEN RETURN -1;
IF NOT .SYMPTR[VARINREGFLG] !FLAG IN SYMBOL/CONSTENT TABLE ENTRIES INDICATING
THEN RETURN -1; !THAT VALUE IS IN A REGISTER
%[1231]% INCR REG FROM 0 TO #15 !IF VALUE IS IN A REGISTER, SEARCH THE REGISTER
DO !STATE TABLE TO DETERMINE WHICH REGISTER-FOR
BEGIN !AN EVEN-ODD PAIR WILL FIND THE EVEN REG FIRST
IF .REGSTATE[.REG,RGVAR1] EQL .SYMPTR !IF EITHER OF THE TWO POSSIBLE VARIABLES WHOSE
THEN RETURN .REG; !VALUES ARE IN THIS REG ARE IDENTICAL
IF .REGSTATE[.REG,RGVAR2] EQL .SYMPTR !TO SYMPTR, THEN THIS
THEN RETURN .REG; !IS THE ENTRY DESIRED
END;
CGERR(); !IF THE "VARINREGFLG" WAS SET IN THE SYMBOL TABLE ENTRY, BUT
!THE VARIABLE COULDN'T BE FOUND IN THE REGSTATE TABLE, HAVE A
!COMPILER ERROR
END; ! REGCONTAINING
GLOBAL ROUTINE VARCLOBB(SYMPTR)=
%(**********
THIS ROUTINE IS CALLED WHEN THE VALUE OF A VARIABLE IS MODIFIED.
IF SOME REGISTER HAS BEEN ASSUMED TO CONTAIN THE VALUE OF THAT VARIABLE,
THEN THAT ASSUMPTION CAN NO LONGER BE MADE.
IF THE VARIABLE IS EQUIVALENCED THEN ALL VARIABLES THAT ARE EQUIVALENCED OR IN
COMMON MUST BE ASSUMED TO BE CLOBBERED
**********)%
BEGIN
MAP PEXPRNODE SYMPTR;
%2407% ! Make sure we handle SUBSTRING. This is important for
%2407% ! common/equivalence.
%2407%
%2407% IF .SYMPTR[OPRCLS] EQL SUBSTRING
%2407% THEN SYMPTR = .SYMPTR[ARG4PTR]; ! Get full string
IF .SYMPTR[OPRCLS] EQL ARRAYREF !IF AN ARRAY ELEMENT IS BEING CLOBBERED
THEN
BEGIN
REGISTER PEXPRNODE ARRAYNM; !PTR TO SYM TAB ENTRY FOR THE ARRAY NAME
ARRAYNM_.SYMPTR[ARG1PTR];
IF .ARRAYNM[IDATTRIBUT(INEQV)] !IF THE ARRAY IS IN AN EQUIVALENCE STMNT
THEN CLOBBCOMEQV() !MUST ASSUME THAT ALL VARS IN EQUIVALENCE OR
! IN COMMON ARE CLOBBERED
ELSE IF .ARRAYNM[IDATTRIBUT(INCOM)] !IF THE VAR IS IN COMMON
THEN CLOBBEQV() ! MUST ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS
! ARE CLOBBERED
END
ELSE
IF .SYMPTR[OPRCLS] EQL DATAOPR !IF ITS A SIMPLE VAR THAT'S BEING CLOBBERED
AND .SYMPTR[OPR1] NEQ CONSTFL
THEN
BEGIN
IF .SYMPTR[IDATTRIBUT(INEQV)] !IF THIS VAN IS EQUIVALENCED
THEN CLOBBCOMEQV() !ASSUME THAT ALL VARS IN EQUIVALENCE OR COMMON
!STMNTS HAVE BEEN CLOBBERED
ELSE
IF .SYMPTR[VARINREGFLG] !IF SOME REG IS ASSUMED TO CONTAIN THE VAL OF
THEN !THIS VARIABLE
BEGIN
SYMPTR[VARINREGFLG]_0; !CAN NO LONGER ASSUME THAT THIS VAR IS IN A REG
%(***SEARCH THE REGSTATE TABLE FOR THE ENTRY FOR THIS VARIABLE AND CLEAR THAT ENTRY**)%
INCR REG FROM 0 TO #15
DO
BEGIN
IF .REGSTATE[.REG,RGVAR1] EQL .SYMPTR !IF THIS IS THE REG THAT CONTAINED "SYMPTR"
THEN !CLEAR ITS ENTRY IN THE REGSTATE TABLE
BEGIN
REGSTATE[.REG,RGVAR1]_0;
IF .REGSTATE[.REG,RGVAR2] EQL 0 !IF "SYMPTR" WAS THE ONLY VARIABLE
THEN !IN THIS REG, THEN RETURN THIS
BEGIN !REG TO THE SET OF FREE REGISTERS
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END;
END;
IF .REGSTATE[.REG,RGVAR2] EQL .SYMPTR !IF THIS IS THE REG THAT CONTAINED "SYMPTR"
THEN !CLEAR ITS ENTRY
BEGIN
REGSTATE[.REG,RGVAR2]_0;
IF .REGSTATE[.REG,RGVAR1] EQL 0 !IF "SYMPTR" WAS THE ONLY VARIABLE
THEN !IN THIS REG, THEN RETURN THIS
BEGIN !REG TO THE SET OF FREE REGISTERS
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END;
END;
END; !END OF INCR LOOP
END; !END OF BLOCK FOR SYMPTR KNOWN TO BE IN A REG
IF .SYMPTR[IDATTRIBUT(INCOM)] !IF SYMPTR IS IN COMMON
THEN CLOBBEQV(); ! MUST ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS
! ARE CLOBBERED
END !END OF BLOCK FOR "SYMPTR" A SIMPLE VARIABLE
END; ! VARCLOBB
ROUTINE COMOREQV(SYMENTRY)=
%(**********
LOCAL ROUTINE TO TEST WHETHER "SYMENTRY" POINTS TO A SYMBOL
TABLE ENTRY FOR A VARIABLE THAT OCCURS IN A COMMON OR
EQUIVALENCE STATEMENT
**********)%
BEGIN
MAP BASE SYMENTRY;
IF .SYMENTRY[OPR1] EQL CONSTFL !IF SYMENTRY IS NOT A SYMBOL TABLE ENTRY
THEN FALSE !(I.E. IS A CONSTANT TABLE ENTRY)
ELSE
(.SYMENTRY[IDATTRIBUT(INEQV)] !FLAG FOR "VARIABLE IS IN AN EQUIVALENCE STMNT"
OR
.SYMENTRY[IDATTRIBUT(INCOM)] !FLAG FOR "VARIABLE IS IN A COMMON STMNT"
)
END; ! COMOREQV
GLOBAL ROUTINE CLOBBCOMEQV=
%(**********
ROUTINE TO ASSUME THAT ALL VARIABLES IN COMMON AND ALL VARIABLES
THAT ARE EQUIVALENCED TO ANYTHING HAVE HAD THEIR VALUES MODIFIED.
REMOVES FROM THE REGSTATE TABLE ALL VARIABLES WHICH ARE IN COMMON OR HAVE
BEEN EQUIVALENCED
**********)%
BEGIN
REGISTER PEXPRNODE SYMENTRY; !POINTER TO SYMBOL/CONSTANT TABLE ENTRY FOR
!THE VARIABLE IN A GIVEN REGISTER
INCR REG FROM 0 TO #15 !LOOK AT THE REGSTATE TABLE ENTRY FOR EACH REG
DO
BEGIN
IF (SYMENTRY_.REGSTATE[.REG,RGVAR1]) NEQ 0 !ONE OF THE VARIABLES IN THIS REGISTER
THEN
BEGIN
IF COMOREQV(.SYMENTRY) !IF VARIABLE IS IN COMMON OR IS EQUIVALENCED
THEN
BEGIN
SYMENTRY[VARINREGFLG]_0;
REGSTATE[.REG,RGVAR1]_0; !CLEAR ENTRY INDICATING THAT CONTAINS VAL OF THIS VAR
IF .REGSTATE[.REG,RGVAR2] EQL 0 !IF THIS REG NO LONGER CONTAINS ANY VARIABLES,
THEN !RETURN IT TO THE SET OF AVAILABLE REGS
BEGIN
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END
END
END;
IF (SYMENTRY_.REGSTATE[.REG,RGVAR2]) NEQ 0 !POSSIBLY A SECOND VARIABLE WHOSE VALUE IS
THEN !IN "REG" (E.G. FOR A=B, FOTH A AND B
BEGIN !ARE IN THE SAME REG)
IF COMOREQV(.SYMENTRY) !IF VARIABLE IS IN COMMON OR IS EQUIVALENCED
THEN
BEGIN
SYMENTRY[VARINREGFLG]_0;
REGSTATE[.REG,RGVAR2]_0; !CLEAR ENTRY INDICATING THAT "REG" CONTAINS VAL OF THIS VARIABLE
IF .REGSTATE[.REG,RGVAR1] EQL 0 !IF THIS REG NO LONGER CONTAINS ANY VARIABLES
THEN !RETURN IT TO THE SET OF AVAILABLE REGS
BEGIN
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END
END
END
END
END; ! CLOBBCOMEQV
GLOBAL ROUTINE CLOBBEQV=
%(***************************************************************************
ROUTINE TO ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS ARE CLOBBERED.
REMOVES FROM THE REGSTATE TABLE ALL VARS THAT ARE IN EQUIVALENCE STMNTS;
***************************************************************************)%
BEGIN
REGISTER PEXPRNODE SYMENTRY; !PTR TO SYMBOL/CONST TABLE ENTRY FOR THE
! VAR IN A GIVEN REG
INCR REG FROM 0 TO #15 !LOOK AT THE ENTRY FOR EACH REG
DO
BEGIN
IF (SYMENTRY_.REGSTATE[.REG,RGVAR1]) NEQ 0 !ONE OF THE VARS IN THIS REG
THEN
BEGIN
IF .SYMENTRY[OPR1] NEQ CONSTFL
AND .SYMENTRY[IDATTRIBUT(INEQV)] !IF THIS VAR IS IN AN EQUIVALENCE
THEN
(SYMENTRY[VARINREGFLG]_0; REGSTATE[.REG,RGVAR1]_0); !CAN NO LONGER ASSUME THAT ITS VAL
! IS IN REG
END;
IF (SYMENTRY_.REGSTATE[.REG,RGVAR2]) NEQ 0 !A 2ND VAR IN THIS REG
THEN
BEGIN
IF .SYMENTRY[OPR1] NEQ CONSTFL
AND .SYMENTRY[IDATTRIBUT(INEQV)] !IF THIS VAR IS IN EQUIVALENCE
THEN
(SYMENTRY[VARINREGFLG]_0; REGSTATE[.REG,RGVAR2]_0); !REMOVE ITS VAL FROM REG
END;
IF .REGSTATE[.REG,RGVAR1] EQL 0 AND .REGSTATE[.REG,RGVAR2] EQL 0 !IF THIS REG NOW
! CONTAINS NO KNOWN VALS
THEN
(REGSTATE[.REG,RGNXUSE]_0; BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)); !RETURN IT TO SET
! OF FREE REGISTERS
END !END OF INCR LOOP
END; ! CLOBBEQV
ROUTINE CLRVAR1FIELD(RG)=
%(**********
ROUTINE TO CLEAR THE "RGVAR1" FIELD OF A REGSTATE TABLE
ENTRY AND IF THE "RGVAR2" FIELD IS ALSO 0, TO RETURN THE
REGISTER TO THE SET OF FREE REGS
***********)%
BEGIN
REGSTATE[.RG,RGVAR1]_0;
IF .REGSTATE[.RG,RGVAR2] EQL 0 !IF THERE IS NOT ANOTHER VAR IN THIS REG
THEN
BEGIN
REGSTATE[.RG,RGNXUSE]_0; !"LOC OF NEXT USE"
BLOCKBSYREGS_ !RETURN "RG" TO SET OF FREE REGS
SETBIT(.BLOCKBSYREGS,.RG)
END
END; ! CLRVAR1FIELD
ROUTINE CLRVAR2FIELD(RG)=
%(**********
ROUTINE TO CLEAR THE "RGVAR2" FIELD OF A REGSTATE TABLE
ENTRY AND IF THE "RGVAR1" FIELD IS ALSO 0, TO RETURN THE
REGISTER TO THE SET OF FREE REGS
***********)%
BEGIN
REGSTATE[.RG,RGVAR2]_0;
IF .REGSTATE[.RG,RGVAR1] EQL 0 !IF THERE IS NOT ANOTHER VAR IN THIS REG
THEN
BEGIN
REGSTATE[.RG,RGNXUSE]_0; !"LOC OF NEXT USE"
BLOCKBSYREGS_ !RETURN "RG" TO SET OF FREE REGS
SETBIT(.BLOCKBSYREGS,.RG)
END
END; ! CLRVAR2FIELD
ROUTINE CHKOTHREGS(SYMPTR,RG)=
%[632]% %(***********
[632] ROUTINE TO CLEAR THE VARINREGFLG FOR SYMPTR IFF SYMPTR IS
[632] ONLY IN REGISTER RG. THIS KEEPS VARINREGFLG SET IF
[632] SOME REG CONTAINING SYMPTR IS CLOBBERED, BUT SYMPTR IS
[632] STILL IN OTHER REG(S).
[632] ************)%
%[632]% BEGIN
%[632]%
%[632]% MAP PEXPRNODE SYMPTR; !THE VAR IN REGISTER RG
%[632]%
%[632]% REGISTER REGX; !INDEX FOR LOOP BELOW
%[632]%
%[632]% SYMPTR[VARINREGFLG]_0; !ASSUME NOT IN ANY OTHER REG
%[632]%
%[632]% REGX_0;
%[632]% WHILE (.REGX LEQ #15) AND NOT .SYMPTR[VARINREGFLG]
%[632]% DO
%[632]% BEGIN
%[632]% IF .REGX NEQ .RG
%[632]% THEN
%[632]% IF .REGSTATE[.REGX,RGVAR1] EQL .SYMPTR
%[632]% OR .REGSTATE[.REGX,RGVAR2] EQL .SYMPTR
![652] MUST BE CAREFUL IF THE VARIABLE WAS DOUBLE WORD IN WHICH
![652] CASE WE NEED TO FIND A REG FAR AWAY (MORE THAN 1)
%[652]% THEN IF NOT .SYMPTR[DBLFLG] THEN SYMPTR[VARINREGFLG]_1
%[652]% ELSE IF (.REGX+1 NEQ .RG) AND (.REGX-1 NEQ .RG)
%[652]% THEN SYMPTR[VARINREGFLG]_1;
%[632]% REGX_.REGX+1
%[632]% END
%[632]% END; ! CHKOTHREGS
GLOBAL ROUTINE REGCLOBB(REG)=
%(**********
THIS ROUTINE IS CALLED WHENEVER THE CONTENTS OF A REGISTER ARE CLOBBERED.
THIS ROUTINE CLEARS THE REGSTATE TABLE ENTRY FOR THE REGISTER "REG".
IF ANY VARIABLES HAVE BEEN ASSUMED TO BE IN REG IT CLEARS THE "VARINREGFLG"
FOR THOSE VARIABLES
IT ALSO SETS THE BIT CORRESPONDING TO THE REGISTER CLOBBERED
IN THE GLOBAL "CLOBBREGS" WHICH IS USED TO DETERMINE WHICH REGS
TO SAVE AND RESTORE IN A FUNCTION
**********)%
BEGIN
REGISTER PEXPRNODE SYMPTR; !POINTER TO SYMBOL TABLE OR CONSTANT TABLE ENTRY FOR
!VARIABLE/CONSTANT WHOSE VALUE IS IN REG
IF .REG GEQ 2 !UNLESS THE REG IS 0 OR 1 (WHICH ARE NEVER SAVE/RESTORED ACROSS A FN)
THEN ! SET THE BIT CORRESPONDING TO THAT REG IN THE GLOBAL USED TO KEEP
CLOBBREGS_ ! TRACK OF ALL REGS THAT MUST BE SAVE/RESTORED
SETBIT(.CLOBBREGS,.REG);
IF (SYMPTR_.REGSTATE[.REG,RGVAR1]) NEQ 0 !IF SOME VARIABLE IS ASSUMED TO
THEN !BE IN "REG"
BEGIN
%[632]% CHKOTHREGS(.SYMPTR,.REG); !CLEAR VARINREGFLG IF NECESSARY
IF .SYMPTR[DBLFLG] !IF THE VAR IS DP OR COMPLEX
THEN !MUST CLEAR THE ENTRY FOR THE OTHER HALF OF THE VAR
BEGIN !WHICH IS IN A REG ADJACENT TO "REG"
IF .REGSTATE[.REG+1,RGVAR1] EQL .SYMPTR !IF "REG" WAS THE 1ST HALF
THEN CLRVAR1FIELD(.REG+1) !CLEAR ENTRY IN NEXT REG
ELSE
IF .REGSTATE[.REG-1,RGVAR1] EQL .SYMPTR !IF "REG" WAS THE 2ND HALF
THEN CLRVAR1FIELD(.REG-1) !CLEAR ENTRY IN PREVIOUS REG
ELSE !(IF "RGVAR1" FIELD WAS USED FOR A GIVEN VAR
! IN ONE REG, CAN ASSUME THAT "RGVAR1" FIELD WILL
! ALSO BE USED FOR THE OTHER HALF OF THE VAR)
CGERR() !IF CANT FIND ENTRY FOR THE OTHER HALF OF THE VAR
END
END;
IF (SYMPTR_.REGSTATE[.REG,RGVAR2]) NEQ 0 !IF SOME SECOND VARIABLE IS ASSUMED
THEN !TO BE IN "REG" (E.G. IF HAD "A=B")
BEGIN
%[632]% CHKOTHREGS(.SYMPTR,.REG); !CLEAR VARINREGFLG IF NEEDED
IF .SYMPTR[DBLFLG] !IF THE VAR IS DP OR COMPLEX
THEN !MUST CLEAR THE ENTRY FOR THE OTHER HALF OF THE VAR
BEGIN !WHICH IS IN A REG ADJACENT TO "REG"
IF .REGSTATE[.REG+1,RGVAR2] EQL .SYMPTR !IF "REG" WAS THE 1ST HALF
THEN CLRVAR2FIELD(.REG+1) !CLEAR ENTRY IN NEXT REG
ELSE
IF .REGSTATE[.REG-1,RGVAR2] EQL .SYMPTR !IF "REG" WAS THE 2ND HALF
THEN CLRVAR2FIELD(.REG-1) !CLEAR ENTRY IN PREVIOUS REG
ELSE !(IF "RGVAR2" FIELD WAS USED FOR A GIVEN VAR
! IN ONE REG, CAN ASSUME THAT "RGVAR2" FIELD WILL
! ALSO BE USED FOR THE OTHER HALF OF THE VAR)
!**;[1212], REGCLOBB, TFV, 29-Apr-81
!**;[1212], Replace LITERAL with HOLLERITH
%[1212]% IF .SYMPTR[VALTYPE] NEQ HOLLERITH ! IF THE "VAR" IS
%[1024]% ! A LITERAL THAT WAS ASSIGNED TO
%[1024]% ! A REAL, ONLY THE 1ST WORD WILL
%[1024]% ! BE IN AN AC
%[1024]% THEN !OTHERWISE, WE SHOULD HAVE FOUND
! AC THAT CONTAINED THE OTHER WORD
CGERR() !IF CANT FIND ENTRY FOR THE OTHER HALF OF THE VAR
END
END;
BLOCKBSYREGS_ !RETURN "REG" TO THE SET
SETBIT(.BLOCKBSYREGS,.REG); !OF FREE REGISTERS
REGSTATE[.REG,RGVAR1]_0; !CLEAR REGSTATE TABLE
REGSTATE[.REG,RGVAR2]_0; !ENTRY FOR REG
REGSTATE[.REG,RGNXUSE]_0;
END; ! REGCLOBB
GLOBAL ROUTINE CLRRGSTATE=
%(**********
THIS ROUTINE CLEARS THE REGSTATE TABLE. IT IS CALLED AT THE END OF REGISTER ALLOCATION
FOR A BASIC BLOCK (WHEN ALL ASSUMPTIONS ABOUT THE CONTENTS OF REGISTERS
MUST BE DISCARDED)
**********)%
BEGIN
REGISTER PEXPRNODE SYMPTR; !POINTER TO SYMBOL/CONSTANT TABLE ENTRY FOR A VARIABLE/CONSTANT
!WHICH IS ASSUMED TO HAVE BEEN LEFT IN SOME REGISTER
DECR REG FROM #15 TO 0 !WALK THRU THE REGSTATE TABLE
DO
BEGIN
IF (SYMPTR_.REGSTATE[.REG,RGVAR1]) NEQ 0 !A VARIABLE WHOSE VALUE IS ASSUMED TO BE IN "REG"
THEN
BEGIN
SYMPTR[VARINREGFLG]_0; !CAN NO LONGER ASSUME THAT THAT VAR IS IN A REG
REGSTATE[.REG,RGVAR1]_0;
END;
IF (SYMPTR_.REGSTATE[.REG,RGVAR2]) NEQ 0 !A SECOND VARIABLE WHOSE VALUE IS ASSUMED TO BE IN "REG"
THEN
BEGIN
SYMPTR[VARINREGFLG]_0; !CAN NO LONGER ASSUME THAT THAT VAR IS IN A REG
REGSTATE[.REG,RGVAR2]_0;
END;
REGSTATE[.REG,RGNXUSE]_0; !ISN OF NEXT USE OF THES REG SET TO 0 (MEANING
END; !END OF DECR LOOP !NO FUTURE USE)
BLOCKBSYREGS_-1; !ALL REGS ARE NOW AVAILABLE
END; ! CLRRGSTATE
GLOBAL ROUTINE INIRGSTATE=
%(**********
THIS ROUTINE INITS THE REGISTER STATE TABLE BY ZEROING ALL
ENTRIES.
*********)%
BEGIN
DECR REG FROM #15 TO 0 !CLEAR THE ENTRY FOR EACH REG
DO
BEGIN
REGSTATE[.REG,RGVAR1]_0; !CLEAR ALL FIELDS OF THE ENTRY
REGSTATE[.REG,RGVAR2]_0;
REGSTATE[.REG,RGNXUSE]_0;
END;
BLOCKBSYREGS_-1; !THIS WORD WILL HAVE THE BIT CORRESPONDING TO EACH
! BUSY REG SET TO 0. INIT IT TO HAVE
! NO BITS SET TO 0
END; ! INIRGSTATE
GLOBAL ROUTINE SAVEREG(REG,SYMENT1,SYMENT2,USEISN)=
%(**********
THIS ROUTINE IS CALLED WHEN IT IS DETERMINED THAT THE REGISTER "REG"
SHOULD BE PRESERVED OVER FUTURE STATEMENTS IN THE CURRENT BASIC BLOCK.
SYMENT1 IS A POINTER TO THE SYMBOL/CONSTANT TABLE ENTRY FOR THE VARIABLE/CONSTANT
WHOSE VALUE IS IN REG. SYMENT2 IS A POINTER TO A POSSIBLE SECOND SYMBOL/CONSTANT
TABLE ENTRY. USEISN IS THE ISN OF THE NEXT USE OF THE VALUE IN REG.
********)%
BEGIN
MAP PEXPRNODE SYMENT1;
MAP PEXPRNODE SYMENT2;
IF .NOBBREGSLOAD !IF CANNOT ASSUME THAT THE CODE FOR THIS EXPR WILL
THEN ! ALWAYS BE EXECUTED, THEN CANNOT KEEP THIS VAL IN THIS REG
RETURN;
IF .SYMENT2 EQL 0 !IF ARE ONLY TRYING TO REMEMBER 1 VAR
AND (.REGSTATE[.REG,RGVAR1] EQL .SYMENT1 ! AND WE ALREADY KNEW THAT THIS
OR .REGSTATE[.REG,RGVAR2] EQL .SYMENT1) ! VAR WAS IN THIS REG
THEN
BEGIN
REGSTATE[.REG,RGNXUSE]_.USEISN; !UPDATE VAL FOR "NEXT USE"
IF .SYMENT1[DBLFLG] !IF ARE SAVING A REG PAIR
THEN REGSTATE[.REG+1,RGNXUSE]_.USEISN; !UPDATE "NXT USE"FOR 2ND HALF
END
ELSE
BEGIN
REGCLOBB(.REG); !IF THIS ENTRY ALREADY CONTAINED
! VARS FORGET ABOUT THEM
REGSTATE[.REG,RGVAR1]_.SYMENT1; !SET UP THE REGSTATE TABLE ENTRY FOR THIS REG
REGSTATE[.REG,RGVAR2]_.SYMENT2;
REGSTATE[.REG,RGNXUSE]_.USEISN;
IF .SYMENT1[DBLFLG] !IF THE VALUE TO BE PRESERVED IS DOUBLE PREC OR COMPLEX
THEN
BEGIN
REGSTATE[.REG+1,RGVAR1]_.SYMENT1; !SET UP REGSTATE TABLE ENTRY FOR THE REG FOLLOWING THIS REG
REGSTATE[.REG+1,RGVAR2]_.SYMENT2;
REGSTATE[.REG+1,RGNXUSE]_.USEISN;
END;
END;
BLOCKBSYREGS_CLRBIT(.BLOCKBSYREGS,.REG); !TURN OFF BIT IN BLOCKBSYREGS CORRESPONDING
!TO THIS REG TO INDICATE IT SHOULD
!BE PRESERVED
IF .SYMENT1[DBLFLG] !IF ARE SAVING A REG PAIR
THEN
BLOCKBSYREGS_CLRBIT(.BLOCKBSYREGS,.REG+1); !CLEAR BIT IN BLOCKBSYREGS TO INDICATE
!THAT REG AFTER "REG" MUST BE
!PRESERVED
SYMENT1[VARINREGFLG]_1; !SET FLAG IN SYMBOL/CONST TABLE ENTRY INDICATING THAT THIS
!VAR IS IN SOME REG
IF .SYMENT2 NEQ 0 !IF A SECOND VARIABLE IS ALSO IN THIS REG (EG FOR A=B)
THEN
SYMENT2[VARINREGFLG]_1; !SET FLAG IN ITS SYMBOL TABLE ENTRY AS WELL
END; ! SAVEREG
GLOBAL ROUTINE FREEPAIRS(BSYREGS)=
%(***************************************************************************
GIVEN A BIT PATTERN "BSYREGS" IN WHICH 0'S INDICATE BUSY REGS AND
1'S INDICATE FREE REGS, THIS ROUTINE RETURNS THE NUMBER
OF EVEN-ODD REG PAIRS THAT ARE FREE
***************************************************************************)%
BEGIN
RETURN ONESCOUNT(
(.BSYREGS AND #525252525252)^(-1) !BITS FOR FREE EVEN REGISTERS
! SHIFTED RIGHT TO INDICATE ODD REG FOLLOWING EACH
AND
(.BSYREGS AND #252525252525) !BITS FOR FREE ODD REGISTERS
)
END; ! FREEPAIRS
END
ELUDOM