Trailing-Edge
-
PDP-10 Archives
-
BB-D480C-SB_1981
-
alcblo.bli
There are 12 other files named alcblo.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
! OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) 1973,1981 BY DIGITAL EQUIPMENT CORPORATION
!AUTHOR: S. MURPHY/SRM/JNG
MODULE ALCBLO(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3))=
BEGIN
GLOBAL BIND ALCBLV = 6^24 + 0^18 + 60; ! Version Date: 24-Jul-81
%(
***** Begin Revision History *****
55 ----- ----- MUST END A BASIC BLOCK ON AN IF THAT CONTAINS A CALL
56 ----- ----- WHEN INSERT AN ENTRY IN REGSTATE TABLE
MUST CLEAR VARINREGFLG OF A POSSIBLE ENTRY
BEING WRITTEN OVER. THIS CAN HAPPEN FOR:
A=B
C=B
WHERE B IS GLOBALLY ALLOCATED TO A REG
57 ----- ----- MUST CHECK FOR A BASIC BLOCK
TERMINATED BY THE NEXT STMNT HAVING A LABEL BEFORE
CHECK FOR IT TERMINATED BY THE PREVIOUS STMNT
A DO STMNT (SINCE IN THAT CASE WE STILL REMEMBER THE
LP INDEX
58 632 24245 IN REGCLOBB, DON'T CLEAR VARINREGFLG FOR THE
VARIABLE IN THE REGISTER IF THE VARIABLE IS
ALSO IN ANOTHER REGISTER. THIS CAN HAPPEN IF
A VAR IS LIVING IN 0, MOVED TO 2 FOR INDEXING,
THEN 0 IS REGLOBB'ED BY A FUNCTION CALL., (JNG)
59 652 NONE EDIT 632 NEEDS TO CARE ABOUT DOUBLE WORD VARS, (DCE)
***** Begin Version 6 *****
60 1024 SRM 21-Nov-80 NONE
Fixed REGCLOBB to work for REAL='literal' when
compiling /gfloating. REGCLOBB had assumed that
if a literal was in an AC the 2nd half must be
in an adjacent AC. This was always true because
we did a "type conversion" on the literal and
created a constant of type REAL that contained
the bits from the literal. When compiling
/gfloating we dont do this "conversion".
***** End Revision History *****
)%
FORWARD ALCBLOCK(0),AFREEREG(3),REGCONTAINING(1),VARCLOBB(1),CLOBBCOMEQV,
CLOBBEQV,CLRRGSTATE,
INIRGSTATE,SAVEREG(5),FREEPAIRS(1);
EXTERNAL CGERR; !ROUTINE TO GIVE MESSAGE WHEN INTERNAL COMPILER ERROR
! IS DETECTED
!REQUIRE OF "FIRST.BLI" AND "TABLES.BLI" - DONT LIST THEM
SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;
BIND RGSENTSIZE=2; !NUMBER OF WDS IN EACH ENTRY OF THE REGSTATE TABLE
OWN REGSTATE[RGSENTSIZE*16]; !THIS TABLE HAS AN ENTRY FOR EACH OF THE 16 ACS
! EACH ENTRY INDICATES WHICH VARS/CONSTS ARE IN EACH REG
OWN BLKISN; !SEQ NUMBER WITHIN THIS BLOCK OF THE STMNT CURRENTLY BEING PROCESSED
GLOBAL ROUTINE ALCBLOCK=
%(**********
THE TOP LEVEL ROUTINE FOR THE SECOND PASS OF THE BASIC BLOCK REGISTER ALLOCATOR.
THIS ROUTINE CAUSES LOCAL REGISTER ALLOCATION TO BE PERFORMED FOR EVERY
STATEMENT IN A BASIC BLOCK.
A BASIC BLOCK IS TERMINATED BY
1. A LABEL WHICH IS REFERENCED OTHER THAN AS A FORMAT
2. A DO STATEMENT
3. FOR PURPOSES OF REGISTER ALLOCATION, A CALL STATEMENT (SINCE SUBROUTINES ARE
ASSUMED TO CLOBBER ALL REGISTERS)
4. AN ENTRY POINT
THIS ROUTINE IS CALLED WITH THE GLOBAL CSTMNT POINTING TO THE FIRST STATEMENT OF
A BASIC BLOCK. IT RETURNS WITH CSTMNT POINTING TO THE FIRST STATEMENT OF
THE NEXT BASIC BLOCK. IF THE END OF THE PROGRAM HAS BEEN REACHED IT
RETURNS CSTMNT=0.
THIS ROUTINE CLEARS THE REGSTATE TABLE WHEN IT HAS COMPLETED THE PASS OVER A
BASIC BLOCK. IF THE LAST STATEMENT OF THE BLOCK WAS A DO STATEMENT THEN IF THAT
DO STATEMENT HAS THE FLAGS "SAVEREGFLG" AND "NEDSMATRLZ" BOTH SET, IT SETS
UP A REGSTATE TABLE ENTRY FOR THE DO LOOP INDEX SO THAT THE REGISTER CONTAINING
THE INDEX CAN BE USED IN THE NEXT BASIC BLOCK.
IT IS ASSUMED THAT WHEN THIS ROUTINE IS CALLED FOR A GIVEN BASIC BLOCK, THE
REGSTATE TABLE IS IN THE STATE IN WHICH THIS ROUTINE LEFT IT AFTER
PROCESSING THE PRECEEDING BASIC BLOCK.
**********)%
BEGIN
REGISTER BASE PRVSTMNT; !THE STMNT JUST PROCESSED
EXTERNAL CSTMNT; !POINTER TO CURRENT STATEMENT BEING PROCESSED
MAP BASE CSTMNT;
EXTERNAL ISN; !INTERNAL SEQ NUMBER OF THE STMNT BEING PROCESSED
! (THIS IS USED FOR ERROR MESSAGES)
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL CLRRGSTATE; !ROUTINE TO CLEAR THE REGSTATE TABLE
EXTERNAL SAVEREG; !ROUTINE TO SET UP A REGSTATE TABLE ENTRY FOR A REGISTER
!WHOSE VALUE SHOULD BE PRESERVED
EXTERNAL ALCSTMN; !ROUTINE TO PERFORM LOCAL REGISTER ALLOCATION
!FOR A GIVEN STATEMENT
EXTERNAL GBSYREGS; !BIT PATTERN REPRESENTING THE REGS LEFT FREE BY THE
! GLOBAL ALLOCATOR (A ONE REPRESENTS A FREE REG, A ZERO A BUSY ONE)
EXTERNAL GBSYCT; !NUMBER OF FREE REGS IN GBSYREGS
EXTERNAL STBSYR; !BIT PATTERN REPRESENTING THE REGS AVAILABLE FOR
! USE WITHIN A GIVEN STMNT
EXTERNAL STRGCT; !NUMBER OF FREE REGS IN STBSYR
EXTERNAL FRSTLNK; !POINT TO THE FIRST TEMPORARY ON THE LINKED LIST
! OF TEMPORARIES THAT HAVE HAD TO BE CREAETED
EXTERNAL FTEMP; !POINTER TO THE TEMPORARY ON THE LINKED LIST
! OF TEMPS THAT SHOULD BE USED NEXT
! ZERO IF NONE IS AVAILABLE (AND HENCE A NEW ONE
! MUST BE ADDED TO THE LIST)
OWN PEXPRNODE STLABEL; !POINTER TO THE LABEL TABLE ENTRY FOR THE LABEL ON THIS STATEMENT (IF ANY)
EXTERNAL OLDGBSYREGS; !BIT PATTERN SET UP BY THE GLOBAL OPTIMIZER TO
! INDICATE REGS AVAILABLE OUTSIDE THE CURRENT DO LOOP
! WHEN THE CURRENT LOOP WAS GLOBALLY ALLOCATED
BLKISN_1; !1ST STMNT IN BASIC BLOCK HAS BLOCK INTERNAL SEQ NO. 1
%(***WALK THRU ALL STATEMENTS IN THE BLOCK***)%
UNTIL .CSTMNT EQL 0 !UNTIL REACH THE END OF THE PROGRAM
DO
BEGIN
ISN_.CSTMNT[SRCISN]; !GET INTERNAL SEQ NUMB OF THE STMNT TO BE PROCESSED NEXT
STBSYR_.GBSYREGS; !INIT SET OF REGS AVAILABLE FOR USE
! IN THIS STMNT
STRGCT_.GBSYCT;
FTEMP_.FRSTLNK; !INIT PTR TO NEXT TEMPORARY TO BE USED SO
! THAT WILL REUSE THE TEMPORARIES THAT
! WERE CREATED FOR PREVIOUS STMNTS
ALCSTMN(); !PERFORM LOCAL REGISTER ALLOCATION FOR THIS STATEMENT
IF .CSTMNT[SRCID] EQL CALLID !IF THIS STATEMENT WAS A CALL STATEMENT,
OR .CSTMNT[SRCID] EQL SFNID ! OR A STMNT FN, THEN
OR (IF .CSTMNT[SRCID] EQL IFLID ! OR A LOG IF
THEN
BEGIN
REGISTER BASE SUBSTMNT;
SUBSTMNT_.CSTMNT[LIFSTATE];
IF .SUBSTMNT[SRCID] EQL CALLID !THAT CONTAINS A CALL
THEN TRUE
ELSE FALSE
END
ELSE FALSE
)
THEN !IT TERMINATES A BASIC BLOCK
BEGIN
CLRRGSTATE(); !CLEAR THE REGSTATE TABLE
CSTMNT_.CSTMNT[SRCLINK]; !AND RETURN WITH CSTMNT POINTING TO THE
RETURN !STATEMENT AFTER THE CALL STATEMENT
END;
PRVSTMNT_.CSTMNT;
CSTMNT_.CSTMNT[SRCLINK]; !GO ON TO THE NEXT STMNT
IF .CSTMNT NEQ 0 !UNLESS THE END OF THE PROGRAM HAS BEEN REACHED
THEN
BEGIN
IF .CSTMNT[SRCID] EQL ENTRID !IF THE NEXT STMNT IS AN ENTRY
OR .CSTMNT[SRCID] EQL SFNID ! OR A STMNT FN
! IT WILL START A NEW BASIC BLOCK
THEN
BEGIN
CLRRGSTATE(); !CLEAR TABLE INDICATING VALS IN REGS
RETURN; ! RETURN WITH CSTMNT POINTING TO THE ENTRY STMNT
END
ELSE
IF (STLABEL_.CSTMNT[SRCLBL]) NEQ 0 !IF THE NEXT STATEMENT HAS A LABEL
THEN
BEGIN
IF .STLABEL[SNREFNO] GTR 1 !WHICH IS REFERENCED OTHER THAN AS A FORMAT
THEN !(THE COUNT IN "SNREFNO" INCLUDES THE DEFINITION OF THE
BEGIN !LABEL AS A REFERENCE-DOES NOT INCLUDE FORMAT NEFS)
IF .STLABEL[SNREFNO]-1 !IF THE NUMBER OF REFERENCES TO THIS LABEL
GTR .STLABEL[SNDOLVL] !IS LARGER THAN THE NUMBER OF DO LOOPS IT TERMINATES
!(I.E. IF THIS LABEL IS REFERENCED OTHER THAN AS A DO LOOP
!TERMINATOR)-THEN THE STATEMENT PRECEEDING
!IT TERMINATED A BASIC BLOCK
THEN
BEGIN
CLRRGSTATE(); !CLEAR THE REGSTATE TABLE
RETURN !AND RETURN WITH CSTMNT POINTING TO THE
!STMNT WITH THE LABEL THAT IS REFERENCED OTHER
!THAN AS A FORMAT OR A LOOP TERMINATOR
END
END
END
END;
IF .PRVSTMNT[SRCID] EQL DOID !IF STATEMENT JUST
! PROCESSED WAS A DO STATEMENT,
THEN !THEN IT TERMINATES A BASIC BLOCK
BEGIN
CLRRGSTATE(); !CLEAR THE REGSTATE TABLE (I.E. CAN NO LONGER ASSUME ANY
!PREVIOUS VALUES IN REGISTERS)
IF .PRVSTMNT[NEDSMATRLZ] !IF THE LOOP INDEX HAS NOT BEEN REPLACED THRUOUT THE
AND .PRVSTMNT[SAVREGFLG] !LOOP BY REGCONTENTS NODES, BUT THE VALUE OF THE
!INDEX SHOULD BE LEFT IN A REG ACROSS THE
!FIRST BASIC BLOCK OF THE LOOP
THEN
BEGIN
REGISTER PEXPRNODE DOIX; !PTR TO SYMBOL TABLE ENTRY FOR INDEX
DOIX_.PRVSTMNT[DOSYM];
IF .DOIX[DBLFLG] !IF LOOP INDEX IS DP OR COMPLEX
THEN BEGIN END ! DONT BOTHER (ON KA10, VAL WONT BE IN A REG)
ELSE
SAVEREG(.PRVSTMNT[DOIREG], !SET UP A REGSTATE TABLE ENTRY FOR THE REG
.PRVSTMNT[DOSYM],0, !CONTAINING THE LOOP INDEX
.PRVSTMNT[SRCSONNXTUSE]);
%(***IF THE LOOP CONST WAS IN "AOBJN" FORM, MUST CHANGE IT
SO THAT THE INITIAL VAL FOR THE LOOP INDEX WILL
BE PICKED UP IN A REG BY ITSELF***)%
IF .PRVSTMNT[FLCWD] !IF CTL CONST HAD COUNT IN LEFT HALF
THEN ! VAR IN RIGHT HALF
BEGIN
REGISTER CT;
REGISTER PEXPRNODE AOBJNCNST;
AOBJNCNST_.PRVSTMNT[DOLPCTL]; !PTR TO CONST TABLE ENTRY
! FOR THE CONST THAT HAS NEG CT IN LEFT HALF
CT_.AOBJNCNST[CONST2]^(-18) !THE NEG NUMBER OF ITERATIONS
OR #777777000000;
PRVSTMNT[DOLPCTL]_ !SET LOOP CTL CONST TO BE
MAKECNST(INTEGER,0,-.CT); !THE POS NUMBER OF ITERATIONS
PRVSTMNT[CTLNEG]_1; !SET FLAGS INDICATING THAT CT SHOULD
PRVSTMNT[CTLIMMED]_1; ! BE PICKED UP WITH "MOVNI" INSTR
PRVSTMNT[INITLIMMED]_1; !SET FLAG INDICATING THAT INIT VAL
! SHOULD BE PICKED UP WITH "MOVEI"
PRVSTMNT[FLCWD]_0; !TURN OFF FLAG FOR "USE AOBJN FORM"
PRVSTMNT[SSIZONE]_1; ! AND IN ITS PLACE, LEAVE FLAG FOR
! "STEP SIZE IS 1"
PRVSTMNT[DOCREG]_ !PICK A FREE REG TO USE FOR THE CT
AFREEREG(CLRBIT(.STBSYR,.PRVSTMNT[DOIREG]),FALSE,FALSE);
END
END;
RETURN !POINTING TO THE STATEMENT AFTER THE DO STATEMENT
END;
BLKISN_.BLKISN+1; !INCR VAL OF "BLOCK INTERNAL SEQ NUMBER"
END; !END OF WALK THRU STMNTS
END; !END OF ROUTINE "ALC BLOCK"
GLOBAL ROUTINE AFREEREG (BSYREGS,BLKFLG,DOUBLFLG)=
%(**********
ROUTINE TO RETURN A REGISTER (OR REGISTER PAIR) TO BE USED FOR A GIVEN COMPUTATION.
THE PARAMETERS FOR THIS ROUTINE ARE:
1. BSYREGS-SPECIFIES REGISTERS THAT IT IS POSSIBLE TO USE. THAT IS, REGISTERS THAT
ARE NOT EITHER:
A. HOLDING INTERMEDIATE RESULTS IN THIS STATEMENT
B. ALLOCATED BY THE GLOBAL REGISTER ALLOCATOR
THE BITS IN BSYREGS EACH REPRESENT A REGISTER. IF A BIT IS ZERO THE CORRESPONDING
REGISTER IS NOT AVAILABLE.
2. BLKFLG-IF THIS FLAG IS "TRUE," THE REGISTER TO BE RETURNED WILL BE USED TO
HOLD A VALUE THAT WILL BE PRESERVED OVER SUCCEEDING STATEMENTS IN THIS BASIC BLOCK
3. DOUBLFLG-SPECIFIES WHETHER A SINGLE REGISTER OR A REGISTER PAIR IS REQUIRED
THIS ROUTINE USES THE GLOBAL "BLOCKBSYREGS" WHICH SPECIFIES REGISTERS THAT WE PREFER TO
NOT USE BECAUSE THEIR CONTENTS WILL BE NEEDED LATER IN THIS BASIC BLOCK. THE
FORMAT OF "BLOCKBSYREGS" IS SIMILAR TO THAT OF "BSYREGS" (I.E. IF A BIT IS ZERO, THE
CORRESPONDING REGISTER SHOULD PREFERABLY NOT BE USED).
WHEN ALL REGISTERS ARE BUSY AND HENCE SOME REGISTER FROM "BLOCKBSYREGS" MUST
BE USED, WE SELECT THE REGISTER WHOSE NEXT USE IS THE FURTHEST IN THE
FUTURE. THE "REGSTATE" TABLE CONTAINS THE INTERNAL SEQUENCE NUMBER
OF THE NEXT USE OF EACH REGISTER THAT BLOCKBSYREGS INDICATES SHOULD BE PRESERVED.
**********)%
BEGIN
EXTERNAL BLOCKBSYREGS; !SPECIFIES REGISTERS WHOSE CONTENTS WILL BE NEEDED LATER
!IN THIS BASIC BLOCK.
REGISTER BESTREGS; !REGISTERS THAT ARE AVAILABLE ACCORDING TO "BSYREGS" AND
!NOT OF FUTURE USE IN THIS BASIC BLOCK
OWN RGTOUSE; !REGISTER WHOSE NEXT USE IS FURTHEST IN THE FUTURE
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
ROUTINE PAIRREGS(BSYRG1)=
%(**********
GIVEN A BIT PATTERN "BSYRG1" IN WHICH ZEROES REPRESENT REGISTERS THAT ARE
BUSY AND ONES REPRESENT REGISTERS THAT ARE FREE, THIS ROUTINE RETURNS
A BIT PATTERN IN WHICH ZEROES REPRESENT REGISTERS FOR WHICH THE OTHER
HALF OF THEIR EVEN-ODD PAIR IS BUSY AND ONES REPRESENT REGISTERS
FOR WHICH THE OTHER HALF OF THEIR EVEN-ODD PAIR IS FREE.
FOR BOTTOMMOST FUNCTIONS, BIT 0 OF EACH BIT PATTERN REPRESENTS REGISTER 2
BIT 1 REPRESENTS REGISTER 3, ETC. FOR NON-BOTTOMMOST FUNCTIONS, BIT
0 REPRESENTS REGISTER 15, BIT 1 REGISTER 14, ETC.
HENCE FOR BOTH NON-BOTTOMMOST FUNCTIONS AND BOTTOMMOST FUNCTIONS,
THE BIT PAIRS 0-1, 2-3, 4-5, ETC CORRESPOND TO THE REGISTER
PAIRS 2-3 (OR 14-15), 4-5 (OR 12-13), ETC
**********)%
(
((.BSYRG1 AND #525252525252)^(-1)) !THE ODD REGS CORRESP TO FREE EVEN REGS;
OR
((.BSYRG1 AND #252525252525)^1) !THE EVEN REGS CORRESPTO FREE ODD REGS;
);
%(***DETERMINE WHICH REGISTERS ARE FREE**)%
BESTREGS_(IF .DOUBLFLG !FOR DOUBLE-PRECISION, MUST
THEN (.BSYREGS AND DPBSYREGS(.BLOCKBSYREGS)) !CONVERT BLOCKBSYREGS TO DP MODE
ELSE (.BSYREGS AND .BLOCKBSYREGS));
IF .BESTREGS NEQ 0
THEN
%(****IF THERE ARE SOME FREE REGISTERS****)%
BEGIN
IF .DOUBLFLG !IF ARE CONSIDERING REGISTER PAIRS ALREADY,
THEN RETURN FIRSTONE(.BESTREGS) !SIMPLY RETURN THE FIRST AVAILABLE PAIR
ELSE
%(***IF A SINGLE REGISTER IS BEING USED, TRY TO USE SINGLE REGISTERS WHOSE
ADJACENT REGISTERS ARE ALREADY IN USE***)%
BEGIN
REGISTER VERYBESTREGS;
IF .BLKFLG !IF THIS REGISTER IS TO BE PRESERVED ACROSS SOME FUTURE
THEN !STATEMENTS
BEGIN
VERYBESTREGS_.BESTREGS AND !IF THERE ARE ANY FREE REGISTERS FOR WHICH THE
NOT PAIRREGS(.BLOCKBSYREGS); !OTHER HALF OF THEIR EVEN-ODD PAIR IS ALREADY
IF .VERYBESTREGS NEQ 0 !HOLDING A VALUE FOR FUTURE STATEMENTS, USE ONE OF THEM
THEN
BESTREGS_.VERYBESTREGS
END;
VERYBESTREGS_.BESTREGS AND !IF THERE ARE ANY FREE REGISTERS FOR WHICH THE OTHER
NOT PAIRREGS(.BSYREGS); !HALF OF THEIR EVEN-ODD PAIR IS ALREADY HOLDING
IF .VERYBESTREGS NEQ 0 !A VALUE ACROSS THIS STATEMENT, USE ONE OF THEM
THEN
BESTREGS_.VERYBESTREGS;
RETURN FIRSTONE(.BESTREGS)
END
END
ELSE
%(***IF THERE ARE NO FREE REGISTERS, THEN MUST USE ONE OF THE REGISTERS THAT HOLDS A
VALUE OF FUTURE USE (I.E. A REGISTER IN BLOCKBSYREGS). PICK THE REGISTERS WHOSE
NEXT USE IS FURTHEST AWAY
****)%
BEGIN
REGISTER MAXNXUSE;
IF .DOUBLFLG
THEN
%(***IF NEED TO GET A REGISTER PAIR***)%
BEGIN
REGISTER NXPAIRUSE; !THE ISN OF THE NEXT STATEMENT AT WHICH EITHER REG IN A PAIR IS USED
%(***WALK THRU THE REGISTER-STATE TABLE TO FIND THE REGISTER PAIR WHOSE NEXT USE
IS THE FURTHEST AWAY***)%
MAXNXUSE_0;
INCR REG FROM #2 TO #14 BY 2
DO
BEGIN
IF .REGSTATE[.REG,RGNXUSE] LSS .BLKISN !IF THE "NEXT USE" OF THIS
AND .REGSTATE[.REG+1,RGNXUSE] LSS .BLKISN ! REG HAS ALREADY
! BEEN PASSED
AND BITSET(.BSYREGS,.REG) !THEN IF THIS REG IS
!LEGAL TO USE, USE IT
THEN RETURN .REG;
NXPAIRUSE_(IF .REGSTATE[.REG,RGNXUSE] EQL 0 !IF THE EVEN REGISTER HAS NO FUTURE USE, THEN
THEN .REGSTATE[.REG+1,RGNXUSE] !THE NEXT USE IS THE NEXT USE FOR THE ODD REG
ELSE IF .REGSTATE[.REG+1,RGNXUSE]EQL 0 !IF THE ODD REGISTER HAS NO FUTURE USE,
THEN .REGSTATE[.REG,RGNXUSE] !THE NEXT USE IS THE NEXT USE FOR THE EVEN REG
ELSE IF .REGSTATE[.REG,RGNXUSE] !IF THE NEXT USE OF THE EVEN REGISTER IS
LEQ .REGSTATE[.REG+1,RGNXUSE] !SOONER THAN THE NEXT USE OF THE ODD REGISTER
THEN .REGSTATE[.REG,RGNXUSE] !THE NEXT USE FOR THE PAIR IS THE NEXT USE FOR THE EVEN REG
ELSE .REGSTATE[.REG+1,RGNXUSE]); !OTHERWISE, IT'S THE NEXT USE FOR THE ODD REG
IF .NXPAIRUSE GTR .MAXNXUSE !IF THE NEXT USE OF THIS PAIR IS
THEN !FURTHER AWAY THAN THE BEST PAIR FOUND
BEGIN !SO FAR,
IF BITSET(.BSYREGS,.REG) !AND THIS PAIR IS A LEGAL ONE TO USE
THEN
BEGIN
MAXNXUSE_.NXPAIRUSE; !THEN USE THIS PAIR
RGTOUSE_.REG
END;
END
END !END OF WALK THRU REGSTATE TABLE FOR PAIRS
END !END OF BLOCK TO FIND A REGISTER PAIR
ELSE
%(***IF NEED A SINGLE REGISTER***)%
BEGIN
%(***WALK THRU THE REGISTER STATE TABLE TO FIND THE REGISTER WHOSE NEXT USE
IS FURTHEST AWAY***)%
MAXNXUSE_0;
INCR REG FROM #2 TO #15 BY 1
DO
BEGIN
IF .REGSTATE[.REG,RGNXUSE] LSS .BLKISN !IF THE "NEXT USE" OF THIS
! REG HAS ALREADY BEEN PASSED
AND BITSET(.BSYREGS,.REG) !THEN IF THIS REG IS LEGAL TO USE
THEN RETURN .REG; !THEN USE THIS REG
IF .REGSTATE[.REG,RGNXUSE] !IF THE NEXT USE OF THIS REG
GTR .MAXNXUSE !IS GREATER THAN THE MAXIMUN FOUND FOR
THEN !ANY REG
BEGIN
IF BITSET(.BSYREGS,.REG) !AND THIS REG IS A LEGAL ONE TO USE
THEN
BEGIN
MAXNXUSE_.REGSTATE[.REG,RGNXUSE]; !USE THIS REG
RGTOUSE_.REG
END
END
END
END; !END OF BLOCK TO FIND A SINGLE REG
IF .MAXNXUSE EQL 0 THEN CGERR(); !IF CAN'T FIND A REG TO USE THAT'S CURRENTLY
!HOLDING A BASIC BLOCK VARIABLE
RETURN .RGTOUSE
END
END; !END OF ROUTINE "AFREEREG"
GLOBAL ROUTINE REGCONTAINING(SYMPTR)=
%(**********
THIS ROUTINE DETERMINES WHETHER THE VALUE OF THE VARIABLE/CONSTANT INDICATED
BY "SYMPTR" IS ALREADY IN SOME REGISTER. IF SO, IT RETURNS THE REGISTER,
IF NOT, IT RETURNS MINUS ONE.
"SYMPTR" POINTS TO THE SYMBOL TABLE OR CONSTANT TABLE ENTRY FOR THE VARIABLE/CONSTANT
**********)%
BEGIN
MAP PEXPRNODE SYMPTR;
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
IF .SYMPTR[OPRCLS] NEQ DATAOPR !IF ARE NOT LOOKING AT A VARIABLE OR CONSTANT
THEN RETURN -1;
IF NOT .SYMPTR[VARINREGFLG] !FLAG IN SYMBOL/CONSTENT TABLE ENTRIES INDICATING
THEN RETURN -1; !THAT VALUE IS IN A REGISTER
INCR REG FROM 0 TO #15 !IF VALUE IS IN A REGISTER, SEARCH THE REGISTER
DO !STATE TABLE TO DETERMINE WHICH REGISTER-FOR
BEGIN !AN EVEN-ODD PAIR WILL FIND THE EVEN REG FIRST
IF .REGSTATE[.REG,RGVAR1] EQL .SYMPTR !IF EITHER OF THE TWO POSSIBLE VARIABLES WHOSE
THEN RETURN .REG; !VALUES ARE IN THIS REG ARE IDENTICAL
IF .REGSTATE[.REG,RGVAR2] EQL .SYMPTR !TO SYMPTR, THEN THIS
THEN RETURN .REG; !IS THE ENTRY DESIRED
END;
CGERR(); !IF THE "VARINREGFLG" WAS SET IN THE SYMBOL TABLE ENTRY, BUT
!THE VARIABLE COULDN'T BE FOUND IN THE REGSTATE TABLE, HAVE A
!COMPILER ERROR
END; !END OF "REGCONTAINING"
GLOBAL ROUTINE VARCLOBB(SYMPTR)=
%(**********
THIS ROUTINE IS CALLED WHEN THE VALUE OF A VARIABLE IS MODIFIED.
IF SOME REGISTER HAS BEEN ASSUMED TO CONTAIN THE VALUE OF THAT VARIABLE,
THEN THAT ASSUMPTION CAN NO LONGER BE MADE.
IF THE VARIABLE IS EQUIVALENCED THEN ALL VARIABLES THAT ARE EQUIVALENCED OR IN
COMMON MUST BE ASSUMED TO BE CLOBBERED
**********)%
BEGIN
MAP PEXPRNODE SYMPTR;
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL BLOCKBSYREGS; !GLOBAL VARIABLE INDICATING WHICH REGS CONTAIN VALUES THAT
!SHOULD BE PRESERVED
IF .SYMPTR[OPRCLS] EQL ARRAYREF !IF AN ARRAY ELEMENT IS BEING CLOBBERED
THEN
BEGIN
REGISTER PEXPRNODE ARRAYNM; !PTR TO SYM TAB ENTRY FOR THE ARRAY NAME
ARRAYNM_.SYMPTR[ARG1PTR];
IF .ARRAYNM[IDATTRIBUT(INEQV)] !IF THE ARRAY IS IN AN EQUIVALENCE STMNT
THEN CLOBBCOMEQV() !MUST ASSUME THAT ALL VARS IN EQUIVALENCE OR
! IN COMMON ARE CLOBBERED
ELSE IF .ARRAYNM[IDATTRIBUT(INCOM)] !IF THE VAR IS IN COMMON
THEN CLOBBEQV() ! MUST ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS
! ARE CLOBBERED
END
ELSE
IF .SYMPTR[OPRCLS] EQL DATAOPR !IF ITS A SIMPLE VAR THAT'S BEING CLOBBERED
AND .SYMPTR[OPR1] NEQ CONSTFL
THEN
BEGIN
IF .SYMPTR[IDATTRIBUT(INEQV)] !IF THIS VAN IS EQUIVALENCED
THEN CLOBBCOMEQV() !ASSUME THAT ALL VARS IN EQUIVALENCE OR COMMON
!STMNTS HAVE BEEN CLOBBERED
ELSE
IF .SYMPTR[VARINREGFLG] !IF SOME REG IS ASSUMED TO CONTAIN THE VAL OF
THEN !THIS VARIABLE
BEGIN
SYMPTR[VARINREGFLG]_0; !CAN NO LONGER ASSUME THAT THIS VAR IS IN A REG
%(***SEARCH THE REGSTATE TABLE FOR THE ENTRY FOR THIS VARIABLE AND CLEAR THAT ENTRY**)%
INCR REG FROM 0 TO #15
DO
BEGIN
IF .REGSTATE[.REG,RGVAR1] EQL .SYMPTR !IF THIS IS THE REG THAT CONTAINED "SYMPTR"
THEN !CLEAR ITS ENTRY IN THE REGSTATE TABLE
BEGIN
REGSTATE[.REG,RGVAR1]_0;
IF .REGSTATE[.REG,RGVAR2] EQL 0 !IF "SYMPTR" WAS THE ONLY VARIABLE
THEN !IN THIS REG, THEN RETURN THIS
BEGIN !REG TO THE SET OF FREE REGISTERS
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END;
END;
IF .REGSTATE[.REG,RGVAR2] EQL .SYMPTR !IF THIS IS THE REG THAT CONTAINED "SYMPTR"
THEN !CLEAR ITS ENTRY
BEGIN
REGSTATE[.REG,RGVAR2]_0;
IF .REGSTATE[.REG,RGVAR1] EQL 0 !IF "SYMPTR" WAS THE ONLY VARIABLE
THEN !IN THIS REG, THEN RETURN THIS
BEGIN !REG TO THE SET OF FREE REGISTERS
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END;
END;
END; !END OF INCR LOOP
END; !END OF BLOCK FOR SYMPTR KNOWN TO BE IN A REG
IF .SYMPTR[IDATTRIBUT(INCOM)] !IF SYMPTR IS IN COMMON
THEN CLOBBEQV(); ! MUST ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS
! ARE CLOBBERED
END !END OF BLOCK FOR "SYMPTR" A SIMPLE VARIABLE
END; !END OF ROUTINE "VARCLOBB"
GLOBAL ROUTINE CLOBBCOMEQV=
%(**********
ROUTINE TO ASSUME THAT ALL VARIABLES IN COMMON AND ALL VARIABLES
THAT ARE EQUIVALENCED TO ANYTHING HAVE HAD THEIR VALUES MODIFIED.
REMOVES FROM THE REGSTATE TABLE ALL VARIABLES WHICH ARE IN COMMON OR HAVE
BEEN EQUIVALENCED
**********)%
BEGIN
REGISTER PEXPRNODE SYMENTRY; !POINTER TO SYMBOL/CONSTANT TABLE ENTRY FOR
!THE VARIABLE IN A GIVEN REGISTER
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL BLOCKBSYREGS; !GLOBAL VARIABLE INDICATING WHICH REGS CONTAIN VALUES THAT
!SHOULD BE PRESERVED
ROUTINE COMOREQV=
%(**********
LOCAL ROUTINE TO TEST WHETHER "SYMENTRY" POINTS TO A SYMBOL
TABLE ENTRY FOR A VARIABLE THAT OCCURS IN A COMMON OR
EQUIVALENCE STATEMENT
**********)%
BEGIN
IF .SYMENTRY[OPR1] EQL CONSTFL !IF SYMENTRY IS NOT A SYMBOL TABLE ENTRY
THEN FALSE !(I.E. IS A CONSTANT TABLE ENTRY)
ELSE
(.SYMENTRY[IDATTRIBUT(INEQV)] !FLAG FOR "VARIABLE IS IN AN EQUIVALENCE STMNT"
OR
.SYMENTRY[IDATTRIBUT(INCOM)] !FLAG FOR "VARIABLE IS IN A COMMON STMNT"
)
END; !END OF "COMOREQV"
INCR REG FROM 0 TO #15 !LOOK AT THE REGSTATE TABLE ENTRY FOR EACH REG
DO
BEGIN
IF (SYMENTRY_.REGSTATE[.REG,RGVAR1]) NEQ 0 !ONE OF THE VARIABLES IN THIS REGISTER
THEN
BEGIN
IF COMOREQV() !IF VARIABLE IS IN COMMON OR IS EQUIVALENCED
THEN
BEGIN
SYMENTRY[VARINREGFLG]_0;
REGSTATE[.REG,RGVAR1]_0; !CLEAR ENTRY INDICATING THAT CONTAINS VAL OF THIS VAR
IF .REGSTATE[.REG,RGVAR2] EQL 0 !IF THIS REG NO LONGER CONTAINS ANY VARIABLES,
THEN !RETURN IT TO THE SET OF AVAILABLE REGS
BEGIN
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END
END
END;
IF (SYMENTRY_.REGSTATE[.REG,RGVAR2]) NEQ 0 !POSSIBLY A SECOND VARIABLE WHOSE VALUE IS
THEN !IN "REG" (E.G. FOR A=B, FOTH A AND B
BEGIN !ARE IN THE SAME REG)
IF COMOREQV() !IF VARIABLE IS IN COMMON OR IS EQUIVALENCED
THEN
BEGIN
SYMENTRY[VARINREGFLG]_0;
REGSTATE[.REG,RGVAR2]_0; !CLEAR ENTRY INDICATING THAT "REG" CONTAINS VAL OF THIS VARIABLE
IF .REGSTATE[.REG,RGVAR1] EQL 0 !IF THIS REG NO LONGER CONTAINS ANY VARIABLES
THEN !RETURN IT TO THE SET OF AVAILABLE REGS
BEGIN
REGSTATE[.REG,RGNXUSE]_0;
BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)
END
END
END
END
END; !END OF "CLOBBCOMEQV"
GLOBAL ROUTINE CLOBBEQV=
%(***************************************************************************
ROUTINE TO ASSUME THAT ALL VARS IN EQUIVALENCE STMNTS ARE CLOBBERED.
REMOVES FROM THE REGSTATE TABLE ALL VARS THAT ARE IN EQUIVALENCE STMNTS;
***************************************************************************)%
BEGIN
REGISTER PEXPRNODE SYMENTRY; !PTR TO SYMBOL/CONST TABLE ENTRY FOR THE
! VAR IN A GIVEN REG
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARS ARE IN WHICH REGS
EXTERNAL BLOCKBSYREGS; !BIT PATTERN INDICATING WHICH REGS ARE IN USE
! BY THE BASIC BLOCK ALLOCATOR
INCR REG FROM 0 TO #15 !LOOK AT THE ENTRY FOR EACH REG
DO
BEGIN
IF (SYMENTRY_.REGSTATE[.REG,RGVAR1]) NEQ 0 !ONE OF THE VARS IN THIS REG
THEN
BEGIN
IF .SYMENTRY[OPR1] NEQ CONSTFL
AND .SYMENTRY[IDATTRIBUT(INEQV)] !IF THIS VAR IS IN AN EQUIVALENCE
THEN
(SYMENTRY[VARINREGFLG]_0; REGSTATE[.REG,RGVAR1]_0); !CAN NO LONGER ASSUME THAT ITS VAL
! IS IN REG
END;
IF (SYMENTRY_.REGSTATE[.REG,RGVAR2]) NEQ 0 !A 2ND VAR IN THIS REG
THEN
BEGIN
IF .SYMENTRY[OPR1] NEQ CONSTFL
AND .SYMENTRY[IDATTRIBUT(INEQV)] !IF THIS VAR IS IN EQUIVALENCE
THEN
(SYMENTRY[VARINREGFLG]_0; REGSTATE[.REG,RGVAR2]_0); !REMOVE ITS VAL FROM REG
END;
IF .REGSTATE[.REG,RGVAR1] EQL 0 AND .REGSTATE[.REG,RGVAR2] EQL 0 !IF THIS REG NOW
! CONTAINS NO KNOWN VALS
THEN
(REGSTATE[.REG,RGNXUSE]_0; BLOCKBSYREGS_SETBIT(.BLOCKBSYREGS,.REG)); !RETURN IT TO SET
! OF FREE REGISTERS
END !END OF INCR LOOP
END; !END OF ROUTINE CLOBBEQV
GLOBAL ROUTINE REGCLOBB(REG)=
%(**********
THIS ROUTINE IS CALLED WHENEVER THE CONTENTS OF A REGISTER ARE CLOBBERED.
THIS ROUTINE CLEARS THE REGSTATE TABLE ENTRY FOR THE REGISTER "REG".
IF ANY VARIABLES HAVE BEEN ASSUMED TO BE IN REG IT CLEARS THE "VARINREGFLG"
FOR THOSE VARIABLES
IT ALSO SETS THE BIT CORRESPONDING TO THE REGISTER CLOBBERED
IN THE GLOBAL "CLOBBREGS" WHICH IS USED TO DETERMINE WHICH REGS
TO SAVE AND RESTORE IN A FUNCTION
**********)%
BEGIN
REGISTER PEXPRNODE SYMPTR; !POINTER TO SYMBOL TABLE OR CONSTANT TABLE ENTRY FOR
!VARIABLE/CONSTANT WHOSE VALUE IS IN REG
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL BLOCKBSYREGS; !GLOBAL VARIABLE INDICATING REGS THAT SHOULD
!BE PRESERVED IF POSSIBLE
EXTERNAL CLOBBREGS; !GLOBAL IN WHICH THE BIT CORRESPONDING TO
! EACH REG CLOBBERED BY A GIVEN SUBPROGRAM
! IS SET (USED TO DETERMINE WHICH REGS TO SAVE/RESTORE)
ROUTINE CLRVAR1FIELD(RG)=
%(**********
ROUTINE TO CLEAR THE "RGVAR1" FIELD OF A REGSTATE TABLE
ENTRY AND IF THE "RGVAR2" FIELD IS ALSO 0, TO RETURN THE
REGISTER TO THE SET OF FREE REGS
***********)%
BEGIN
REGSTATE[.RG,RGVAR1]_0;
IF .REGSTATE[.RG,RGVAR2] EQL 0 !IF THERE IS NOT ANOTHER VAR IN THIS REG
THEN
BEGIN
REGSTATE[.RG,RGNXUSE]_0; !"LOC OF NEXT USE"
BLOCKBSYREGS_ !RETURN "RG" TO SET OF FREE REGS
SETBIT(.BLOCKBSYREGS,.RG)
END
END;
ROUTINE CLRVAR2FIELD(RG)=
%(**********
ROUTINE TO CLEAR THE "RGVAR2" FIELD OF A REGSTATE TABLE
ENTRY AND IF THE "RGVAR1" FIELD IS ALSO 0, TO RETURN THE
REGISTER TO THE SET OF FREE REGS
***********)%
BEGIN
REGSTATE[.RG,RGVAR2]_0;
IF .REGSTATE[.RG,RGVAR1] EQL 0 !IF THERE IS NOT ANOTHER VAR IN THIS REG
THEN
BEGIN
REGSTATE[.RG,RGNXUSE]_0; !"LOC OF NEXT USE"
BLOCKBSYREGS_ !RETURN "RG" TO SET OF FREE REGS
SETBIT(.BLOCKBSYREGS,.RG)
END
END;
%[632]% ROUTINE CHKOTHREGS(SYM,RG)=
%[632]% %(***********
[632] ROUTINE TO CLEAR THE VARINREGFLG FOR SYM IFF SYM IS
[632] ONLY IN REGISTER RG. THIS KEEPS VARINREGFLG SET IF
[632] SOME REG CONTAINING SYM IS CLOBBERED, BUT SYM IS
[632] STILL IN OTHER REG(S).
[632] ************)%
%[632]% BEGIN
%[632]%
%[632]% MAP PEXPRNODE SYM; !THE VAR IN REGISTER RG
%[632]% MAP RGSTBL REGSTATE; !THE REG STATE TABLE
%[632]%
%[632]% REGISTER REGX; !INDEX FOR LOOP BELOW
%[632]%
%[632]% SYM[VARINREGFLG]_0; !ASSUME NOT IN ANY OTHER REG
%[632]%
%[632]% REGX_0;
%[632]% WHILE (.REGX LEQ #15) AND NOT .SYM[VARINREGFLG]
%[632]% DO
%[632]% BEGIN
%[632]% IF .REGX NEQ .RG
%[632]% THEN
%[632]% IF .REGSTATE[.REGX,RGVAR1] EQL .SYM
%[632]% OR .REGSTATE[.REGX,RGVAR2] EQL .SYM
![652] MUST BE CAREFUL IF THE VARIABLE WAS DOUBLE WORD IN WHICH
![652] CASE WE NEED TO FIND A REG FAR AWAY (MORE THAN 1)
%[652]% THEN IF NOT .SYM[DBLFLG] THEN SYM[VARINREGFLG]_1
%[652]% ELSE IF (.REGX+1 NEQ .RG) AND (.REGX-1 NEQ .RG)
%[652]% THEN SYM[VARINREGFLG]_1;
%[632]% REGX_.REGX+1
%[632]% END
%[632]% END;
IF .REG GEQ 2 !UNLESS THE REG IS 0 OR 1 (WHICH ARE NEVER SAVE/RESTORED ACROSS A FN)
THEN ! SET THE BIT CORRESPONDING TO THAT REG IN THE GLOBAL USED TO KEEP
CLOBBREGS_ ! TRACK OF ALL REGS THAT MUST BE SAVE/RESTORED
SETBIT(.CLOBBREGS,.REG);
IF (SYMPTR_.REGSTATE[.REG,RGVAR1]) NEQ 0 !IF SOME VARIABLE IS ASSUMED TO
THEN !BE IN "REG"
BEGIN
%[632]% CHKOTHREGS(.SYMPTR,.REG); !CLEAR VARINREGFLG IF NECESSARY
IF .SYMPTR[DBLFLG] !IF THE VAR IS DP OR COMPLEX
THEN !MUST CLEAR THE ENTRY FOR THE OTHER HALF OF THE VAR
BEGIN !WHICH IS IN A REG ADJACENT TO "REG"
IF .REGSTATE[.REG+1,RGVAR1] EQL .SYMPTR !IF "REG" WAS THE 1ST HALF
THEN CLRVAR1FIELD(.REG+1) !CLEAR ENTRY IN NEXT REG
ELSE
IF .REGSTATE[.REG-1,RGVAR1] EQL .SYMPTR !IF "REG" WAS THE 2ND HALF
THEN CLRVAR1FIELD(.REG-1) !CLEAR ENTRY IN PREVIOUS REG
ELSE !(IF "RGVAR1" FIELD WAS USED FOR A GIVEN VAR
! IN ONE REG, CAN ASSUME THAT "RGVAR1" FIELD WILL
! ALSO BE USED FOR THE OTHER HALF OF THE VAR)
CGERR() !IF CANT FIND ENTRY FOR THE OTHER HALF OF THE VAR
END
END;
IF (SYMPTR_.REGSTATE[.REG,RGVAR2]) NEQ 0 !IF SOME SECOND VARIABLE IS ASSUMED
THEN !TO BE IN "REG" (E.G. IF HAD "A=B")
BEGIN
%[632]% CHKOTHREGS(.SYMPTR,.REG); !CLEAR VARINREGFLG IF NEEDED
IF .SYMPTR[DBLFLG] !IF THE VAR IS DP OR COMPLEX
THEN !MUST CLEAR THE ENTRY FOR THE OTHER HALF OF THE VAR
BEGIN !WHICH IS IN A REG ADJACENT TO "REG"
IF .REGSTATE[.REG+1,RGVAR2] EQL .SYMPTR !IF "REG" WAS THE 1ST HALF
THEN CLRVAR2FIELD(.REG+1) !CLEAR ENTRY IN NEXT REG
ELSE
IF .REGSTATE[.REG-1,RGVAR2] EQL .SYMPTR !IF "REG" WAS THE 2ND HALF
THEN CLRVAR2FIELD(.REG-1) !CLEAR ENTRY IN PREVIOUS REG
ELSE !(IF "RGVAR2" FIELD WAS USED FOR A GIVEN VAR
! IN ONE REG, CAN ASSUME THAT "RGVAR2" FIELD WILL
! ALSO BE USED FOR THE OTHER HALF OF THE VAR)
%[1024]% IF .SYMPTR[VALTYPE] NEQ LITERAL ! IF THE "VAR" IS
%[1024]% ! A LITERAL THAT WAS ASSIGNED TO
%[1024]% ! A REAL, ONLY THE 1ST WORD WILL
%[1024]% ! BE IN AN AC
%[1024]% THEN !OTHERWISE, WE SHOULD HAVE FOUND
! AC THAT CONTAINED THE OTHER WORD
CGERR() !IF CANT FIND ENTRY FOR THE OTHER HALF OF THE VAR
END
END;
BLOCKBSYREGS_ !RETURN "REG" TO THE SET
SETBIT(.BLOCKBSYREGS,.REG); !OF FREE REGISTERS
REGSTATE[.REG,RGVAR1]_0; !CLEAR REGSTATE TABLE
REGSTATE[.REG,RGVAR2]_0; !ENTRY FOR REG
REGSTATE[.REG,RGNXUSE]_0;
END;
GLOBAL ROUTINE CLRRGSTATE=
%(**********
THIS ROUTINE CLEARS THE REGSTATE TABLE. IT IS CALLED AT THE END OF REGISTER ALLOCATION
FOR A BASIC BLOCK (WHEN ALL ASSUMPTIONS ABOUT THE CONTENTS OF REGISTERS
MUST BE DISCARDED)
**********)%
BEGIN
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL BLOCKBSYREGS; !THIS WORD CONTAINS A BIT PATTERN IN WHICH ONES REPRESENT
!REGISTERS THAT ARE FREE, ZEROES REPRESENT REGISTERS WHOSE
!CONTENTS WILL BE NEEDED LATER IN THIS BASIC BLOCK
REGISTER PEXPRNODE SYMPTR; !POINTER TO SYMBOL/CONSTANT TABLE ENTRY FOR A VARIABLE/CONSTANT
!WHICH IS ASSUMED TO HAVE BEEN LEFT IN SOME REGISTER
DECR REG FROM #15 TO 0 !WALK THRU THE REGSTATE TABLE
DO
BEGIN
IF (SYMPTR_.REGSTATE[.REG,RGVAR1]) NEQ 0 !A VARIABLE WHOSE VALUE IS ASSUMED TO BE IN "REG"
THEN
BEGIN
SYMPTR[VARINREGFLG]_0; !CAN NO LONGER ASSUME THAT THAT VAR IS IN A REG
REGSTATE[.REG,RGVAR1]_0;
END;
IF (SYMPTR_.REGSTATE[.REG,RGVAR2]) NEQ 0 !A SECOND VARIABLE WHOSE VALUE IS ASSUMED TO BE IN "REG"
THEN
BEGIN
SYMPTR[VARINREGFLG]_0; !CAN NO LONGER ASSUME THAT THAT VAR IS IN A REG
REGSTATE[.REG,RGVAR2]_0;
END;
REGSTATE[.REG,RGNXUSE]_0; !ISN OF NEXT USE OF THES REG SET TO 0 (MEANING
END; !END OF DECR LOOP !NO FUTURE USE)
BLOCKBSYREGS_-1; !ALL REGS ARE NOW AVAILABLE
END; !END OF CLRRGSTATE
GLOBAL ROUTINE INIRGSTATE=
%(**********
THIS ROUTINE INITS THE REGISTER STATE TABLE BY ZEROING ALL
ENTRIES.
*********)%
BEGIN
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL BLOCKBSYREGS; !GLOBAL INDICATING WHICH REGS CONTAIN VALS OF
! FUTURE USE IN THIS BASIC BLOCK (AND HENCE
! HAVE ENTRIES IN THE REGSTATE TABLE)
DECR REG FROM #15 TO 0 !CLEAR THE ENTRY FOR EACH REG
DO
BEGIN
REGSTATE[.REG,RGVAR1]_0; !CLEAR ALL FIELDS OF THE ENTRY
REGSTATE[.REG,RGVAR2]_0;
REGSTATE[.REG,RGNXUSE]_0;
END;
BLOCKBSYREGS_-1; !THIS WORD WILL HAVE THE BIT CORRESPONDING TO EACH
! BUSY REG SET TO 0. INIT IT TO HAVE
! NO BITS SET TO 0
END; !END OF INIRGSTATE
GLOBAL ROUTINE SAVEREG(REG,SYMENT1,SYMENT2,USEISN)=
%(**********
THIS ROUTINE IS CALLED WHEN IT IS DETERMINED THAT THE REGISTER "REG"
SHOULD BE PRESERVED OVER FUTURE STATEMENTS IN THE CURRENT BASIC BLOCK.
SYMENT1 IS A POINTER TO THE SYMBOL/CONSTANT TABLE ENTRY FOR THE VARIABLE/CONSTANT
WHOSE VALUE IS IN REG. SYMENT2 IS A POINTER TO A POSSIBLE SECOND SYMBOL/CONSTANT
TABLE ENTRY. USEISN IS THE ISN OF THE NEXT USE OF THE VALUE IN REG.
********)%
BEGIN
MAP PEXPRNODE SYMENT1;
MAP PEXPRNODE SYMENT2;
MAP RGSTBL REGSTATE; !TABLE INDICATING WHICH VARIABLES/CONSTANTS ARE IN WHICH REGISTERS
EXTERNAL BLOCKBSYREGS; !BIT PATTERN IN WHICH ZEROES REPRESENT REGISTERS
!WHOSE VALUES ARE TO BE PRESERVED
EXTERNAL NOBBREGSLOAD; !FLAG INDICATING THE BB ALLOCATOR CANNOT ASSUME
! THAT THE CODE FOR THE EXPRESSION CURRENTLY BEING
! PROCESSED WILL ALWAYS BE EXECUTED AND
! HENCE THAT WE CANNOT ASSUME THAT REGS LOADED
! IN PROCESSING THIS EXPR HAVE THE VALS INDICATED
! (E.G. THIS FLAG IS SET WHEN PROCESSING A LOG IF)
IF .NOBBREGSLOAD !IF CANNOT ASSUME THAT THE CODE FOR THIS EXPR WILL
THEN ! ALWAYS BE EXECUTED, THEN CANNOT KEEP THIS VAL IN THIS REG
RETURN;
IF .SYMENT2 EQL 0 !IF ARE ONLY TRYING TO REMEMBER 1 VAR
AND (.REGSTATE[.REG,RGVAR1] EQL .SYMENT1 ! AND WE ALREADY KNEW THAT THIS
OR .REGSTATE[.REG,RGVAR2] EQL .SYMENT1) ! VAR WAS IN THIS REG
THEN
BEGIN
REGSTATE[.REG,RGNXUSE]_.USEISN; !UPDATE VAL FOR "NEXT USE"
IF .SYMENT1[DBLFLG] !IF ARE SAVING A REG PAIR
THEN REGSTATE[.REG+1,RGNXUSE]_.USEISN; !UPDATE "NXT USE"FOR 2ND HALF
END
ELSE
BEGIN
REGCLOBB(.REG); !IF THIS ENTRY ALREADY CONTAINED
! VARS FORGET ABOUT THEM
REGSTATE[.REG,RGVAR1]_.SYMENT1; !SET UP THE REGSTATE TABLE ENTRY FOR THIS REG
REGSTATE[.REG,RGVAR2]_.SYMENT2;
REGSTATE[.REG,RGNXUSE]_.USEISN;
IF .SYMENT1[DBLFLG] !IF THE VALUE TO BE PRESERVED IS DOUBLE PREC OR COMPLEX
THEN
BEGIN
REGSTATE[.REG+1,RGVAR1]_.SYMENT1; !SET UP REGSTATE TABLE ENTRY FOR THE REG FOLLOWING THIS REG
REGSTATE[.REG+1,RGVAR2]_.SYMENT2;
REGSTATE[.REG+1,RGNXUSE]_.USEISN;
END;
END;
BLOCKBSYREGS_CLRBIT(.BLOCKBSYREGS,.REG); !TURN OFF BIT IN BLOCKBSYREGS CORRESPONDING
!TO THIS REG TO INDICATE IT SHOULD
!BE PRESERVED
IF .SYMENT1[DBLFLG] !IF ARE SAVING A REG PAIR
THEN
BLOCKBSYREGS_CLRBIT(.BLOCKBSYREGS,.REG+1); !CLEAR BIT IN BLOCKBSYREGS TO INDICATE
!THAT REG AFTER "REG" MUST BE
!PRESERVED
SYMENT1[VARINREGFLG]_1; !SET FLAG IN SYMBOL/CONST TABLE ENTRY INDICATING THAT THIS
!VAR IS IN SOME REG
IF .SYMENT2 NEQ 0 !IF A SECOND VARIABLE IS ALSO IN THIS REG (EG FOR A=B)
THEN
SYMENT2[VARINREGFLG]_1; !SET FLAG IN ITS SYMBOL TABLE ENTRY AS WELL
END; !END OF ROUTINE SAVEREG
GLOBAL ROUTINE FREEPAIRS(BSYREGS)=
%(***************************************************************************
GIVEN A BIT PATTERN "BSYREGS" IN WHICH 0'S INDICATE BUSY REGS AND
1'S INDICATE FREE REGS, THIS ROUTINE RETURNS THE NUMBER
OF EVEN-ODD REG PAIRS THAT ARE FREE
***************************************************************************)%
BEGIN
RETURN ONESCOUNT(
(.BSYREGS AND #525252525252)^(-1) !BITS FOR FREE EVEN REGISTERS
! SHIFTED RIGHT TO INDICATE ODD REG FOLLOWING EACH
AND
(.BSYREGS AND #252525252525) !BITS FOR FREE ODD REGISTERS
)
END;
!END OF "SAVEREG"