perm filename IO.PAL[V,VDS]1 blob
sn#264833 filedate 1977-02-15 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00007 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .TITLE IO
C00003 00003 "TYPSTR" - TELETYPE OUTPUT ROUTINE
C00006 00004 "INSTR" - TELETYPE INPUT ROUTINE
C00009 00005 "RNUM" - STRING TO SCALED INTEGER NUMBER CONVERSION
C00016 00006 "PNUM" - PRINTS A SCALED INTEGER AS A REAL NUMBER
C00020 00007 "CLRCMA"&"PRTCMA"
C00022 ENDMK
C⊗;
.TITLE IO
;CONSOLE TELETYPE INTEFACE LOCATIONS
TTYIS =177560
TTYIR =177562
TTYOS =177564
TTYOR =177566
;"TYPSTR" - TELETYPE OUTPUT ROUTINE
;"TYPSTR" OUTPUTS A STRING ENDING WITH A NULL CHARACTER. A POINTER TO
;THE START OF THE STRING MUST BE LOADED INTO THE SP REGISTER. NO
;OTHER REGISTERS ARE AFFECTED.
TYPSTR: MOV R0,-(SP)
MOVB (SG)+,R0 ;FIRST BYTE OF THE STRING
TSLOOP: JSR PC,TYPCHR ;TYPE THIS CHARACTER
MOVB (SG)+,R0 ;NEXT BYTE
BNE TSLOOP ;REPEAT TILL END OF THE STRING
MOV (SP)+,R0
RTS PC
TYPCHR: TSTB @#TTYOS ;TTY AVAILABLE?
BPL TYPCHR ;NO, BUSY WAIT
MOVB R0,@#TTYOR ;YES, SEND OFF THE CHARACTER
CMP #12,R0 ;WAS IT A LINE FEED?
BNE TYPRET ;IF NOT THAT CODE, THEN DONE
CLR R0 ;OUTPUT 3 NULLS
JSR PC,TYPCHR
JSR PC,TYPCHR
JSR PC,TYPCHR
TYPRET: RTS PC
;"LINOUT" TYPES A ASC STRING OF CHARACTERS ON TO THE TELETYPE. THE
;ASC STRING IS A ASSUME TO END WITH A NULL CHARACTER. A CR/LF IS
;ADDED TO THE END OF THE STRING DURING TYPE OUT.
LINOUT: JSR PC,TYPSTR
MOV #CRLFX,SG
JSR PC,TYPSTR
RTS PC
;"CRLF" IS A SUBROUTINE FOR TYPING OUT ONE CARRIAGE RETURN AND LINE
;FEED ON THE TELETYPE.
CRLF: MOV #CRLFX,SG
JSR PC,TYPSTR
RTS PC
CRLFX: .BYTE 15,12,0,0
;"NULLS" PRINTS OUT A SERIES OF NULL CHARACTERS THAT SERVES
;AS A LEADER FOR PUNCHED PAPER TAPES.
NULLS: MOV R0,-(SP)
MOV R1,-(SP)
MOV #80.,R1 ;PUNCH THIS MANY NULLS
CLR R0
JSR PC,TYPCHR ;PUNCH A NULL
SOB R1,.-4
MOV (SP)+,R1
MOV (SP)+,R0
RTS PC
;END OF OUTPUT ROUTINES
;"INSTR" - TELETYPE INPUT ROUTINE
;THE STRING BYTE POINTER MUST BE IN SG. A CARRIAGE RETURN IS ASSUMED
;TO BE THE ACTIVATION CHARACTER. A RUB OUT IS A DELETING BACKSPACE
;CHARACTER. AT THE COMPLETION OF THIS ROUTINE, A NULL CHARACTER IS
;PLACED IN THE INPUT STRING. SG IS LEFT UNCHANGED
;REGISTERS USED:
;
; SG PASSES THE ARGUMENT AND IS NOT MODIFIED
INSTR: MOV SG,-(SP)
MOV R0,-(SP)
CLR @#CCNT ;RESET CHARACTER COUNT
IN2: INCB @#TTYIS ;START PAPER TAPE READER IF NEC.
TSTB @#TTYIS ;TTY READY?
BPL .-4
MOVB @#TTYIR,R0 ;GET A CHARACTER
BIC #177600,R0 ;MASK OFF - MAKE IT 7 BITS
CMP R0,#177 ;BACK SPACE?
BNE IN3 ;BRANCH IF NOT
TST @#CCNT ;CANT DO ANYTHING IF NO CHARACTERS
BEQ IN2 ;BRANCH IF CANT COMPLY
DEC SG ;REMOVE LAST CHARACTER FROM BUFFER
DEC @#CCNT
MOV #134,R0 ;TYPE \ TO INDICATE RUB OUT
BR IN4
IN3: CMP R0,#15 ;C/R?
BEQ IN5 ;TERMINATE IF ITS A CR
CMP R0,#40 ;LEGAL CHARACTER?
BLT IN2 ;IGNOR IT IS ITS NOT LEGAL
MOVB R0,(SG)+ ;ELSE SAVE THE CHARACTER
INC @#CCNT ;INCREMENT CHARACTER COUNT
IN4: TSTB @#TTYOS ;ECHO
BPL .-4
MOVB R0,@#TTYOR
BR IN2
IN5: MOVB R0,(SG)+ ;END OF STRING, PUT IN A CR
CLRB (SG) ;PUT IN A NULL CHARACTER
JSR PC,CRLF ;TYPE CR/LF
MOV (SP)+,R0
MOV (SP)+,SG
RTS PC
CCNT: 0
;END OF "INSTR"
;"RNUM" - STRING TO SCALED INTEGER NUMBER CONVERSION
;THIS ROUTINE CONVERTS A REAL NUMBER STRING OF THE FORM SIII.DDD INTO
;A SCALED INTEGER. "S" IS AN OPTIONAL SIGN CHARACTER, III IS THE
;INTEGER FIELD, AND DDD IS THE DECIMAL FRACTION FIELD. THE LENGTH OF
;EACH FIELD IS VARIABLE AND EITHER THE INTEGER OF FRACTIONAL FIELD CAN
;BE OMITTED. IF THE FRACTIONAL FIELD IS MISSING, THE DECIMAL POINT
;NEED NOT BE TYPED. LEADING SPACE CHARACTERS ARE IGNORED AND SCANNING
;CONTINUES UNTIL AN UNEXPECTED CHARACTER IS ENCOUNTERED. AFTER THE
;NUMBER IS READ IN, IT IS CONVERTED TO A SINGLE 16 BIT INTEGER NUMBER
;ACCORDING TO THE FOLLOWING FORMULA:
;
; INTEGER NUMBER ← (NUMBER*10↑X*2↑14)/SCALE
; WHERE
; X ← 5 - (MAX. # OF INTEGER DIGITS ANY NUMBER CAN HAVE)
; SCALE ← INTEGER(LARGEST NUMBER TO READ IN*10↑X)/2
;
;THERE ARE SEVERAL ENTRIES POINTS INTO THIS PROGRAM. IT ENTRY POINTS
;SETS UP "X" AND "SCALE" TO HANDLE A PARTICULAR TYPE OF NUMBER. A
;TYPICAL CALLING SEQUENCE FOLLOWS:
;
; MOV #STRING,SG ;POINT TO ASC STRING
; JSR PC,GETINT ;DECODE A INTEGER NUMBER
; BCS ERROR ;BRANCH IF NUMBER TOO LARGE OR
; ; NO NUMBER FOUND
; MOV R0,NUMBER
;
;IF THE INPUT STRING IS INVALID, THE C BIT IS SET AND R1 IS RETURNED
;NON-ZERO. IF NO NUMBER WAS ENCOUNTERED, THE C BIT IS SET AND R1 IS
;ZERO. OTHERWISE THE C BIT IS CLEARED. SG IS LEFT POINTING AT THE
;FIRST CHARACTER FOLLOWING THE NUMBER.
;REGISTERS USED:
; SG, R0, R1 PASS ARGUMENTS AND ARE ALTERED
;MULTIPLE ENTRY POINTS
GETANG: MOV #2,-(SP) ;ANGLES: -360 ≤ THETA < 360
MOV #18000.,-(SP)
BR RNUM
GETDIS: MOV #3,-(SP) ;DISTANCES -32 ≤ D < 32
MOV #16000.,-(SP)
BR RNUM
GETINT: CLR -(SP) ;INTEGERS '100000 ≤ INT ≤ 77777
MOV #40000,-(SP)
;START OF MAIN PROGRAM
RNUM: MOV R3,-(SP) ;SAVE REGISTERS
MOV R2,-(SP)
CLR -(SP) ;INDICATE NO NUMBER ENCOUNTERED YET
CLR R0 ;ACCUMULATE NUMBER IN HERE
CLR R1
;SCAN PAST LEADING ZEROS AND CHECK FOR SIGN CHARACTER
CHKSP: MOVB (SG)+,R2 ;PICK UP A CHARACTER
CMP #40,R2 ;IGNOR SPACE CHARACTERS
BEQ CHKSP
CMP #53,R2 ;IGNOR "+"
BEQ FNDSGN
CMP #55,R2 ;"-"?
BNE CHKZRO ;BRANCH IF NOT
NEG 6(SP) ;ELSE COMPLEMENT SCALE FACTOR
FNDSGN: MOVB #BADNUM,(SP) ;INDICATE SIGN ENCOUNTERED
SKPZRO: MOVB (SG)+,R2 ;SKIP OVER LEADING ZEROS
CHKZRO: CMP #60,R2
BNE .+10
MOV #BADNUM+400,(SP);INDICATE DIGIT ENCOUNTERED
BR SKPZRO
;CHECK IF CHARACTER IS A DIGIT
MOV #6,R3 ;5-X IS THE # OF INT. DIG. TO READ
SUB 10(SP),R3
BR .+4
CHKDG: MOVB (SG)+,R2 ;GET THE NEXT CHARACTER
CMP R2,#60 ;COMPARE TO ASC ZERO
BLT CHKDP ;BRANCH IF OUT OF RANGE
CMP R2,#71 ;COMPARE TO ASC 9
BGT CHKDP
JSR PC,ADDDIG ;ACCUMULATE SUM
MOV #BADNUM+400,(SP);INDICATE DIGIT ENCOUNTERED
SOB R3,CHKDG
BR BADSYN ;BRANCH IF TOO MANY INTEGERS READ IN
;CHECK IF THE CHARACTER IS A DECIMAL POINT AND PICK UP FRACTION PART
CHKDP: MOV 10(SP),R3 ;GET X
CMP #56,R2 ;"."?
BNE NORM ;SKIP IF NOT D.P.
MOVB #BADNUM,(SP) ;INDICATE D.P. ENCOUNTERED
GETFC: MOVB (SG)+,R2 ;GET NEXT CHARACTER
CMP R2,#60 ;BRANCH IF NOT A DIGIT
BLT NORM
CMP R2,#71
BGT NORM
MOV #BADNUM+400,(SP);INDICATE DIGIT ENCOUNTERED
DEC R3 ;IGNOR IF ALREADY READ IN FRACTION
BMI GETFC
JSR PC,ADDDIG ;ACCUMULATE SUM
BR GETFC
;EXIT IF NO NUMBER ENCOUNTERED, ELSE NORMALIZE AND SCALE
NORM: TSTB 1(SP) ;CHECK IF ANY NUMBERS ENCOUNTERED
BEQ BADSYN ;BRANCH IF NONE FOUND
TST R3 ;BRANCH IF NUMBER ALREADY NORMALIZED
BLE SCALIT
NORMIT: MOV #60,R2 ;ELSE SUM ← SUM*10+0
JSR PC,ADDDIG
SOB R3,NORMIT
SCALIT: ASHC #14.,R0 ;SUM ← SUM*2↑14
DIV 6(SP),R0 ;SUM ← SUM/SCALE
BVC RNUMDN ;EXIT CLEANLY IF NO ERROR
;EXIT SEQUENCE
BADSYN: SEC ;INDICATE SOME TYPE OF ERROR
RNUMDN: MOVB (SP)+,R1 ;THIS IS PART OF THE ERROR CODE
MOV (SP)+,R2
MOV (SP)+,R3
BIT (SP)+,(SP)+ ;CLEAR X AND SCALE OFF STACK
DEC SG ;ADJUST STRING POINTER
RTS PC
;SUBR TO ADD ANOTHER DIGIT TO THE ACCUMULATED SUM IN R0,R1
ADDDIG: ASHC #1,R0 ;SUM*2
MOV R0,-(SP) ;SAVE IT
MOV R1,-(SP)
ASHC #2,R0 ;SUM*8
ADD (SP)+,R1 ;SUM*8+SUM*2
ADC R0
ADD (SP)+,R0
BIC #60,R2 ;MASK OUT ASC BASE OF NEW DIGIT
ADD R2,R1 ;SUM*10+NEW DIGIT
ADC R0
RTS PC
;END OF "RNUM"
;"PNUM" - PRINTS A SCALED INTEGER AS A REAL NUMBER
;PERFORMS THE REVERSE OPERATION OF RNUM. A TYPICAL CALLING SEQUENCE
;TO ONE OF THE MULTIPLY ENTRY POINTS FOLLOWS:
;
; MOV NUMBER,R0 ;SCALED INTEGER
; MOV #STRING,SG ;PUT CONVERTED STRING IN HERE
; JSR PC,PUTINT
;
;AFTER CONVERSION, THE STRING POINTER IS LEFT POINTING AT A NULL
;CHARACTER WHICH FOLLOWS THE FINAL CHARACTER OF THE CONVERTED
;NUMBER.
;REGISTERS USED:
; R0, SG PASS ARGUMENTS AND R0,R1,SG ARE ALTERED
;MULTIPLE ENTRY POINTS
PRTANG: MOV #18000.,R1 ;ANGLES
MOV #2-6,-(SP)
BR PNUM
PRTDIS: MOV #16000.,R1 ;DISTANCES
MOV #3-6,-(SP)
BR PNUM
PRTINT: MOV #40000,R1
MOV #0-6,-(SP)
;START OF MAIN PROGRAM
PNUM: MOV R2,-(SP) ;SAVE REGISTERS
MOV R3,-(SP)
MOV #-60,-(SP) ;THIS + ASC 0 = NULL CHARACTER
MOV #60,R3 ;ASSUME NUMBER POSITIVE
MUL R1,R0 ;SCALE NUMBER UP
BGE NUMPOS ;SKIP IF NUMBER > 0
MOV #55,R3 ;ELSE SAVE NEGATIVE SIGN
COM R0 ;ABS(NUMBER)
NEG R1
BCS .+4
INC R0
NUMPOS: ADD #20000,R1 ;ROUND OFF
ADC R0
ASHC #-14.,R0 ;NORMALIZE
MOV #4,R2 ;4 DECIMAL DIGITS + 1
DIVLP: DIV #10.,R0
MOV R1,-(SP) ;LEAST SIGNIFICANT DIGIT
MOV R0,R1 ;POSITION FOR NEXT DIVISION
CLR R0
SOB R2,DIVLP
MOV #6,R0 ;COUNT TO PRINT 5 DIGITS AND NULL
MOV 16(SP),R2 ;GET X
BR .+4 ;FORM COMPLETE STRING
POPTHM: MOV (SP)+,R1 ;GET BACK A DIGIT
INC R2 ;BUMP UP INTEGER DIGIT COUNT
BCS CHKDCM ;BRANCH IF SIGN ALREADY PRINTED
BEQ SETSGN ;GO PRINT SIGN BEFORE DECIMAL PT
TST R1
BNE .+10
MOVB #40,(SG)+
BR NXTDG
BIC #20,R3 ;SPACE=+ OR - BEFORE 1ST DIGIT
SETSGN: MOVB R3,(SG)+ ;SIGN CHARACTER
TST R2 ;TIME TO PRINT DEC. PT?
CHKDCM: BNE .+6
MOVB #56,(SG)+ ;SEND OFF DECIMAL POINT
ADD #60,R1 ;ADD ASC BASE TO NUMBER AND SEND OFF
MOVB R1,(SG)+
SEC ;INDICATE SIGN PRINTED
NXTDG: SOB R0,POPTHM
MOV (SP)+,R3 ;RESTORE REGISTERS
MOV (SP)+,R2
TST (SP)+ ;CLEAR X OFF STACK
DEC SG ;POINT TO NULL CHARACTER
RTS PC
;END OF "PNUM"
;"CLRCMA"&"PRTCMA"
;"CLRCMA" CAN BE CALLED FOLLOWING A STRING SCANNING ROUTINE TO ADJUST
;THE STRING POINTER IN SG TO SKIP OVER COMMA CHARACTERS WHICH ARE
;USED TO SEPARATE NUMBERS. SG MUST BE POINTING AT THE INPUT STRING.
;IF ANY CHARACTER OTHER THAN A SPACE OR C/R IS ENCOUNTERED BEFORE THE
;COMMA, THE C BIT IS SET, SG IS LEFT POINTING AT THE OFFENDING
;CHARACTER AND AN ERROR CODE IS SET IN R1.
CLRCMA: CMPB #40,(SG)+ ;IGNOR LEADING SPACE CHARACTERS
BEQ .-4
CMPB #15,-(SG) ;EXIT IF END OF STRING
BEQ CLRCXX
CMPB #54,(SG)+ ;SKIP OVER COMMA
BEQ CLRCXX
DEC SG ;ELSE SIGNAL ERROR
MOV #NOCOMA,R1
SEC
CLRCXX: RTS PC
;"PRTCMA" PUTS A COMMA FOLLOWED BY A SPACE CHARACTER IN THE OUTPUT
;STRING.
PRTCMA: MOVB #54,(SG)+
MOVB #40,(SG)+
CLRB (SG)
RTS PC
;"TICKLE" RETURNS WITH THE C BIT SET IF A C/R CHARACTER HAS BEEN
;TYPED ON THE TELETYPE, OTHERWISE THE C BIT IS CLEARED. THE
;CHARACTER TYPED IS FLUSHED.
TICKLE: TSTB @#TTYIS ;TTY KEYBOARD TICKLED?
BPL TICKDN ;NO
MOVB @#TTYIR,-(SP) ;DID SOMEONE TYPE A C/R?
BIC #200,(SP)
CMPB #15,(SP)+
BNE TICKDN ;NO
SEC ;YES
BR .+4
TICKDN: CLC
RTS PC
;END OF TICKLE