.TITLE UTIL various utility routines .IDENT /02.05/ ; ; This file contains routines for blocking direct I/O to the system console ; (formerly SYSIO), conversion of words to RAD50 or OCTAL representation ; (formerly RAD50 and OCTAL).-di and a hashing function for RAD50 words. ; ; R50HSH hashes two RAD50 words (or any other 32bit value) to a hash. ; ; RADDEC converts its first argument from RAD50 encoding to a 4-byte ASCIZ ; string at the location pointed to by its second argument. R0 will contain ; a pointer to the trailing zero byte of the output string. ; ; OCTAL converts its first argument to octal ASCII representation with leading ; zeros, storing the result at the 7 byte buffer pointed to by its second ; argument, leaving R0 pointong to the trailing zero byte after the last digit ; written. ; ; SYSPUT writes a zero-terminated string pointed to by its first argument ; directly to the console, bypassing any driver. The state of the device will ; be saved and restored. The system is blocked until SYSPUT returns. ; The constant CHRDLY contains the number of iterations of a tight delay loop ; that is executed after every PUTC in SYSPUT to slow down output. ; ; SYSGET reads a CR-terminated string to the buffer pointed to by its first ; argument, replacing the CR with a terminating zero, directly from the ; console, bypassing any driver. The state of the device will be saved and ; restored. The system is blocked until SYSGET returns. SYSGET processes BS and ; DEL to delete characters from the input, beeping if there are no characters ; to delete left. The second argument contains a count of characters to be ; read (including the terminating CR), any additional characters typed will not ; be stored and not be echoed, instead SYSGET will beep. SYSGET will not return ; until the terminating CR is received. The number of characters read is ; returned in R0. ; ; 16-AUG-2005 H. Rosenfeld added delay loop to SYSPUT to avoid input buffer ; overflow in the console terminal (VT102 at 9600 ; in this case, VT220 didn't need it) ; 04-JUL-2005 H. Rosenfeld minor changes to hash algorithm in R50HSH ; 12-JUN-2005 H. Rosenfeld minor tweaks to R50HSH ; 11-JUN-2005 H. Rosenfeld added R50HSH ; 24-MAY-2005 H. Rosenfeld return number of characters read in SYSGET ; 08-APR-2005 H. Rosenfeld renamed RAD50 to RADDEC to avoid collision with ; MACRO directive .RAD50 ; 24-JAN-2005 H. Rosenfeld now using the new calling convention, changed ; OCTAL back to use DIV instruction ; 05-NOV-2004 H. Rosenfeld extended SYSGET to be more userfriendly ; (BS/DEL support, waiting for CR) ; 18-OCT-2004 H. Rosenfeld added RADENC & OCTENC, SYSGET/SYSPUT direct ; console I/O replaces old SYSMSG routine ; 02-OCT-2004 H. Rosenfeld added macro .OCTAL ; 10-JUL-2004 H. Rosenfeld replaced DIV by BIC and ROR ; 09-JUL-2004 H. Rosenfeld ; .LIST ME .NLIST CND .ENABL REG .LIBRARY /CALL.SML/ .MCALL .CALL,.ENTRY,.RETRN TKS=177560 ; terminal keyboard status TKB=177562 ; terminal keyboard buffer TPS=177564 ; terminal printer status TPB=177566 ; terminal printer buffer CHRDLY=400 ; delay loop count .CSECT ; R50HSH ; input: 32bit key (two RAD50 words), table size ; output: none ; return: R0 hash of the key, lower than table size .MACRO .R50HSH KEY1,KEY2,TSIZ .GLOBL R50HSH .CALL R50HSH,KEY1,KEY2,TSIZ .ENDM R50HSH::.ENTRY CLR R0 ; clear hash MOV #50,R1 ; we assume Rad-50 characters MOV 6(R5),R3 ; get first part of key BEQ 1$ ; skip if zero CLR R2 ; prepare for division DIV R1,R2 ; R2 = remaining key, R3 = character XOR R3,R0 ; hash it ASL R0 ; shift hash MOV R2,R3 ; repeat with remaining key BEQ 1$ ; skip if zero CLR R2 ; prepare for division DIV R1,R2 ; R2 = character, R3 = character XOR R3,R0 ; hash it ASL R0 ; shift hash XOR R2,R0 ; hash it ASL R0 ; shift hash 1$: MOV 10(R5),R3 ; get second part of key BEQ 2$ ; stop if zero CLR R2 ; prepare for division DIV R1,R2 ; R2 = remaining key, R3 = character XOR R3,R0 ; hash it ASL R0 ; shift hash MOV R2,R3 ; repeat with remaining key BEQ 2$ ; stop if zero CLR R2 ; prepare for division DIV R1,R2 ; R2 = character, R3 = character XOR R3,R0 ; hash it ASL R0 ; shift hash XOR R2,R0 ; hash it 2$: MOV R0,R1 ; prepare for division CLR R0 DIV 12(R5),R0 ; divide hash by table size MOV R1,R0 ; return remainder as hash .RETRN ; RADDEC ; input: value, string buffer ; output: RAD50-decoded value in string buffer ; return: R0 pointer to end of string .MACRO .RADDEC VAL,STR .GLOBL RADDEC .CALL RADDEC,VAL,STR .ENDM RADDEC::.ENTRY MOV 6(R5),R0 ; first argument: word to convert MOV 10(R5),R2 ; second argument: output buffer MOV #3,R3 ; 3 characters / word 1$: MOV R0,R1 ; prepare for division CLR R0 DIV #50,R0 ; R0 now contains undecoded part of word, R1 ; the next character in RAD50 code MOVB CNVTBL(R1),-(SP); store decoded character SOB R3,1$ MOV #3,R3 ; 3 characters are stored in the stack 2$: MOVB (SP)+,(R2)+ ; store character in output buffer SOB R3,2$ CLRB (R2) ; mark end of character string MOV R2,R0 ; return pointer to end of string .RETRN ; OCTAL ; input: value, string buffer ; output: ASCII character string representing value as octal in string buffer ; return: R0 pointer to end of string .MACRO .OCTAL VAL,STR .GLOBL OCTAL .CALL OCTAL,VAL,STR .ENDM OCTAL:: .ENTRY MOV #6,R2 ; 6 characters / word MOV 10(R5),R3 ; second argument: output buffer MOV 6(R5),R1 ; first argument: input buffer 1$: CLR R0 ; prepare for division DIV #10,R0 ; R0 now contains the undecoded part of the ; word, R1 the next decoded number ADD #'0,R1 ; convert to ASCII MOV R1,-(SP) ; store character MOV R0,R1 ; continue with undecoded part SOB R2,1$ MOV #6,R2 ; 6 characters stored in stack 2$: MOVB (SP)+,(R3)+ ; store character in output buffer SOB R2,2$ CLRB (R3) ; mark end of character string MOV R3,R0 ; return pointer to end of string .RETRN ; SYSPUT ; input: string ; output: string on console device ; return: none .MACRO .SYSPUT STR .GLOBL SYSPUT .CALL SYSPUT,STR .ENDM SYSPUT::.ENTRY MFPS -(SP) MTPS #340 ; we do not want to be interrupted MOV 6(R5),R1 ; first argument: pointer to string MOV @#TPS,R0 ; save terminal printer status CLRB @#TPS ; reset terminal printer 1$: MOVB (R1)+,R2 ; get next character JSR PC,PUTC ; and print it MOV #CHRDLY,R3 ; delay loop 2$: SOB R3,2$ TSTB (R1) ; done? BNE 1$ ; nay, repeat MOV R0,@#TPS ; restore terminal printer status MTPS (SP)+ .RETRN ; SYSGET ; input: string buffer, buffer size ; output: string read from the console ; return: R0 number of characters read .MACRO .SYSGET BUF,CNT .GLOBL SYSGET .CALL SYSGET,BUF,CNT .ENDM SYSGET::.ENTRY MFPS -(SP) MTPS #340 ; we do not want to be interrupted MOV 6(R5),R0 ; first argument: input buffer MOV 10(R5),R1 ; second argument: byte count DEC R1 ; raw byte count, without CR MOV R1,-(SP) ; save for comparisions MOV @#TPS,R4 ; save terminal printer status MOV @#TKS,R3 ; save terminal keyboard status CLRB @#TPS ; reset terminal printer CLRB @#TKS ; reset terminal keyboard CLR R2 1$: JSR PC,GETC ; read character CMPB #15,R2 ; CR? BEQ 2$ ; yea, finish CMPB #10,R2 ; BS? BEQ 3$ ; yea, do delete CMPB #177,R2 ; DEL BEQ 3$ ; yea, do delete TST R1 ; buffer full? BEQ 4$ ; yea, beep JSR PC,PUTC ; echo character MOVB R2,(R0)+ ; store character DEC R1 ; decrement character count BR 1$ 2$: CLRB (R0)+ ; mark end of character string MOV R4,@#TPS ; restore terminal printer status MOV R3,@#TKS ; restore terminal keyboard status NEG R1 ; calculate no. of bytes read ADD (SP)+,R1 MOV R1,R0 ; return in R0 MTPS (SP)+ .RETRN 3$: CMP R1,(SP) ; no characters in buffer? BEQ 4$ ; yea, beep INC R1 TSTB -(R0) ; rewind output buffer MOV #134,R2 ; print backslash to indicate deletion JSR PC,PUTC BR 1$ 4$: MOV #7,R2 ; print BEL JSR PC,PUTC BR 1$ GETC: TSTB @#TKS ; terminal keyboard ready? BPL GETC ; nay, retry MOVB @#TKB,R2 ; get character off keyboard buffer RTS PC PUTC: TSTB @#TPS ; terminal printer ready? BPL PUTC ; nay, retry MOVB R2,@#TPB ; print character RTS PC .PSECT CONST CNVTBL: .ASCII / ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789/ .ASCII /????????????????????????????????????????/ .END