.TITLE DDT MACHINE SUPPORT ; DDT - symbolic machine language debugger ; Machine language support for the PDP-11 .CSECT ZDDT ; Name changed to make last thing loaded ; .ENABL ISD ; FOR DEBUGGING ONLY!! .INSRT 11lm.sml ; Globals provided .GLOBL DDT ; START ADDRESS OF DDT .GLOBL START ; Default start address for this DDT .GLOBL D.ERRT, D.NXMT ; So others can set up the vectors .GLOBL D.ILGT, D.BRK ; for traps, etc. .GLOBL D_ISYMT ; Internal symbol table .GLOBL ddtexec ; Routine to reset CPU before $G .GLOBL ddtmov ; Accesses memory .GLOBL ddterr ; Fatal DDT internal error .IF NE, DDTDBG .GLOBL ddtbug ; As above, but prints string .ENDC .GLOBL ddtgps, ddtpps ; Access to PS .GLOBL ddtps, ddtpc ; Registers needed by hardcore .GLOBL ddtgetc ; I/O interface in hardcore .GLOBL ddtputc .GLOBL ddtputs ; Globals used .GLOBL ddthc ; DDT initialization point .GLOBL ddtrte ; DDT error entry point .GLOBL ddtbpt ; DDT BPT entry point .GLOBL ddttrc ; DDT trace trap entry point .GLOBL $START ; Real default start address for 11 code DSSIZ = 150. ; DDT STACK SIZE - USES ABOUT 100 NOW ESSIZ = 10. ; DDT ERROR STACK .IF DF D.TTY D.RCSR = D.TTY ; READER STATUS REGISTER D.RDB = D.TTY+2 ; READER DATA BUFFER D.TCSR = D.TTY+4 ; PRINTER STATUS REGISTER D.TDB = D.TTY+6 ; PRINTER DATA BUFFER .IFF .ERROR ; NO OUTPUT DEVICE FOR DDT .ENDC TRCBIT = 20 ; TRACE BIT PRIMSK = 340 ; MASK FOR PRIORITY BITS HIPRI = 340 ; SPL HIGH NXMT = 4 ; LOCATION OF NXM AND OTHER TRAPS ILGT = 10 BPTT = 14 IOTT = 20 EMTT = 30 TRPT = 34 ETSHFT = 400 ; SHIFT FOR ACCESSING EMT/TRAP OPCODE .IF EQ LSI11 PS = 177776 ; PROCESSOR STATUS .ENDC .MACRO $GETPS LOC ; FOR GETTING AND PUTTING PS .IF EQ LSI11 MOV @#PS, LOC .IFF MFPS LOC .ENDC .ENDM .MACRO $PUTPS LOC .IF EQ LSI11 MOV LOC, @#PS .IFF MTPS LOC .ENDC .ENDM .MACRO $RTT .IF EQ P1120 RTT .IFF RTI .ENDC .ENDM ; INITIAL ENTRY POINT FOR DDT DDT: MOV #HIPRI,R1 ; Entry at DDT is hard start $PUTPS R1 ; DONT GET HASSLED MOV #D.STK,SP ; SET UP STACK CLR R0 ; FILL STARTING WITH ERROR TRAP MOV #D.ERRT,(R0)+ ; FILL ERROR TRAP INITIALLY MOV R1,(R0)+ ; SET HIGH STATUS FOR ERROR TRAP MOV #D.NXMT,(R0)+ ; SET FOR EXTERNAL NXMS MOV R1,(R0)+ ; SET HIGH STATUS MOV #D.ILGT,(R0)+ ; SET FOR ILLEGAL INSTRUCTIONS MOV R1,(R0)+ ; SET HIGH STATUS MOV #D.BRK,(R0)+ ; SET FOR BREAKPOINTS MOV R1,(R0)+ ; SET HIGH STATUS CLRB D.RAI ; AND NOT IN MIDDLE OF ABORTED INST JSR PC,D.SAVE ; SAVE REST OF INITIAL STATE JSR PC,ddthc ; CALL INTO PARSER BR D.PROC ; FIRST CALL RETURNS HERE ; INTERFACE TO REAL START CODE; REAL SYMBOL INACCESSIBLE FROM C START: JMP $START ; CODE TO RESET MACHINE FOR $G COMMAND ddtexec: CLR -(SP) ; MAKE SURE THE TTY IS DONE JSR PC,ddtputc JSR PC,ddtputc ; TWICE, SINCE THIS MIGHT BE AN ASYN L/I TST (SP)+ RESET ; RESET WORLD $PUTPS #HIPRI ; AND PREVENT NOSINESS CLR D.TSAV ; RESET TTY MANUALLY CLR D.TSAV+2 MOV #D.STK,D.UR6 ; LET USER START ON OUR STACK RTS PC ; CODE TO SIMULATE CERTAIN TRAPS D.INXM: MOV #D.NM,-(SP) ; SET UP ERROR MESSAGE JSR PC,ddtrte ; CALL INTO PARSER BR D.PROC ; DON'T BOTHER TO POP ARG D.ITRC: JSR PC,ddttrc ; SIMULATE TRACE TRAP ; ON RETURN WILL FALL THROUGH INTO PROC ; CODE TO RETURN MACHINE TO RUNNING D.PROC: MOV ddtpc,R5 ; GET STARTING ADDRESS BIT #1,R5 ; ODD ADDRESS? BNE D.INXM ; YES, ERROR, SIMULATE NXM BIT #TRCBIT,ddtps ; IS THE T-BIT BE ON? BNE D.TFIX ; BRANCH IF SO (SINCE TRACE TRAPS DON'T WORK ON D.RST: JMP D.REST ; SOME INST'S, AND THEY HAVE TO BE SIMULATED) ; OTHERWISE RESUME PROCESSING D.TFIX: MOV R5,D.TPC ; SAVE PC FOR ABORTED INST HACK CMP (R5),#RESET ; IS INSTRUCTION RESET? BNE D.NRST ; NOPE, TRY NEXT CLASS CLR -(SP) ; YES, MAKE SURE THE TTY IS DONE JSR PC,ddtputc JSR PC,ddtputc ; TWICE, SINCE THIS MIGHT BE AN ASYN L/I TST (SP)+ RESET ; DO RESET FOR HIM TST (R5)+ ; BUMP PC MOV R5,ddtpc ; SAVE IT CLR D.TSAV ; RESET TTY MANUALLY CLR D.TSAV+2 ; TO MIMIC HARDWARE INIT D.STRC: BIS #TRCBIT,ddtps ; Make sure trace trap bit is still on BR D.ITRC ; AND SIMULATE A TRACE TRAP D.NRST: CMP (R5),#RTI ; Is instruction RTI? BEQ D.DRT ; Yes, we have to simulate it CMP (R5),#RTT ; Is instruction RTT? BNE D.NRT ; No, go try next class D.DRT: MOV D.UR6,R5 ; Get user stack pointer MOV (R5)+,ddtpc ; Pop new PC from stack to virtual PC MOV (R5)+,ddtps ; Pop new PS from stack to virtual PS MOV R5,D.UR6 ; Remember that we have popped them off BR D.STRC D.NRT: CMP (R5),#IOT ; Is instruction IOT? BNE D.NIOT ; No, try other trap instructions MOV @#IOTT,-(SP) ; Yes, push its vector on DDT stack MOV @#IOTT+2,-(SP) BR D.STRP ; And go simulate trap D.NIOT: CMPB 1(R5),#TRAP/ETSHFT ; is instruction TRAP? BNE D.NTRP ; No, try EMT MOV @#TRPT,-(SP) ; Yes, push its vector on DDT stack MOV @#TRPT+2,-(SP) BR D.STRP D.NTRP: CMPB 1(R5),#EMT/ETSHFT ; Is instruction EMT? BNE D.RST ; No, go do trace trap on instruction MOV @#EMTT,-(SP) ; Yes, push its vector on DDT stack MOV @#EMTT+2,-(SP) D.STRP: TST (R5)+ ; Increment "PC" as if inst were executed MOV R5,ddtpc ; and remember it BIC #TRCBIT,ddtps ; Remove trace trap bit from this context MOV D.UR6,R5 ; Use R5 for user stack MOV ddtps,-(R5) ; Push User PS MOV ddtpc,-(R5) ; and PC on User stack MOV (SP)+,ddtps ; Replace with PS MOV (SP)+,ddtpc ; and PC from vector MOV R5,D.UR6 ; Remember that we have popped them off BR D.STRC ; Go set trap bit and simulate trace trap ; ERROR TRAPS D.ERRT: MOV #D.EM,D.ERF ; MARK ERROR TRAP ENTRY BR D.DERR ; HANDLE BREAKPOINT D.NXMT: MOV #D.NM,D.ERF ; NXM TRAP SERVICE BR D.DERR ; HANDLE BREAKPOINT D.ILGT: MOV #D.IM,D.ERF ; ILLEGAL INSTRUCTION D.DERR: MOV (SP)+,ddtpc ; SAVE PC AND STATUS MOV (SP)+,ddtps ; SAVE PS JSR PC,D.SAVE ; SAVE VARIOUS REGISTERS MOV D.ERF,-(SP) ; PUSH STRING ARG JSR PC,ddtrte ; CALL INTO PARSER D.PRC: JMP D.PROC ; ON RETURN, RESTART - DON'T BOTHER TO POP ARG ; BREAKPOINT AND TRACE TRAP HANDLER D.BRK: MOV (SP)+,ddtpc ; SAVE PC AND STATUS TSTB D.RAI ; REDOING ABORTED INST AT HIGH PRI? BEQ D.BRK0 ; NO CLRB D.RAI BIC #PRIMSK,(SP) ; YES, RESTORE OLD PRIORITY BITS BIS D.OPS,(SP) ; IN PS WORD ON STACK D.BRK0: MOV (SP)+,ddtps ; SAVE PS JSR PC,D.SAVE ; SAVE VARIOUS REGISTERS BIT #TRCBIT,ddtps ; WERE WE TRACING? BNE D.BRK1 ; GO HANDLE AS TRACE JSR PC,ddtbpt ; DO BREAKPOINT BR D.PRC ; ON RETURN, RESUME CODE D.BRK1: CMP ddtpc,D.TPC ; DID WE EXECUTE THE INTRUCTION? BNE D.BRK2 ; YES, DO NORMAL TRACE ACTION INCB D.RAI ; YES, TRY IT AGAIN, AT HIGH PRI MOV ddtps,D.OPS ; AFTER SAVING OLD LEVEL BIC #^C,D.OPS ; SO THAT IT CAN BE PATCHED BACK BIS #HIPRI,ddtps BR D.PRC D.BRK2: JSR PC,ddttrc ; CALL IN PARSER BR D.PRC ; RESTART USER CODE ; SUBROUTINE TO DO MOVE, TRAPPING REFERENCES TO NXM's, ETC. ; NOTE THAT COUNT IS CLEARED IF MOV FAILS ddtmov: MOV R2,-(SP) ; NEED A TEMP MOV 4(SP),R0 ; LENGTH MOV 6(SP),R1 ; SRC MOV 10(SP),R2 ; DEST $GETPS -(SP) ; DON'T GET DISTURBED $PUTPS #HIPRI MOV @#NXMT,-(SP) ; SAVE TIMEOUT VECTOR WORDS MOV @#NXMT+2,-(SP) MOV #D.NOMV,@#NXMT ; NEW TIMEOUT VADDR MOV #HIPRI,@#NXMT+2 ; NEW TIMEOUT PS CMP R0,#1 ; ONE BYTE? BEQ D.MVBY ; HANDLE SEPARATELY BIT #1,R1 ; CHECK FOR LSI11 LOSSAGE WHERE WORD BNE D.MVER ; ACCESS ON ODD BOUNDARY IS NOT ERROR BIT #1,R2 ; AND SIMULATE ERROR BNE D.MVER CMP R0,#2 ; LONG? BEQ D.MVSH ; ONLY DO ONE WORD CMP R0,#4 ; LONG? BNE D.MVER ; ONLY DO ONE WORD MOV (R1)+,(R2)+ ; DO FIRST WORD D.MVSH: MOV (R1)+,(R2)+ ; DO SHORT OR SECOND WORD OF LONG BR D.OKMV ; SKIP ERROR CODE D.MVBY: MOVB (R1)+,(R2)+ BR D.OKMV D.NOMV: CMP (SP)+,(SP)+ ; POP INT PS AND PC D.MVER: CLR R0 ; FLAG ERROR D.OKMV: MOV (SP)+,@#NXMT+2 ; RESTORE TIMEOUT VECTOR WORDS MOV (SP)+,@#NXMT $PUTPS (SP)+ ; RESTORE PS MOV (SP)+,R2 ; RESTORE REGISTER RTS PC ; AND RETURN ; SAVE THE WORLD D.SAVE: MOV R5,D.UR5 ; GET A TEMPORARY MOV (SP)+,R5 ; PICK UP RETURN ADDRESS FROM STACK MOV SP,D.UR6 ; SAVE USER STACK ADDRESS MOV #D.UR4,SP ; SET TO USER REG STORE AREA (R5 ALREADY THERE) MOV R4,@SP ; REGISTERS MOV R3,-(SP) ; 4 MOV R2,-(SP) ; THRU MOV R1,-(SP) ; 0 MOV R0,-(SP) ; SAVED HERE MOV #D.STK,SP ; RESET DDT SP MOV #HIPRI,R1 ; HIGH PS CLR R0 ; ADDRESS OF TRAP VECTORS MOV #D.TSAV,R2 ; SAVE USERS VECTORS, ETC HERE MOV @#D.RCSR,(R2)+ ; SAVE KEYBOARD STATUS CLR @#D.RCSR ; TURN OFF ALL INTERRUPTS MOV @#D.TCSR,(R2)+ ; SAVE PRINTER STATUS CLR @#D.TCSR ; REMOVE ALL ENABLES MOV (R0),(R2)+ ; SAVE OLD 0 MOV #D.ERRT,(R0)+ ; RESET ERROR TRAP FOR BAD ENTRY MOV (R0),(R2)+ ; AND PS MOV R1,(R0)+ ; AND SET HIGH PRI MOV (R0),(R2)+ ; 4 MOV #ddterr,(R0)+ ; RESET NXM ADDRESS FOR INTERNAL NXMS MOV (R0),(R2)+ MOV R1,(R0)+ MOV (R0),(R2)+ ; 10 MOV #ddterr,(R0)+ ; ILLEGAL INSTRUCTION MOV (R0),(R2)+ MOV R1,(R0)+ MOV (R0),(R2)+ ; 14 MOV #ddterr,(R0)+ ; BPT VECTOR MOV (R0),(R2)+ MOV R1,(R0)+ JMP @R5 ; RETURN ; RESTORE THE WORLD AS WE FOUND IT D.REST: MOV #D.TSAV,SP ; SET STACK POINTER TO BASE OF USER INFO 1$: TSTB @#D.TCSR ; CHARACTER OUTPUT FINISHED? BPL 1$ ; LOOP UNTIL DONE MOV (SP)+,@#D.RCSR ; PUT KEYBOARD STATUS BACK MOV (SP)+,@#D.TCSR ; PUT TELETYPE STATUS BACK CLR R0 ; RESTORE HIS VECTORS MOV (SP)+,(R0)+ ; 0 MOV (SP)+,(R0)+ ; 2 MOV (SP)+,(R0)+ ; 4 MOV (SP)+,(R0)+ ; 6 MOV (SP)+,(R0)+ ; 10 MOV (SP)+,(R0)+ ; 12 MOV (SP)+,(R0)+ ; 14 MOV (SP)+,(R0)+ ; 16 MOV (SP)+,R0 ; RESTORE MOV (SP)+,R1 ; USER MOV (SP)+,R2 ; REGISTERS MOV (SP)+,R3 ; 0 MOV (SP)+,R4 ; THRU MOV (SP)+,R5 ; 5 MOV (SP),SP ; RESTORE USER STACK MOV ddtps,-(SP) ; AND STATUS MOV ddtpc,-(SP) ; AND PC $RTT ; Gets changed to "RTI" if 11/20, etc... ; FOR ANY 'IMPOSSIBLE' ERRORS IN DDT ddterr: MOV SP,D.ESP ; SAVE SP (MAY BE BAD) MOV #D.ESTK,SP ; GET GUARANTEED GOOD ONE $GETPS -(SP) ; SAVE PS $PUTPS #HIPRI ; NO HASSLES MOV R0,-(SP) ; THIS WILL BE TRASHED MOV #D.ERRM,-(SP) ; PRINT ERROR MSG JSR PC,ddtputs TST (SP)+ ; POP ARG MOV (SP)+,R0 ; RESTORE R0 1$: HALT ; AND DIE BR 1$ .IF NE, DDTDBG ; LIKE ABOVE, BUT PRINTS A SPECIFIC ERROR MSG ddtbug: MOV SP,D.ESP ; SAVE SP (MAY BE BAD) MOV #D.ESTK,SP ; GET GUARANTEED GOOD ONE $GETPS -(SP) ; SAVE PS $PUTPS #HIPRI ; NO HASSLES MOV R0,-(SP) ; THIS WILL BE TRASHED MOV D.ESP,R0 ; GET ERROR MSG FROM STACK MOV 6(R0),-(SP) ; (NOTICE STACK NOT IN SP) JSR PC,ddtputs MOV #D.ERRM,@SP ; PRINT ERROR MSG JSR PC,ddtputs TST (SP)+ ; POP ARG MOV (SP)+,R0 ; RESTORE R0 1$: HALT ; LET USER FIGURE IT OUT BR 1$ .ENDC ; GET A CHARACTER INTO R0 ddtgetc: TSTB @#D.RCSR ; CHARACTER TYPED? BPL ddtgetc ; LOOP UNTIL FOUND MOVB @#D.RDB,R0 ; GET A CHARACTER BIC #177600,R0 ; CLEAR META, CNTL AND SHIFT STUFF RTS PC ; RETURN ; TYPE THE CHARACTER ON STACK ddtputc: TSTB @#D.TCSR ; PRINTER READY FOR CHARACTER? BPL ddtputc ; LOOP IF NOT MOVB 2(SP),@#D.TDB ; PUT OUT CHARACTER RTS PC ; RETURN ; TYPE THE STRING POINTED TO ON STACK ddtputs: MOV 2(SP),R0 ; GET STRING D.PSL: TSTB @R0 ; END OF STRING? BEQ D.PSD ; QUIT IF SO MOVB (R0)+,-(SP) ; GET CHARACTER JSR PC,ddtputc ; PUT OUT CHARACTER TST (SP)+ ; POP ARG BR D.PSL ; AND LOOP D.PSD: RTS PC ; RETURN ; ROUTINES TO ACCESS PS. NOTE THAT CAN'T USE $PUTPS SINCE YOU ; CAN'T SET THE T BIT THAT WAY. HAPPILY, STUFF ON STACK IS IN RIGHT ; ORDER FOR RTI! ddtgps: $GETPS R0 RTS PC ddtpps: RTI .CSECT ZDDTD, STATIC ; BYTE ALIGNED CONSTANTS D.ERRM: .ASCIZ <15><12>/Fatal DDT error/<15><12> D.EM: .ASCIZ /ERR/ D.NM: .ASCIZ /NXM/ D.IM: .ASCIZ /ILG/ ; BYTE ALIGNED VARIABLES D.RAI: .BYTE 0 ; ON IF RETRYING ABORTED INST AT HIGH PRI ; WORD ALIGNED VARIABLES; DDT AND USER STATE VARIABLES. LATTER DESCRIBE ; THE USER'S PROGRAM STATE. THESE LOCATIONS MUST BE CONTIGUOUS!! .EVEN .BLKW DSSIZ ; ACTIVE DDT STACK AREA D.STK: ; BASE OF ACTIVE DDT STACK .BLKW ESSIZ ; ERROR STACK AREA D.ESTK: ; BASE OF ERROR DDT STACK D.ESP: 0 ; SP AT TIME OF ERROR D.TPC: 0 ; PC BEFORE EXECUTION OF SINGLE INST D.OPS: 0 ; OLD PRIORITY LEVEL OF CPU ON ABORTED INST D.ERF: 0 ; ADDRESS OF ERROR STRING ON MACHINE FAULT D.TSAV: 0 ; SAVE CELL - R C/SR 0 ; SAVE CELL - T C/SR D.U0: 0,0,0,0 ; USER LOCATION 0,2,4,6 0,0,0,0 ; USER LOCATIONS 10,12,14,16 D.UR0: 0 ; USER REGISTER 0 D.UR1: 0 ; USER REGISTER 1 D.UR2: 0 ; USER REGISTER 2 D.UR3: 0 ; USER REGISTER 3 D.UR4: 0 ; USER REGISTER 4 D.UR5: 0 ; USER REGISTER 5 D.UR6: 0 ; USER SP ddtpc: 0 ; USER PC ddtps: 0 ; USER STATUS .CSECT ZDDTST, STATIC ; THE INTERNAL SYMBOL TABLE D_ISYMT:.RAD50 /R0 / ; THIS SYMBOL TABLE MUST APPEAR D.UR0 ; AT THE END OF DDT SINCE IT IS .RAD50 /R1 / ; EXTENDED MAGICALLY BY LINK11 D.UR1 ; STARTING AT ADDRESS D.SYMT .RAD50 /R2 / D.UR2 ; Unordered symbol table, .RAD50 /R3 / ; searched linearly. D.UR3 .RAD50 /R4 / D.UR4 .RAD50 /R5 / D.UR5 .RAD50 /SP / D.UR6 .RAD50 /R6 / D.UR6 .RAD50 /PC / ddtpc .RAD50 /R7 / ddtpc .RAD50 /PS / ddtps .END