.TITLE BEISS debugger & command interpreter .IDENT /02.04/ ; ; Beiss is a debugger and command interpreter for Grumpf. ; ; memory inspection and modification variables: ; CURVAL current value ; CURREL current relocation register ; CURLOC current location pointer, contents of CURREL will be added for ; memory references ; PRVLOC previous location ; ; memory inspection and modification commands: ; 0-7 enter a number, will be used to form CURVAL ; , set new CURREL from low 3 bits of CURVAL ; / open location CURVAL, this sets CURLOC from CURVAL and CURVAL ; from contents of CURLOC ; CR save CURVAL in CURLOC, close location ; LF save CURVAL in CURLOC, close location, advance CURLOC, open ; location CURLOC ; ^ save CURVAL in CURLOC, close location, rewind CURLOC, open ; location CURLOC ; @ close location CURLOC, save CURLOC as PRVLOC, set CURLOC to ; CURVAL (adjusted to current relocation), open location CURLOC ; _ close location CURLOC, save CURLOC as PRVLOC, set CURLOC from ; CURVAL (interpreted as PC-relative address), open location ; CURLOC ; > close location CURLOC, save CURLOC as PRVLOC, set CURLOC from ; CURVAL (interpreted as branch instruction), open location ; CURLOC ; < close location CURLOC, restore CURLOC from PRVLOC, open ; location CURLOC ; $$A read CURVAL as two ASCII characters, must be finished with CR ; $$X read CURVAL as three ASCII characters, save in RAD50 encoding, ; must be finished with CR ; $A print ASCII representation of CURVAL ; $E set contents of current relocation register CURREL from CURVAL ; $O calculate byte offset from CURLOC to CURVAL ; $$O calculate word offset from CURLOC to CURVAL ; $X print RAD50 representation of CURVAL ; $R print CURVAL, CURLOC, CURREL and the contents of the relocation ; registers ; $D get device list from I/O system and print it ; Ctrl-C close location without writing CURVAL ; Ctrl-H right shift CURVAL by 3 bits, this undoes the last entered ; digit ; Ctrl-L redraw line (CURREL,CURLOC/CURVAL) ; Ctrl-? delete, works the same as Ctrl-H ; ; 29-AUG-2005 H. Rosenfeld changed user interface ; 29-MAY-2005 H. Rosenfeld added bus error handling, Ctrl-V ; 28-MAY-2005 H. Rosenfeld ; .LIST ME .NLIST CND .ENABL REG .LIBRARY /USRLIB.SML/ .LIBRARY /JOBCTL.SML/ .LIBRARY /MEMORY.SML/ .LIBRARY /SYSCLL.SML/ .LIBRARY /TTYCTL.SML/ .LIBRARY /IOSYS.SML/ .LIBRARY /CALL.SML/ .MCALL $SYS .MCALL $EXIT,$WAIT,$BUSHND,$CRASH .MCALL $IOREQ,$OPEN,$CLOS,$MODE,$READ .MCALL $M$ALLO,$P$INIT,$P$ALLO .MCALL .IOSYS,.IOFUNC,.IOERR,.IOCLR,.DEVCTL .MCALL .IMAGE,.CALL,.ENTRY,.RETRN .MCALL .TTYMOD .MCALL .ULDEFS,$CNV16S,$CNVS16,$GETC,$PUTC,$GETS,$PUTS .IOSYS .IOFUNC .IOERR .TTYMOD .ULDEFS .DEVCTL S$NUMV=000001 ; CURVAL is valid S$PNUM=000002 ; print CURVAL S$2ESC=000004 ; got 2 escapes .IMAGE BEISS .CSECT BEISS:: .ENTRY $M$ALLO #0,#200,#^RUSR,#^RB$P,#^ROOL ; allocate pool partition BCC 3$ ; continue if no error JMP INIERR ; abort on error 3$: $P$INIT R0,#200,#20 ; initialize pool partition .IOCLR #IORQP ; clear I/O request packet $CLOS #IORQP ; initialize I/O channels BCS INIERR ; abort on error 2$: $OPEN #IORQP,#^RTTY,#^R000,#^RTTY ; open terminal BCC 1$ ; continue if successful $WAIT #^RTTY,#^R000 ; otherwise, wait for terminal BR 2$ ; try again 1$: MOVB R0,IORQP ; store I/O channel number $MODE #IORQP,#0 ; switch terminal into character mode BCS INIERR ; abort on error CLR CURREL ; clear variables CLR CURLOC CLR CURVAL CLR STATE MOV #RELTAB,R0 MOV #10,R1 4$: CLR (R0)+ SOB R1,4$ MOV R5,BUSR5 ; save frame pointer for restart MOV SP,BUSSP ; dito for stack pointer RESTRT: .CALL B$LOOP ; do something useful $EXIT INIERR: $CRASH ; fatal error occured, crash Beiss B$LOOP: .ENTRY 4$: $GETC #IORQP ; get next character BCS INIERR ; abort on error MOV R0,R2 ; save character MOV #CMDLST,R4 ; get command character list MOV #CMDCNT,R3 ; get command count 1$: CMPB R0,(R4)+ ; is this the command? BEQ 2$ ; yea SOB R3,1$ MOV #CMDERR,R0 ; unknown character BR 3$ 2$: DEC R4 ; calculate offset in CMDTAB SUB #CMDLST,R4 ASL R4 MOV CMDTAB(R4),R0 ; get command routine address 3$: .CALL @R0,R2 ; call with character as argument BR 4$ BUSERR: MOV BUSR5,R5 ; restore frame pointer MOV BUSSP,R5 ; restore stack pointer $MODE #IORQP,#0 ; put terminal back in character mode $PUTS #IORQP,#QUEST,#3 ; new line BIC #S$NUMV,STATE ; invalidate CURVAL JMP RESTRT ; restart Beiss ; octal digit was typed ; if CURVAL not valid, clear it ; add digit to CURVAL OCTNUM: .ENTRY MOV 6(R5),R4 ; get digit $PUTC #IORQP,R4 ; echo digit BIT #S$NUMV,STATE ; CURVAL valid? BNE 1$ ; yea, skip clearing CLR CURVAL ; clear CURVAL BIS #S$NUMV,STATE ; set CURVAL valid 1$: SUB #'0,R4 ; convert to binary MOV CURVAL,R3 ; get CURVAL ASH #3,R3 ; shift for new digit ADD R4,R3 ; add new digit MOV R3,CURVAL ; save CURVAL .RETRN ; read two ASCII characters ASCINP: .ENTRY MOV CURVAL,R4 ; save CURVAL $PUTC #IORQP,#75 ; echo equals sign $MODE #IORQP,#T$LINE!T$ECHO!T$COOK ; put terminal in cooked line echo mode $GETS #IORQP,#CURVAL,#2 ; read two characters BCS 1$ ; stop if user typed ctrl-c 2$: $MODE #IORQP,#0 ; put terminal back in character mode .CALL CLOSE ; close location .RETRN 1$: MOV R4,CURVAL ; restore CURVAL BR 2$ ; read three ASCII characters, convert to RAD50 RADINP: .ENTRY $PUTC #IORQP,#75 ; echo equals sign $MODE #IORQP,#T$LINE!T$ECHO!T$COOK ; put terminal in cooked line echo mode $GETS #IORQP,#OCTBUF,#3 ; read three characters BCS 1$ ; stop if user typed ctrl-c CLRB OCTBUF+3 ; mark end of string $CNVS16 #R$R50,#OCTBUF ; convert to RAD50 MOV R0,CURVAL ; save as CURVAL 1$: $MODE #IORQP,#0 ; put terminal back in character mode .CALL CLOSE ; close location .RETRN ; a comma was typed ; set new CURREL from low 3 bits of CURVAL ; adjust RELBUF string COMMA: .ENTRY $PUTC #IORQP,6(R5) ; echo comma MOV CURVAL,R4 ; get CURVAL BIC #177770,R4 ; leave low 3 bits MOV R4,CURREL ; set new CURREL ADD #'0,R4 ; convert to ASCII MOVB R4,RELBUF ; modify RELBUF string ASL CURREL ; adjust CURREL to be word index BIC #S$NUMV,STATE ; CURVAL is now invalid .RETRN ; open location ; set new CURLOC from CURVAL ; set new CURVAL from contents of CURLOC ; print CURVAL OPEN: .ENTRY $PUTC #IORQP,6(R5) ; echo open character MOV CURVAL,CURLOC ; set new CURLOC MOV CURLOC,R3 ; get CURLOC MOV CURREL,R4 ; get CURREL ADD RELTAB(R4),R3 ; add relocation constant $BUSHND #BUSERR ; protect from bus error MOV @R3,CURVAL ; set new CURVAL from location contents $BUSHND #0 ; unprotect from bus error $CNV16S #R$OCT,CURVAL,#OCTBUF ; convert to octal MOVB #40,(R0)+ ; add whitespace to buffer $PUTS #IORQP,#OCTBUF,#7 ; print buffer BIC #S$NUMV,STATE ; CURVAL is now invalid .RETRN ; close location ; save CURVAL in contents of CURLOC CLOSE: .ENTRY $PUTS #IORQP,#CRLF,#2 ; new line MOV CURREL,R4 ; get CURREL MOV CURLOC,R3 ; get CURLOC ADD RELTAB(R4),R3 ; add relocation constant $BUSHND #BUSERR ; protect from bus error MOV CURVAL,@R3 ; set location contents from CURVAL $BUSHND #0 ; unprotect from bus error BIC #S$NUMV,STATE ; CURVAL is now invalid .RETRN ; linefeed typed ; close location, advance CURLOC, reopen location NEXT: .ENTRY .CALL CLOSE ; close location ADD #2,CURLOC ; advance CURLOC JMP REOPEN ; up arrow typed ; close location, rewind CURLOC, reopen location UARROW: .ENTRY .CALL CLOSE ; close location SUB #2,CURLOC ; rewind CURLOC JMP REOPEN ; @ typed ; close location, save CURLOC as PRVLOC, calculate new (relative) CURLOC from ; (absolute) CURREL ATSIGN: .ENTRY .CALL CLOSE ; close location MOV CURLOC,PRVLOC ; set PRVLOC from CURLOC MOV CURVAL,CURLOC ; set CURLOC from CURVAL MOV CURREL,R4 ; get CURREL SUB RELTAB(R4),CURLOC ; adjust absolute CURLOC to current ; relocation constant JMP REOPEN ; back arrow typed ; close location, save CURLOC as PRVLOC, calculate new CURLOC from CURVAL ; (interpreted as PC-relative address) BARROW: .ENTRY .CALL CLOSE ; close location MOV CURLOC,PRVLOC ; set PRVLOC from CURLOC ADD #2,CURLOC ; adjust for PC increment ADD CURVAL,CURLOC ; calculate new CURLOC JMP REOPEN ; < typed ; close location, restore CURLOC from PRVLOC BACK: .ENTRY .CALL CLOSE ; close location MOV PRVLOC,CURLOC ; restore CURLOC from PRVLOC JMP REOPEN ; > typed ; close location, save CURLOC in PRVLOC, calculate new CURLOC from CURVAL ; (interpreted as relative branch) BRANCH: .ENTRY .CALL CLOSE ; close location MOV CURLOC,PRVLOC ; set PRVLOC from CURLOC ADD #2,CURLOC ; adjust for PC increment MOVB CURVAL,R0 ; get low byte of branch instruction ASL R0 ; create word offset ADD R0,CURLOC ; calculate new CURLOC JMP REOPEN ; reopen location ; print CURLOC, set CURVAL from CURLOC for open routine, open location REOPEN: $PUTS #IORQP,#RELBUF,#2 ; new line $CNV16S #R$OCT,CURLOC,#OCTBUF ; convert CURLOC to octal $PUTS #IORQP,#OCTBUF,#6 ; pritn CURLOC MOV CURLOC,CURVAL ; set CURVAL to CURLOC .CALL OPEN,#'/ ; reopen location .RETRN ; interpret CURVAL as two ASCII bytes, print dots instead of control characters ASCII: .ENTRY $PUTC #IORQP,#75 ; print equals sign MOV CURVAL,R4 ; get CURVAL MOV R4,R3 ; in both R4 and R3 SWAB R3 ; swap bytes in R3 CMPB #40,R4 ; control character? BLOS 1$ ; nay, just print MOV #'.,R4 ; print a dot instead 1$: $PUTC #IORQP,R4 ; print low character CMPB #40,R3 ; control character? BLOS 2$ ; nay, just print MOV #'.,R3 ; print a dot instead 2$: $PUTC #IORQP,R3 ; print high character $PUTC #IORQP,#40 ; print whitespace .RETRN ; interpret CURVAL as RAD50 RAD50: .ENTRY $PUTC #IORQP,#75 ; print equals sign $CNV16S #R$R50,CURVAL,#OCTBUF ; convert CURVAL to RAD50 MOVB #40,(R0)+ ; append a whitespace to buffer $PUTS #IORQP,#OCTBUF,#4 ; print CURVAL .RETRN ; DELETE or Ctrl-H typed ; right shift CURVAL by 3 to erase last typed digit DELETE: .ENTRY $PUTC #IORQP,#'\ ; print a backslash MOV CURVAL,R4 ; get CURVAL ASH #-3,R4 ; right shift by 3 MOV R4,CURVAL ; save CURVAL .RETRN ; Ctrl-L typed ; redraw line ; actually, print CURLOC, slash, contents of CURLOC, whitespace ; if CURVAL is valid, print CURVAL too REDRAW: .ENTRY $PUTS #IORQP,#CRLF,#2 ; new line $PUTS #IORQP,#RELBUF,#2 ; print relocation string $CNV16S #R$OCT,CURLOC,#OCTBUF ; convert CURLOC to octal MOVB #'/,(R0)+ ; add slash to buffer $PUTS #IORQP,#OCTBUF,#7 ; print CURLOC and slash MOV CURREL,R4 ; get CURREL MOV CURLOC,R3 ; get CURLOC ADD RELTAB(R4),R3 ; add relocation constant $BUSHND #BUSERR ; protect from bus error MOV @R3,R3 ; get contents of location $BUSHND #0 ; unprotect from bus error $CNV16S #R$OCT,R3,#OCTBUF ; convert contents of CURLOC to octal MOVB #40,(R0)+ ; add whitespace to buffer $PUTS #IORQP,#OCTBUF,#7 ; print contents of CURLOC BIT #S$NUMV,STATE ; CURVAL valid? BEQ 1$ ; nay, don't print $CNV16S #R$OCT,CURVAL,#OCTBUF ; convert CURVAL to octal MOVB #40,(R0)+ ; add whitespace to buffer $PUTS #R$OCT,#OCTBUF,#6 ; print CURVAL .RETRN 1$: MOV R3,CURVAL ; set CURVAL from CURLOC contents .RETRN ; Ctrl-C typed ; close location without writing CURVAL CTRL$C: .ENTRY $PUTS #IORQP,#CRLF,#2 ; new line BIC #S$NUMV,STATE ; CURVAL is now invalid .RETRN ; save CURVAL as new relocation constant ENTER: .ENTRY MOV CURREL,R4 ; get CURREL MOV CURVAL,RELTAB(R4) ; save CURVAL as relocation constant $PUTS #IORQP,#CRLF,#2 ; new line BIC #S$NUMV,STATE ; CURVAL is now invalid .RETRN ; calculate byte and word offsets to CURVAL OFFS$B: .ENTRY $PUTC #IORQP,#75 ; print equals sign MOV CURVAL,R3 ; get CURVAL MOV CURLOC,R4 ; get CURLOC ADD #2,R4 ; adjust for PC increment SUB R4,R3 ; calculate byte offset $CNV16S #R$OCT,R3,#OCTBUF ; convert to octal MOVB #40,(R0)+ ; add whitespace to buffer $PUTS #IORQP,#OCTBUF,#7 ; print offset .RETRN OFFS$W: .ENTRY $PUTC #IORQP,#75 ; print equals sign MOV CURVAL,R3 ; get CURVAL MOV CURLOC,R4 ; get CURLOC ADD #2,R4 ; adjust for PC increment SUB R4,R3 ; calculate byte offset ASR R3 ; shift to get word offset $CNV16S #R$OCT,R3,#OCTBUF ; convert to octal MOVB #40,(R0)+ ; add whitespace to buffer $PUTS #IORQP,#OCTBUF,#7 ; print offset .RETRN ; print CURLOC, CURVAL, CURREL and relocation registers REGVAL: .ENTRY $PUTS #IORQP,#CRLF,#2 ; new line MOV #OCTBUF,R0 ; get output buffer MOVB #'L,(R0)+ ; L as in Location MOVB #40,(R0)+ ; whitespace $CNV16S #R$OCT,CURLOC,#OCTBUF+2 ; convert CURLOC MOVB #15,(R0)+ ; CR MOVB #12,(R0)+ ; LF $PUTS #IORQP,#OCTBUF,#12 ; print CURLOC MOVB #'V,OCTBUF ; V as in Value $CNV16S #R$OCT,CURVAL,#OCTBUF+2 ; convert CURVAL $PUTS #IORQP,#OCTBUF,#12 ; print CURVAL MOVB #'R,OCTBUF ; R as in Relocation MOV CURREL,R4 ; get CURREL ASR R4 ; CURREL is word index, so shift it $CNV16S #R$OCT,R4,#OCTBUF+2 ; convert CURREL $PUTS #IORQP,#OCTBUF,#12 ; print CURREL MOV #10,R4 ; 8 relocation registers 1$: MOV #10,R3 ; calculate register number SUB R4,R3 MOV R3,R2 ADD #'0,R2 ; calculate ASCII register number MOVB R2,OCTBUF ; store in output buffer ASL R3 ; shift to get index in table $CNV16S #R$OCT,RELTAB(R3),#OCTBUF+2 ; convert register contents $PUTS #IORQP,#OCTBUF,#12 ; print register contents SOB R4,1$ .RETRN ; ESCAPE character ESCAPE: .ENTRY BIC #S$2ESC,STATE ; clear 2esc flag 1$: $PUTC #IORQP,#'$ ; echo $ $GETC #IORQP ; get next character CMP #33,R0 ; another escape? BNE 2$ ; nay BIS #S$2ESC,STATE ; set 2esc flag BR 1$ 2$: CMP R0,#'a ; lower case letter? BLO 3$ ; nay CMP #'z,R0 ; lower case letter? BLO 3$ ; nay BIC #040,R0 ; convert to upper case 3$: MOV R0,R2 ; save character MOV #ESCLST,R4 ; get escape command character list MOV #ESCCNT,R3 ; get escape command count 4$: CMPB R0,(R4)+ ; is this the command? BEQ 5$ ; yea SOB R3,4$ MOV #CMDERR,R0 ; unknown character BR 7$ 5$: $PUTC #IORQP,R2 ; echo command character DEC R4 ; calculate offset in ESCTAB SUB #ESCLST,R4 ASL R4 ; shift to calculate word index BIT #S$2ESC,STATE ; 2 escapes? BEQ 6$ ; nay INC R4 ; yea 6$: ASL R4 ; shift to calculate 2-word index MOV ESCTAB(R4),R0 ; get command routine address 7$: .CALL @R0,R2 ; call with character as argument .RETRN ; DEVLST, get device list from I/O system and print it DEVLST: .ENTRY SUB #10,SP ; allocate I/O request packet on stack MOV SP,R4 SUB #SIZE$D,SP ; allocate device buffer on stack MOV SP,R3 MOV #OCTBUF,R2 ; use OCTBUF for output .IOCLR R4 ; clear packet $PUTS #IORQP,#HDLINE,#112 ; print headline 2$: $READ R4,#SIZE$D,R3 ; read device entry BCS 5$ ; stop on error $CNV16S #R$R50,D$NAME(R3),R2 ; print device name $CNV16S #R$R50,D$NUM(R3),R0 ; and number MOVB #72,(R0)+ ; followed by a colon MOVB #11,(R0)+ ; and a tab $CNV16S #R$R50,D$TYPE(R3),R0 ; print device type MOVB #11,(R0)+ ; and a tab $PUTS #IORQP,R2,#14 ; print line MOV D$INFO(R3),R0 ; get driver information BEQ 4$ ; skip if not present MOV R0,R1 ; save pointer 3$: TSTB (R1)+ ; check for end of string BNE 3$ SUB R0,R1 ; R1 = length of string + 1 DEC R1 ; R1 = length of string $PUTS #IORQP,R0,R1 ; print driver information 4$: $PUTS #IORQP,#CRLF,#2 ; new line JMP 2$ 5$: .RETRN ; unimplemented commands TRACE: UNTRC: BREAKP: UNBRKP: FLOAT: FLOINP: CMDERR: .ENTRY $PUTC #IORQP,#'? .RETRN .PSECT DATA RELTAB: .BLKW 10 ; relocation registers CURREL: .BLKW 1 ; current relocation register CURVAL: .BLKW 1 ; current value CURLOC: .BLKW 1 ; current location pointer PRVLOC: .BLKW 1 ; previous location pointer STATE: .BLKW 1 ; Beiss state BUSR5: .BLKW 1 ; frame pointer for bus error recovery BUSSP: .BLKW 1 ; stack pointer for bus error recovery OCTBUF: .BLKW 10 ; output buffer for $CNV16S IORQP: .BLKW 10 ; I/O request packet RELBUF: .ASCII /0,/ ; relocation string .PSECT CONST CMDTAB: .WORD OCTNUM ; command routine table .WORD OCTNUM ; order must be same as in CMDLST .WORD OCTNUM .WORD OCTNUM .WORD OCTNUM .WORD OCTNUM .WORD OCTNUM .WORD OCTNUM .WORD COMMA .WORD UARROW .WORD ATSIGN .WORD BARROW .WORD BACK .WORD BRANCH .WORD CTRL$C .WORD DELETE .WORD NEXT .WORD REDRAW .WORD CLOSE .WORD ESCAPE .WORD OPEN .WORD DELETE CMDLST: .ASCII /01234567,^@_<>/ ; command characters .ASCII <3><10><12><14><15><33><57><177> CMDCNT=26 ; command count ESCTAB: .WORD ASCII ; $A (ASCII output) .WORD ASCINP ; $$A (ASCII input) .WORD RAD50 ; $X (RAD50 output) .WORD RADINP ; $$X (RAD50 input) .WORD FLOAT ; $F (FLOAT output) .WORD FLOINP ; $$F (FLOAT input) .WORD OFFS$B ; $O (byte offset) .WORD OFFS$W ; $$O (word offset) .WORD REGVAL ; $R (internal register printout) .WORD CMDERR ; $$R unknown .WORD ENTER ; $E (enter value in reloc register) .WORD CMDERR ; $$E unknown .WORD BREAKP ; $B (set breakpoint) .WORD UNBRKP ; $$B (unset breakpoint) .WORD TRACE ; $T (enable trace) .WORD UNTRC ; $$T (disable trace) .WORD DEVLST ; $D (print device list) .WORD CMDERR ; $$D unknown ESCLST: .ASCII /AXFOREBTD/ ; escape command characters ESCCNT=11 QUEST: .ASCII <77> ; ? HDLINE: .ASCII <15><12>/NAME TYPE DRIVER INFORMATION / .ASCII <15><12>/---------------------------------------/ CRLF: .ASCII <15><12> ; CR, LF .END BEISS