Google
 

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