.TITLE CC201 .IDENT /X01/ .NLIST BEX .ENABL LC ; ; C COMPILER ; EXPRESSION TREE MODIFIER (NON EIS) ; ; VERSION X01 ; ; DAVID G. CONROY 01-APR-78 ; .GLOBL MODIFY .GLOBL MWCON .GLOBL NODE .GLOBL CONZER .MCALL CALL .MCALL CALLR .MCALL RETURN ; ; LOCAL DATA ; CHANGE: .BLKW 1 ;SOMETHING CHANGED FLAG MWPSFG: .BLKW 1 ;PSECT FLAG FOR MWCON NLIST: .BLKW 15. ;NODE LIST (RORDER) LLIST: .BLKW 15. ;LEAF LIST (RORDER) ; ; STRINGS. ; STR01: .ASCIZ " .psect .mwcn."<12> STR02: .ASCIZ " .psect .prog."<12> STR03: .ASCIZ " .word " .EVEN .PAGE ;+ ; ** MODIFY - MODIFY AN EXPRESSION TREE ; ; THIS ROUTINE IS CALLED TO MODIFY AN EXPRESSION TREE PRIOR TO ACTUAL ; CODE GENERATION. SOME OF THE TRANSFORMATIONS ARE MADE TO MAKE THE ; CODE GENERATOR'S LIFE A LITTLE EASIER. ; ; THE MODIFICATION LOOP IS TABLE DRIVEN. IT REPEATS UNTIL EITHER THE ; TREE REDUCES TO A LEAF NODE, OR A PASS IS MADE WITH NO CHANGES. ; ; INPUTS: ; R5=TREE ; ; OUTPUTS: ; R5=MODIFIED TREE ;- MODIFY: CLR CHANGE ;NOTHING HAS CHANGED CALL MOD1 ;DO A MODIFICATION PASS TST CHANGE ;REPEAT IF ANY CHANGES BNE MODIFY ; RETURN ; MOD1: MOV R3,-(SP) ;SAVE REGISTERS MOV R4,-(SP) ; MOV R5,-(SP) ; MOV (R5),R4 ;OP MOV R4,R3 ; ASL R3 ; MOV OPDOPE(R3),R3 ;OPDOPE BIT #LEAF,R3 ;LEAF NODES GET BNE 30$ ;NO MODIFICATION TST E.ROP(R5) ;IS THERE A RIGHT SUBTREE BEQ 10$ ;NO MOV E.ROP(R5),R5 ;YES, MODIFY IT CALL MOD1 ;BY CALLING OURSELF MOV R5,R0 ; MOV (SP),R5 ; MOV R0,E.ROP(R5) ; 10$: MOV E.LOP(R5),R5 ;MODIFY LEFT SUBTREE CALL MOD1 ;BY CALLING OURSELF MOV R5,R0 ; MOV (SP),R5 ; MOV R0,E.LOP(R5) ; ; ; NOW APPLY MODIFICATIONS TO THE NODE ITSELF. ; MOV #40$,R2 ;SET UP FOR MODIFICATION LOOP 20$: CMP R2,#50$ ;BREAK IF DONE BHIS 30$ ;ALL MODIFICATIONS CALL @(R2)+ ;CALL FUNCTION MOV (R5),R4 ;REFRESH OP MOV R4,R3 ; ASL R3 ; MOV OPDOPE(R3),R3 ;AND DOPE BIT #LEAF,R3 ;DO THE NEXT ONE IF BEQ 20$ ;WE HAVN'T TURNED INTO A LEAF 30$: TST (SP)+ ;THROW AWAY R5 MOV (SP)+,R4 ;RETURN MOV (SP)+,R3 ; RETURN ; 40$: .WORD RORDER ;REORDER (MUST BE FIRST) .WORD FOLD ;FOLD INTEGERS .WORD FFOLD ;FOLD FLOATING POINT .WORD UNARY ;DELETE NEEDLESS UNARY OPERATIONS .WORD AMPER ;SPECIAL FIXES FOR AMPERSAND .WORD SUBSUM ;SUBSUME CONSTANTS IN &A+CONST .WORD STAR ;SPECIAL FIXES FOR STAR .WORD AUTOS ;EXPLOIT AUTO(INC/DEC) ADDRESSING .WORD FIXCVR ;ADJUST OP.CVR NODES .WORD MOP1 ;DELETE USELESS MULOPS .WORD MKBIC ;AND INTO BIC .WORD DZEROP ;DELETE OPERATIONS WITH ZERO 50$: ;THE END .PAGE ;+ ; ** RORDER - REORDER. ; ; THIS ROUTINE EXAMINES THE SUBTREES OF COMMUTATIVE OPERATIONS AND RE ; ORDERS THE NODES IN AN "OPTIMAL" MANNER. THE CONSTANTS ARE PULLED ; TOGETHER FOR THE BENEFIT OF THE FOLDER. ALL TREE NODES WITH ADDRESS ; ARE MOVED TO RIGHT BRANCHES OF THE UPPERMOST TREE NODES. HOPEFULLY ; THIS MOVES THE HARD COMPUTATION TO THE BOTTOMOST LEFT BRANCHES. ; ; THE REORDERING IS A THREE PASS PROCESS. FIRST ALL OF THE TIP NODES ; ARE LOCATED. THESE ARE PACKED INTO THE "LLIST". THE NODES IN THIS ; LIST ARE ORDERED "ORDINARY, ADDRESSABLE, CONSTANTS". THE "NLIST" IS ; USED TO SAVE POINTERS TO THE NODES. SECONDLY A RECONSTAUCTION PASS ; FROM BACK TO FRONT IS DONE TO COLLECT ALL OF THE CONSTANT NODES FOR ; FUTURE FOLDING. A POINTER TO THIS TREE IS SAVED BACK INTO THE LLIST ; FINALLY A FRONT TO BACK REASSEMBLY OF ALL THE TIP NODES IS DONE. ;- RORDER: BIT #COMMUT,R3 ;THE OPERATION MUST BE BEQ 50$ ;COMMUTATIVE BIT #RELOP,R3 ;BUT NOT A BNE 50$ ;RELATIONAL MOV R2,-(SP) ;SAVE R2 MOV #NLIST,R2 ;GET POINTERS TO NODE LIST MOV #LLIST,R3 ;AND LEAF LIST CALL INSERT ;INSERT TREE INFO IN THEM MOV -(R3),R5 ;START WITH A LEAF 10$: CMP R3,#LLIST ;THEN, AS LONG AS THERE ARE BLOS 20$ ;MORE LEAVES CMP @-2(R3),#OP.CON ;AND THE LEAF IS A BNE 20$ ;CONSTANT MOV -(R2),R0 ;GET A NODE AND MOV R5,E.LOP(R0) ;LINK IT INTO THE MOV -(R3),E.ROP(R0) ;NEW TREE MOV R0,R5 ;MAKE THE NEW NODE THE TREE TOP BR 10$ ;AND CONTINUE TIL DONE 20$: MOV R5,(R3)+ ;SAVE THE CONSTANT TREE MOV R3,-(SP) ;SAVE END OF LLIST POINTER MOV #LLIST,R3 ;MOVE BACK TO THE FRONT MOV (R3)+,R5 ;START WITH A LEAF 30$: CMP R3,(SP) ;MORE? BHIS 40$ ;NO MOV -(R2),R0 ;GRAB A NODE MOV R5,E.LOP(R0) ;SET LEFT AND MOV (R3)+,E.ROP(R0) ;RIGHT SUBTREES MOV R0,R5 ;RESET NODE POINTER AND BR 30$ ;REPEAT 40$: TST (SP)+ ;FIX STACK MOV (SP)+,R2 ;RESTORE AND 50$: RETURN ;RETURN ; ; INSERT ENTRIES INTO LLIST AND NLIST. ; USED BY RORDER. ; INSERT: CMP (R5),R4 ;IS THE OPERATOR CORRECT BNE 10$ ;NO, ITS A LEAF MOV R5,(R2)+ ;MAKE ENTRY INTO THE NLIST MOV R5,-(SP) ;SAVE THE TREE MOV E.LOP(R5),R5 ;INSERT THE CALL INSERT ;LEFT SUBTREE MOV (SP)+,R5 ;RECOVER THE TREE MOV E.ROP(R5),R5 ;INSERT THE CALL INSERT ;RIGHT SUBTREE BR 60$ ;DONE 10$: CMP (R5),#OP.CON ;IS IT A CONSTANT BNE 20$ ;NO MOV R5,(R3)+ ;APPEND TO THE LEAF BR 60$ ;LIST 20$: MOV R3,R0 ;MUST MOVE THE TST (R3)+ ;ENTIRE MOV R3,R1 ;LIST FORWARD CALL HASADR ;IS THIS ADDRESSABLE BCS 40$ ;NO, ON FRONT 30$: CMP R0,#LLIST ;MOVE ONLY THE CONSTANTS BLOS 50$ ;BACK CMP @-2(R0),#OP.CON ;SO THE ADDRESSABLES BNE 50$ ;END UP IN THE MOV -(R0),-(R1) ;RIGHT BR 30$ ;PLACE 40$: CMP R0,#LLIST ;DONE BLOS 50$ ;YES MOV -(R0),-(R1) ;NO, MOVE AN ENTRY BR 40$ ;AND GO FOR MORE 50$: MOV R5,(R0) ;MAKE ENTRY ON THE FRONT 60$: RETURN ;COMMON RETURN .PAGE ;+ ; ** FOLD - FOLD INTEGER EXPRESSIONS ; ; THIS ROUTINE COLLAPSES EXPRESSIONS WITH CONSTANT INTEGER OPERANDS ; YES VIRGINIA, THERE IS A TEST FOR DIVIDE BY ZERO IN BOTH DIVISION ; AND REMAINDER NODES. ;- FOLD: MOV R2,-(SP) ;SAVE REGISTERS MOV E.ROP(R5),R2 ;GET THE RIGHT OPERAND BEQ 10$ ;ISN'T ONE CMP (R2),#OP.CON ;CHECK FOR WORD CONSTANT BNE 140$ ; CMPB E.TYPE(R2),#TY.LNG ; BHIS 140$ ; MOV E.VAL(R2),R2 ;GET ITS VALUE 10$: MOV E.LOP(R5),R1 ;GET THE LEFT OPERAND CMP (R1),#OP.CON ;CHECK FOR WORD CONSTANT BNE 140$ ; CMPB E.TYPE(R1),#TY.LNG ; BHIS 140$ ; MOV E.VAL(R1),R1 ;GET ITS VALUE CMP R4,#OP.ADD ;LONG ELSE-IF DOING THE FOLD BNE 20$ ; ADD R2,R1 ;ADDITION BR 130$ ; 20$: CMP R4,#OP.SUB ;SUBTRACTION BNE 30$ ; SUB R2,R1 ; BR 130$ ; 30$: CMP R4,#OP.MUL ;MULTIPLICATION BNE 40$ ; MOV R2,-(SP) ; CALL $MULR1 ; TST (SP)+ ; BR 130$ ; 40$: CMP R4,#OP.DIV ;DIVISION BNE 50$ ; TST R2 ;DO NOTHING ON DIVIDE CHECK BEQ 140$ ; CLR R0 ; TST R1 ; BPL 42$ ; COM R0 ; 42$: MOV R2,-(SP) ; CALL $DIVR0 ; TST (SP)+ ; MOV R0,R1 ; BR 130$ ; 50$: CMP R4,#OP.MOD ;REMAINDER BNE 60$ ; TST R2 ;DO NOTHING ON DIVIDE CHECK BEQ 140$ ; CLR R0 ; TST R1 ; BPL 52$ ; COM R0 ; 52$: MOV R2,-(SP) ; CALL $DIVR0 ; TST (SP)+ ; BR 130$ ; 60$: CMP R4,#OP.ASL ;SHIFT LEFT BNE 70$ ; 62$: DEC R2 ; BMI 130$ ; ASL R1 ; BR 62$ ; 70$: CMP R4,#OP.ASR ;SHIFT RIGHT BNE 80$ ; 72$: DEC R2 ; BMI 130$ ; ASR R1 ; BR 72$ ; 80$: CMP R4,#OP.AND ;BITWISE AND BNE 90$ ; COM R2 ; BIC R2,R1 ; BR 130$ ; 90$: CMP R4,#OP.OR ;BITWISE OR BNE 100$ ; BIS R2,R1 ; BR 130$ ; 100$: CMP R4,#OP.XOR ;BITWISE EXCLUSIVE OR BNE 110$ ; MOV R2,-(SP) ;XOR = (A BIC B) BIS (B BIC A). BIC R1,R2 ; BIC (SP)+,R1 ; BIS R2,R1 ; BR 130$ ; 110$: CMP R4,#OP.NEG ;UNARY NEGATION BNE 120$ ; NEG R1 ; BR 130$ ; 120$: CMP R4,#OP.COM ;BITWISE COMPLEMENT BNE 140$ ; COM R1 ; 130$: MOV E.LOP(R5),R5 ;USE LEFT CONST NODE FOR RESULT MOV R1,E.VAL(R5) ; INC CHANGE ;SAY SOMETHING CHANGED 140$: MOV (SP)+,R2 ;RETURN RETURN ; .PAGE ;+ ; ** FFOLD - FOLD FLOATING EXPRESSIONS ; ; THIS ROUTINE ONLY FOLDS UNARY NEGATION. THIS IS PRIMARILY TO ALLOW ; NEGATIVE CONSTANTS IN INITIALISERS. ;- FFOLD: CMP R4,#OP.NEG ;NEGATION BNE 10$ ;NO CMPB E.TYPE(R5),#TY.DBL ;WITH DOUBLE RESULT BNE 10$ ;NO MOV E.LOP(R5),R0 ;GET LEFT SUBTREE CMP (R0),#OP.CON ;CONSTANT BNE 10$ ;NO ADD #100000,E.VAL(R0) ;REVERSE THE SIGN BIT MOV R0,R5 ;DELETE THE NEGATION INC CHANGE ;MARK A CHANGE 10$: RETURN ;DONE .PAGE ;+ ; ** UNARY - DELETE USELESS UNARY OPERATORS ; ; THIS ROUTINE SEARCHES FOR NEG OR NEG, COM OF COM AND NOT OF NOT AND ; THROWS THEM BOTH AWAY. THE MOST IMPRORTANT OF THESE IS PROBABLY COM ; OF COM, WHICH GETS GENERATED OFTEN IN THE RIGHT SUBTREE OF BIT TEST ; NODES. ;- UNARY: CMP R4,#OP.COM ;LOOK FOR OP.COM BEQ 10$ ; CMP R4,#OP.NEG ;OP.NEG BEQ 10$ ; CMP R4,#OP.NOT ;AND OP.NOT BNE 20$ ;NOT ANY OF THEM 10$: MOV E.LOP(R5),R0 ;GET SUBTREE CMP R4,(R0) ;DO WE DELETE BNE 20$ ;NO MOV E.LOP(R0),R5 ;YES, DELETE BOTH INC CHANGE ;SAY SOMETHING CHANGED 20$: RETURN ;DONE .PAGE ;+ ; ** AMPER - SPECIAL CHECKS FOR AMPERSAND ; ; THIS ROUTINE PERFORMS TWO OPTIMISATIONS FOR THE ADDRESS OPERATOR. IT ; FIRST LOOKS FOR ADDRESS OF AN INDIRECTION, AND DELETES THEM (THIS IS ; GENERATED IN ARRAY ACCESSING). IT THEN LOOKS FOR THE ADDRESS OF AN ; INDEX NODE (ADDRESS OF AN AUTO) AND TRANSFORMS IT INTO AN ADDITION. ;- AMPER: CMP R4,#OP.ADR ;IS THE OP AN AMPER BNE 30$ ;NO MOV E.LOP(R5),R1 ;CHECK IF THE SUBTREE CMP (R1),#OP.IND ;STARTS OFF WITH INDIRECTION BNE 10$ ;NO MOV E.LOP(R1),R5 ;IF YES, DELETE BOTH BR 20$ ;AND GO TO COMMON EXIT 10$: CMP (R1),#OP.INX ;AMPER OF INDEX BNE 30$ ;NO MOV #ES.CON,R4 ;CONVERT TO ADDITION CALL TREESP ;FIRST GET A CONSTANT NODE MOV #OP.CON,(R4) ; MOVB #TY.INT,E.TYPE(R4) ; MOV E.OFFS(R1),E.VAL(R4) ; MOV R4,R0 ; MOV #OP.REG,(R1) ;MAKE THE INDEX INTO A MOVB #TY.PTR,E.TYPE(R1) ;POINTER IN A REG MOV #ES.OP,R4 ;THEN BUILD THE ADD NODE CALL TREESP ; MOV #OP.ADD,(R4) ; MOVB #TY.PTR,E.TYPE(R4) ; MOV R1,E.LOP(R4) ; MOV R0,E.ROP(R4) ; MOV R4,R5 ; 20$: INC CHANGE ;MARK A CHANGE 30$: RETURN ;RETURN ;+ ; ** SUBSUM - SUBSUME CONSTANTS IN &A+CONST ; ; SEARCH FOR NODES OF THE GENERAL FORM &A+B, WHERE A IS EITHER AN ID ; OR A LOCAL ID, AND B IS A CONSTANT. ADD THE CONSTANT INTO THE OFFSET ; OF THE ID, THEN DELETE THE CONSTANT. HELPS WHEN REFERENCING CONSTANT ; SUBSCRIPTS INTO EXTERNALS AND STATICS. ;- SUBSUM: CMP R4,#OP.ADD ;IF THE TOP OF THE TREE ISN'T '+' BNE 50$ ;FORGET THIS MOV E.LOP(R5),R0 ;GET LEFT AND MOV E.ROP(R5),R1 ;RIGHT SUBTREES CMP (R0),#OP.CON ;IS THE LEFT A CONSTANT BNE 20$ ;NO CMP (R1),#OP.ADR ;YES, IS THE RIGHT AN ADDRESS BNE 20$ ;NO MOV E.LOP(R1),R1 ;YES, SEE IF THE ADDRESS IS OF CMP (R1),#OP.ID ;EITHER AN BEQ 10$ ;ID CMP (R1),#OP.LID ;OR A LOCAL ID BNE 20$ ;NO 10$: ADD E.VAL(R0),E.OFFS(R1) ;ADJUST OFFSET MOV E.ROP(R5),R5 ;DELETE THE ADDITION BR 40$ ;AND GO TO COMMON EXIT 20$: MOV E.ROP(R5),R1 ;RECOVER RIGHT SUBTREE CMP (R1),#OP.CON ;IS THE RIGHT A CONSTANT BNE 50$ ;NO CMP (R0),#OP.ADR ;IS THE LEFT AN ADDRESS BNE 50$ ;NO MOV E.LOP(R0),R0 ;YES, SEE IF THE ADDRESS IS OF CMP (R0),#OP.ID ;AN ID BEQ 30$ ;OR CMP (R0),#OP.LID ;A BNE 50$ ;LOCAL ID 30$: ADD E.VAL(R1),E.OFFS(R0) ;ADJUST OFFSET MOV E.LOP(R5),R5 ;DELETE THE '+' 40$: INC CHANGE ;SOMETHING CHANGED 50$: RETURN ;DONE .PAGE ;+ ; ** STAR - SPECIAL CHECKS FOR STAR ; ; THIS ROUTINE PERFORMS TWO SPECIFIC OPTIMISATIONS FOR INDIRECTION. IT ; FIRST CHECKS FOR INDIRECTION THROUGH AN ADDRESS. THIS HAPPENS WHEN ; A REFERENCE IS MADE TO A[0] (THE +0 GETS DELETED). BOTH OF THE NODES ; ARE DELETED. ; ; IT THEN LOOKS FOR NODES OF THE FORM *(A+B) WHERE ONE SIDE OF THE '+' ; IS A REGISTER AND THE OTHER SIDE IS A CONSTANT, AND MAKES THIS INTO ; AN INDEX NODE. ;- STAR: MOV R2,-(SP) ;NEED A LOT OF REGISTERS CMP R4,#OP.IND ;CHECK FOR INDIRECTION BNE 50$ ;NO MOV E.LOP(R5),R1 ;LOOK FOR STAR CMP (R1),#OP.ADR ;ON TOP OF AN AMPER BNE 10$ ;NO MOV E.LOP(R1),R5 ;DELETE BOTH BR 40$ ;GO TO COMMON EXIT 10$: CMP (R1),#OP.ADD ;ADD NODE BNE 50$ ;NO, NOTHING TO DO MOV E.LOP(R1),R0 ;TEST IF LOP IS A WORD CONSTANT CMP (R0),#OP.CON ; BNE 20$ ; CMPB E.TYPE(R0),#TY.LNG ; BHIS 20$ ; MOV E.ROP(R1),R2 ;TEST IF ROP IS A REGISTER CMP (R2),#OP.REG ; BNE 20$ ; CMPB E.TYPE(R2),#TY.LNG ; BHIS 20$ ; MOV E.VAL(R0),E.OFFS(R2) ; MOVB E.TYPE(R5),E.TYPE(R2) ; MOV R2,R5 ; BR 30$ ; 20$: MOV E.LOP(R1),R0 ;CHECK IF LOP IS A REGISTER CMP (R0),#OP.REG ; BNE 50$ ; CMPB E.TYPE(R0),#TY.LNG ; BHIS 50$ ; MOV E.ROP(R1),R2 ;CHECK IF ROP IS A WORD CONSTANT CMP (R2),#OP.CON ; BNE 50$ ; CMPB E.TYPE(R2),#TY.LNG ; BHIS 50$ ; MOV E.VAL(R2),E.OFFS(R0) ; MOVB E.TYPE(R5),E.TYPE(R0) ; MOV R0,R5 ; 30$: MOV #OP.INX,(R5) ;OP.REG TO OP.INX 40$: INC CHANGE ;MARK A CHANGE 50$: MOV (SP)+,R2 ;RETURN RETURN ; .PAGE ;+ ; ** AUTOS - EXPLOIT AUTO(INC/DEC) ADDRESSING ; ; LOOK FOR *P++ AND *--P, WHERE P IS IN A REGISTER AND THE RESULT IS ; EITHER A BYTE OR WORD QUANTITY, AND CHANGE IT INTO (P)+ OR -(P). ;- AUTOS: CMP R4,#OP.IND ;TOP OF THE TREE A '*' BNE 30$ ;NO, QUIT CMPB E.TYPE(R5),#TY.LNG ;WORD OR BYTE QUANTITY BHIS 30$ ;NO, QUIT MOV E.LOP(R5),R0 ;GET SUBTREE CMP (R0),#OP.INA ;LOOK FOR P++ BEQ 10$ ; CMP (R0),#OP.DEB ;AND --P BNE 30$ ;NOT FOUND 10$: MOV E.LOP(R0),R1 ;NOW CHECK FOR REGISTER CMP (R1),#OP.REG ; BNE 30$ ;NOT A REGISTER MOV #OP.AUI,(R1) ;CHANGE THE OPERATOR CMP (R0),#OP.INA ; BEQ 20$ ; MOV #OP.AUD,(R1) ; 20$: MOVB E.TYPE(R5),E.TYPE(R1) ;ADJUST TYPE MOV R1,R5 ;GET NEW TREE INC CHANGE ;INDICATE SOMETHING CHANGED 30$: RETURN ;RETURN .PAGE ;- ; ** FIXCVR - ADJUST OP.CVR NODES ; ; THIS ROUTINE SEARCHES OUT CONVERSION NODES THAT ARE ACTUALLY DONE ; WITH MULTIPLIES AND/OR DIVIDES (POINTER TO INT AND INT TO POINTER) ; AND MAKES THE CHANGE. HOPEFULLY THE FOLDER WILL DO SOME ACTION. ;- FIXCVR: CMP R4,#OP.CVR ;QUIT IF THE BNE 40$ ;OPERATOR IS WRONG MOVB E.TYPE(R5),R0 ;GET RESULT TYPE MOV E.LOP(R5),R1 ;GET LEFT SUBTREE CMP R0,#TY.PTR ;IS THE RESULT A POINTER BNE 20$ ;NO CMPB E.TYPE(R1),#TY.INT ;IS THE LEFT A WORD BEQ 10$ ;YES CMPB E.TYPE(R1),#TY.UNS ;OR AN UNSIGNED BEQ 10$ ;YES MOV #OP.CVR,R4 ;NO, CONVERT IT TO ONE CALL NODE ; MOVB #TY.INT,E.TYPE(R1) ; MOV R1,E.LOP(R5) ; 10$: MOV #OP.MUL,(R5) ;CHANGE THE OPERATOR TO A MULTIPLY BR 30$ ; 20$: CMP R0,#TY.INT ;LOOK FOR POINTER TO INT BNE 40$ ;NO CMPB E.TYPE(R1),#TY.PTR ;MAYBE BNE 40$ ;NO MOV #OP.DIV,(R5) ;CHANGE INTO DIVIDE 30$: INC CHANGE ;SOMETHING CHANGED 40$: RETURN .PAGE ;+ ; ** MOP1 - DELETE USELESS MULOPS ; ; THIS ROUTINE LOOKS FOR INTEGER MULTIPLICATIONS AND DIVISIONS BY ONE ; AND DISCARDS THEM. THESE OPERATIONS ARE GENERATED FOR PTR-INT AND ; INT-PTR CONVERSIONS ON CHARACTER POINTERS. ; ; THIS ROUTINE IS PROBABLY TOO SPECIALISED. THE REMOVAL OF MULOPS OF ; ONE SHOULD PROBABLY ALSO BE DONE FOR ASSIGNMENT TYPE OPS, AND ALSO ; FOR OTHER DATA TYPES. ;- MOP1: CMP R4,#OP.MUL ;IS THE OPERATOR A MULTIPLY BEQ 5$ ;OR CMP R4,#OP.DIV ;DIVIDE BNE 30$ ;NO 5$: CMPB E.TYPE(R5),#TY.INT ;WITH AN INTEGER RESULT BNE 30$ ;NO MOV E.LOP(R5),R0 ;GET THE MOV E.ROP(R5),R1 ;SUBTREES CMP (R0),#OP.CON ;TEST FOR CONST 1 ON LEFT BNE 10$ ;NO CMP E.VAL(R0),#1 ;MAYBE BNE 10$ ;NO MOV R1,R5 ;DELETE IT BR 20$ ;FINISH IN COMMON CODE 10$: CMP (R1),#OP.CON ;TEST FOR CONST 1 ON RIGHT BNE 30$ ;NO CMP E.VAL(R1),#1 ;MAYBE BNE 30$ ;NO MOV R0,R5 ;DELETE IT 20$: INC CHANGE ;AND INDICATE A CHANGE 30$: RETURN ;DONE .PAGE ;+ ; ** MKBIC - CHANGE AND TO BIC ; ; THE PDP-11 LACKS AN AND INSTRUCTION. SEARCH FOR AN AND OR ASSIGNED ; AND NODES AND TRANSFORM THEM INTO BIC OR ASSIGNED BIC. IF POSSIBLE ; COMMUTE ANY CONSTANT TO THE LEFT (TO ASSIST FOLDING). ;- MKBIC: CMP R4,#OP.ANA ;ASSIGNED AND BEQ 10$ ;YES CMP R4,#OP.AND ;AND BNE 40$ ;NO MOV E.LOP(R5),R0 ;IF THE LEFT IS A CMP (R0),#OP.CON ;CONSTANT BNE 10$ ;THEN MOV E.ROP(R5),E.LOP(R5) ;SWAP THE SUBTREES MOV R0,E.ROP(R5) ;SO THE COM CAN FOLD INTO IT 10$: MOV E.ROP(R5),R1 ;ADD A COM NODE MOV #OP.COM,R4 ; CALL NODE ; MOV R1,E.ROP(R5) ; CMP (R5),#OP.AND ;WAS THE OLD OP OP.AND BNE 20$ ;NO MOV #OP.BIC,(R5) ;YES, MAKE IT BIC BR 30$ ; 20$: MOV #OP.BCA,(R5) ;OP.ANA BECOMES ASSIGNED BIC 30$: INC CHANGE ; 40$: RETURN ; .PAGE ;+ ; ** DZEROP - DELETE ZERO OPERANDS ; ; CERTAIN OPERATORS (AS MARKED IN THE OPDOPE TABLE) CAN HAVE OPERANDS ; OF ZERO DELETED. THIS FUNCTION DOES THIS. ;- DZEROP: BIT #DZOL,R3 ;DELETE ZERO ON LEFT BEQ 10$ ;NO MOV E.LOP(R5),R1 ;CHECK FOR ZERO OPERAND CALL CONZER ; BCS 10$ ;NO MOV E.ROP(R5),R5 ;NEW TREE BR 20$ ; 10$: BIT #DZOR,R3 ;DELETE ZERO ON RIGHT BEQ 30$ ; MOV E.ROP(R5),R1 ;CHECK FOR ZERO OPERAND CALL CONZER ; BCS 30$ ; MOV E.LOP(R5),R5 ;NEW TREE 20$: INC CHANGE ; 30$: RETURN ; .PAGE ;+ ; ** CONZER - CHECK IF A NODE IS A CONSTANT 0 ; ; THIS ROUTINE IS USED ALL OVER THE COMPILER TO TEST IF A NODE IS A ; CONSTANT WITH VALUE 0. CONVERSIONS ARE IGNORED. ; ; INPUTS: ; R1=POINTER TO THE NODE ; ; OUTPUTS: ; C BIT CLEAR IF CONSTANT 0 ;- CONZER: MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; 10$: CMP (R1),#OP.CVR ;IGNORE CONVERSIONS BNE 20$ ; MOV E.LOP(R1),R1 ; BR 10$ ; 20$: CMP (R1),#OP.CON ;DO WE HAVE A CONSTANT BNE 30$ ;NO ADD #E.VAL,R1 ;YES, POINT AT THE VALUE MOV (R1)+,R0 ;TEST FOR ZERO BIS (R1)+,R0 ; BIS (R1)+,R0 ; BIS (R1),R0 ; BNE 30$ ;BR IF NOT ZERO CLC ;CLEAR C BIT IF ZERO BR 40$ ; 30$: SEC ;SET C BIT IF NON ZERO 40$: MOV (SP)+,R1 ;RETURN MOV (SP)+,R0 ; RETURN ; .PAGE ;+ ; ** NODE - MAKE A UNARY OPERATOR NODE ; ; INPUTS: ; R1=OLD TREE (BECOMES LOP) ; R4=OPERATOR ; ; OUTPUTS: ; R1=NEW TREE ;- NODE: MOV R4,-(SP) ;SAVE THE OPERATOR WHILE WE MOV #ES.OP,R4 ;GET TREE NODE CALL TREESP ; MOV (SP)+,(R4) ;OP MOVB E.TYPE(R1),E.TYPE(R4) ; MOV E.HFPR(R1),E.HFPR(R4) ; MOV E.HGPR(R1),E.HGPR(R4) ; MOV R1,E.LOP(R4) ; CLR E.ROP(R4) ; MOV R4,R1 ; RETURN ; .PAGE ;+ ; ** MWCON - FIX MULTI WORD CONSTANTS ; ; CERTAIN CONSTANTS (LONGS, SOME DOUBLES) WILL NOT FIT INTO A SINGLE ; PDP-11 MACHINE WORD AND CANNOT, THEREFORE, BE EXPRESSED IN A MODE ; 2 ADDRESS FIELD. THIS ROUTINE SEARCHES FOR SUCH CONSTANTS. IT THEN ; BUILDS A CONSTANT POOL IN PSECTION .MWCN. ; THERE IS NO CHECKING FOR DUPLICATION IN THE POOL. ; THE NODES ARE ALTERED INTO STATIC VARIABLES POINTING TO THE LABELS ; IN THE POOL. ; ; INPUTS: ; R5=POINTER TO THE TREE ;- MWCON: CLR MWPSFG ;SET NEED PSECT DIRECTIVE CALL MWCON1 ;DO THE NASTY STUFF TST MWPSFG ;NEED TO SWITCH BACK BEQ 10$ ;NO MOV #STR02,R0 ;PSECT .PROG. CALL CODSTR ; 10$: RETURN ; MWCON1: MOV R5,-(SP) ;SAVE ARGUMENT MOV (R5),R0 ;GET OPERATOR CMP R0,#OP.CON ;CONSTANT BNE 40$ ;NO MOVB E.TYPE(R5),R0 ;GET TYPE OF CONSTANT CMP R0,#TY.LNG ;LONG BEQ 10$ ;YES, ITS MULTIWORD CMP R0,#TY.DBL ;DOUBLE BNE 50$ ;NO MOV E.VAL+2(R5),R1 ;SEE IF LAST 3 WORDS ARE ZERO BIS E.VAL+4(R5),R1 ; BIS E.VAL+6(R5),R1 ; BEQ 50$ ;YES, SHORT 10$: TST MWPSFG ;NEED PSECT SWITCH BNE 20$ ;NO INC MWPSFG ;YES CALL PFLUSH ;FLUSH PENDING BRANCHES MOV #STR01,R0 ; CALL CODSTR ; 20$: CALL GENLAB ;GENERATE A LABEL MOV R0,-(SP) ;SAVE IT CALL LABEL ;OUTPUT IT IN THE PSECT MOV #STR03,R0 ;.WORD CALL CODSTR ; MOV E.VAL(R5),R0 ;FIRST WORD CALL CODNUM ; CALL 60$ ;',' MOV E.VAL+2(R5),R0 ;SECOND WORD CALL CODNUM ; CMPB E.TYPE(R5),#TY.LNG ;DO 2 MORE WORDS IF BEQ 30$ ;DOUBLE CALL 60$ ;',' MOV E.VAL+4(R5),R0 ; CALL CODNUM ; CALL 60$ ; MOV E.VAL+6(R5),R0 ; CALL CODNUM ; 30$: CALL CODNL ;WRAP IT UP MOV #OP.LID,(R5) ;MAKE LOCAL ID NODE CLR E.OFFS(R5) ; MOV (SP)+,E.LAB(R5) ; BR 50$ ; 40$: ASL R0 ;NOT CONSTANT, TEST FOR LEAF BIT #LEAF,OPDOPE(R0); BNE 50$ ;IS LEAF MOV E.LOP(R5),R5 ;DO LEFT CALL MWCON1 ; MOV (SP),R5 ;DO RIGHT MOV E.ROP(R5),R5 ; BEQ 50$ ; CALL MWCON1 ; 50$: MOV (SP)+,R5 ;RETURN RETURN ; 60$: MOVB #',,R0 ;OUTPUT COMMA CALLR CODC ; .END