.TITLE CC205 .IDENT /X01/ .NLIST BEX .ENABL LC ; ; C COMPILER ; BRANCH OPTIMISATION AND INPUT/OUTPUT ; ; VERSION X01 ; ; DAVID G. CONROY 08-FEB-78 ; .GLOBL GENLAB .GLOBL CODSTR .GLOBL CODNL .GLOBL CODC .GLOBL CODNUM .GLOBL CODLAB .GLOBL BRANCH .GLOBL CBRNCH .GLOBL PFLUSH .GLOBL LABEL .MCALL CALL .MCALL CALLR .MCALL RETURN .MCALL PUT$S ; ; EQUIVALENCES ; NL = 12 ;NEWLINE OBSIZE = 80. ;SIZE OF OUTPUT BUFFER ; ; DATA USED BY THE BRANCH OPTIMISER. ; PENDU: .WORD 0 ;ISN OF PENDING UNCONDITIONAL BRANCH PENDC: .WORD 0 ;ISN OF PENDING CONDITIONAL BRANCH PENDCT: .BLKW 1 ;TABLE FOR PENDING CONDITIONAL BRANCH PENDCO: .BLKW 1 ;OP FOR PENDING CONDITIONAL BRANCH ; ; LOCAL DATA ; ISN: .WORD 77777 ;WORK DOWN FROM L77777 OPTR: .WORD OBUF ;BUFFER POINTER OBUF: .BLKB OBSIZE ;OUTPUT BUFFER ; ; DIAGNOSTICS ; ERR01: .ASCIZ "I/O error on S file" ; ; CODE STRINGS ; BR: .ASCIZ " br " .EVEN .PAGE ;+ ; ** GENLAB - GENERATE A LABEL ; ; GENERATE A LABEL FOR PASS 2. START AT .77777 AND WORK DOWNWARD. NO ; CHECK IS MADE FOR COLLISION WITH PASS 1 LABELS, WHICH STARTS AT .1 ; AND WORK UPWARDS. ; ; OUTPUTS: ; R0=LABEL NUMBER ;- GENLAB: MOV ISN,R0 ;GET LABEL DEC ISN ;UPDATE GENERATOR RETURN ;RETURN ;+ ; ** CODC - PUT OUT A CHARACTER ; ; OUTPUT A SINGLE CHARACTER TO THE CODE FILE. FLUSH THE LINE BUFFER ; ON NEWLINE. THERE IS NO CHECK FOR BUFFER OVERFLOW. ; ; INPUTS: ; R0=CHARACTER ; ; USES: ; R0 ;- CODC: CMPB R0,#NL ;NEWLINE BEQ 10$ ;YES MOVB R0,@OPTR ;NO, JUST STORE IN THE BUFFER INC OPTR ; RETURN ; 10$: SUB #OBUF,OPTR ;PUT OUT THE LINE PUT$S #AFDB,#OBUF,OPTR; BCS 30$ ;ERROR MOV #OBUF,OPTR ;BACK UP POINTER RETURN ; 30$: MOV #ERR01,R0 ;I/O ERROR JMP CCABRT ; ;+ ; ** CODSTR - PUT OUT A STRING ; ; OUTPUT A STRING TO THE CODE FILE VIA REPEATED CALLS TO CODC. ; ; INPUTS: ; R0=POINTER TO STRING ;- CODSTR: MOV R0,-(SP) ;SAVE STUFF MOV R1,-(SP) ; MOV R0,R1 ;COPY OF THE STRING POINTER 10$: MOVB (R1)+,R0 ;GET CHARACTER BEQ 20$ ;DONE CALL CODC ; BR 10$ ; 20$: MOV (SP)+,R1 ;RETURN MOV (SP)+,R0 ; RETURN ; ;+ ; ** CODNL - PUT OUT A NEWLINE ; ; OUTPUT A NEWLINE TO THE CODE FILE. USES NO REGISTERS AT ALL. ;- CODNL: MOV R0,-(SP) ;SAVE REGISTERS MOVB #NL,R0 ;PUT OUT NEWLINE VIA CODC CALL CODC ; MOV (SP)+,R0 ;RETURN RETURN ; ;+ ; ** CODNUM - PUT OUT AN OCTAL NUMBER ; ; OUTPUT AN OCTAL NUMBER TO THE CODE FILE VIA CALLS TO CODC. LEADING ; ZEROS ARE SUPRESSED. ; ; INPUTS: ; R0=THE NUMBER ;- CODNUM: MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; MOV R2,-(SP) ; MOV #4,R2 ;DIGIT COUNT MOV R0,R1 ;COPY THE NUMBER ASL R1 ;TOP DIGIT BCC 20$ ;ZERO, SUPRESS MOVB #'1,R0 ; CALL CODC ; BR 30$ ;STOP SUPRESSION 20$: MOV #6,R0 ;BUILD DIGIT ASL R1 ; ROL R0 ; ASL R1 ; ROL R0 ; ASL R1 ; ROL R0 ; CMPB R0,#'0 ;IF A '0', DON'T PRINT BNE 40$ ; DEC R2 ;SUPRESS UP TO 4 ZEROS BNE 20$ ; 30$: MOV #6,R0 ;PUT OUT THE REST ASL R1 ; ROL R0 ; ASL R1 ; ROL R0 ; ASL R1 ; ROL R0 ; 40$: CALL CODC ; DEC R2 ; BGE 30$ ; MOV (SP)+,R2 ;RETURN MOV (SP)+,R1 ; MOV (SP)+,R0 ; RETURN ; ;+ ; ** CODLAB - OUTPUT A LABEL ; ; INPUTS: ; R0=LOCAL LABEL NUMBER ; ; USES: ; R0 ;- CODLAB: MOV R0,-(SP) ;SAVE LABEL NUMBER MOVB #'.,R0 ;PUT OUT THE '.' CALL CODC ; MOV (SP)+,R0 ;PUT OUT THE NUMBER CALLR CODNUM ; ;+ ; ** LABEL - PUT OUT A LOCAL LABEL ; ; THIS ROUTINE IS CALLED TO PUT OUT A LOCAL LABEL. IT CHECKS THE LABEL ; AGAINST THE PENDING BRANCHES AND MAKES MODIFICATIONS AS REQUIRED. ; NOTE THAT ALL OF THIS DEPENDS ON THERE BEING A LABEL BEFORE THE 'X' ; AT FUNCTION END. ; ; INPUTS: ; R0=LABEL ; ; USES: ; R0 ;- LABEL: MOV R0,-(SP) ;SAVE LABEL TST PENDU ;PENDING UNCONDITIONAL BEQ 20$ ;NO CMP R0,PENDU ;POINT AT THE LABEL BNE 10$ ;NO CLR PENDU ;MAKE IT GO AWAY BR 20$ ; 10$: TST PENDC ;PENDING CONDITIONAL BEQ 30$ ;NO CMP R0,PENDC ;POINTING AT THE LABEL BNE 30$ ;NO MOV PENDU,PENDC ;POINT CBR AT BR GOAL MOV PENDCO,R0 ;FLIP SUB #OP.EQ,R0 ; ASL R0 ; MOV OTHER(R0),PENDCO; CLR PENDU ;DELETE THE UNCONDITIONAL MOV (SP),R0 ;RECOVER LABEL 20$: TST PENDC ;PENDING CONDITIONAL BEQ 30$ ;NO CMP R0,PENDC ;POINTING TO THE LABEL BNE 30$ ;NO CLR PENDC ;DELETE IT 30$: CALL PFLUSH ;FLUSH BRANCHES MOV (SP)+,R0 ;LABEL CALL CODLAB ; MOVB #':,R0 ;COLON CALL CODC ; CALLR CODNL ; ;+ ; ** BRANCH - PUT OUT A BRANCH ; ; THIS ROUTINE IS CALLED TO PUT OUT AN UNCONDITIONAL BRANCH. IF THERE ; IS A PENDING UNCONDITIONAL BRANCH THE REQUESTED BRANCH CANNOT EVER ; BE REACHED AND IS DISCARDED; OTHERWISE IT BECOMES THE PENDING UNCON ; DITIONAL BRANCH. ; ; INPUTS: ; R0=LOCAL LABEL NUMBER ; ; USES: ; R0 ;- BRANCH: TST PENDU ;IS THERE A PENDING BRANCH BNE 10$ ;YES MOV R0,PENDU ;MAKE THIS A PENDING ONE 10$: RETURN ;DONE ;+ ; ** CBRNCH - OUTPUT A CONDITIONAL BRANCH ; ; THIS ROUTINE IS CALLED TO OUTPUT A CONDITIONAL BRANCH INSTRUCTION. ; IF THERE IS A PENDING UNCONDITIONAL BRANCH THIS NEW BRANCH CANNOT ; BE REACHED AND IS DISCARDED. OTHERWISE ANY OLD BRANCHES ARE FLUSHED ; OUT AND THE NEW BRANCH BECOMES THE PENDING CONDITIONAL BRANCH. ; ; INPUTS: ; R0=LABEL ; R1=TABLE ; R2=OP ; ;- CBRNCH: TST PENDU ;PENDING UNCONDITIONAL BNE 10$ ;YES MOV R0,-(SP) ;FLUSH BRANCHES CALL PFLUSH ; MOV (SP)+,PENDC ;SET PENDING CONDITIONAL MOV R1,PENDCT ; MOV R2,PENDCO ; 10$: RETURN ;DONE ;+ ; ** PFLUSH - FLUSH PENDING BRANCHES ; ; THIS ROUTINE IS CALLED TO FLUSH OUT ANY BRANCH INSTRUCTIONS THAT ARE ; STILL PENDING. ; ; USES: ; R0 ;- PFLUSH: TST PENDC ;PENDING CONDITIONAL BEQ 10$ ;NO MOVB #11,R0 ;TAB CALL CODC ; MOV PENDCO,R0 ;OPCODE ASL R0 ; ADD PENDCT,R0 ; MOV (R0),R0 ; CALL CODSTR ; MOVB #11,R0 ;TAB CALL CODC ; MOV PENDC,R0 ;LABEL CALL CODLAB ; CALL CODNL ; 10$: TST PENDU ;PENDING UNCONDITIONAL BEQ 20$ ;NO MOV #BR,R0 ;OPCODE CALL CODSTR ; MOV PENDU,R0 ;LABEL CALL CODLAB ; CALL CODNL ; 20$: CLR PENDC ;CLEAR PENDING BRANCHES CLR PENDU ; RETURN ;DONE .END