Trailing-Edge
-
PDP-10 Archives
-
decuslib10-04
-
43,50325/final.bli
There are 11 other files named final.bli in the archive. Click here to see a list.
! File: FINAL.BLI
!
! This work was supported by the Advanced Research
! Projects Agency of the Office of the Secretary of
! Defense (F44620-73-C-0074) and is monitored by the
! Air Force Office of Scientific Research.
MODULE FINAL(TIMER=EXTERNAL(SIX12))=
BEGIN
! FINAL MODULE
! ------------
!
! J. APPERSON
! S. HOBBS
!
!
SWITCHES NOLIST;
REQUIRE COMMON.BEG;
SWITCHES LIST;
REQUIRE JBEG.BEG;
EXTERNAL
BRAK1,
BRAK2,
CHANGE,
NLHEAD;
EXTERNAL ! THESE USED TO BE FORWARD
GETCELL,
NEWCODECELL,
NEWLABCELL,
PUSHTOP,
PUSHBOT;
FORWARD
ADRLEN,
ADRSIMP,
AFTER,
BACKEQ,
BACKOV,
BACKSET,
BEFORE,
BRIMPLY,
CELLLENGTH,
CLEARTOLAB,
COMBLAB,
CONDJMPSRC,
DELADR,
DELETE,
DELBACKREF,
DELTST,
DETACH,
DOWNDATE,
DUPADR,
EMPTY,
EMPTYDET,
EQUIVADR,
EQUIVFWD,
EQUIVIND,
ERASE,
ERASEDET,
ERASELIST,
FINAL,
FINAL1,
FINAL2,
FINAL3,
FIXJMPIND,
LABREFED,
LABREFP,
MAKEADR,
MAKEINFLOOP,
MAKELABREF,
MAKEJMP,
MAYPOP,
MAYREFERP,
MAYUSEP,
MVLABREF,
NEWBOT,
NEWLAB,
NEWTOP,
NXTCC,
NXTLCC,
OPTADDSUB,
OPTBIC,
OPTBIS,
OPTBIT,
OPTBOOL,
OPTCLC,
OPTCLR,
OPTCLVC,
OPTCMP,
OPTDEC,
OPTINC,
OPTJSR,
OPTMOV,
OPTTST,
PCASPARAM,
PCONDJMP,
PLAB,
PREVNONBR,
PRVCC,
PRVLCC,
PUNCONDJMP,
REACH,
SAMEADRP,
SAMECMPP,
SAMEINDP,
SETSCC,
TESTCC,
TESTEQL,
TESTPOP,
TESTPP,
TESTPUSH,
UPDATE;
BIND ! A DISPATCH PLIT FOR THE INSTRUCTION-SPECIFIC ROUTINES
NORMALVEC OPTROUTINE = PLIT(
NXTLCC, !UUO
OPTMOV, !MOV
OPTMOV, !MOVB
OPTCMP, !CMP
OPTCMP, !CMPB
OPTBIT, !BIT
OPTBIT, !BITB
OPTBIC, !BIC
OPTBIC, !BICB
OPTBIS, !BIS
OPTBIS, !BISB
OPTADDSUB, !ADD
OPTADDSUB, !SUB
OPTCLR, !CLR
OPTCLR, !CLRB
NXTLCC, !COM
NXTLCC, !COMB
OPTINC, !INC
NXTLCC, !INCB
OPTDEC, !DEC
NXTLCC, !DECB
PTST-PNEG: NXTLCC,
OPTTST, !TST
OPTTST, !TSTB
PJMP-PROR: NXTLCC,
PUNCONDJMP, !JMP
NXTLCC, !SWAB
OPTJSR, !JSR
PBR-PJSR-1: NXTLCC,
PUNCONDJMP, !BR
DELETE, !NBR
PNOP-PBNE: PCONDJMP, !CONDITIONAL BRANCHES
NXTLCC, !NOP
OPTCLC, !CLC
OPTCLVC, !CLVC
NXTLCC, !.WORD
PCASPARAM, !CASEPARAMETER (PCASE)
4:NXTLCC, !MFPI,MFPD,MTPI,MTPD
NXTLCC, !INFLOOPOP
NXTLCC); !SETEQLOP
! EACH OF THE FOLLOWING PLITS RETURNS INFORMATION ABOUT SPECIFIC
! INSTRUCTIONS -- AND IS INDEXED BY INSTRUCTION TYPE.
BIND ! .ALTERSRCDST[.I] <=> INSTRUCTION #I ALTERS ITS SOURCE OR DESTINATION
! WHEN EXECUTED.
NORMALVEC GRUNT1 = PLIT(ALTERSRCDST GLOBALLY NAMES
0, !UUO
1,1, !MOV, MOVB
0,0,0,0, !CMP, CMPB, BIT, BITB
PTST-PBIC: 1, !SINGLE OPERAND OPS
0,0, !TST, TSTB
PJMP-PROR: 1, !MOVE SINGLE OPERAND OPS
0, !JMP
1, !SWAB
INFLOOPOP-PJSR+1: 0,
0); !SETEQLOP
BIND
NORMALVEC GRUNT2 = PLIT(OPBYTES GLOBALLY NAMES
0, !UUO
(PADD-PMOV)/2: (2,1), !DOUBLE OPERAND OPS
2,2, !ADD,SUB
(PJMP-PCLR)/2: (2,1), !SINGLE OPERAND OPS
0, !JMP
2, !SWAB
INFLOOPOP-PJSR+1: 0,
0); !SETEQLOP
BIND
NORMALVEC GRUNT3 = PLIT(OPERTYPE GLOBALLY NAMES
NOOP, !UUO
PCLR-PMOV: TWOOP, !DOUBLE OPERAND OPS
PJMP-PCLR: ONEOP, !SINGLE OPERAND OPS
BROP,ONEOP,JSROP, !JMP,SWAB,JSR
RTSOP,3:NOOP, !RTS,HALT,WAIT,RTI
2:NOOP,2:TRAPOP, !IOT,RESET,EMT,TRAP
PNOP-PBR: BROP, !BRANCH OPS
3:NOOP, !NOP,CLC,CLVC
WORDOP,CASEOP, !.WORD,CASE
4:ONEOP, !MFPI,MFPD,MTPI,MTPD
NOOP,NOOP); !INFLOOPOP,SETEQLOP
MAP NORMALVEC ALTERSRCDST:OPBYTES:OPERTYPE;
BIND ! .STOPFSCAN[.I] <=> INSTRUCTION #I ACTS AS A STOP OR BLOCK
! TO ANY FURTHER FORWARD CODE SCANNING BY VARIOUS ROUTINES,
! GENERALLY BECAUSE OF A POSSIBLE CONTROL TRANSFER.
NORMALVEC STOPFSCAN = PLIT(
1, !UUO
PJMP-PMOV: 0,
1, !JMP
0, !SWAB
1,1,1, !JSR,RTS,HALT
0,1,1, !WAIT,RTI,IOT
0,1,1,1, !RESET,EMT,TRAP,PBR
PWORD-PNBR: 0,
1,1, !.WORD, CASE
4:1, !MFPI,ETC.
1, !INFLOOPOP
0); !SETEQLOP
BIND ! .STOPBSCAN[.I] <=> INSTRUCTION #I ACTS AS A STOP OR BLOCK
! TO ANY FURTHER BACKWARD CODE SCANNING BY VARIOUS ROUTINES,
! GENERALLY BECAUSE OF A POSSIBLE CONTROL TRANSFER.
NORMALVEC STOPBSCAN = PLIT(
1, !UUO
PJMP-PMOV: 0,
1, !JMP
0, !SWAB
1,1, !JSR,RTS
1,0, !HALT, WAIT
1,1, !RTI, IOT
0, !RESET
PNOP-PEMT: 1, !BRANCHES
0,0,0, !NOP, CLC, CLVC
1,1, !.WORD, CASE
4:1, !MFPI, ETC.
1,0); !INFLOOPOP, SETEQLOP
BIND
NCCBIT=#1, !NEGATIVE CCBIT FLAG.
ZCCBIT=#2, !ZERO CCBIT FLAG,
VCCBIT=#4, !OVERFLOW CCBIT FLAG,
CCCBIT=#10, !CARRY CCBIT FLAG,
JCCBIT=#20, !JUMP INSTRUCTION FLAG.
NACBIT=#40; !DOESN'T AFFECT CARRY FLAG.
BIND ! INDICATES FOR EACH INSTRUCTION
! (1) WHAT PDP-11 CONDITION CODES IT USES,
! (2) WHETHER OR NOT IT IS A BRANCH,
! (3) WHETHER OR NOT IT AFFECTS THE CARRY BIT (IF IT'S NOT A BRANCH).
NORMALVEC CCUSETYPE = PLIT(
NCCBIT+ZCCBIT+VCCBIT+CCCBIT+CCSHIFT(NCCBIT+ZCCBIT+VCCBIT+CCCBIT), !UUO
2: NACBIT, ! MOV,MOVB
2: 0, ! CMP,CMPB
PADD-PBIT: NACBIT, ! BIT, BIS, BIC
PINC-PADD: 0, ! ORDINARY DATA OPS
PNEG-PINC: NACBIT, ! INC, DEC
2: 0, ! NEG, NEGB
4:CCCBIT+CCSHIFT(CCCBIT), !ADC AND SBC.
2:0, !TST
4:CCCBIT, !ROR AND ROL
4:0, !ASR, ASL
JCCBIT, !JMP
0, !SWAB
PBR-PJSR:NCCBIT+ZCCBIT+VCCBIT+CCCBIT, !JSR, RTS, TRAP, ETC.
JCCBIT, !BR
NCCBIT+ZCCBIT+VCCBIT+CCCBIT, !NBR
2:ZCCBIT+JCCBIT+CCSHIFT(ZCCBIT), !BNE,BEQ
2:NCCBIT+VCCBIT+JCCBIT+CCSHIFT(NCCBIT+VCCBIT), !BGE, BLT
2:NCCBIT+ZCCBIT+VCCBIT+JCCBIT+CCSHIFT(NCCBIT+ZCCBIT+VCCBIT), !BLE, BGT
2:NCCBIT+JCCBIT+CCSHIFT(NCCBIT), !BPL, BMI
2:ZCCBIT+CCCBIT+JCCBIT+CCSHIFT(ZCCBIT+CCCBIT), !BHI,BLOS
2:VCCBIT+JCCBIT+CCSHIFT(VCCBIT), !BVC,BVS
2:CCCBIT+JCCBIT+CCSHIFT(CCCBIT), !BHIS,BLO
NCCBIT+ZCCBIT+VCCBIT+CCCBIT, !NOP
NCCBIT+ZCCBIT+VCCBIT+CCSHIFT(NCCBIT+ZCCBIT+VCCBIT), !CLC
NCCBIT+ZCCBIT+CCSHIFT(NCCBIT+ZCCBIT), !CLVC
2:NCCBIT+ZCCBIT+VCCBIT+CCCBIT, !WORD,CASE
4:NACBIT, !MFPI, ETC.
2:0); !INFLOOPOP,SETEQLOP
BIND ! .CCSETTYPE[.I] IS A NUMBER INDICATING HOW INSTRUCTION #I
! SETS THE CONDITION CODES. SEE ROUTINE SETSCC.
NORMALVEC CCSETTYPE = PLIT(
0, !UUO
1,1, !MOV
4:0, !CMP,BIT
4:2, !BIT,BIS
3,3, !ADD,SUB
4:4, !CLR,COM
PTST-PINC:5, !SINGLE OPS
4,4, !TST
PJMP-PROR:5, !SINGLE OPS
0, !JMP
4, !SWAB
PNBR-PJSR:0, !SUBROUTINE OPS
PNOP-PNBR:7, !CONDITIONAL BRANCHES
PCASE+1-PNOP:0,
4:6, !MFPI,ETC.
0,0); ! INFLOOPOP,SETEQLOP
! DEFINITIONS FOR "BASE" ADDRESSES
BIND ADRVARSTR PCADR = ADRPLIT(#10,7,UNUSED,NORMNAME,0);
BIND ADRVARSTR IMMEDZERO = ADRPLIT(#12,7,IMMEDAT,NORMNAME,0);
BIND ADRVARSTR IMMEDONE = ADR1PLIT(#12,7,IMMEDAT,NORMNAME,0);
BIND ADRVARSTR MEMADR = ADRPLIT(#16,7,MEMAT,LABELNAME,0);
BIND ADRVARSTR REGADR = ADRPLIT(0,0,REGAT,NORMNAME,0);
BIND ADRVARSTR SPADR = ADRPLIT(0,6,REGAT,NORMNAME,0);
EXTERNAL FINRTNSIZE,PUSHPOPFLAG;
BIND ROUTINESIZE = FINRTNSIZE;
! THIS SECTION CONTAINS THE REAL WORK
! OF FINAL -- CROSS-JUMPS, ETC.
ROUTINE ADRLEN(ADR) =
!
! FUNCTION:
! RETURN THE LENGTH IN WORDS (EITHER 1 OR 0) OF THE PDP-11
! REPRESENTATION OF ADDRESS 'ADR'. HAS AN OPTIMIZATION SIDE EFFECT.
!
BEGIN
IF .ADR[AFORM] EQL 6 AND
.ADR[ANAME] LEQ 1 AND
.ADR[AOFFSET] EQL 0 ! CHANGE 0(REG)
THEN ADR[AFORM]_1; ! TO @REG
RETURN IF ONEOF(.ADR[AFORM],BIT6(6,7,#12,#13,#16,#17)) THEN 1 ELSE 0
END;
ROUTINE ADRSIMP(A) =
!
! MEASURES THE SIMPLICITY OF AN ADDRESS.
! USED BY EQUIVADR AND EQUIVIND.
!
BEGIN
BIND NORMALVEC SIMPLICITY = PLIT(
0,1,0,6,0,0,0,0,0,5,0,5,
16,17,16,17,12,0,14,0,15,13,15,13,
4,10,11,10,3,0,8,0,9,7,9,7);
IF .A[ATYPE] EQL REGAT THEN RETURN 2
ELSF NOT ONEOF(.A[ATYPE],BIT3(IMMEDAT,MEMAT,INDAT)) THEN RETURN 0;
BEGIN
BIND A1 = 1*(.A[AREG] EQL 7);
BIND A2 = 2*(.A[AOFFSET] NEQ 0);
BIND A4 = 4*(IF .A[ANAME] EQL 0 THEN 0
ELSF .A[ANAME] EQL 1 THEN 1
ELSE 2);
BIND A12= 12*(IF .A[ATYPE] EQL IMMEDAT THEN 0
ELSF .A[ATYPE] EQL INDAT THEN 1
ELSE 2);
RETURN .SIMPLICITY[A12 + A4 + A2 + A1]
END
END;
GLOBAL ROUTINE AFTER(C1,C2) = !PLACE UNATTACHED C2 AFTER C1
BEGIN
NEXTPT(.C1)_.C2;
C2[PREVF]_.C1;
C2[NEXTF]_.C1[NEXTF];
C1[NEXTF]_.C2
END;
ROUTINE BACKEQ(A,B,DA,DB) =
!
! TRUE IF ADDRESSES A AND B ARE
! EQUIVALENT ENOUGH TO BE CROSS-JUMPED OVER.
! DA AND DB ARE STACK ADJUSTS (OR ADJUSTS TO OTHER REGISTERS),
! AND THERE MAY BE SIDE-EFFECTS ON THESE.
!
IF .A[ANAMET] EQL NORMNAME THEN
IF .A[ATYPREGNAME] EQL .B[ATYPREGNAME] AND .A[ATYPE] NEQ UNUSED THEN
IF .A[AREG] NEQ SP THEN
.A[AOFFSET] EQL .B[AOFFSET] AND .A[ADELTA] EQL .B[ADELTA]
ELSF AOFFSETV(A) + ..DA EQL AOFFSETV(B) + ..DB THEN
IF .A[ATYPE] EQL REGAT THEN ..DA EQL 0
ELSF ..DA EQL 0 AND ..DB EQL 0 AND .A[ADELTA] EQL .B[ADELTA] THEN 1
ELSE
BEGIN ! MUST CHANGE STACK ADJUSTS, OFFSETS, DELTAS, OR EVEN MODES.
A[AOFFSET]_AOFFSETV(A) + ..DA;
B[AOFFSET]_AOFFSETV(B) + ..DB;
.DA_..DA - ADELTAV(A);
.DB_..DB - ADELTAV(B);
A[ADELTA]_B[ADELTA]_0;
A[AMODE]_IF .A[ATYPE] EQL INDAT THEN 7
ELSF .A[AOFFSET] EQL 0 THEN 1 ELSE 6;
B[AMODE]_IF .B[ATYPE] EQL INDAT THEN 7
ELSF .B[AOFFSET] EQL 0 THEN 1 ELSE 6;
1
END
ELSE 0
ELSE 0
ELSF .A[ANAMET] EQL LABELNAME THEN
IF .B[ANAMET] EQL LABELNAME THEN .ST[.A[ANAME],REFEF] EQL .ST[.B[ANAME],REFEF]
ELSE 0
ELSE 0;
COMMENT ! BACKOV
!
! FUNCTION:
! THIS ROUTINE PERFORMS CROSS-JUMPING. F AND T ARE POINTERS TO
! THE ENDS OF TWO BLOCKS OF CODE (THE "FROM" BLOCK AND THE "TO" BLOCK),
! WHICH JOIN EACH OTHER BY BRANCHING OF SOME SORT.
!
! IDENTIFIERS:
! DF,DT -- (DELTA F, DELTA T) CONTAIN THE AMOUNT THE STACK MUST BE
! ADJUSTED AT THE TOP OF EACH BLOCK.
! SDF,SDT -- BEFORE ATTEMPTING TO BACK OVER A CODE CELL,
! BACKOV SAVES DF & DT IN THESE TWO.
! ADJUST -- THE AMOUNT THE STACK MUST BE ADJUSTED AT THE
! BOTTOM OF THE "TO" BLOCK.
! FLAG -- INITIALLY 1; SET TO 0 AS SOON AS A CELL IS SUCCESSFULLY
! BACKED OVER.
! SKIPFLAG -- IS SET FOR ONE OF TWO REASONS. THE FIRST IS WHEN
! A TWO-WORD STACK ADJUSTMENT IS NECESSARY IF THE
! CURRENT CELL IS TO BE BACKED OVER; THIS PREVENTS
! CROSS-JUMPING FROM LOSING BY INSERTING TWO WORDS
! OF STACK-ADJUSTING CODE TO SAVE ONE WORD OF CROSS-
! JUMPED CODE. THE SECOND REASON HAS TO DO WITH CMU'S
! "HYDRA" ROUTINE LINKAGE, WHICH INVOLVES WORDS OF
! CODE WHICH MUST NOT BE BACKED OVER UNLESS THE PREVIOUS
! WORD CAN BE BACKED OVER.
!
ROUTINE BACKOV(F,T) =
BEGIN
LOCAL ADJUST,DF,DT,SDF,SDT,FINIT,TINIT,FLAG,SKIPFLAG;
LOCAL ADRVARSTR DSTF:DSTT;
FINIT_.F;
TINIT_PRVCC(.T);
SKIPFLAG_0;
FLAG_-1;
F_PRVCC(BACKSET(.F,DF));
T_BACKSET(.T,DT);
T_.T[PREVF];
ADJUST_.DT-.DF;
IF .ADJUST NEQ 0 THEN
IF .ADJUST LSS 0 THEN BEGIN
IF .DF EQL 0 AND .ADJUST LSS -4 THEN SKIPFLAG_-1;
DF_-.ADJUST;
ADJUST_DT_0
END ELSE BEGIN
IF .DT EQL 0 AND .ADJUST GTR 4 THEN SKIPFLAG_-1;
DT_.ADJUST;
DF_0
END
ELSF .DF NEQ 0 THEN BEGIN
F_NXTCC(.F);
T_NXTCC(.T);
ADJUST_DF_DT_0
END;
WHILE 1 DO
BEGIN
SDF_.DF;
SDT_.DT;
IF NOT CODEP(.T) THEN
IF .DT NEQ 0 THEN EXITLOOP ELSE T_PRVCC(.T);
IF NOT CODEP(.F) THEN
IF .DF NEQ 0 THEN EXITLOOP ELSE F_PRVCC(.F);
IF .T[OPF] NEQ .F[OPF] THEN EXITLOOP;
CASE .OPERTYPE[.T[OPF]] OF
SET
% NOOP %
(IF .T[OPF] EQL PINLINE OR
.T[OPF] EQL PRTI THEN EXITLOOP;
IF .T[OPF] EQL PIOT THEN
IF .DF NEQ 0 OR .DT NEQ 0 THEN EXITLOOP);
% ONEOP %
IF NOT BACKEQ(SRCP(.F),SRCP(.T),DF,DT)
THEN EXITLOOP;
% TWOOP %
BEGIN
COPYADR(DSTF,DSTP(.F));
COPYADR(DSTT,DSTP(.T));
IF NOT BACKEQ(DSTP(.F),DSTP(.T),DF,DT) THEN EXITLOOP;
IF NOT BACKEQ(SRCP(.F),SRCP(.T),DF,DT) THEN
BEGIN
COPYADR(DSTP(.F),DSTF);
COPYADR(DSTP(.T),DSTT);
EXITLOOP;
END;
END;
% BROP %
IF .T[OPF] EQL PJMP OR
.T[OPF] EQL PBR OR
.DF NEQ 0 OR
.DT NEQ 0 THEN EXITLOOP
ELSF NOT BACKEQ(SRCP(.F),SRCP(.T),DF,DT) THEN EXITLOOP;
% JSROP %
IF .DF NEQ 0 OR
.DT NEQ 0 OR
.F[SRCREG] NEQ .T[SRCREG] THEN EXITLOOP
ELSF NOT BACKEQ(DSTP(.F),DSTP(.T),DF,DT) THEN EXITLOOP;
% RTSOP % EXITLOOP;
% TRAPOP %
IF .DF NEQ 0 OR
.DT NEQ 0 OR
.F[SRCOFFSET] NEQ .T[SRCOFFSET] THEN EXITLOOP;
% WORDOP %
IF NOT .F[HYDWORD] OR
NOT .T[HYDWORD] THEN EXITLOOP
ELSF .DF NEQ 0 OR
.DT NEQ 0 THEN EXITLOOP
ELSF NOT BACKEQ(SRCP(.F),SRCP(.T),DF,DT)
THEN EXITLOOP
ELSE SKIPFLAG_-1;
% CASEOP % EXITLOOP
TES;
IF .SKIPFLAG AND CELLLENGTH(.F) EQL 1 THEN SKIPFLAG_0
ELSE BEGIN
SETCHANGE;
FLAG_0;
F_BEFORE(.F,NEWCODECELL());
MAKEJMP(.F,.T);
T_.T[PREVF];
SKIPFLAG_0;
END;
T_.T[PREVF];
F_.F[PREVF];
END;
IF .FLAG THEN RETURN .FINIT[NEXTF];
IF .ADJUST NEQ 0 THEN BEGIN
TINIT_AFTER(.TINIT,NEWCODECELL());
TINIT[OPF]_PADD;
TINIT[OPTYPEF]_ADDIOPT;
COPYADR(DSTP(.TINIT),SPADR);
COPYADR(SRCP(.TINIT),IMMEDZERO);
TINIT[SRCOFFSET]_.ADJUST
END;
F_.F[NEXTF];
IF .SDF NEQ 0 THEN BEGIN
F_BEFORE(.F,NEWCODECELL());
F[OPF]_PSUB;
F[OPTYPEF]_ADDIOPT;
COPYADR(DSTP(.F),SPADR);
COPYADR(SRCP(.F),IMMEDZERO);
F[SRCOFFSET]_.SDF;
END;
IF .SDT NEQ 0 THEN BEGIN
T_AFTER(.T,NEWCODECELL());
T[OPF]_PSUB;
T[OPTYPEF]_ADDIOPT;
COPYADR(DSTP(.T),SPADR);
COPYADR(SRCP(.T),IMMEDZERO);
T[SRCOFFSET]_.SDT;
END;
RETURN .F
END;
COMMENT ! BACKSET
!
! FUNCTION:
! BACK OVER ANY STACK ADJUSTING INSTRUCTIONS, UPDATING BOTH
! CODE CELL POINTER "A" AND DELTA-VALUE "DA". THIS IS ESSENTIALLY
! A SETTING-UP ROUTINE FOR "BACKOV".
!
ROUTINE BACKSET(A,DA) =
BEGIN
LOCAL B;
B_PRVCC(.A);
.DA_0;
IF .B[SRCTYPE] NEQ IMMEDAT OR .B[SRCNAME] NEQ 0 OR
.B[DSTTYPE] NEQ REGAT OR .B[DSTREG] NEQ SP
THEN RETURN .A;
IF .B[OPF] EQL PADD THEN .DA_-SRCOFFSETV(B)
ELSF .B[OPF] EQL PSUB THEN .DA _SRCOFFSETV(B)
ELSE RETURN .A;
RETURN (IF ..DA EQL 0 THEN BACKSET(DELETE(.B)) ELSE .B)
END;
GLOBAL ROUTINE BEFORE(C2,C1) = !PLACE UNATTACHED C1 BEFORE C2
BEGIN
PREVPT(.C2)_.C1;
C1[PREVF]_.C2[PREVF];
C1[NEXTF]_.C2;
C2[PREVF]_.C1
END;
ROUTINE BRIMPLY(F,T) =
!
! F AND T ARE OPF VALUES OF TWO
! CONDITIONAL BRANCH INSTRUCTIONS.
!
! VALUE:
! 2 - WHENEVER F CAUSES A BRANCH, T WILL NOT.
! 1 - WHENEVER F CAUSES A BRANCH, T WILL ALSO.
! 0 - NEITHER OF THE ABOVE.
!
IF .T EQL PBR OR .T EQL PJMP THEN 1
ELSF .T EQL .F THEN 1
ELSF .T EQL REVCOND(.F) THEN 2
ELSF .F EQL PBEQ
THEF .T EQL PBLE OR .T EQL PBLOS THEN 1
ELSF .FINALSW AND .T EQL PBPL THEN 1
ELSF .T EQL PBGT OR .T EQL PBHI THEN 2
ELSF .FINALSW AND .T EQL PBMI THEN 2
ELSE 0
ELSF .F EQL PBLO
THEF .T EQL PBLOS THEN 1
ELSF .T EQL PBHI THEN 2
ELSE 0
ELSF .F EQL PBHI OR .F EQL PBGT OR (.FINALSW AND .F EQL PBMI)
THEF .T EQL PBNE THEN 1
ELSF .T EQL PBEQ THEN 2
ELSE 0
ELSE 0;
ROUTINE CELLLENGTH(CURS)=
CASE .OPERTYPE[.CURS[OPF]] OF
SET
% NOOP % IF .CURS[OPF] EQL PINLINE
THEN #201 * (1 - .CURS[INLCOM])
ELSE 1;
% ONEOP % 1+ADRLEN(SRCP(.CURS));
% TWOOP % 1+ADRLEN(SRCP(.CURS))+ADRLEN(DSTP(.CURS));
% BROP % IF LABREFP(.CURS) AND .CURS[OPF] NEQ PJMP THEN 1
ELSF .CURS[OPF] EQL PBR
OR .CURS[OPF] EQL PJMP THEN 1+ADRLEN(SRCP(.CURS))
ELSE 2+ADRLEN(SRCP(.CURS));
% JSROP % 1+ADRLEN(DSTP(.CURS));
% RTSOP % 1;
% TRAPOP % 1;
% WORDOP % 1;
% CASEOP % 1
TES;
ROUTINE CLEARTOLAB(IND) =
BEGIN
LOCAL NEXT;
UNTIL (NEXT_NXTLCC(.IND); LABELP(.NEXT) OR .NEXT EQL .BRAK2) DO
DELETE(.NEXT);
RETURN .NEXT
END;
ROUTINE COMBLAB(LAB) =
BEGIN
LOCAL CURS,LABCURS;
WHILE LABELP(LABCURS_PRVLCC(.LAB)) DO
LAB_.LABCURS;
WHILE LABELP(LABCURS_NXTLCC(.LAB)) DO
BEGIN
SETCHANGE;
CURS_.LABCURS[TOPF];
UNTIL .CURS EQL .LABCURS DO
CURS_MVLABREF(.CURS,.LAB);
IF USERLABP(.LABCURS) THEN !COPY OVER ONTO LAB
BEGIN
LAB[LABTYPEF]_.LABCURS[LABTYPEF];
LAB[LABNAMF]_.LABCURS[LABNAMF]
END;
ERASE(.LABCURS)
END;
RETURN .LAB
END;
COMMENT ! CONDJMPSRC
!
! FUNCTION:
! THIS ROUTINE RETURNS THE ULTIMATE DESTINATION OF
! THE BRANCHING CELL "CONDJ". "LAB" IS THE LABEL THAT IT
! REFERENCES (NOT THE SAME ON TWO DIFFERENT RECURSIONS).
!
ROUTINE CONDJMPSRC(LAB,CONDJ) =
BEGIN
LOCAL NEXT;
IF LABSEENP(.LAB) THEN RETURN .LAB;
NEXT_NXTCC(.LAB);
IF INFLOOPP(.NEXT) THEN RETURN .LAB;
IF NOT JMPP(.NEXT) THEN RETURN .LAB;
IF NOT LABREFP(.NEXT) THEN RETURN .LAB;
CASE BRIMPLY(.CONDJ[OPF],.NEXT[OPF]) OF
SET
RETURN .LAB;
BEGIN
LAB[LABSEENF]_1;
NEXT_CONDJMPSRC(LABREFED(.NEXT),.CONDJ);
LAB[LABSEENF]_0;
RETURN .NEXT
END;
RETURN .NEXT[NEXTF]
TES;
END;
ROUTINE DELADR(ADR,IND) =
BEGIN
IF .ADR[ADELTA] NEQ 0 THEN BEGIN
LOCAL CELL;
CELL_NEWCODECELL();
CELL[OPF]_IF ADELTAV(ADR) LSS 0 THEN PSUB ELSE PADD;
CELL[OPTYPEF]_ADDIOPT;
COPYADR(SRCP(.CELL),IMMEDZERO);
COPYADR(DSTP(.CELL),REGADR);
CELL[SRCOFFSET]_ABS(ADELTAV(ADR));
CELL[DSTREG]_.ADR[AREG];
CELL[MINLOCF]_.IND[MINLOCF];
RETURN BEFORE(.IND,.CELL)
END
ELSF .ADR[ANAMET] EQL LABELNAME THEN ERASE(.ADR[ANAME]);
RETURN .IND
END;
ROUTINE DELETE(IND) =
BEGIN
LOCAL T;
SETCHANGE;
T_.IND[PREVF];
IF HASSOURCE(.IND[OPF])
THEN DELADR(SRCP(.IND),.IND);
IF HASDEST(.IND[OPF])
THEN DELADR(DSTP(.IND),.IND);
ERASE(.IND);
RETURN .T[NEXTF]
END;
ROUTINE DELBACKREF(IND,ADR,BYTES) =
!
! SCAN BACKWARDS FROM IND,
! DELETING CELLS WHOSE SOLE PURPOSE
! IS TO CHANGE THE CONTENTS OF ADR.
!
WHILE 1 DO
BEGIN
LOCAL CURS,ADRVARSTR REF;
CURS_.IND;
COPYADR(REF,.ADR);
DOWNDATE(.ADR,REF);
WHILE 1 DO
BEGIN
CURS_.CURS[PREVF];
IF CODEP(.CURS) THEN BEGIN
IF .STOPBSCAN[.CURS[OPF]] THEN RETURN;
SELECT .OPERTYPE[.CURS[OPF]] OF
NSET
ONEOP: IF SAMEADRP(REF,SRCP(.CURS)) AND
.BYTES GEQ .OPBYTES[.CURS[OPF]]
THEN (DELETE(.CURS); EXITLOOP)
ELSF MAYUSEP(SRCP(.CURS),REF) OR
MAYUSEP(REF,SRCP(.CURS)) OR
(.BYTES LSS .OPBYTES[.CURS[OPF]] AND
MAYREFERP(SRCP(.CURS),REF))
THEN RETURN
ELSE DOWNDATE(SRCP(.CURS),REF);
TWOOP: IF SAMEADRP(REF,DSTP(.CURS)) AND
.BYTES GEQ .OPBYTES[.CURS[OPF]]
THEN (DELETE(.CURS); EXITLOOP)
ELSF MAYUSEP(DSTP(.CURS),REF) OR
MAYUSEP(REF,DSTP(.CURS)) OR
(.BYTES LSS .OPBYTES[.CURS[OPF]] AND
MAYREFERP(DSTP(.CURS),REF))
THEN RETURN
ELSE BEGIN
DOWNDATE(DSTP(.CURS),REF);
IF MAYREFERP(SRCP(.CURS),REF) OR
MAYUSEP(SRCP(.CURS),REF)
THEN RETURN
ELSE DOWNDATE(SRCP(.CURS),REF)
END
TESN
END
END
END;
ROUTINE DELTST(CURS) =
!
! CALLED FROM DUPADR, OPTADDSUB. EITHER
! DELETE A CODE CELL, OR CHANGE IT
! TO A TST, OR DO NOTHING, DEPENDING
! ON THE ENSUING CONDITION CODE TESTING.
!
BEGIN LOCAL NZV,C,A;
NZV_TESTCC(.CURS,NCCBIT+ZCCBIT+VCCBIT);
C_TESTCC(.CURS,CCCBIT);
A_ADDIMMEDP(.CURS);
IF .NZV
THEF NOT (.C AND NOT .A)
THEN (SETCHANGE;
CURS[OPF]_ IF .OPBYTES[.CURS[OPF]] EQL 1
THEN PTSTB
ELSE PTST;
REDUCEADR(.CURS);
RETURN .CURS);
IF NOT .NZV
THEF NOT (.C AND .A)
THEN RETURN DELETE(.CURS);
.CURS[NEXTF]
END;
GLOBAL ROUTINE DETACH(IND) =
BEGIN
NEXTPT(.IND)_.IND[PREVF];
PREVPT(.IND)_.IND[NEXTF];
RETURN .IND
END;
ROUTINE DOWNDATE(A,B) =
IF .A[AREG] EQL .B[AREG] THEN B[AOFFSET]_AOFFSETV(B)+ADELTAV(A);
ROUTINE DUPADR(CURS) =
!
! THS ROUTINE PERFORMS WHATEVER ACTION IS NECESSARY
! WHEN IT IS DISCOVERED THAT THE SOURCE AND
! DESTINATION OPERANDS OF CURS ARE IDENTICAL.
!
BEGIN
LOCAL BYTES;
BIND NORMALVEC DUPTYPE = PLIT(0,0,1,1,0,0,2,2,0,0,3,2);
IF .CURS[OPF] EQL PMOVB
THEF .CURS[DSTTYPE] EQL REGAT
THEN RETURN NXTLCC(.CURS);
BYTES_.OPBYTES[.CURS[OPF]];
CASE .DUPTYPE[.CURS[OPF]-PMOV] OF
SET
CURS_DELTST(.CURS); ! MOV, BIT, BIS
IF TESTEQL(.CURS) ! CMP
THEN BEGIN
SETCHANGE;
DELADR(SRCP(.CURS),.CURS);
DELADR(DSTP(.CURS),.CURS);
CURS[OPF]_SETEQLOP
END
ELSE CURS_DELETE(.CURS);
BEGIN ! BIC, SUB
SETCHANGE;
CURS[OPF]_IF .BYTES EQL 1 THEN PCLRB ELSE PCLR;
REDUCEADR(.CURS)
END;
BEGIN ! ADD
SETCHANGE;
CURS[OPF]_PASL;
REDUCEADR(.CURS)
END
TES;
RETURN .CURS
END;
ROUTINE EMPTY(I) =
I[BOTF]_I[TOPF]_EMPTYDET(.I);
ROUTINE EMPTYDET(IND) =
BEGIN
LOCAL CURS;
CURS_.IND[TOPF];
UNTIL .CURS EQL .IND DO
CURS_ERASEDET(.CURS);
RETURN .IND
END;
ROUTINE EQUIVADR(A,B,C,I) =
!
! IF ADDRESS C IN INSTRUCTION I
! IS EQUIVALENT TO THE LESS SIMPLE OF
! A AND B, REPLAC4 IT BY THE MORE
! SIMPLE OF THE TWO.
!
IF .C[ADELTA] NEQ 0 THEN RETURN 0
ELSE BEGIN
LOCAL ASIMP,BSIMP;
ASIMP_ADRSIMP(.A);
BSIMP_ADRSIMP(.B);
IF .ASIMP EQL 0 OR
.BSIMP EQL 0 OR
.ASIMP EQL .BSIMP
THEN RETURN 0;
IF .ASIMP GTR .BSIMP THEN SWAP(A,B);
IF NOT SAMEADRP(.B,.C) THEN RETURN 0;
DELADR(.C,.I);
MAKEADR(.C,.A,.I);
RETURN 1
END;
ROUTINE EQUIVFWD(IND,IA,IB,BYTES) =
!
! SCAN FORWARD FROM IND, LOOKING FOR INSTANCES OF
! THE MORE COSTLY ONE OF IA AND IB, AND REPLACING
! THEM WITH THE CHEAPER 0NE.
!
WHILE 1 DO
BEGIN
LOCAL CURS,ADRVARSTR A:B,T;
CURS_.IND;
COPYADR(A,.IA);
COPYADR(B,.IB);
UPDATE(B,A);
WHILE 1 DO
BEGIN
CURS_.CURS[NEXTF];
IF NOT CODEP(.CURS) THEN RETURN;
IF .STOPFSCAN[.CURS[OPF]] THEN RETURN;
SELECT .OPERTYPE[.CURS[OPF]] OF
NSET
ONEOP: BEGIN
UPDATE(SRCP(.CURS),A);
UPDATE(SRCP(.CURS),B);
IF .BYTES EQL 2
THEN EQUIVIND(A,B,SRCP(.CURS),.CURS);
IF .ALTERSRCDST[.CURS[OPF]]
THEF MAYREFERP(SRCP(.CURS),A) OR
MAYREFERP(SRCP(.CURS),B) OR
MAYUSEP(A,SRCP(.CURS)) OR
MAYUSEP(B,SRCP(.CURS))
THEN RETURN
ELSE
ELSF .BYTES GEQ .OPBYTES[.CURS[OPF]]
THEN EQUIVADR(A,B,SRCP(.CURS),.CURS);
IF MAYPOP(SRCP(.CURS),A) OR
MAYPOP(SRCP(.CURS),B)
THEN RETURN;
END;
TWOOP: BEGIN
IF .UNLOCFLG AND
.CURS[DSTTYPE] EQL REGAT AND
.CURS[DSTREG] EQL SP AND
.CURS[SRCTYPE] EQL IMMEDAT
THEN BEGIN
IF .CURS[OPF] EQL PADD THEN T_SRCOFFSETV(CURS)
ELSF .CURS[OPF] EQL PSUB THEN T_-SRCOFFSETV(CURS)
ELSE EXITCOMPOUND;
IF .T GTR 0
THEF .A[ATYPE] EQL INDAT OR
.B[ATYPE] EQL INDAT
THEN RETURN
ELSE BEGIN
IF .A[ATYPE] EQL MEMAT
THEF .A[ANAME] LEQ 1
THEF .A[AREG] LSS SP
THEN RETURN
ELSF .A[AREG] EQL SP AND
AOFFSETV(A) LSS .T
THEN RETURN;
IF .B[ATYPE] EQL MEMAT
THEF .B[ANAME] LEQ 1
THEF .B[AREG] LSS SP
THEN RETURN
ELSF .B[AREG] EQL SP AND
AOFFSETV(A) LSS .T
THEN RETURN;
END;
END;
UPDATE(SRCP(.CURS),A);
UPDATE(SRCP(.CURS),B);
IF .BYTES GEQ .OPBYTES[.CURS[OPF]]
THEF NOT EQUIVADR(A,B,SRCP(.CURS),.CURS)
THEF .BYTES EQL 2
THEN EQUIVIND(A,B,SRCP(.CURS),.CURS);
T_(SAMEADRP(A,SRCP(.CURS)) OR
SAMEADRP(B,SRCP(.CURS))) AND
.BYTES GEQ .OPBYTES[.CURS[OPF]];
UPDATE(DSTP(.CURS),A);
UPDATE(DSTP(.CURS),B);
IF .T AND
(SAMEADRP(A,DSTP(.CURS)) OR
SAMEADRP(B,DSTP(.CURS)))
THEN (DUPADR(.CURS); RETURN)
ELSE BEGIN
IF .BYTES EQL 2
THEN EQUIVIND(A,B,DSTP(.CURS),.CURS);
IF .ALTERSRCDST[.CURS[OPF]]
THEF MAYREFERP(DSTP(.CURS),A) OR
MAYREFERP(DSTP(.CURS),B) OR
MAYUSEP(A,DSTP(.CURS)) OR
MAYUSEP(B,DSTP(.CURS))
THEN RETURN
ELSE
ELSF .BYTES GEQ .OPBYTES[.CURS[OPF]]
THEN EQUIVADR(A,B,DSTP(.CURS),.CURS);
END;
IF MAYPOP(SRCP(.CURS),A) OR
MAYPOP(SRCP(.CURS),B) OR
MAYPOP(DSTP(.CURS),A) OR
MAYPOP(DSTP(.CURS),B)
THEN RETURN;
END
TESN
END
END;
ROUTINE EQUIVIND(A,B,C,I) =
!
! LIKE EQUIVADR, BUT C IS
! ONE LEVEL OF INDIRECTION ABOVE A AND B.
!
IF .C[ADELTA] NEQ 0 OR NOT ONEOF(.C[ATYPE],BIT2(MEMAT,INDAT))
THEN RETURN 0
ELSE BEGIN
BIND NORMALVEC NEWFORM = PLIT
(1,7,7,0,7,0,7,0, 0,0,#13,#17,0,0,#17,0);
LOCAL ASIMP,BSIMP;
ASIMP_ADRSIMP(.A);
BSIMP_ADRSIMP(.B);
IF .ASIMP EQL 0 OR
.BSIMP EQL 0 OR
.ASIMP EQL .BSIMP
THEN RETURN 0;
IF .ASIMP GTR .BSIMP THEN SWAP(A,B);
IF .A[ATYPE] EQL INDAT THEN RETURN 0;
IF NOT SAMEINDP(.B,.C) THEN RETURN 0;
IF .PICSW AND .A[AFORM] EQL #13 THEN RETURN 0;
MAKEADR(.C,.A,.I);
C[ATYPE]_ IF .C[ATYPE] EQL MEMAT THEN INDAT ELSE MEMAT;
C[AFORM]_.NEWFORM[.C[AFORM]];
RETURN 1
END;
ROUTINE ERASE(IND) =
ERASEDET(DETACH(.IND));
ROUTINE ERASEDET(IND) =
BEGIN
BIND VAL = .IND[NEXTF];
EMPTYDET(.IND);
RELEASESPACE(ST,.IND-MINCELLSIZE,.IND[CELLSIZEF]+MINCELLSIZE);
RETURN VAL
END;
ROUTINE ERASELIST(HDR) =
BEGIN
LOCAL CURS;
CURS_.HDR[NEXTF];
UNTIL .CURS EQL .HDR DO
CURS_ERASEDET(.CURS);
RETURN .HDR
END;
GLOBAL ROUTINE FERASEDET(X) =
ERASEDET(.X);
GLOBAL ROUTINE FELIST(X)=ERASELIST(.X);
GLOBAL ROUTINE FINAL =
BEGIN
SETCHANGE;
FINAL1();
FINAL2();
SETCHANGE;
FINAL3()
END;
ROUTINE FINAL1 =
BEGIN
LOCAL CURS,COUNT,ADRVARSTR REF;
COUNT_2;
WHILE (IF FAST
THEN (COUNT_.COUNT-1) GEQ 0
ELSE .CHANGE)
DO
BEGIN
CHANGE_0;
CURS_.BRAK1;
UNTIL .CURS EQL .BRAK2 DO
CURS _
BEGIN
IF LABELP(.CURS) THEN
PLAB
ELSF NOT CODEP(.CURS) THEN
NXTLCC
ELSF (IF .OPERTYPE[.CURS[OPF]] EQL TWOOP THEN
BEGIN
COPYADR(REF,SRCP(.CURS));
UPDATE(DSTP(.CURS),REF);
SAMEADRP(DSTP(.CURS),REF)
END
ELSE 0
) THEN DUPADR
ELSE .OPTROUTINE[.CURS[OPF]]
END
(.CURS)
END;
END;
ROUTINE FINAL2 =
BEGIN
LOCAL MINLOC,CURS,VAL,LASTRTS;
MACRO
UPLOCFS(I) = (ST[I,MINLOCF]_.MINLOC)$,
UPLOCS(I) = (MINLOC_.MINLOC+.ST[I,MINLENF])$;
LASTRTS_0;
MINLOC_0;
CURS_.BRAK1;
UNTIL (CURS_NXTLCC(.CURS)) EQL .BRAK2 DO
BEGIN
UPLOCFS(.CURS);
IF CODEP(.CURS) THEN BEGIN
IF INFLOOPP(.CURS)
THEN COMBLAB(MAKEJMP(.CURS,.CURS))
ELSF SETEQLP(.CURS) THEN
BEGIN
CURS[OPF]_PCMP;
COPYADR(SRCP(.CURS),PCADR);
COPYADR(DSTP(.CURS),PCADR)
END
ELSF ADDIMMEDP(.CURS) THEN
BEGIN
CURS[OPTYPEF]_UNUSED;
VAL_IF .CURS[OPF] EQL PSUB
THEN -SRCOFFSETV(CURS)
ELSE SRCOFFSETV(CURS);
IF .CURS[SRCNAME] EQL 0 AND
ABS(.VAL) EQL 1 AND
NOT TESTCC(.CURS,CCCBIT)
THEN BEGIN
CURS[OPF]_IF .VAL GTR 0 THEN PINC ELSE PDEC;
REDUCEADR(.CURS);
END
ELSF .CURS[SRCNAME] EQL 0 AND
.CURS[DSTTYPE] EQL REGAT AND
.CURS[DSTREG] EQL SP AND
NOT TESTCC(.CURS,NCCBIT+ZCCBIT+VCCBIT+CCCBIT)
THEF ABS(.VAL) EQL 4
THEN BEGIN
CURS[OPF]_PCMP;
IF .VAL GTR 0
THEN (CURS[DSTDELTA]_2; ! CMP (SP)+,(SP)+
CURS[DSTOFFSET]_-2;
CURS[DSTFORM]_2)
ELSE (CURS[DSTDELTA]_-2; ! CMP -(SP),-(SP)
CURS[DSTFORM]_4);
CURS[DSTTYPE]_MEMAT;
COPYADR(SRCP(.CURS),DSTP(.CURS));
END
ELSF ABS(.VAL) EQL 2
THEN BEGIN
CURS[OPF]_PTST;
IF .VAL GTR 0
THEN (CURS[DSTDELTA]_2; ! TST (SP)+
CURS[DSTOFFSET]_-2;
CURS[DSTFORM]_2)
ELSE (CURS[DSTDELTA]_-2; ! TST -(SP)
CURS[DSTFORM]_4);
CURS[DSTTYPE]_MEMAT;
COPYADR(SRCP(.CURS),DSTP(.CURS));
END;
END
ELSF UNCONDJMPP(.CURS)
THEN (IF FAST THEN CLEARTOLAB(.CURS); ! CLEAN UP AFTER CROSS-JUMPING
IF LABREFP(.CURS) THEN
BEGIN
VAL_NXTCC(LABREFED(.CURS));
IF .VAL[OPF] EQL PRTS OR
.VAL[OPF] EQL PRTI OR
(.VAL[OPF] EQL PHALT AND .VAL[NEXTF] EQL .BRAK2)
THEN BEGIN
CURS[OPF]_.VAL[OPF];
CURS[OPTYPEF]_NORMALOPT;
COPYADR(SRCP(.CURS),SRCP(.VAL));
IF .VAL[NEXTF] EQL .BRAK2 THEN LASTRTS_.CURS;
END
END);
IF .OPERTYPE[.CURS[OPF]] EQL TWOOP THEN BEGIN ! LOOK FOR
IF .CURS[SRCREG] EQL .CURS[DSTREG] ! OP @REG,@0(REG)
THEF .CURS[SRCREG] NEQ PC ! (OR THE LIKE)
THEF .CURS[SRCREG] EQL SP OR .OPBYTES[.CURS[OPF]] EQL 2 ! AND CHANGE IT TO
THEF .CURS[SRCOFFSET] EQL 0 AND .CURS[DSTOFFSET] EQL 0 ! OP (REG)+,@-(REG).
THEF .CURS[SRCNAME] LEQ 1 AND .CURS[DSTNAME] LEQ 1
THEF INDORMEMP(SRCP(.CURS))
THEF INDORMEMP(DSTP(.CURS))
THEF .CURS[SRCDELTA] EQL 0 AND .CURS[DSTDELTA] EQL 0
THEN BEGIN
CURS[SRCDELTA]_2;
CURS[SRCOFFSET]_-2;
CURS[SRCMODE]_IF .CURS[SRCTYPE] EQL MEMAT THEN 2 ELSE 3;
CURS[DSTDELTA]_-2;
CURS[DSTMODE]_IF .CURS[DSTTYPE] EQL MEMAT THEN 4 ELSE 5;
END;
ADRLEN(DSTP(.CURS)); ! LOOK FOR
IF .CURS[SRCTYPE] EQL IMMEDAT ! OP #N,N(REG)
THEF ONEOF(.CURS[DSTFORM],BIT3(6,7,#13)) ! AND CHANGE #N TO @PC.
THEF .CURS[SRCOFFSET] EQL .CURS[DSTOFFSET]
THEF .CURS[DSTNAME] EQL .CURS[SRCNAME] OR
(.CURS[SRCNAME] EQL 0 AND .CURS[DSTNAME] EQL 1)
THEN CURS[SRCMODE]_1;
END;
CURS[MINLENF]_CELLLENGTH(.CURS);
UPLOCS(.CURS)
END
END;
CURS_.BRAK2[PREVF];
IF .LASTRTS NEQ 0 AND UNCONDJMPP(PRVCC(.CURS)) THEN BEGIN
VAL_BEFORE(.LASTRTS,DETACH(.CURS[PREVF]));
VAL[MINLOCF]_.LASTRTS[MINLOCF];
ERASE(.CURS);
END;
END;
ROUTINE FINAL3 =
BEGIN
LOCAL CURS,VAL,NEXT,LAB,MINLOC;
MACRO
UPLOCFS(I) = (ST[I,MINLOCF]_.MINLOC)$,
UPLOCS(I) = (MINLOC_.MINLOC+.ST[I,MINLENF])$;
WHILE .CHANGE DO
BEGIN
CHANGE_0;
MINLOC_0;
CURS_.BRAK1;
UNTIL (CURS_NXTLCC(.CURS)) EQL .BRAK2 DO
BEGIN DUMMYBLOCK
UPLOCFS(.CURS);
IF LABELP(.CURS) THEN
CONTLOOP;
IF JMPP(.CURS)
THEF LABREFP(.CURS)
THEF REACH(.CURS) EQL 0 THEN !JMP NECESSARY
BEGIN
SETCHANGE;
NEXT_NXTCC(LABREFED(.CURS));
IF CONDJMPP(.CURS) THEN
BEGIN
VAL_NEWCODECELL();
BEFORE(.CURS,.VAL);
COMBLAB(MAKEJMP(.VAL,NXTCC(.CURS)));
VAL[OPF]_REVCOND(.CURS[OPF]);
VAL[MINLENF]_1;
UPLOCFS(.VAL);
UPLOCS(.VAL);
VAL[OPTYPEF]_NORMALOPT;
VAL_.CURS[SRCNAME];
VAL[OPTYPEF]_UNCONDJMPT;
END;
IF .NEXT[OPF] EQL PJMP THEN COPYADR(SRCP(.CURS),SRCP(.NEXT));
CURS[OPTYPEF]_NORMALOPT;
CURS[OPF]_PJMP;
CURS[MINLENF]_2;
UPLOCFS(.CURS)
END;
UPLOCS(.CURS)
END !SCAN LOOP
END; !CHANGE LOOP
ROUTINESIZE_.MINLOC;
CODESIZE_.CODESIZE+.MINLOC;
IF .MINLOC LEQ 127 THEN RETURN;
CURS_.BRAK1;
UNTIL (CURS_NXTCC(.CURS)) EQL .BRAK2 DO
IF JMPP(.CURS)
THEF LABREFP(.CURS) THEN
BEGIN
LAB_LABREFED(.CURS);
VAL_REACH(.CURS);
IF .LAB NEQ .VAL THEN
BEGIN
LAB_COMBLAB(BEFORE(.VAL,NEWLAB()));
LAB[MINLOCF]_.VAL[MINLOCF];
MAKELABREF(.CURS,.LAB);
END;
END;
END;
ROUTINE FIXJMPIND(IND) =
BEGIN
LOCAL NEXT,LAB,IL;
IF INFLOOPP(.IND) THEN
RETURN 1;
IF NOT LABREFP(.IND) THEN
RETURN 0;
LAB_LABREFED(.IND);
IF LABSEENP(.LAB) THEN
(MAKEINFLOOP(.IND); RETURN 1);
NEXT_NXTCC(.LAB);
IF NOT UNCONDJMPP(.NEXT) THEN
RETURN 0;
!EXTRA LEVELS OF INDIRECTION. MUST RECUR
LAB[LABSEENF]_1;
IL_FIXJMPIND(.NEXT);
LAB[LABSEENF]_0;
IF NOT .IL THEN
BEGIN ! BRANCH-TO-BRANCH STUFF
IF NOT LABREFP(.NEXT) THEN
IF CASPARAMP(.IND) OR
ADRLEN(SRCP(.NEXT)) NEQ 0
THEN RETURN 0;
DELADR(SRCP(.IND),.IND);
MAKEADR(SRCP(.IND),SRCP(.NEXT),.IND);
SETCHANGE;
RETURN 0
END
ELSF UNCONDJMPP(.IND) THEN
(MAKEINFLOOP(.IND); RETURN 1)
ELSE
RETURN 0
END;
ROUTINE LABREFED(IND) =
COMBLAB(.ST[.IND[SRCNAME],REFEF]);
ROUTINE LABREFP(I) =
IF ONEOF(.OPERTYPE[.I[OPF]],BIT2(BROP,CASEOP))
THEN .I[SRCNAMET] EQL LABELNAME;
ROUTINE MAKEADR(A,B,IND) =
!
! REPLACE ADDRESS A IN INSTRUCTION IND BY B.
!
BEGIN
COPYADR(.A,.B);
IF .IND[OPF] EQL PADD OR
.IND[OPF] EQL PSUB
THEF .A EQL SRCP(.IND)
THEF .A[ATYPE] EQL IMMEDAT
THEN IND[OPTYPEF]_ADDIOPT;
IF .A[ADELTA] NEQ 0 THEN
BEGIN
A[ADELTA]_0;
A[AFORM]_ IF .A[ATYPE] EQL INDAT THEN 7
ELSF .A[AOFFSET] EQL 0 THEN 1
ELSE 6
END;
IF .A[ANAMET] EQL LABELNAME THEN
BEGIN
LOCAL REF;
REF_A[ANAME]_GETCELL(REFCELLT,REFCELLSIZE);
REF[OPTYPEF]_.IND[OPTYPEF];
REF[REFRF]_.IND;
PUSHBOT(REF[REFEF]_.ST[.B[ANAME],REFEF],.REF)
END
END;
ROUTINE MAKEINFLOOP(I) =
BEGIN
IF INFLOOPP(.I) THEN
RETURN;
SETCHANGE;
DELADR(SRCP(.I),.I);
I[OPF]_INFLOOPOP
END;
ROUTINE MAKEJMP(F,T) =
BEGIN
LOCAL LAB;
LAB_NEWLAB();
BEFORE(.T,.LAB);
LAB[MINLOCF]_.T[MINLOCF];
F[OPTYPEF]_UNCONDJMPT;
F[OPF]_PBR;
MAKELABREF(.F,.LAB);
RETURN .LAB
END;
ROUTINE MAKELABREF(IND,LAB) =
BEGIN
LOCAL REF;
COPYADR(SRCP(.IND),MEMADR);
REF_IND[SRCNAME]_GETCELL(REFCELLT,REFCELLSIZE);
REF[OPTYPEF]_.IND[OPTYPEF];
REF[REFEF]_.LAB;
REF[REFRF]_.IND;
PUSHBOT(.LAB,.REF)
END;
ROUTINE MAYPOP(A,B) =
!
! TRUE IF A MAY POP B OFF STACK.
!
IF NOT .FINALSW AND ADELTAV(A) NEQ 0
THEN NOT INDORMEMP(.B)
ELSF NOT .UNLOCFLG OR
ADELTAV(A) LEQ 0 OR
.A[AREG] NEQ SP THEN 0
ELSF .B[ATYPE] EQL INDAT THEN 1
ELSF .B[ATYPE] NEQ MEMAT THEN 0
ELSF .B[ANAME] GTR 1 OR .B[AREG] EQL PC THEN 0
ELSF .B[AREG] EQL SP THEN AOFFSETV(A) LSS 0
ELSE 1;
ROUTINE MAYREFERP(A,B) =
!
! TRUE IF ADDRESS A MAY REFER TO ADDRESS B
!
BEGIN
IF .A[ATYPE] GTR .B[ATYPE] THEN SWAP(A,B);
RETURN CASE .A[ATYPE] OF
SET
1; ! UNUSED
0; ! IMMEDAT
IF .B[ATYPE] EQL REGAT ! REGAT
THEN .A[AREG] EQL .B[AREG]
ELSE 0;
IF NOT .UNLOCFLG AND ! INDAT
.B[ATYPE] EQL MEMAT AND
.B[ANAME] EQL 1 AND
.FINALSW THEN 0 ELSE 1;
IF NOT .FINALSW ! MEMAT
THEN 1
ELSF .A[AREG] NEQ .B[AREG]
THEN .A[ANAME] EQL 0 OR
.B[ANAME] EQL 0 OR
.A[ANAME] EQL .B[ANAME]
ELSE .A[ANAME] EQL .B[ANAME] AND
ABS(AOFFSETV(A)-AOFFSETV(B)) LSS 2
TES
END;
ROUTINE MAYUSEP(A,B) =
!
! TRUE IF ADDRESS A MAY USE ADDRESS B.
!
BEGIN
RETURN CASE .A[ATYPE] OF
SET
1; ! UNUSED
0; ! IMMEDAT
0; ! REGAT
IF NOT .FINALSW ! INDAT
THEN .B[ATYPE] NEQ IMMEDAT
ELSF .B[ATYPE] EQL REGAT
THEN .A[AREG] EQL .B[AREG]
ELSE
BEGIN
LOCAL ADRVARSTR T;
COPYADR(T,.A);
T[ATYPE]_MEMAT;
MAYREFERP(T,.B)
END;
IF NOT .FINALSW ! MEMAT
THEN .B[ATYPE] NEQ IMMEDAT
ELSF .B[ATYPE] EQL REGAT
THEN .A[AREG] EQL .B[AREG]
ELSE 0
TES
END;
ROUTINE MOVEJMP(F,T) =
BEGIN
IF NOT LABELP(.T)
THEF LABELP(.T[PREVF]) THEN T_.T[PREVF]
ELSE BEGIN
LOCAL LAB;
LAB_NEWLAB();
BEFORE(.T,.LAB);
LAB[MINLOCF]_.T[MINLOCF];
T_.LAB;
END;
MVLABREF(.F[SRCNAME],.T);
END;
ROUTINE MVLABREF(IND,LAB) =
BEGIN
BIND VAL = .IND[NEXTF];
SETCHANGE;
IND[REFEF]_.LAB;
PUSHBOT(.LAB,DETACH(.IND));
RETURN VAL
END;
GLOBAL ROUTINE NEWBOT(HD,TYPE,SIZE) =
PUSHBOT(.HD,GETCELL(.TYPE,.SIZE));
ROUTINE NEWLAB=NEWLABCELL(LABNAME(COMPLABT,GETLABEL()));
GLOBAL ROUTINE NEWTOP(HD,TYPE,SIZE) =
PUSHTOP(.HD,GETCELL(.TYPE,.SIZE));
LCCROUT(NXTCC,NEXTF,CCP);
LCCROUT(NXTLCC,NEXTF,LCCP);
ROUTINE OPTADDSUB(I) =
BEGIN
LOCAL PPFLAG,CURS, ADRVARSTR DST1;
IF NOT ADDIMMEDP(.I) THEN RETURN .I[NEXTF];
IF .I[SRCNAME] EQL 0 THEN
IF .I[SRCOFFSET] EQL 0 THEN RETURN DELTST(.I) ! ADD #0,ANY
ELSF SRCOFFSETV(I) LSS 0 THEN
BEGIN ! CHANGE ADD(SUB) #-N,ANY
I[OPF]_IF .I[OPF] EQL PSUB THEN PADD ELSE PSUB; ! TO SUB(ADD) #N,ANY
I[SRCOFFSET]_ABS(SRCOFFSETV(I))
END;
IF FAST THEN RETURN .I[NEXTF];
IF .I[DSTTYPE] EQL INDAT THEN RETURN .I[NEXTF];
IF .I[DSTTYPE] EQL REGAT THEN
BEGIN
CURS_.I;
PPFLAG_IF .I[SRCNAME] NEQ 0 THEN #177776
ELSF .I[OPF] EQL PADD THEN SRCOFFSETV(I)
ELSE -SRCOFFSETV(I);
PUSHPOPFLAG_.PPFLAG;
WHILE 1 DO
BEGIN
CURS_.CURS[PREVF];
IF NOT CODEP(.CURS) THEN EXITLOOP;
IF .STOPFSCAN[.CURS[OPF]] OR .STOPBSCAN[.CURS[OPF]] THEN EXITLOOP;
SELECT .OPERTYPE[.CURS[OPF]] OF
NSET
ONEOP: IF TESTPOP(SRCP(.CURS),.I,.CURS) THEN EXITLOOP;
TWOOP:IF TESTPOP(DSTP(.CURS),.I,.CURS) THEN EXITLOOP
ELSF TESTPOP(SRCP(.CURS),.I,.CURS) THEN EXITLOOP
TESN;
END;
IF .I[SRCOFFSET] EQL 0 AND .I[SRCNAME] EQL 0 THEN RETURN DELTST(.I);
CURS_.I;
PUSHPOPFLAG_-.PPFLAG;
WHILE 1 DO
BEGIN
CURS_.CURS[NEXTF];
IF NOT CODEP(.CURS) THEN EXITLOOP;
IF .STOPFSCAN[.CURS[OPF]] OR .STOPBSCAN[.CURS[OPF]] THEN EXITLOOP;
SELECT .OPERTYPE[.CURS[OPF]] OF
NSET
ONEOP: IF TESTPUSH(SRCP(.CURS),.I,.CURS) THEN EXITLOOP;
TWOOP: IF TESTPUSH(SRCP(.CURS),.I,.CURS) THEN EXITLOOP
ELSF TESTPUSH(DSTP(.CURS),.I,.CURS) THEN EXITLOOP
TESN;
END;
IF .I[SRCOFFSET] EQL 0 AND .I[SRCNAME] EQL 0 THEN RETURN DELTST(.I);
END;
CURS_.I;
COPYADR(DST1,DSTP(.I));
WHILE 1 DO
!
! SCAN FORWARD FROM I,
! COMBINING ADDS(SUBS) OF LITERALS TO I'S DST
! WITH I ITSELF.
!
BEGIN
CURS_.CURS[NEXTF];
IF NOT CODEP(.CURS) THEN EXITLOOP;
IF .STOPFSCAN[.CURS[OPF]] OR .STOPBSCAN[.CURS[OPF]] THEN EXITLOOP;
SELECT .OPERTYPE[.CURS[OPF]] OF
NSET
ONEOP:
BEGIN
UPDATE(SRCP(.CURS),DST1);
IF MAYUSEP(SRCP(.CURS),DST1) OR
MAYREFERP(SRCP(.CURS),DST1) OR
(MAYUSEP(DST1,SRCP(.CURS)) AND
.ALTERSRCDST[.CURS[OPF]])
THEN EXITLOOP
END;
TWOOP:
BEGIN
UPDATE(SRCP(.CURS),DST1);
IF MAYUSEP(SRCP(.CURS),DST1) OR
MAYREFERP(SRCP(.CURS),DST1)
THEN EXITLOOP;
UPDATE(DSTP(.CURS),DST1);
IF ADDIMMEDP(.CURS) AND
SAMEADRP(DST1,DSTP(.CURS))
THEN IF .I[SRCNAME] NEQ 0 AND
(.CURS[SRCNAME] NEQ 0 OR
.CURS[OPF] NEQ .I[OPF])
THEN EXITLOOP
ELSE
BEGIN
CURS[SRCNAME]_.CURS[SRCNAME]+.I[SRCNAME];
CURS[SRCOFFSET]_SRCOFFSETV(CURS)+
(IF .I[OPF] EQL .CURS[OPF]
THEN SRCOFFSETV(I)
ELSE -SRCOFFSETV(I));
RETURN DELETE(.I)
END
ELSF MAYUSEP(DSTP(.CURS),DST1) OR
MAYREFERP(DSTP(.CURS),DST1) OR
(MAYUSEP(DST1,DSTP(.CURS)) AND
.ALTERSRCDST[.CURS[OPF]])
THEN EXITLOOP
END;
TESN
END;
RETURN .I[NEXTF];
END;
ROUTINE OPTBIC(I) = OPTBOOL(.I,PBIC,PBICB,PBIS,PBISB);
ROUTINE OPTBIS(I) = OPTBOOL(.I,PBIS,PBISB,PBIC,PBICB);
ROUTINE OPTBIT(I) =
IF TESTCC(.I,NCCBIT+ZCCBIT+VCCBIT) THEN .I[NEXTF] ELSE DELETE(.I);
ROUTINE OPTBOOL(I,PBOOL,PBOOLB,XBOOL,XBOOLB) =
BEGIN
IF SLOW THEN
IF .I[SRCTYPE] EQL IMMEDAT AND
.I[SRCNAME] EQL 0 AND
.I[DSTTYPE] NEQ INDAT THEN
BEGIN
!
! SCAN FORWARD FROM I, USING LOCAL CURS,
! TRYING EITHER TO DELETE I, DELETE CURS,
! OR CHANGE CURS TO A MOV(B). DURING
! THIS FORWARD SCAN THE FOLLOWING INFORMATION
! IS KEPT AROUND:
!
! FWDF,BACKF - FWDF IS SET IF A LABEL IS SEEN, BACKF
! IS SET IF A CONDITIONAL BRANCH IS SEEN
! OR I'S DST IS USED. IF SOMETHING ELSE
! HAPPENS, SUCH AS AN UNCONDITIONAL BRANCH
! BEING SEEN, THEY ARE BOTH SET; ANY TIME
! THEY ARE BOTH SET, THE SCAN IS ENDED.
! FWDMASK - A MASK OF THE BITS AFFECTED BY "PBOOL(B)" (AND
! NOT BY "XBOOL(B)") BETWEEN I AND CURS.
! ONLY VALID UNTIL FWDF IS SET.
! BACKMASK - A MASK OF THE BITS AFFECTED BY "PBOOL(B)" (AND
! NOT BY "XBOOL(B)") BETWEEN I AND WHENEVER FWDF
! WAS SET, BUT NOT AFFECTED SINCE THEN.
! NOT VALID AFTER BACKF IS SET.
!
LOCAL FWDF,BACKF,FWDMASK,BACKMASK,CURS,ADRVARSTR ADR;
FWDF_BACKF_0;
IF .I[OPF] EQL .PBOOLB THEN I[SRCOFFSET]_.I[SRCOFFSET] AND #377;
IF .I[SRCOFFSET] EQL 0 THEN RETURN DELETE(.I);
FWDMASK_BACKMASK_.I[SRCOFFSET];
COPYADR(ADR,DSTP(.I));
CURS_.I;
WHILE 1 DO
BEGIN
CURS_.CURS[NEXTF];
IF NOT CODEP(.CURS) THEN
IF .BACKF THEN EXITLOOP ELSE FWDF_-1
ELSE BEGIN
IF .STOPFSCAN[.CURS[OPF]] THEN FWDF_-1;
IF .STOPBSCAN[.CURS[OPF]] THEN BACKF_-1;
IF .BACKF AND .FWDF THEN EXITLOOP;
SELECT .OPERTYPE[.CURS[OPF]] OF
NSET
ONEOP:
BEGIN
UPDATE(SRCP(.CURS),ADR);
IF .ALTERSRCDST[.CURS[OPF]]
THEF MAYREFERP(SRCP(.CURS),ADR) OR
MAYUSEP(ADR,SRCP(.CURS))
THEN EXITLOOP
ELSE
ELSF MAYREFERP(SRCP(.CURS),ADR)
THEN BACKF_-1;
IF MAYUSEP(SRCP(.CURS),ADR) THEN BACKF_-1;
END;
TWOOP:
BEGIN
UPDATE(SRCP(.CURS),ADR);
IF MAYREFERP(SRCP(.CURS),ADR) OR
MAYUSEP(SRCP(.CURS),ADR)
THEN BACKF_-1;
UPDATE(DSTP(.CURS),ADR);
IF .CURS[SRCTYPE] EQL IMMEDAT AND
.CURS[SRCNAME] EQL 0 AND
SAMEADRP(DSTP(.CURS),ADR)
THEN
IF .CURS[OPF] EQL .PBOOL OR
.CURS[OPF] EQL .PBOOLB THEN
BEGIN
IF .CURS[OPF] EQL .PBOOLB
THEN CURS[SRCOFFSET]_.CURS[SRCOFFSET] AND #377;
IF .FWDF
THEF (BACKMASK_.BACKMASK AND NOT .CURS[SRCOFFSET]) EQL 0
THEN RETURN DELETE(.I)
ELSE EXITSELECT
ELSF .BACKF
THEF (NOT .FWDMASK AND .CURS[SRCOFFSET]) EQL 0
THEN (DELETE(.CURS); RETURN(.I))
ELSE (FWDMASK_.FWDMASK OR .CURS[SRCOFFSET]; EXITSELECT)
ELSE
BEGIN
CURS[SRCOFFSET]_.CURS[SRCOFFSET] OR .FWDMASK;
IF .I[OPF] EQL .PBOOL THEN CURS[OPF]_.PBOOL;
RETURN DELETE(.I)
END
END
ELSF .CURS[OPF] EQL .XBOOL OR
.CURS[OPF] EQL .XBOOLB THEN
BEGIN
IF .CURS[OPF] EQL .XBOOLB
THEN CURS[SRCOFFSET]_.CURS[SRCOFFSET] AND #377;
IF NOT .BACKF
THEF (BACKMASK_.BACKMASK AND NOT .CURS[SRCOFFSET]) EQL 0
THEN RETURN DELETE(.I);
IF NOT .FWDF
THEF ((.FWDMASK OR .CURS[SRCOFFSET]) AND #177777) EQL #177777
OR (.I[OPF] EQL .PBOOLB AND
.CURS[OPF] EQL .XBOOLB AND
((.FWDMASK OR .CURS[SRCOFFSET]) AND #377) EQL #377)
THEN
BEGIN
CURS[OPF]_IF .I[OPF] EQL .PBOOLB AND
.CURS[OPF] EQL .XBOOLB
THEN PMOVB ELSE PMOV;
IF .I[OPF] EQL PBIS OR .I[OPF] EQL PBISB
THEN CURS[SRCOFFSET]_NOT .CURS[SRCOFFSET];
SETCHANGE;
IF NOT .BACKF
THEN RETURN DELETE(.I)
ELSE RETURN .I[NEXTF];
END;
FWDMASK_.FWDMASK AND NOT .CURS[SRCOFFSET];
EXITSELECT
END;
IF .ALTERSRCDST[.CURS[OPF]]
THEF MAYREFERP(DSTP(.CURS),ADR) OR
MAYUSEP(ADR,DSTP(.CURS))
THEN EXITLOOP
ELSE
ELSF MAYREFERP(DSTP(.CURS),ADR)
THEN BACKF_-1;
IF MAYUSEP(DSTP(.CURS),ADR) THEN BACKF_-1
END
TESN;
END
END
END;
RETURN(.I[NEXTF])
END;
ROUTINE OPTCLC(I) =
IF TESTCC(.I,CCCBIT) THEN .I[NEXTF] ELSE DELETE(.I);
ROUTINE OPTCLR(CURS) =
BEGIN
LOCAL BYTES;
BYTES_.OPBYTES[.CURS[OPF]];
IF REGORMEMP(SRCP(.CURS)) THEN
BEGIN
EQUIVFWD(.CURS,SRCP(.CURS),IMMEDZERO,.BYTES);
DELBACKREF(.CURS,SRCP(.CURS),.BYTES)
END;
RETURN NXTLCC(.CURS)
END;
ROUTINE OPTCLVC(I) =
BEGIN
LOCAL NEXT;
NEXT_.I[NEXTF];
IF CODEP(.NEXT)
THEF .NEXT[OPF] EQL PBGE THEN NEXT[OPF]_PBPL
ELSF .NEXT[OPF] EQL PBLT THEN NEXT[OPF]_PBMI;
RETURN IF TESTCC(.I,VCCBIT+CCCBIT)
THEN .I[NEXTF]
ELSE DELETE(.I);
END;
ROUTINE OPTCMP(CURS) =
IF NOT TESTCC(.CURS,NCCBIT+ZCCBIT+VCCBIT+CCCBIT) THEN RETURN DELETE(.CURS)
ELSE
BEGIN
LOCAL PREV,CURS1,PREV1,LABCURS,ADRVARSTR CMPSRC;
IF .CURS[DSTTYPE] EQL IMMEDAT THEN
BEGIN ! TRY TO CHANGE CMP(B) TO TST(B)
IF .CURS[OPF] EQL PCMPB
THEN CURS[DSTOFFSET]_.CURS[DSTOFFSET] AND #377;
IF .CURS[DSTNAME] EQL 0 AND
.CURS[DSTOFFSET] EQL 0
THEN (CURS[OPF]_IF .CURS[OPF] EQL PCMPB
THEN PTSTB
ELSE PTST;
SETCHANGE;
RETURN OPTTST(.CURS));
END;
PREV_PREVNONBR(.CURS);
IF CODEP(.PREV)
THEF SAMECMPP(.PREV,.CURS)
THEN RETURN DELETE(.CURS)
ELSE RETURN .CURS[NEXTF];
IF .PREV NEQ .CURS[PREVF]
THEN RETURN .CURS[NEXTF];
LABCURS_.PREV[TOPF];
UNTIL .LABCURS EQL .PREV DO
BEGIN
CURS1_.LABCURS[REFRF];
LABCURS_.LABCURS[NEXTF];
IF JMPP(.CURS1) ! CAUSE SOME BRANCHES TO A COMPARE
! TO BRANCH TO THE NEXT STATEMENT.
THEF CODEP(PREV1_PREVNONBR(.CURS1))
THEF .PREV1 NEQ .CURS
THEF SAMECMPP(.PREV1,.CURS)
THEN MOVEJMP(.CURS1,.CURS[NEXTF]);
END;
RETURN .CURS[NEXTF];
END;
ROUTINE OPTDEC(CURS) =
IF TESTCC(.CURS,CCCBIT) THEN .CURS[NEXTF]
ELSE
BEGIN
SETCHANGE;
COPYADR(DSTP(.CURS),SRCP(.CURS));
COPYADR(SRCP(.CURS),IMMEDONE);
CURS[OPF]_PSUB;
CURS[OPTYPEF]_ADDIOPT;
RETURN OPTADDSUB(.CURS);
END;
ROUTINE OPTINC(CURS) =
IF TESTCC(.CURS,CCCBIT) THEN .CURS[NEXTF]
ELSE
BEGIN
SETCHANGE;
COPYADR(DSTP(.CURS),SRCP(.CURS));
COPYADR(SRCP(.CURS),IMMEDONE);
CURS[OPF]_PADD;
CURS[OPTYPEF]_ADDIOPT;
RETURN OPTADDSUB(.CURS);
END;
ROUTINE OPTJSR(CURS) =
BEGIN
LOCAL NEXT;
NEXT_NXTCC(.CURS);
IF UNCONDJMPP(.NEXT)
THEF LABREFP(.NEXT)
THEN NEXT_NXTCC(LABREFED(.NEXT));
IF .NEXT[OPF] EQL PRTS AND
.NEXT[SRCREG] EQL 7 AND
.CURS[SRCREG] EQL 7 THEN
BEGIN
SETCHANGE;
CURS[OPF]_PBR;
CURS[OPTYPEF]_UNCONDJMPT;
IF NOT (
IF .CURS[DSTNAMET] EQL NORMNAME
THEF .CURS[DSTNAME] EQL .CURROUT
THEF .CURS[SRCOFFSET] EQL 0
THEN (MAKEJMP(.CURS,.BRAK1[NEXTF]);1) )
THEN COPYADR(SRCP(.CURS),DSTP(.CURS));
RETURN PUNCONDJMP(.CURS)
END;
RETURN .CURS[NEXTF];
END;
ROUTINE OPTMOV(CURS) =
BEGIN
LOCAL BYTES,ADRVARSTR REF;
IF .CURS[DSTFORM] EQL #10 ! MOV ANY,PC
THEN CLEARTOLAB(.CURS); ! IS LIKE A JMP OR BR
BYTES_.OPBYTES[.CURS[OPF]];
IF .CURS[SRCTYPE] EQL IMMEDAT AND
.CURS[SRCNAME] EQL 0 AND
.CURS[SRCOFFSET] EQL 0 AND
NOT TESTCC(.CURS,CCCBIT) THEN ! CHANGE MOV(B) #0,ANY
BEGIN ! TO CLR(B) ANY
SETCHANGE;
REDUCEADR(.CURS);
CURS[OPF]_IF .BYTES EQL 2 OR .CURS[DSTMODE] EQL 0
THEN PCLR ELSE PCLRB;
RETURN .CURS
END;
IF FAST THEN RETURN .CURS[NEXTF];
COPYADR(REF,SRCP(.CURS));
UPDATE(DSTP(.CURS),REF);
IF REGORMEMP(SRCP(.CURS)) AND
NOT MAYUSEP(REF,DSTP(.CURS)) THEN
BEGIN
EQUIVFWD(.CURS,SRCP(.CURS),DSTP(.CURS),.BYTES);
IF NOT MAYREFERP(REF,DSTP(.CURS)) THEN
BEGIN
COPYADR(REF,DSTP(.CURS));
DOWNDATE(SRCP(.CURS),REF);
DELBACKREF(.CURS,REF,IF .CURS[DSTMODE] EQL 0
THEN 2 ELSE .BYTES);
END
END;
RETURN NXTLCC(.CURS)
END;
ROUTINE OPTTST(CURS) =
IF NOT TESTCC(.CURS,NCCBIT+ZCCBIT+VCCBIT+CCCBIT) THEN DELETE(.CURS)
ELSF .CURS[SRCDELTA] NEQ 0 THEN RETURN .CURS[NEXTF]
ELSE BEGIN
LOCAL PREV,LABCURS,CURS1,PREV1;
PREV_PREVNONBR(.CURS);
IF CODEP(.PREV) THEN
CASE SETSCC(.PREV,.CURS) OF
SET
RETURN .CURS[NEXTF]; ! 0
RETURN DELETE(.CURS); ! 1
IF TESTCC(.CURS,CCCBIT) ! 2
THEN
BEGIN
DELADR(SRCP(.CURS),.CURS);
CURS[OPF]_PCLC;
RETURN(.CURS);
END
ELSE RETURN DELETE(.CURS);
IF TESTCC(.CURS,VCCBIT+CCCBIT) ! 3
THEN
BEGIN
DELADR(SRCP(.CURS),.CURS);
CURS[OPF]_PCLVC;
RETURN (.CURS);
END
ELSE RETURN DELETE(.CURS)
TES;
IF .PREV NEQ .CURS[PREVF]
THEN RETURN .CURS[NEXTF];
LABCURS_.PREV[TOPF];
UNTIL .LABCURS EQL .PREV DO
BEGIN
CURS1_.LABCURS[REFRF];
LABCURS_.LABCURS[NEXTF];
IF JMPP(.CURS1) ! CAUSE SOME BRANCHES TO A TEST
! TO BRANCH TO THE NEXT INSTRUCTION.
THEF CODEP(PREV1_PREVNONBR(.CURS1))
THEF .PREV1 NEQ .CURS
THEN CASE SETSCC(.PREV1,.CURS) OF
SET
0;
MOVEJMP(.CURS1,.CURS[NEXTF]);
IF NOT TESTCC(.CURS,CCCBIT)
THEN MOVEJMP(.CURS1,.CURS[NEXTF]);
IF NOT TESTCC(.CURS,VCCBIT+CCCBIT)
THEN MOVEJMP(.CURS1,.CURS[NEXTF]);
TES;
END;
RETURN .CURS[NEXTF];
END;
ROUTINE PCASPARAM(IND) =
BEGIN
LOCAL NEXT;
NEXT_NXTLCC(.IND);
IF NOT CASPARAMP(.NEXT) THEN NEXT_CLEARTOLAB(.IND);
FIXJMPIND(.IND);
RETURN .NEXT
END;
ROUTINE PCONDJMP(IND) =
BEGIN
LOCAL NEXT,NEXTC,LAB;
NEXT_NXTLCC(.IND);
IF NOT LABREFP(.IND) THEN
BEGIN
NEXTC_NEWCODECELL();
BEFORE(.IND,.NEXTC);
COMBLAB(MAKEJMP(.NEXTC,.NEXT));
NEXTC[OPF]_REVCOND(.IND[OPF]);
ST[.NEXTC[SRCNAME],OPTYPEF]_NEXTC[OPTYPEF]_CONDJMPT;
IND[OPF]_PJMP;
IND[OPTYPEF]_UNCONDJMPT;
RETURN .NEXTC;
END;
!LABEL REF
LAB _LABREFED(.IND);
IF .LAB EQL .NEXT THEN ! LOOK FOR
RETURN DELETE(.IND); ! BCOND .+1
IF CODEP(.NEXT) ! LOOK FOR
THEF .NEXT[NEXTF] EQL .LAB ! BCOND LAB1
THEF LABREFP(.NEXT) ! BR LAB2 (OR BCOND' LAB2)
! LAB1:
THEF BRIMPLY(.IND[OPF],.NEXT[OPF]) EQL 2
THEN RETURN DELETE(.IND)
ELSF .NEXT[OPF] EQL PBR THEN
BEGIN
DELADR(SRCP(.IND),.IND);
MAKEADR(SRCP(.IND),SRCP(.NEXT),.IND);
IND[OPF]_REVCOND(.IND[OPF]);
DELETE(.NEXT);
RETURN .IND
END;
NEXTC_NXTCC(.IND);
IF UNCONDJMPP(.NEXTC) ! LOOK FOR
THEF LABREFP(.NEXTC) ! BCOND LAB1
THEF LABREFED(.NEXTC) EQL .LAB ! BR LAB1
THEN RETURN DELETE(.IND);
NEXTC_CONDJMPSRC(.LAB,.IND);
IF .NEXTC NEQ .LAB THEN
BEGIN
SETCHANGE;
MOVEJMP(.IND,.NEXTC);
END;
RETURN .NEXT
END;
ROUTINE PLAB(LAB) =
BEGIN
LOCAL VAL,CURS1,CURS2,J1,J2;
LAB_COMBLAB(.LAB);
VAL_NXTLCC(.LAB);
IF EMPTYP(.LAB) THEN !NOT REFED
BEGIN
SETCHANGE;
ERASE(.LAB);
RETURN .VAL;
END;
!LABEL IS REFED.
CURS1_.LAB[TOPF];
UNTIL .CURS1 EQL .LAB DO !CROSS JUMPING
BEGIN
IF UNCONDJMPP(.CURS1) THEN
BEGIN
CURS2_.CURS1;
UNTIL (CURS2_.CURS2[NEXTF]) EQL .LAB DO
IF UNCONDJMPP(.CURS2) THEN
BEGIN
J1_.CURS1[REFRF];
J2_.CURS2[REFRF];
IF .J1[MINLOCF] GTR .J2[MINLOCF] THEN
SWAP(J1,J2);
BACKOV(.J1,.J2)
END
END;
CURS1_.CURS1[NEXTF]
END;
RETURN .VAL
END;
ROUTINE PREVNONBR(CURS)=
!
! GET PREVIOUS NON-BRANCH CELL.
!
BEGIN
DO CURS_.CURS[PREVF] WHILE IF CODEP(.CURS) THEN CONDJMPP(.CURS);
RETURN .CURS;
END;
LCCROUT(PRVCC,PREVF,CCP);
LCCROUT(PRVLCC,PREVF,LCCP);
ROUTINE PUNCONDJMP(IND) =
BEGIN
LOCAL NEXT,LAB,SVCHANGE,PREV,TMPRES,LAB1;
NEXT_CLEARTOLAB(.IND);
IF NOT LABREFP(.IND) THEN BEGIN
IND[OPF]_PJMP;
RETURN .NEXT
END;
!LABEL REF
LAB _LABREFED(.IND);
IF .LAB EQL .NEXT THEN ! BR .+1
RETURN DELETE(.IND);
IF FIXJMPIND(.IND) THEN ! INF LOOP
RETURN .NEXT;
!NOT INF LOOP. BACK UP.
LAB_LABREFED(.IND);
SVCHANGE_.CHANGE; CHANGE_0;
TMPRES_BACKOV(.IND,.LAB);
IF .CHANGE THEN RETURN .TMPRES
ELSE BEGIN
CHANGE_.SVCHANGE;
PREV_PRVLCC(.IND);
IF CODEP(.PREV)
THEF CONDJMPP(.PREV)
THEF LABREFP(.PREV) !SHOULD ALWAYS BE TRUE IF CONDJMPP IS TRUE!
THEN
BEGIN ! SWITCH THE TWO BRANCHES AND TRY CROSS-JUMPING AGAIN
LAB1_LABREFED(.PREV);
MOVEJMP(.PREV,.LAB);
MOVEJMP(.IND,.LAB1);
PREV[OPF]_REVCOND(.PREV[OPF]);
LAB_LABREFED(.IND);
CHANGE_0;
TMPRES_BACKOV(.IND,.LAB);
CHANGE_.CHANGE OR .SVCHANGE;
END;
RETURN .TMPRES
END
END;
ROUTINE REACH(CURS) =
BEGIN
LOCAL LAB,DIST,NDIST,REF,BEST,BDIST,REFCELL;
LAB_LABREFED(.CURS);
DIST_.LAB[MINLOCF] - .CURS[MINLOCF];
IF .DIST LEQ 127 AND .DIST GTR -128 THEN RETURN .LAB;
REF_.LAB[TOPF];
BEST_0;
BDIST_0;
UNTIL .REF EQL .LAB DO
BEGIN
REFCELL_.REF[REFRF];
NDIST_.REFCELL[MINLOCF] - .CURS[MINLOCF];
IF .NDIST LEQ 127 AND
.NDIST GTR -128 AND
ABS(.NDIST) GTR .BDIST AND
BRIMPLY(.CURS[OPF],.REFCELL[OPF]) EQL 1 AND
(BRIMPLY(.REFCELL[OPF],.CURS[OPF]) NEQ 1 OR
SIGN(.NDIST) EQL SIGN(.DIST))
THEN BEGIN
BDIST_ABS(.NDIST);
BEST_.REFCELL;
END;
REF_.REF[NEXTF];
END;
RETURN .BEST;
END;
ROUTINE SAMEADRP(A,B) =
RETURN
IF .A[ANAMET] EQL NORMNAME THEN
.A[ATYPREGNAME] EQL .B[ATYPREGNAME] AND
.A[AOFFSET] EQL .B[AOFFSET] AND
.A[ATYPE] NEQ UNUSED
ELSF .A[ANAMET] EQL LABELNAME
THEF .B[ANAMET] EQL LABELNAME
THEN .ST[.A[ANAME],REFEF] EQL .ST[.B[ANAME],REFEF]
ELSE 0
ELSE 0;
ROUTINE SAMECMPP(PREV,CURS)=
IF .PREV[OPF] EQL .CURS[OPF] AND
.CURS[SRCDELTA] EQL 0 AND
.CURS[DSTDELTA] EQL 0
THEF SAMEADRP(DSTP(.PREV),DSTP(.CURS)) THEN
BEGIN
LOCAL ADRVARSTR CMPSRC;
COPYADR(CMPSRC,SRCP(.CURS));
UPDATE(DSTP(.PREV),CMPSRC);
RETURN SAMEADRP(SRCP(.PREV),CMPSRC);
END;
ROUTINE SAMEINDP(A,B) =
!
! TRUE IF ADDRESS B IS ADDRESS A + INDIRECT
!
IF .A[AREGNAME] EQL .B[AREGNAME]
THEF .A[AOFFSET] EQL .B[AOFFSET]
THEN IF IMMORREGP(.A)
THEN .B[ATYPE] EQL MEMAT
ELSF .A[ATYPE] EQL MEMAT
THEN .B[ATYPE] EQL INDAT;
ROUTINE SETSCC(I,T) =
!
! T IS A TST INSTRUCTION, I IS THE PREVIOUS INSTRUCTION.
! THE RESULT RETURNED IS:
! 0 - T MUST NOT BE DELETED
! 1 - T IS SUPERFLUOUS, MAY BE DELETED
! 2 - T IS SUPERFLUOUS IF NOBODY IS WORRIED ABOUT CARRY
! 3 - T IS SUPERFLUOUS IF NOBODY IS WORRIED ABOUT CARRY OR OVERFLOW
!
IF NOT CODEP(.I) THEN RETURN 0
ELSE RETURN CASE .CCSETTYPE[.I[OPF]] OF
SET
0;
IF .OPBYTES[.I[OPF]] EQL .OPBYTES[.T[OPF]]
THEF SAMEADRP(DSTP(.I),SRCP(.T)) THEN 2
ELSF NOT MAYUSEP(SRCP(.T),DSTP(.I)) THEN
BEGIN
LOCAL ADRVARSTR A;
COPYADR(A,SRCP(.T));
DOWNDATE(DSTP(.I),A);
IF SAMEADRP(SRCP(.I),A) THEN 2 ELSE 0
END;
IF .OPBYTES[.I[OPF]] EQL .OPBYTES[.T[OPF]]
THEF SAMEADRP(DSTP(.I),SRCP(.T)) THEN 2;
IF .OPBYTES[.I[OPF]] EQL .OPBYTES[.T[OPF]]
THEF SAMEADRP(DSTP(.I),SRCP(.T)) THEN 3;
IF .OPBYTES[.I[OPF]] EQL .OPBYTES[.T[OPF]]
THEF SAMEADRP(SRCP(.I),SRCP(.T)) THEN 1;
IF .OPBYTES[.I[OPF]] EQL .OPBYTES[.T[OPF]]
THEF SAMEADRP(SRCP(.I),SRCP(.T)) THEN 3;
IF .OPBYTES[.T[OPF]] EQL 2
THEF SAMEADRP(SRCP(.I),SRCP(.T)) THEN 2;
BEGIN
I_.I[PREVF];
IF .T EQL .I THEN 0 ELSE SETSCC(.I,.T)
END
TES;
ROUTINE TESTCC(CURS,CCS) =
!
! TRUE IF ANY CC BITS INDICATED BY CCS
! ARE USED BEFORE BEING RESET, ON ANY
! CONTROL PATH FOLLOWING CURS.
!
BEGIN
LOCAL CCSL,CCUSE;
CCSL_IF .FINALSW THEN CCSHIFT(.CCS) ELSE .CCS;
CURS_NXTCC(.CURS);
CCUSE_.CCUSETYPE[.CURS[OPF]];
RETURN IF (.CCUSE AND .CCSL) NEQ 0 THEN 1
ELSF (.CCUSE AND JCCBIT) NEQ 0
THEF LABREFP(.CURS)
THEN BEGIN
LOCAL LAB,T;
LAB_LABREFED(.CURS);
IF LABSEENP(.LAB) THEN RETURN 0;
LAB[LABSEENF]_1;
T_TESTCC(.LAB,.CCS);
LAB[LABSEENF]_0;
RETURN IF .T THEN 1
ELSF CONDJMPP(.CURS) THEN TESTCC(.CURS,.CCS)
ELSE 0;
END
ELSE NOT .FINALSW
ELSF (.CCUSE AND NACBIT) NEQ 0 AND
(.CCSL AND CCCBIT) NEQ 0
THEN TESTCC(.CURS,CCCBIT)
END;
ROUTINE TESTEQL(CURS) =
!
! MODIFY NEXT INSTRUCTION TO ASSUME ZERO CONDITION
! CODE. RETURNS 1 IF MODIFICATION NOT POSSIBLE.
!
BEGIN
LOCAL CURS1;
BIND NORMALVEC NOTBREQL = PLIT
(0,1,1,0,0,1,0,1,0,1,1,0,0,1,0,1);
CURS1_NXTCC(.CURS);
IF CODEP(.CURS1)
THEF CONDJMPP(.CURS1)
THEF .NOTBREQL[.CURS1[OPF]-PBR] THEN BEGIN
DELETE(.CURS1);
RETURN 0;
END
ELSE BEGIN
SETCHANGE;
CURS1[OPF]_PBR;
CURS1[OPTYPEF]_UNCONDJMPT;
RETURN 0;
END;
RETURN TESTCC(.CURS,NCCBIT+ZCCBIT+VCCBIT+CCCBIT);
END;
ROUTINE TESTPOP(A,IADD,I) =
!
! FUNCTION:
! SEE IF ADDRESS "A" IN CODE CELL "I" CAN BE MODIFIED BECAUSE
! OF THE EXISTENCE OF LATER IMMEDIATE ADD (SUB) INSTRUCTION "IADD".
! CALLED FROM A BACKWARD SCAN IN OPTADDSUB;
! A RETURN VALUE OF 1 TERMINATES THE SCAN.
!
BEGIN
LOCAL BYTES,OFFST,NEWADD,NEWOFFSET;
IF .A[AREG] NEQ .IADD[DSTREG] THEN RETURN
IF NOT .FINALSW THEN NOT IMMORREGP(.A) ! RETURN 1 IF AN ADJUSTMENT
ELSF .IADD[DSTREG] NEQ SP OR NOT .UNLOCFLG THEN 0 ! TO IADD MIGHT CAUSE A TO
ELSF .A[ATYPE] EQL INDAT THEN 1 ! POINT ABOVE TOP OF (SP) STACK.
ELSF .A[ATYPE] EQL MEMAT AND
.A[ANAME] EQL 0 AND
.A[AREG] NEQ PC THEN 1
ELSE 0;
IF .A[AFORM] EQL 0 THEN RETURN 1;
IF .A[ANAME] GTR 1 THEN RETURN 0;
OFFST_IF .IADD[OPF] EQL PSUB
THEN -SRCOFFSETV(IADD)
ELSE SRCOFFSETV(IADD);
IF ADELTAV(A) GTR 0
THEF (.OFFST LSS 0 OR
.IADD[SRCNAME] NEQ 0)
AND .A[ATYPE] NEQ INDAT
THEN
BEGIN ! CHANGE A FROM (REG)+ TO @REG.
BYTES_-ADELTAV(A);
A[AFORM]_1;
A[ADELTA]_A[AOFFSET]_0;
END
ELSE RETURN 1
ELSF ADELTAV(A) LSS 0 THEN RETURN 1 ! A IS -(REG) OR @-(REG)
ELSE
BEGIN
BYTES_IF .A[ATYPE] EQL INDAT
OR .A[AREG] GEQ SP
THEN 2
ELSE .OPBYTES[.I[OPF]];
IF AOFFSETV(A) EQL -.BYTES THEN
BEGIN ! CHANGE A FROM -2(REG) TO -(REG)
BYTES_-.BYTES; ! OR FROM @-2(REG) TO @-(REG).
A[ADELTA]_.BYTES;
A[AFORM]_.A[AFORM]-2;
A[AOFFSET]_0
END
ELSF AOFFSETV(A) EQL 0 THEN
IF (.IADD[SRCNAME] EQL 0 AND
.OFFST-.BYTES GEQ 0)
OR (.A[ATYPE] EQL INDAT AND
(.A[AREG] NEQ SP OR .OFFST GTR 0))
THEN
BEGIN ! CHANGE A FROM @REG TO (REG)+
A[ADELTA]_.BYTES; ! OR FROM @0(REG) TO @(REG)+.
A[AFORM]_IF .A[ATYPE] EQL MEMAT THEN 2 ELSE 3;
A[AOFFSET]_-.BYTES
END
ELSE RETURN 1
ELSF
BEGIN ! THIS BLOCK CHECKS TO SEE IF WE CAN,
NEWOFFSET_AOFFSETV(A); ! IN EFFECT, PUT IADD BEFORE I, TO
IF .A[AREG] NEQ SP ! CHANGE A FROM N(REG) TO @REG OR (REG)+.
THEF (.NEWOFFSET EQL .OFFST AND
.A[ATYPE] EQL MEMAT)
OR .NEWOFFSET EQL .OFFST-.BYTES
THEN PUSHPOPFLAG_.OFFST;
IF (.NEWOFFSET EQL .PUSHPOPFLAG AND
.A[ATYPE] EQL MEMAT)
OR .NEWOFFSET EQL .PUSHPOPFLAG-.BYTES
THEF .A[ATYPE] EQL MEMAT OR
.A[AREG] NEQ SP OR
NOT .UNLOCFLG
THEF .OPERTYPE[.I[OPF]] NEQ TWOOP THEN 1
ELSF SRCP(.I) EQL .A THEN 1
ELSF .I[SRCREG] NEQ .A[AREG] THEN
(IF .A[AREG] NEQ SP OR NOT .UNLOCFLG THEN 1
!
! A IS N(SP) AND UNLOCFLG IS ON -- MUST CHECK IF
! SRCP(.I) MAY POINT TO STACK.
!
ELSF .I[SRCTYPE] EQL INDAT THEN 0
ELSF .I[SRCTYPE] EQL MEMAT AND
.I[SRCNAME] EQL 0 AND
.I[SRCREG] NEQ PC
THEN 0
ELSE 1)
ELSF .I[SRCTYPE] NEQ REGAT AND
.I[SRCDELTA] EQL 0
THEF .I[SRCTYPE] NEQ INDAT
OR .A[AREG] NEQ SP
OR NOT .UNLOCFLG
THEF .A[AREG] NEQ SP
OR SRCOFFSETV(I) GEQ .NEWOFFSET-2
THEN ! MUST CHANGE SRCP(.I),
BEGIN ! SINCE TESTPP WILL NOT.
I[SRCOFFSET]_SRCOFFSETV(I)-AOFFSETV(A);
IF SRCOFFSETV(I) EQL -.BYTES AND
.I[SRCNAME] LEQ 1 THEN
BEGIN
I[SRCDELTA]_.BYTES;
I[SRCFORM]_IF .I[SRCTYPE] EQL MEMAT THEN 2 ELSE 3;
NEWOFFSET_.NEWOFFSET-.BYTES;
END;
1
END
END
THEN % IT WORKED! %
BEGIN
IF AOFFSETV(A) EQL .PUSHPOPFLAG THEN
(A[AOFFSET]_0;
A[AFORM]_1) ELSE
(A[ADELTA]_.BYTES;
A[AOFFSET]_-.BYTES;
A[AFORM]_IF .A[ATYPE] EQL MEMAT THEN 2 ELSE 3);
NEWADD_BEFORE(.I,NEWCODECELL());
NEWADD[OPF]_PADD;
NEWADD[OPTYPEF]_ADDIOPT;
COPYADR(DSTP(.NEWADD),DSTP(.IADD));
COPYADR(SRCP(.NEWADD),IMMEDZERO);
NEWADD[SRCOFFSET]_.NEWOFFSET;
BYTES_.PUSHPOPFLAG;
END
ELSE
(IF AOFFSETV(A) LSS .PUSHPOPFLAG+.BYTES
THEN PUSHPOPFLAG_AOFFSETV(A);
RETURN 0);
END;
OFFST_.OFFST-.BYTES;
IADD[SRCOFFSET]_IF .IADD[OPF] EQL PSUB
THEN -.OFFST
ELSE .OFFST;
WHILE 1 DO ! FIX UP CELLS BETWEEN I AND IADD
BEGIN ! TO REFLECT CHANGES IN THOSE TWO CELLS.
IADD_.IADD[PREVF];
SELECT .OPERTYPE[.IADD[OPF]] OF
NSET
ONEOP: IF TESTPP(.A,SRCP(.IADD),.BYTES) THEN EXITLOOP;
TWOOP: IF TESTPP(.A,DSTP(.IADD),.BYTES) THEN EXITLOOP
ELSF TESTPP(.A,SRCP(.IADD),.BYTES) THEN EXITLOOP
TESN;
END;
SETCHANGE;
RETURN 1
END;
COMMENT ! TESTPP
!
! FUNCTION:
! ADJUST ADDRESS "I" BY AN AMOUNT "DELTA" IF ADDRESSES
! "A" AND "I" USE THE SAME REGISTER. RETURN TRUE IF
! A EQUALS I, TO SIGNAL THE END OF AN ADDRESS ADJUSTMENT SCAN.
!
ROUTINE TESTPP(A,I,DELTA) =
IF .A EQL .I THEN RETURN 1
ELSF .A[AREG] EQL .I[AREG] THEN BEGIN
IF (I[AOFFSET]_AOFFSETV(I)-.DELTA) EQL 0 THEN
IF .I[AFORM] EQL 6 THEN I[AFORM]_1;
RETURN 0
END
ELSE RETURN 0;
ROUTINE TESTPUSH(A,IADD,I) =
!
! FUNCTION:
! SEE IF ADDRESS "A" IN INSTRUCTION "I" CAN BE MODIFIED BECAUSE OF
! THE EXISTENCE OF EARLIER IMMEDIATE ADD (SUB) INSTRUCTION "IADD".
! CALLED FROM A FORWARD SCAN IN OPTADDSUB;
! A RETURN VALUE OF 1 TERMINATES THE SCAN.
!
BEGIN
LOCAL BYTES,OFFST,NEWADD,NEWOFFSET;
IF .A[AREG] NEQ .IADD[DSTREG] THEN
RETURN (IF NOT .FINALSW THEN NOT IMMORREGP(.A));
IF .A[AFORM] EQL 0 THEN RETURN 1;
IF .A[ANAME] GTR 1 THEN RETURN 0;
OFFST_IF .IADD[OPF] EQL PSUB
THEN -SRCOFFSETV(IADD)
ELSE SRCOFFSETV(IADD);
IF ADELTAV(A) LSS 0
THEF (.OFFST GTR 0 OR
.IADD[SRCNAME] NEQ 0) AND
.A[ATYPE] NEQ INDAT
THEN BEGIN ! CHANGE A FROM -(REG) TO @REG.
BYTES_ADELTAV(A);
A[AFORM]_1;
A[ADELTA]_A[AOFFSET]_0;
END
ELSE RETURN 1
ELSF ADELTAV(A) GTR 0 THEN RETURN 1 ! A IS (REG)+ OR @(REG)+
ELSE
BEGIN
BYTES_IF .A[ATYPE] EQL INDAT
OR .A[AREG] GEQ SP
THEN 2
ELSE .OPBYTES[.I[OPF]];
IF AOFFSETV(A) EQL -.BYTES THEN
BEGIN ! CHANGE A FROM -2(REG) TO (REG)+
A[ADELTA]_.BYTES; ! OR FROM @-2(REG) TO @(REG)+.
A[AFORM]_.A[AFORM]-4;
BYTES_-.BYTES;
END
ELSF AOFFSETV(A) EQL 0 THEN
IF (.IADD[SRCNAME] EQL 0 AND
.OFFST+.BYTES LEQ 0)
OR (.A[ATYPE] EQL INDAT
AND .A[AREG] NEQ SP)
THEN ! CHANGE A FROM @REG TO -(REG)
BEGIN ! OR FROM @0(REG) TO @-(REG).
A[ADELTA]_-.BYTES;
A[AFORM]_IF .A[ATYPE] EQL MEMAT THEN 4 ELSE 5;
A[AOFFSET]_0
END
ELSE RETURN 1
ELSF
BEGIN ! THIS BLOCK CHECKS TO SEE IF WE CAN,
NEWOFFSET_AOFFSETV(A); ! IN EFFECT, PUT IADD AFTER I, TO
IF .A[AREG] NEQ SP ! CHANGE A FROM -N(REG) TO @REG OR -(REG).
THEF (.NEWOFFSET EQL -.OFFST AND
.A[ATYPE] EQL MEMAT)
OR .NEWOFFSET EQL -.OFFST-.BYTES
THEN PUSHPOPFLAG_-.OFFST;
IF NOT TESTCC(.I,NCCBIT+ZCCBIT+VCCBIT+CCCBIT)
THEF (.NEWOFFSET EQL .PUSHPOPFLAG AND
.A[ATYPE] EQL MEMAT)
OR .NEWOFFSET EQL .PUSHPOPFLAG-.BYTES
THEF .OPERTYPE[.I[OPF]] NEQ TWOOP THEN 1
ELSF DSTP(.I) EQL .A THEN 1
ELSF .I[DSTREG] NEQ .A[AREG] THEN 1
ELSF .I[DSTTYPE] NEQ REGAT AND
.I[DSTDELTA] EQL 0
THEF .A[AREG] NEQ SP
OR DSTOFFSETV(I) GEQ .NEWOFFSET-2
THEN ! MUST CHANGE DSTP(.I),
BEGIN ! SINCE TESTPP WILL NOT.
I[DSTOFFSET]_DSTOFFSETV(I)-AOFFSETV(A);
IF DSTOFFSETV(I) EQL -.BYTES AND
.I[DSTNAME] LEQ 1 THEN
BEGIN
I[DSTOFFSET]_0;
I[DSTDELTA]_-.BYTES;
I[DSTFORM]_IF .I[DSTTYPE] EQL MEMAT
THEN 4 ELSE 5;
NEWOFFSET_.NEWOFFSET-.BYTES;
END;
1
END
END
THEN % IT WORKED! %
BEGIN
IF AOFFSETV(A) EQL .PUSHPOPFLAG
THEN A[AFORM]_1
ELSE (A[ADELTA]_-.BYTES;
A[AFORM]_IF .A[ATYPE] EQL MEMAT
THEN 4 ELSE 5);
NEWADD_AFTER(.I,NEWCODECELL());
NEWADD[OPF]_PADD;
NEWADD[OPTYPEF]_ADDIOPT;
COPYADR(DSTP(.NEWADD),DSTP(.IADD));
COPYADR(SRCP(.NEWADD),IMMEDZERO);
NEWADD[SRCOFFSET]_-.NEWOFFSET;
BYTES_.PUSHPOPFLAG;
A[AOFFSET]_0;
END
ELSE
(IF AOFFSETV(A) LSS .PUSHPOPFLAG+.BYTES
THEN PUSHPOPFLAG_AOFFSETV(A);
RETURN 0)
END;
OFFST_.OFFST+.BYTES;
IADD[SRCOFFSET]_IF .IADD[OPF] EQL PSUB
THEN -.OFFST
ELSE .OFFST;
WHILE 1 DO ! FIX UP CELLS BETWEEN IADD AND I,
BEGIN ! REFLECTING CHANGES IN THOSE TWO CELLS.
IADD_.IADD[NEXTF];
SELECT .OPERTYPE[.IADD[OPF]] OF
NSET
ONEOP: IF TESTPP(.A,SRCP(.IADD),.BYTES) THEN EXITLOOP;
TWOOP: IF TESTPP(.A,SRCP(.IADD),.BYTES) THEN EXITLOOP
ELSF TESTPP(.A,DSTP(.IADD),.BYTES) THEN EXITLOOP
TESN;
END;
SETCHANGE;
RETURN 1
END;
ROUTINE UPDATE(A,B) =
IF .A[AREG] EQL .B[AREG] THEN B[AOFFSET]_AOFFSETV(B)-ADELTAV(A);
END
END
ELUDOM