.IIF NDF RSX RSX = 1 ;Assume RSX ;01+ .TITLE CC205 .ident /X01.09/ .NLIST BEX, CND .ENABL LC, GBL .LIST MEB ;01 - ; ; C COMPILER ; DATA INITIALIZER/BRANCH OPTIMISATION AND INPUT/OUTPUT ; ; VERSION X01 ; ; DAVID G. CONROY 08-FEB-78 ; ; Edit history ; 01 04-Mar-80 MM Added RT11 support ; 02 16-May-80 MM Changed abort exit ; 03 05-Jan-81 RBD Emit successive .BYTE and .WORD directives on same ; line. Vastly speeds AS up. ; 04 09-Mar-81 MM Added CODSP ; 05 04-Dec-81 MM Addec CODPS ; 06 08-Feb-82 MM/CG Fixed Fixed codstr ; 07 09-Mar-82 RBD Added abort on null string to CODSTR. ; 08 23-Jul-82 MM Globalized pstext ; 09 31-Jul-82 MM Added CODID ; .GLOBL GENLAB .GLOBL CODSTR .GLOBL CODID ;09 .GLOBL CODNL .GLOBL CODSP ;04 .GLOBL CODPS ;05 .GLOBL CODC .GLOBL CODNUM .GLOBL CODLAB .GLOBL BRANCH .GLOBL CBRNCH .GLOBL PFLUSH .GLOBL LABEL .GLOBL STR11,STR13 ;03 .IF NE RSX ;01 .MCALL CALL .MCALL CALLR .MCALL RETURN .ENDC ;01 ; ; 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 ; ; DATA USED BY THE INITIALIZER OPTIMIZER ; DSTRNG: .BLKW 1 ;POINTS TO CURRENTLY OPTIMIZED DATA DIR. DSTATE: .WORD 0 ;OPTIMIZER STATE: ; 0 = NORMAL STATE ; 1 = DATA DIR. JUST RECOGNIZED ; -1= NEWLINE JUST SEEN AFTER DATA DIR. ; ; 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 output [.S] file" ;01 ERR02: .ASCIZ "Null opcode string in CODSTR. Get help" ; ; CODE STRINGS ; BR: .ASCIZ " br " PSTEXT:: ;08 .ASCIZ " .psect " .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 ;+ ; ** CODPS - PUT OUT A PSECT NAME ;05+ ; ; OUTPUT A PROGRAM SECTION NAME ; ; INPUTS: ; R0 -> SECTION STRING ; ; USES R0 ;- CODPS: MOV R0,-(SP) ;SAVE ARG MOV #PSTEXT,R0 ;HEADER CALL CODSTR ;DO IT MOV (SP)+,R0 ;ARG CALL CODSTR ;DO IT CALLR CODNL ;TERMINATOR ;05- ;+ ; ** CODC - PUT OUT A CHARACTER ; ** CODSP - PUT OUT ONE SPACE ; ; OUTPUT A SINGLE CHARACTER TO THE CODE FILE. IN DSTATE 0, FLUSH CODE ; BUFFER ON NEWLINE, ELSE PUT CHARACTER INTO BUFFER. NO BUFFER OVERFLOW ; CHECKS. NEWLINE IN DSTATE 1 CAUSES TRANSITION TO DSTATE -1, NEWLINE ; IS SUPRESSED. ANY CALL IN DSTATE -1 CAUSES A BUFFER FLUSH (NEWLINE), ; AND A TRANSITION BACK TO DSTATE 0. ; ; INPUTS: ; R0=CHARACTER (CODC ONLY) ; ; USES: ; R0 ;- CODSP: MOV #040,R0 ;SPACE ;04 CODC: TST DSTATE ;IN STATE -1? ;03+ BGE 10$ ;NO MOV R0,-(SP) ;YES,SAVE THIS CHARACTER CALL 30$ ;DO A NEWLINE MOV (SP)+,R0 ;RESTORE CHARACTER AND CLR DSTATE ;BACK TO NORMAL MODE ... 10$: CMPB R0,#NL ;NEWLINE BNE 20$ ;NO TST DSTATE ;YES, IN STATE 1? BLE 30$ ;NO, NORMAL BUFFER FLUSH NEG DSTATE ;YES, THIS CAUSES STATE -1 RETURN ; AND SUPRESSION OF NEWLINE 20$: MOVB R0,@OPTR ;NO, JUST STORE IN THE BUFFER ;03- INC OPTR ; RETURN ; 30$: SUB #OBUF,OPTR ;PUT OUT THE LINE MOV OPTR,-(SP) ;HERE'S THE LENGTH ;01+ MOV #OBUF,-(SP) ;AND THE BUFFER MOV #P2OUT,R0 ;AND THE FILE DATA BLOCK CALL PUTTXT ;THERE IT GOES BIT (SP)+,(SP)+ ;CLEAN THE STACK ;01- BCS 40$ ;ERROR ;03 MOV #OBUF,OPTR ;BACK UP POINTER RETURN ; 40$: MOV #ERR01,R0 ;I/O ERROR ;03 JMP ABORT2 ; ;02 ;+ ; ** CODID - PUT OUT A GLOBAL NAME ; ** CODSTR - PUT OUT A STRING ; ; CODID OUTPUTS A GLOBAL NAME TO THE ASSEMBLER. IT IS MARKED ; WITH A LEADING '_' WHICH WILL EVENTUALLY BE STRIPPED OUT. ; THE PURPOSE OF THE '_' IS TO ALLOW GLOBAL SYMBOLS SUCH AS 'sp' ; WHICH WOULD OTHERWISE BE CONFUSED WITH AS INTERNAL NAMES. ; ; OUTPUT A STRING TO THE CODE FILE VIA REPEATED CALLS TO CODC. ; IN DSTATE 0, NORMAL STRING OUTPUT IS DONE UNTIL '.WORD' OR ; '.BYTE' IS RECOGNIZED. IF EITHER OF THESE IS SEEN, IT IS SENT, ; DSTATE 1 IS ENTERED, AND A POINTER TO WHICH ONE (.BYTE) ; OR (.WORD) WAS JUST SEEN IS SAVED. IN STATE 1, NORMAL OUTPUT ; IS DONE WITH NO CHECKS. IN STATE -1, A MATCH TO THE POINTED TO ; STRING CAUSES A ',' TO BE SENT, AND A TRANSITION TO STATE 1, ; OTHERWISE, NORMAL OUTPUT IS DONE. NOTE THAT CODC WILL DO THE SWITCH ; TO STATE 0 FROM STATE -1 IF CALLED. ; ; INPUTS: ; R0=POINTER TO STRING ; ; ABORTS IF IT IS PASSED A NULL STRING. THIS 'FEATURE' WAS ADDED AFTER ;07+ ; A SCREW-UP IN THE BRANCH GENERATIO LOGIC CAUSED A NULL OPCODE STRING ; TO BE BE PASSED. ;07- ;- CODID: MOV R0,-(SP) ;SAVE STRING NAME ;09+ MOV #'_,R0 ;MARKER CALL CODC ;OUTPUT IT MOV (SP)+,R0 ;REGET STRING NAME .BR CODSTR ;(CALLR CODSTR) ;09- CODSTR: TSTB (R0) ;NULL STRING? ;07+ BNE 5$ ;(NO, OK) MOV #ERR02,R0 ;YES, DIE JMP ABORT2 5$: MOV R1,-(SP) ;SAVE STUFF ;03+ MOV R0,-(SP) ; TST DSTATE ;STATE 1? BGT 40$ ;YES, SEND EVERYTHING BEQ 20$ ;STATE 0, TEST FOR .BYTE OR .WORD MOV DSTRNG,R1 ;STATE -1. ANOTHER OF SAME DIR? CALL STRCMP BCS 10$ ;NO. END OF THESE DATA DIR'S. CMP OPTR,#OBUF+OBSIZE-28. ; ANOTHER, ROOM ON THIS LINE? ;06 BHIS 10$ ;NO NEG DSTATE ;ROOM, BACK TO STATE 1 MOV #',,R0 ;SEND A COMMA CALL CODC BR 60$ ;AND THAT'S ALL 10$: CLR DSTATE ;END OF OPTIMIZED LINE. --> STATE 0 CALL CODNL ;FINISH IT OFF WITH A NEWLINE MOV (SP),R0 ;RESTORE R0, ;AND FALL THROUGH ... 20$: MOV #STR11,R1 ;R1 --> ".byte" CALL STRCMP ;TEST FOR MATCH BCS 30$ ;BRANCH ON NO MATCH MOV #STR11,DSTRNG ;SAVE POINTER TO '.BYTE' INC DSTATE ;CHANGE TO STATE 1 BR 40$ ;SEND IT NORMALLY 30$: MOV (SP),R0 ;RECOVER INPUT STRING POINTER MOV #STR13,R1 ;R1 --> ".word" CALL STRCMP ;TEST FOR MATCH BCS 40$ ;BRANCH ON NO MATCH MOV #STR13,DSTRNG ;SAVE POINTER TO '.WORD' INC DSTATE ;SWITCH TO STATE 1 ;;; BR 40$ ;SEND IT NORMALLY 40$: MOV (SP),R1 ;COPY OF THE STRING POINTER 50$: MOVB (R1)+,R0 ;GET CHARACTER BEQ 60$ ;DONE CALL CODC ; BR 50$ ; 60$: MOV (SP)+,R0 ;RETURN MOV (SP)+,R1 ; RETURN ; ;+ ; ** STRCMP - COMPARE STRINGS ; ; INPUTS: ; R0 ==> STRING A ; R1 ==> STRING B ; ; OUTPUTS: ; CARRY SET IF DIFFERENT, CLEAR IF SAME ; ; R0 AND R1 ARE WIPED OUT ;- STRCMP: CMPB (R0)+,(R1) ;CHARACTERS SAME? BNE 10$ ;NOPE TSTB (R1)+ ;END OF STRING B? BNE STRCMP ;NOPE, KEEP TRYING. RETURN ;YES, MATCHED. (CARRY'S CLEAR) 10$: SEC ;FAILED, SET CARRY RETURN ;+ ; ** CODNL - PUT OUT A NEWLINE ; ; OUTPUT A NEWLINE TO THE CODE FILE. USES NO REGISTERS AT ALL. ; IF IN .BYTE/.WORD HACK MODE, SUPRESS THE NEWLINE. ;- 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