! 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