.MCALL .MODULE .MODULE ID,RELEASE=X01,VERSION=03,COMMENT=,AUDIT=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL Edit History ;+ ; ; ID ; Out of address space debugger. Low memory portion recieves ; breakpoint and dispatches to debugger in high memory mapped ; through PAR1. ; ; Debugger is based on ODT/VDT with modifications to provide a ; more SD-like user interface. ; ; X01 (000) 18-Jun-88 Began conversion from program stub to system ; MBG program and from there to handler, placing ; major portion of debugger in high memory. ; ; Completed 6-Jul-88. ; ; X01 (001) 09-Aug-88 Fixed problems with initial breakpoint ; MBG table. ; ; X01 (002) 15-Aug-88 Fix of routine to convert physical (PAR bias/offset) ; MBG to virtual address. Added audit trail info. ; ; X01 (003) 18-Aug-88 Added method of getting Kernel PAR1 contents ; MBG when in debugger. Contents in word following ; special register $K. ; ;- .SBTTL Definitions ; RT-11 System macros to be used .MCALL .DRDEF, .ADDR ; Define our own macros .MACRO MWLHCL SRC,DST ;Move word low to high, code low MOV SRC,@#20000+ .ENDM .MACRO MWHLCL SRC,DST ;Move word high to low, code low MOV @#20000+,DST .ENDM .MACRO MWLHCH SRC,DST ;Move word low to high, code high MOV O..IDT,-(SP) ADD #,(SP) MOV @(SP)+,DST .ENDM .MACRO MWHLCH SRC,DST ;Move word high to low, code high MOV O..IDT,-(SP) ADD #,(SP) MOV SRC,@(SP)+ .ENDM .MACRO CALLH DST CALL @#20000+ .ENDM .MACRO BRDEF ARG1,ARG2 .MACRO 'ARG1'. DST,?L ARG2 L JMP DST L: .ENDM ;'ARG1'. .MACRO 'ARG2'. DST,?L ARG1 L JMP DST L: .ENDM ;'ARG2'. .ENDM ;BRDEF BRDEF BEQ,BNE ;Define BEQ. and BNE. BRDEF BGE,BLT ;Define BGE. and BLT. BRDEF BLE,BGT ;Define BLE. and BGT. ; RT-11 System communication area JSW =: 44 ;Job status word TCBIT$ =: 000100 ;FB,XM; Inhibit terminal wait bit TTSPC$ =: 010000 ;Special mode terminal bit TTLC$ =: 040000 ;Lower-case bit for console ERRBYT =: 52 ;EMT error byte USERRB =: 53 ;User error reporting byte SYSPTR =: 54 ;Pointer to $RMON TTFILL =: 56 ;Fill character TTNFIL =: 57 ;Fill count ; RT-11 Fixed offsets CONFIG =: 300 ;Configuration word 1 KT11$ =: 010000 ;Mapped system running under XM TTKS =: 304 ;Address of keyboard status MEMPTR =: 430 ;Pointer to memory pointers CORPTX =: 4 ;Offset to extended memory block P1EXT =: 432 ;PAR1 Externalization routine FINDGR =: -10. ;JMP to find global region routine XALLOC =: -6 ;JMP to extended memory allocation routine BLKMOV =: -2 ;BR to block memory move routine $TRPLS =: 434 ;-> FIXTRP list ; Hardware definitions NXM.V =: 4 ;Non-existant memory trap vector BPT.V =: 14 ;Breakpoint trap vector SISAR0 =: 172240 ;Supervisor I-Space PAR0 KISAR0 =: 172340 ;Kernel I-Space PAR0 KISAR1 =: KISAR0+2 ;Kernel I-Space PAR1 KISAR2 =: KISAR0+4 ;Kernel I-Space PAR2 UISAR0 =: 177640 ;User I-Space PAR0 PS =: 177776 ;Processor status word PS.CMM =: 140000 ;Current mode mask PS.PMM =: 030000 ;Previous mode mask PS.PR7 =: 000340 ;Priority 7 PS.T =: 000020 ;Trace trap bit ; Miscellaneous definitions RC.IE =: 000100 ;Receiver interrupt enable XC.IE =: 000100 ;Transmitter interrupt enable KTGRAN =: 32. ;KT-11 Granularity BLOCK = 512. ;Size of a block in bytes O.BKP =: 16 ;Number of *2 O.RLR =: 16 ;Number of *2 .IIF NDF $DEBUG $DEBUG = 0 ; Global region control block (in free area) GR.SIZ =: 0 ;Size in 32 word blocks GR.ADR =: 2 ;Base address in 32-word blocks GR.STA =: 4 ;Status byte GR.PVT = 100000 ;Private region GR.NRF = 000040 ;Don't return memory to free list GR.NAM =: 6 ;Name (2 words rad50) GR.ESZ =: 10. ;GRCB size in bytes ; Define the device .DRDEF ID,62,,0,0,0 .DRPTR FETCH=*NO*,LOAD=LOAD,UNLOAD=UNLOAD .DREST CLASS=DVC.PS .SBTTL Installation code .DRINS ID BR 10$ ;Data device installation BR O.BAD ;System device installation 10$: MOV @#SYSPTR,R0 ;R0 -> $RMON BIT KT11$,CONFIG(R0) ;Running under XM? BEQ O.BAD ;Nope... ; Now we allocate a region in extended memory for our use MOV @#SYSPTR,R1 ;R1 -> $RMON MOV MEMPTR(R1),R0 ;R0 = Offset to memory tables ADD R1,R0 ;R0 -> True address MOV CORPTX(R0),R5 ;R5 = Offset to extended ALLOC ADD R1,R5 ;R5 -> True address 20$: CMP (R5)+,#-1 ;End of free memory list? BNE 20$ ;Nope, loop until found 30$: CMP (R5),#-1 ;End of RCB list? BEQ O.BAD ;Yes, reject installation TST (R5) ;Is it a free RCB? BEQ 40$ ;Yes, go use it ADD #GR.ESZ,R5 ;Nope, on to next RCB BR 30$ 40$: MOV P1EXT(R1),R0 ;R0 -> PAR1 Externalization routine MOV #>/KTGRAN,R2 ;R2 = Size of region needed CALL XALLOC(R0) ;Go allocate the space BCS O.BAD ;Couldn't, reject installation MOV R2,(R5)+ ;Build RCB (size) MOV R1,(R5)+ ; (address) MOV #GR.PVT,(R5)+ ; (status) MOV DEVNAM,(R5)+ ; (name) MOV #<^R$ >,(R5) ; (name) BR O.GOOD .DSABL LSB .SBTTL Set code .DRSET CSR, 160000, O.CSR, .DRSET BREAK, -1, O.BREA ; SET ID NOCSR=0 ; SET ID CSR=n O.CSR: TST R0 ;Address = 0? BEQ 10$ ;Yes, then bypass check CMP R0,R3 ;CSR in range? BLO O.BAD ;Nope... 10$: MOV R0,DISCSR ;Set the display- MOV R0,INSCSR ; and install-time CSR .ADDR #O.$TKS,R1 ;R1 -> Console terminal CSR table MOV #4,R2 ;R2 = Count of locations to set 20$: MOV R0,(R1)+ ;Set a register address ADD #2,R0 ;On to next address SOB R2,20$ ;Loop until console CSRs are set BR O.GOOD ; SET ID BREAK O.BREA: CALL FINDRV ;Check if handler is in memory BCS O.BAD ;Nope... BPT ;BPT so we can enter handler BR O.GOOD FINDRV: .ADDR #DEVNAM,R0 ;R0 -> Device name in Rad50 .ADDR #DAREA,-(SP) ;(SP) -> .DSTAT info area EMT 342 ;*** .DSTAT #DAREA,#DEVNAM *** BCS O.BAD ;Device is not known... MOV DAREA+4,R1 ;Get handler entry point BEQ O.BAD ;It's not loaded... O.GOOD: TST (PC)+ ;*C=0* Good return O.BAD: SEC ;*C=1* Error return RETURN ;*C* DEVNAM: .RMODUL ;Handler name DAREA: .BLKW 4 ;.DSTAT INFORMATION BLOCK .SBTTL Handler entry point .DRBEG ID MOV IDCQE,R4 ;R4 -> Current queue element BIS #HDERR$,@-(R4) ;Return hard error on all requests .DRFIN ID IDINT: RETURN .SBTTL O.BRKL - Low memory breakpoint handler ;+ ; ; O.BRKL ; Resides in low memory and fields BPT instructions, passing ; them on to high-memory portion of debugger. ; ; Notes ; o Routine executes in KERNEL mode ; o PS and virtual PC at time of breakpoint are on ; KERNEL stack ; o Saves kernel PAR1 and maps the debugger through it ; ;- O.BRKL: .IF NE $DEBUG MOV O.$BPT,@#BPT.V BPT .ENDC ;NE $DEBUG MOV @#KISAR1,O.$KP1 ;Save kernel PAR1 contents MOV O.$DP1,@#KISAR1 ;Map to the debugger MOV @#NXM.V,O.$NXM ;Save NXM trap vector contents MOV #O.NXM+<20000-O..IDT>,@#NXM.V ; and redirect NXM traps to ; debugger O.$DSP: CALLH O.BRKH ;Call the debugger MOV O.$KP1,@#KISAR1 ;Restore kernel PAR1 contents MOV O.$NXM,@#NXM.V ;Restore NXM traps to monitor .IF NE $DEBUG .ADDR #O.BRKL,-(SP) MOV (SP)+,@#BPT.V .ENDC ;NE $DEBUG RTT ;Return from breakpoint ; possibly with TRACE-TRAP bit set O.$TRP: .BLKW ; : TRPLST BPT contents O.$DP1: .BLKW ; : Debugger PAR1 contents O.$BPT: .BLKW ; : BPT Vector contents O.$KP1: .BLKW ; : Kernel PAR1 contents O.$NXM: .BLKW ; : NXM Vector contents O.$TKS: .WORD 0 ; : Address of keyboard status O.$TKB: .WORD 0 ; : Address of keyboard buffer O.$TPS: .WORD 0 ; : Address of printer status O.$TPB: .WORD 0 ; : Address of pritner buffer .DREND ID .SBTTL LOAD - Handler load code .PSECT SETOVR OVRBK0: .ENABL LSB LOAD: MOV R2,(PC)+ ;Save $SLOT*2 $SLOT2: .BLKW ; : $SLOT*2 MOV R4,(PC)+ ;Save address of read routine $READR: .BLKW ; : -> Monitor read routine MOV R5,(PC)+ ;Save pointer to $ENTRY table entry $ENTRY: .BLKW ; : -> $ENTRY table entry MOV @#SYSPTR,R0 ;R0 -> $RMON MOV P1EXT(R0),R3 ;R3 -> PAR1 externalization routine .ADDR #IDNAME,R5 ;R5 -> Handler name CALL FINDGR(R3) ;Find the region BCS L.BAD MOV @$ENTRY,R5 ;R5 -> $ENTRY address MOV GR.ADR(R1),(R5) ;Inform handler of PAR1 bias ; for reaching high-memory portion ; Determine starting block and length of debugger MOV $ENTRY,R0 ;R0 -> $ENTRY table entry ADD $SLOT2,R0 ;Build pointer to associated ADD #2,R0 ; $DVREC entry ADD $SLOT2,R0 ;R0 -> $DVREC table entry MOV @R0,R0 ;R0 = Block 1 block number ADD #-1,R0 ;R0 = Debugger starting block number MOV R0,(PC)+ ;Save the DEBUGB: .BLKW ; : Debugger starting block number MOV #O...SZ,(PC)+ ;Save the DEBUGS: .BLKW ; : Debugger size in words CLR (PC)+ ;Clear the DEBUGO: .BLKW ; : Debugger relocation offset ; Read and relocate debugger 10$: MOV DEBUGB,R0 ;R0 = Block to read MOV #256.,R1 ;R1 = Words to read (1 block worth) .ADDR #OVRBK1,R2 ;R2 -> Second block in USR buffer CALL @$READR ;Read a block BCS L.BAD ;In case of error... MOV R3,R0 ;We need a pointer to P1EXT MOV R3,-(SP) ;Save it also MOV R5,-(SP) ;And pointer to in-memory handler .ADDR #OVRBK1,R1 ;R1 = Address of block MOV R1,R2 ;Make a copy BIC #17777,R1 ;R1 = Source PAR1 bias SWAB R1 ; ... ASL R1 ; ... ASL R1 BIC #^C<17777>,R2 ;R2 = Source PAR1 offset BIS #20000,R2 ; ... MOV (R5),R3 ;R3 = Destination PAR1 bias MOV DEBUGO,R4 ;R4 = Destination PAR1 offset BIS #20000,R4 MOV #256.,R5 ;R5 = Word count CMP R5,DEBUGS ;Whole block to move? BLE 20$ ;Yep... MOV DEBUGS,R5 ;Nope, use what is needed 20$: CALL BLKMOV(R0) ;Do the transfer MOV (SP)+,R5 ;Restore pointer to in-memory handler MOV (SP)+,R3 ; and to P1EXT INC DEBUGB ;On to next block of debugger ADD #BLOCK,DEBUGO ;Update the relocation offset SUB #256.,DEBUGS ;More to read? BGT 10$ ;Yep... ; Now we have to reset the breakpoint tables MOV @#KISAR1,-(SP) ;Save kernel PAR1 MOV (R5),@#KISAR1 ;Map to the debugger MOV #40000+,R0 ;R0 -> Prototype BPT CLR R1 ;R1 = Table index 30$: CMP R1,#O.BKP+2 ;Done with table? BHI 40$ ;Yep... MOV R0,20000+(R1) ;Address -> Prototype BPT MOV (R5),20000+(R1) ;PAR2 bias for location MOV #BPT,20000+(R1) ;Instruction = BPT CLR 20000+(R1) ;Count = 0 TST (R1)+ ;On to next table entry BR 30$ 40$: MOV (SP)+,@#KISAR1 ;Restore kernel PAR1 ; Now we direct system breakpoints to our code MOV @#SYSPTR,R0 ;R0 -> $RMON MOV @$TRPLS(R0),(R5) ;Save old contents of FIXTRP MOV @#BPT.V,(R5) ; and the breakpoint vector MOV R5,R1 ;R1 -> Entry point of handler ADD #,R1 ;R1 -> Low memory breakpoint handler MOV R1,@$TRPLS(R0) ;Redirect breakpoints to our code MOV R1,@#BPT.V ; ... L.GOOD: TST (PC)+ L.BAD: SEC RETURN .DSABL LSB UNLOAD: MOV @R5,R5 ;R5 -> Handler entry point MOV @#SYSPTR,R0 ;R0 -> $RMON MOV (R5),@#BPT.V ;Restore breakpoint vector MOV (R5),@$TRPLS(R0) ; don't forget FIXTRP BR L.GOOD IDNAME: .RMODUL .RAD50 /$ / .SBTTL STACK SPACE AND REGISTER STORAGE . = OVRBK0 + <1*BLOCK> ;Place debugger on block boundary OVRBK1: O..IDT: .BLKW ; : Return address to low-memory ; also used to move info to ; low memory portion of handler .REPT 50. ; : Stack space .WORD 125252 .WORD 52525 .ENDR ; Debugger internal register area O.IRLL = . ;Internal register low limit O.UR0: .WORD 0 ; : General register 0 ($0) .WORD 0 ; : General register 1 ($1) .WORD 0 ; : General register 2 ($2) .WORD 0 ; : General register 3 ($3) .WORD 0 ; : General register 4 ($4) .WORD 0 ; : General register 5 ($5) O.USP: .WORD 0 ; : User stack ($6) O.UPC: .WORD 0 ; : User PC ($7) O.UST: .WORD 0 ; : User status ($S) O.KSP: .WORD 0 ; : Kernel stack ($K) O.KP1: .WORD 0 ; : KISAR1 contents O.PRI: .WORD 7 ; : Priority ($P) O.MSK: .WORD 0 ; : Mask ($M) O.LOW: .WORD 0 ; : Program low limit O.HI: .WORD 0 ; : Program hi limit O.CNST: .WORD 0 ; : Constant register ($C) O.FORM: .WORD 0 ; : Typeout format ($F) ; = 0 - Relative typeout ; <> 0 - Absolute typeout O.RELT: ;Relocation registers ($R) .REPT 8. .WORD -1 ;Initially set to high address .ENDR ; Breakpoint tables O.P2B: .BLKW /2 ;Bias O.ADR1: .BLKW /2 ;Address (PAR2 Offset) ($B) O.UIN: .BLKW /2 ;Location contents O.CT: .BLKW /2 ;Proceed count O.IRHL = . ;Internal register high limit .SBTTL O.DCOD - Instruction disassembly ;+ ; ; O.DCOD ; Disassembles and displays an instruction. ; ;- O.DCOL: MOVB #'|,R0 ;Print the JSR R5,O.PUTC ; disassembly delimiter O.DCOD: TST O.BW ;Is there an open word? BEQ 10$ ;Nope... MOV O.CAD,R5 ;R5->Start of instruction BIT #1,R5 ;Odd address? BNE 10$ ;Yes, so don't do a decode MOV #20000+,DCDFLG ;Enable special decode MOV #20000+,R4 ;R4 -> Decode buffer MOVB #11,(R4)+ ;Start with a delimiter CALL O.OPCD ;Do the disassembly MOV R0,O.BW ;Save the instruction size MOVB #40,(R4) ;Terminate with a MOV R4,R3 ;R3 -> Last character in buffer MOV #20000+,R4 ;R4->First character in buffer JSR R5,O.TYPE ;Print the buffer JMP O.DCD3 ;Scan for another command character 10$: JMP O.ERR .SBTTL O.TTYC - Display/change debug terminal ;+ ; ; O.TTYC ; Display/change current debug terminal. ; ; ;T displays current addresses ; n;T redirects debug terminal ; ;- O.TTYC: TSTB O.SMFD ;Proper delimiter entered? BEQ 30$ ;Nope, invalid command TST R3 ;Was address specified? BNE 10$ ;Yes, go change terminal MOV #20000+,R4 ;Now print the 'CSR = ' MOV #20000+,R3 ; string JSR R5,O.TYPE ; ... MOV O..TKS,R0 ;Get base address of debug terminal JSR R5,O.CADV ;Print it BR 20$ 10$: CMP R5,#160000 ;Is address in I/O page? BLO 30$ JSR R5,O.RSTT ;Restore current terminal MOV #20000+,R3 ;R3 -> Internal CSR storage MOV R5,(R3)+ ;Set TKS ADD #2,R5 TST (R3)+ ;Bypass a word MOV R5,(R3)+ ;Set TKB ADD #2,R5 MOV R5,(R3)+ ;Set TPS ADD #2,R5 TST (R3)+ ;Bypass a word MOV R5,(R3) ;Set TPB MOV #20000+,R2 ;R2 -> New terminal setting MOV O..IDT,R3 ;R3 -> Low-memory CSR table ADD #,R3 ; ... MOV (R2)+,(R3)+ ;Set new TKS TST (R2)+ MOV (R2)+,(R3)+ ;Set new TKB MOV (R2)+,(R3)+ ;Set new TPS TST (R2)+ MOV (R2)+,(R3)+ ;Set new TPB JSR R5,O.SVTT ;Save new terminal 20$: JMP O.DCD ;Return to command scanner 30$: JMP O.ERR .SBTTL O.CVTP - Convert virtual address to PAR2 bias/offset ;+ ; ; O.CVTP ; Converts a user virtual address to PAR2 bias and offset ; using mapping of previous mode. ; ; Call: ; MOV #virtual_address,-(SP) ; CALL O.CVTP ; ; Return: ; (SP) = PAR2 bias ; 2(SP) = PAR2 offset ; ;- O.CVTP: MOV @SP,-(SP) ;Shuffle the stack a little MOV 4(SP),2(SP) ; ... BIC #160000,4(SP) ;Strip PAR info, then ADD #40000,4(SP) ; make it PAR2 reference MOV R0,-(SP) ;Save R0 for awhile MOV 4(SP),R0 ;R0 = Virtual address BIC #^C<160000>,R0 ;Strip to PAR information SWAB R0 ;Move to low byte ASR R0 ;Then shift ASR R0 ; right four ASR R0 ; bit positions ASR R0 ; for PAR_number * 2 MOV #KISAR0,-(SP) ;Assume kernel MOV @#PS,-(SP) ;Get processor status word BIC #^C,(SP) ;Strip to previous mode BEQ 20$ ;It is kernel mode... CMP (SP),#PS.PMM ;Is it user mode? BNE 10$ ;Nope, must be supervisor ADD #,2(SP) ;Yes, adjust to proper address 10$: ADD #,2(SP) ; ... 20$: TST (SP)+ ;Discard PS ADD (SP)+,R0 ;R0 -> PAR for bias MOV (R0),4(SP) ;Return PAR bias info MOV (SP)+,R0 ;Restore R0 RETURN .SBTTL O.CPTV - Convert PAR2 bias/offset to virtual address ;+ ; ; O.CPTV ; Converts the PAR2 bias and offset to a virtual address in ; previous mode using previous mode mapping. ; ; Call: ; MOV #PAR2_offset,-(SP) ; MOV #PAR2_bias,-(SP) ; CALL O.CPTV ; ; Return: ; (SP) = Virtual address ; ;- O.CPTV: MOV R0,-(SP) ;Save R0 MOV R1,-(SP) ; and R1 for awhile MOV #KISAR0,R0 ;Assume kernel registers MOV @#PS,-(SP) ;Get processor status word BIC #^C,(SP) ;Strip to previous mode BEQ 20$ ;It is kernel mode... CMP (SP),#PS.PMM ;Is it user mode? BNE 10$ ;Nope, must be supervisor ADD #,R0 ;Yes, adjust to proper address 10$: ADD #,R0 ; ... 20$: TST (SP)+ ;Discard PS CMP R0,#KISAR0 ;Kernel mapping? BNE 30$ ;Nope... MWLHCH O.$KP1,R1 ;Get original kernel PAR1 bias CMP R1,6(SP) ;Is this the BIAS we're looking for? BNE 30$ ;Nope... MOV #KISAR1,R0 ;Yes, then we're using kernel PAR1 BR 50$ 30$: MOV #8.,R1 ;R1 = Number of registers to check 40$: CMP 6(SP),@R0 ;Match this APR? BEQ 50$ ;Yep... TST (R0)+ ;On to next APR DEC R1 ;More to check? BGT 40$ ;Yep... HALT 50$: BIC #177760,R0 ;Strip to PAR_number * 2 SWAB R0 ;Move to high byte ASL R0 ;Then shift ASL R0 ; left four ASL R0 ; bit positions ASL R0 ; for PAR base BIC #160000,10(SP) ;Strip PAR info from offset BIS R0,10(SP) ; and replace with correct PAR info MOV (SP)+,R1 ;Restore previously saved R1 MOV (SP)+,R0 ; and R0 MOV (SP)+,(SP) ;Shuffle stack prior to return RETURN .SBTTL O.PMOD - Print mode identifier string ;+ ; ; O.PMOD ; Determines and prints a string identifying the previous ; mode (code being debugged). ; ;- O.PMOD: MOV @#PS,-(SP) ;Get current processor status BIC #^C,(SP) ;Strip to previous mode BEQ 20$ ;Kernel mode, no identifier MOVB #'U,O.MID+1 ;Assume user CMP (SP),#PS.PMM ;Correct assumption? BEQ 10$ ;Yep... MOVB #'S,O.MID+1 ;Nope, supervisor 10$: MOV R3,-(SP) ;Save R3 MOV R4,-(SP) ; and R4 for awhile MOV #20000+,R4 ;R4 -> Start of ID MOV #20000+,R3 ;R3 -> End of ID JSR R5,O.TYPE ;Print the identifier MOV (SP)+,R4 ;Restore previously MOV (SP)+,R3 ; saved registers 20$: TST (SP)+ ;Discard PS info RETURN .SBTTL O.SETB - Set breakpoint ;+ ; ; O.SETB ; Sets a breakpoint in memory. ; ; Call ; R0 = Breakpoint_number * 2 ; ;- O.SETB: MOV R1,-(SP) ;Save R1 for awhile MOV @#KISAR2,-(SP) ;Save kernel PAR2 MOV O.P2B+<20000-O..IDT>(R0),@#KISAR2 ; and set mapping MOV O.ADR1+<20000-O..IDT>(R0),R1 ; to reach location MOV @R1,O.UIN+<20000-O..IDT>(R0);Save the old contents MOV #BPT,@R1 ;Replace with a BPT instruction MOV (SP)+,@#KISAR2 ;Restore previous PAR2 contents MOV (SP)+,R1 ; and previously saved register RETURN .SBTTL O.RESB - Replace a breakpoint with original instruction ;+ ; ; O.RESB ; Removes a breakpoint by replacing the breakpoint with the ; original instruction. ; ; Call ; R0 = Breakpoint_number * 2 ; ;- O.RESB: MOV R1,-(SP) ;Save R1 MOV @#KISAR2,-(SP) ; and kernel PAR2 for awhile MOV O.P2B+<20000-O..IDT>(R0),@#KISAR2 ;Set new mapping MOV O.ADR1+<20000-O..IDT>(R0),R1 ; to reach location MOV O.UIN+<20000-O..IDT>(R0),@R1 ;Restore original contents MOV (SP)+,@#KISAR2 ;Restore kernel PAR2 contents MOV (SP)+,R1 ; and previously saved R1 RETURN .SBTTL O.REGT - SPECIAL NAME HANDLER ;+ ; ; O.REGT ; Processes special register names, building the address ; of the internal location storing the required information. ; ;- O.REGT: CLRB O.IRFG ;Reset internal register access flag JSR R5,O.GETC ;Get internal register name MOV #20000+,R4 ;R4 -> Special name table 10$: TSTB @R4 ;End of table? BNE 20$ ;Nope... JMP O.ERR ;Yes, invalid register name 20$: CMPB R0,@R4 ;Match this entry? BEQ 30$ ;Yep... ADD #4,R4 ;Nope, on to next entry BR 10$ 30$: MOV 2(R4),R4 ;R4 = Offset ADD #20000-O..IDT,R4 ;R4 -> Internal location INC R2 ;Set found flag INCB O.IRFG ;Set the internal register flag JMP O.SCAN ;Go find out what to do with it .SBTTL O.MOD - MOD40 STRING PRINT AND ACCEPT ; RETYPE OPENED WORD IN ASCII (CONVERTED FROM MOD40) O.MODL: MOV O.CAD,R0 ;Get word contents CALL O.GTWD JSR R5,O.CADV ; and print it MOVB #'X,R0 ;Entry due to JSR R5,O.PUTC O.MOD: MOV #20000+,DCDFLG ;Enable special decode MOV O.CAD,R0 ;R0 = Address of word to unpack MOV #20000+,R1 ;R1 -> Character storage CALL UNPA00 ;Unpack the MOD40 word MOV #20000+,R4 ;R4 -> '=' before first character MOV R1,R3 ;R3 -> Space beyond last character JSR R5,O.TYPE ;Print the characters JSR R5,O.GETC ;Get a character CMPB R0,#'_ ;Flag character to indicate user ; inputted Rad50 follows? BNE 1$ ;Nope... INCB O.SCRN ;Indicate spaces are allowed via GETC MOV #3,R4 ;R4 = Count of character to get MOV #20000+,R1 ;R1 -> Where to store them 10$: JSR R5,O.GETC ;Get a character MOVB R0,(R1)+ ; and store it DEC R4 ;More to get? BGT 10$ ;Yes... CLRB O.SCRN ;Indicate spaces are not allowed MOVB #40,R0 ;Echo an additional delimiter JSR R5,O.PUTC ; ... MOV #20000+,R1 ;R1 -> ASCII to pack MOV #20000+,R0 ;R0 -> Where to place packed result CALL PACK00 ;Go pack MOV O.XXX,R0 ;R0 = Result JSR R5,O.CADV ;Print it MOV #1,R2 ;Make result appear as if it had MOV O.XXX,R4 ; been typed in CLR R3 ; ... CLR R5 ; ... JMP O.SCAN ;Let the command scanner do its job 1$: CLR R4 ;Make it appear as if CLR R2 ; no numbers have been entered JMP O.SCN1 ;Continue scanning .SBTTL O.ORPC - BACK ARROW HANDLER ; "BACKARROW" HANDLER - OPEN INDEXED ON THE PC (BACK ARROW) O.ORPC: JSR R5,O.TCLS ;TEST WORD MODE AND CLOSE MOV R0,-(SP) MOV R2,R0 CALL O.GTWD ADD R0,R2 MOV (SP)+,R0 INC R2 INC R2 ; NEW ADDRESS O.PCS: MOV R2,O.CAD ;UPDATE CAD CLR R2 ;CLEAR NUMBER TYPED FLAG CLRB O.IRFG ;Reset internal register access flag JMP O.OP2A ;GO FINISH UP O.ORAB: JSR R5,O.TCLS ;TEST WORD MODE AND CLOSE MOV R0,-(SP) MOV R2,R0 CALL O.GTWD MOV R0,R2 MOV (SP)+,R0 BR O.PCS O.ORRB: JSR R5,O.TCLS ;TEST AND CLOSE MOV R0,-(SP) MOV R2,R0 CALL O.GTWD MOV R0,R1 MOV (SP)+,R0 MOVB R1,R1 ;EXTEND THE SIGN ASL R1 ;R2=2(@R2) INC R1 ; +2 INC R1 ADD R1,R2 ; +PC BR O.PCS O.TCLS: CALL O.CLSE ;CLOSE CURRENT CELL CMP O.BW,#2 ;ONLY WORD MODE ALLOWED BNE 1$ ;BRANCH IF ERROR MOV O.CAD,R2 ;CURRENT ADDRESS IN R2 RTS R5 1$: TST (SP)+ O.TCL2: JMP O.ERR ;POP A WORD AND SHOW THE ERROR .SBTTL O.SNGL - PROCESS SINGLE INSTRUCTION MODE ;+ ; ; O.SNGL ; Entered when ;S is typed, causes execution of a single ; instruction. ; ; O.ESC ; Entered when is typed, echoes ';S' and performs ; same function as above. ; ;- .ENABL LSB O.SNGL: TSTB O.SMFD ;Was a ';' typed? BEQ O.TCL2 ;Nope...invalid syntax BR 15$ ;Yes, assume n;S format 10$: CLR R2 ;Discard everything CLR R3 ; ... CLR R4 ; ... CLR R5 ; ... INCB O.SMFD ;Indicate ';' was typed ; (simulated for ) CLRB O.CMFD ;Clear ',' flag 15$: MOVB #-1,O.S ;Set single instruction flag JMP O.PROC ; and proceed ; Single instruction execution, ala SD O.ESC: MOVB #';,R0 ;First echo as if ';S' had been JSR R5,O.PUTC ; entered MOVB #'S,R0 JSR R5,O.PUTC BR 10$ ;Then join common code .DSABL LSB .SBTTL O.COMM - COMMA PROCESSING ; COMMA PROCESSING. N IN R4 IS THE RELOCATION REGISTER NUMBER O.COMM: INCB O.CMFD ;SET "COMMA FOUND" SWITCH TO ON TST R2 ;WAS A NUMBER TYPED IN? BEQ 1$ ;NO,USE CURRENT BIAS; I.E.,EXIT BIC #177770,R4 ;MAKE SURE THAT N IS LESS THAN 10(8) ASL R4 ;YES, LOCATE RELOC. REGISTER MOV 20000+(R4),O.BIAS ;PUT BIAS IN O.BIAS 1$: BR O.MIN1 ;GO BACK TO DECODER .SBTTL O.REL - RELOCATION REGISTER PROCESSOR ;+ ; ; R PROCESSING. SEVERAL POSSIBILITIES- ; A. ;R WAS TYPED. ZERO OUT ALL RELOCATION REGISTERS ; B. ;NR WAS TYPED. ZERO OUT $NR ; C. REXP;NR WAS TYPED. SET $NR TO REXP ; D. NR WAS TYPED, WHILE A WORD WAS OPENED- ; COMPUTE (O.CAD)-($NR) AND PRINT IT ; ;- O.REL: TSTB O.SMFD ;TEST IF A SEMICOLON WAS TYPED BEQ 5$ ;NO CASE D TST R2 ;NOTHING OPENED, WAS N TYPED? BEQ 2$ ;N NOT TYPED 1$: BIC #177770,R4 ;GUARANTEE THAT N<10 ASL R4 ;N TYPED, CASE B OR C. SET $NR. TST R3 ;IF REXP NOT TYPED,CLEAR TO -1 BEQ 3$ MOV R5,20000+(R4) ;IF REXP NOT TYPED, R5=0. CASE B. BR O.H1 ;EXIT TO DECODER 2$: TST R3 ;IF REXP TYPED, CASE B OR C WITH N=0 BEQ 4$ ;NEITHER REXP NOR N TYPED, CLEAR ALL. BR 1$ ;REXP TYPED- N NOT TYPED 3$: MOV #-1,20000+(R4) BR O.H1 ; CLEAR RELOCATION REGISTERS. 4$: JSR R5,O.CLRR ;CLEAR RELOC REG'S JMP O.DCD ;GO BACK TO SCAN 5$: CMP O.BW,#2 ;CASE D, PRINT @O.CAD IN RELATIVE FORM BNE O.TCL2 ;ERROR IF BYTE OPENED TST R2 ; CHECK IF R BNE 7$ ; IF R MOV O.CAD,R0 CALL O.GTWD JSR R5,O.LOC ; THEN FIND BEST N CMP R0,#-1 ;WAS A RELOC REG FOUND? BNE 6$ ;BR IF YES. ELSE-- MOVB #'=,R0 ;TYPE "=" JSR R5,O.PUTC MOV O.CAD,R0 CALL O.GTWD BR 9$ ;OF OPENED LOC. 6$: MOV R0,R4 ; PUT NEW N INTO R4 7$: MOV R0,-(SP) MOV O.CAD,R0 CALL O.GTWD MOV R0,R1 MOV (SP)+,R0 MOV R4,O.TMP1 ; SAVE N ASL R4 ;GET BIAS FROM $NR SUB 20000+(R4),R1 ;BIAS IS THE SUBTRAHEND MOVB #'=,R0 ;TYPE "=" JSR R5,O.PUTC MOV O.TMP1,R0 ; PREPARE INPUT FOR O.PUTC ADD #'0,R0 ; CONVERT N TO ASCII JSR R5,O.PUTC ; TYPE N MOVB #',,R0 ;PREPARE INPUT FOR O.PUTC JSR R5,O.PUTC ; TYPE COMMA TST R2 ; CHECK IF R BNE 8$ ; IF R MOV O.XXY,R0 ; THEN PREPARE INPUT FOR O.CADV 8$: MOV R1,R0 ;TYPE THE VALUE (@O.CAD)-($NR) 9$: JSR R5,O.CADV BR O.DCD1 .SBTTL O.CNS - CONSTANT (C) PROCESSOR ;+ ; ; C PROCESSING. ; A. REXP;C WAS TYPED- PRINT THE VALUE OF REXP AND STORE IN $C ; B. ;C WAS TYPED- SAME AS C., BUT REXP=0 BY DEFAULT ; C. NO SEMICOLON HAS BEEN TYPED-REPLACE R4 WITH THE CONTENTS OF $C ; ;- O.CNS: TSTB O.SMFD ;WAS A SEMICOLON TYPED? BNE 1$ ;REXP TYPED PRIOR TO ; CASE A MOV O.CNST,R4 ;CASE C. REPLACE R4 WITH ($C) MOV #1,R2 BR O.SCAN ;RETURN TO SCAN MORE 1$: MOV #2,O.BW ;Force word mode MOVB #'=,R0 ;Print delimiter JSR R5,O.PUTC MOV R5,R0 JSR R5,O.CADV MOV R5,O.CNST ;AND STORE IN $C O.H1: BR O.DCD .SBTTL O.MIN - UNARY MINUS PROCESSOR O.MIN: INCB O.MINS ;SET MINUS FOUND SWITCH ON O.MIN1: BR O.DCD1 .SBTTL O.RCMP - ABSOLUTE TO RELATIVE ADDRESS PROCESSOR ;+ ; ; A. N! WAS TYPED--PRINT N,((O.CAD)-($NR)) ; B. ! WAS TYPED. FIND THE CLOSEST BIAS LESS THAN ; (O.CAD) AND USE ITS "N" -- THEN DO CASE A. ; ;- O.RCMP: MOVB #'=,R0 ;FIRST TYPE A "=" JSR R5,O.PUTC ;WAS N TYPED IN? TST R2 ;WAS N TYPED IN? BNE 2$ ;BRANCH IF YES MOV O.CAD,R0 JSR R5,O.LOC ;ELSE, FIND BEST N CMP R0,#-1 ;IF REL.REG FOUND, BNE 1$ ; BR, ELSE-- MOV O.CAD,R0 ;PRINT ADDR IN ABS. JSR R5,O.CADV BR O.DCD1 1$: ADD #'0,R0 ;CONVERT N TO ANSCII JSR R5,O.PUTC ;TYPE N MOVB #',,R0 ;TYPE COMMA JSR R5,O.PUTC MOV O.BW,-(SP) ;SAVE O.BW MOV #2,O.BW ;ARTIFCIALLY SET MODE FOR WORDS MOV O.XXY,R0 ;TYPE RELATIVE AMOUNT JSR R5,O.CADV MOV (SP)+,O.BW ;RESTORE MODE BR O.DCD1 ;EXIT TO SCAN ROUTINE 2$: MOV R4,R0 ;GET N. THIS CODE SIMULATES O.LOC ASL R0 ;TIMES 2 FOR INDEXING MOV O.CAD,O.XXY SUB 20000+(R0),O.XXY ;COMPUTE DIFFERENCE ASR R0 ;RESTORE N. BR 1$ ;PRINT RESULTS .SBTTL O.FILL - MEMORY WORD FILL PROCESSOR ; FILL MEMORY WORDS. LIMITS ARE THE SEARCH LIMITS. O.FILL: MOV #2,O.BW ;SET MODE TO "OPEN WORD" O.FIL1: TSTB O.SMFD ;DONT REACT UNLESS ";" WAS TYPED BEQ O.ERR ;IF NOT TYPED, ERROR. MOV O.CNST, R0 ;ACTUAL VALUE MOV O.LOW,R4 ;USE SEARCH LIMITS FOR MOV O.HI,R3 ; FILL LIMITS. JSR R5,O.ST BR O.DCD ;EXIT .SBTTL O.INIT - MEMORY BYTE FILL PROCESSOR ; INITIALIZE MEMORY BYTES. O.INIT: MOV #1,O.BW BR O.FIL1 ;LET O.FILL DO THE WORK .SBTTL COMMAND DECODER/DISPATCHER ; ALL REGISTERS MAY BE USED (R0-R5), O.NXM: MOV #O.ERR+<20000-O..IDT>,(SP) ;Redirect return RTI ; and dismiss interrupt O.ERR: MOV #O.UR0+<20000-O..IDT>,SP ;Ensure stack on all errors MOVB #'?,R0 ; ? TO BE TYPED JSR R5,O.PUTC ; OUTPUT ? O.DCD: CLR O.BW ;CLOSE ALL JSR R5,O.CRLS ;TYPE * O.DCD3: CLRB O.SMFD ;SEMICOLON FOUND FLAG CLRB O.CMFD ;COMMA FOUND FLAG CLRB O.MINS ;MINUS SIGN FOUND FLAG CLR R3 ;R3 IS A SAVE REGISTER FOR R2 CLR R5 ;R5 IS A SAVE REGISTER FOR R4 O.DCD1: CLR R4 ; R4 CONTAINS THE CONVERTED OCTAL CLR R2 ; R2 IS THE NUMBER FOUND FLAG O.SCAN: JSR R5,O.GETC ;GET A CHAR, RETURN IN R0 O.SCN1: CMPB R0,#'0 ;COMPARE WITH ASCII 0 BLO 1$ ;CHECK LEGALITY IF NON-NUMERIC CMPB R0,#'7 ;COMPARE WITH ASCII 7 BHI 1$ ;CHECK LEGALITY IF NOT OCTAL BIC #177770,R0 ;CONVERT TO BCD ASL R4 ; MAKE ROOM ASL R4 ; IN ASL R4 ; R4 ADD R0,R4 ;PACK THREE BITS IN R4 INC R2 ;R2 HAS NUMERIC FLAG BR O.SCAN ; AND TRY AGAIN 1$: CLR R1 ;CLEAR INDEX 2$: CMPB R0,20000+(R1) ;DO THE CODES MATCH? BEQ 3$ ;JUMP IF YES INC R1 ; SET INDEX FOR NEXT SEARCH CMP R1,#O.CLGT ;IS THE SEARCH DONE? BLO 2$ ;NOPE...RE-LOOP BR O.ERR ; OOPS! 3$: TSTB O.MINS ;Was '-' typed? BEQ 4$ ;Nope... NEG R4 ;Yes, take 2's complement 4$: CLRB O.MINS ;Reset flag for continued scan TSTB O.CMFD ;IF A COMMA NOT TYPED, BEQ 5$ ;SKIP NEXT INSTRUCTION. ADD O.BIAS,R4 ;OTHERWISE, ADD RELOC. BIAS TO (R4) 5$: ASL R1 ;Shift for word offset into table MOV 20000+(R1),R1 ;R1 = Offset to routine ADD #20000-O..IDT,R1 ;R1 -> Routine JMP @R1 ;Dispatch to routine .SBTTL O.SEMI SEMI-COLON PROCESSOR O.SEMI: MOV R2,R3 ;A SEMI-COLON HAS BEEN RECEIVED MOV R4,R5 ;NUMERIC FLAG TO R3, CONTENTS TO R5 INCB O.SMFD ;SET SEMICOLON FOUND FLAG CLRB O.CMFD ;RESET COMMA FOUND FLAG CLRB O.IRFG ;Reset internal register access flag BR O.DCD1 ;GO BACK FOR MORE .SBTTL O.WRD - OPEN LOCATION IN WORD MODE .SBTTL O.BYT - OPEN LOCATION IN BYTE MODE ;+ ; ; INPUT - IF R2 IS NON-ZERO A NEW REXP HAS BEEN TYPED IN ; INPUT - -ADDRESS OF WORD TO BE OPENED IS IN R4 ; ;- O.LBRA: CLR DCDFLG ;Disable special decode flag MOV #2,O.BW ;Force word mode BR O.WB1 O.WRD: MOV #O.DCOD+<20000-O..IDT>,DCDFLG ;Enable special decode MOV #2,O.BW ;OPEN WORD BR O.WB1 O.BYT1: ROL R4 ;GET THE ADDRESS BACK O.BYT: CLR DCDFLG ;Reset special decode flag MOV #1,O.BW ;OPEN BYTE O.WB1: TST R2 ;GET VALUE IF R2 IS NON-ZERO BNE 3$ ;BRANCH IF NUMBER INPUT TSTB O.CMFD ;TEST FOR ","AND";" BEQ 2$ 1$: JMP O.ERR ;ERROR IF PRESENT WITHOUT NUMBER. 2$: TSTB O.SMFD BNE 1$ BR O.WRD1 ;NO NUMBER - REOPEN PREVIOUS LOCATION 3$: MOV R4,O.DOT ;PUT VALUE IN DOT MOV R4,O.CAD ; ALSO IN CAD O.WRD1: TST DCDFLG ;Special decode needed? BEQ 10$ ;Nope... JMP @DCDFLG ;Yes, go do it 10$: CMP O.BW,#1 ;CHECK BYTE MODE BEQ 1$ ;JUMP IF BYTE MOV O.CAD,R4 ASR R4 ;MOVE ONE BIT TO CARRY BCS O.BYT1 ;JUMP IF ODD ADDRESS MOV O.CAD,R0 CALL O.GTWD BR 2$ 1$: MOV O.CAD,R0 CALL O.GTBT 2$: JSR R5,O.CADV ;GO GET AND TYPE OUT @CAD CMP O.BW,#1 ;CHECK IF BYTE MODE. BNE. O.DCD3 ;IF NOT WE'RE DONE. ELSE: MOVB #'=,R0 ;TYP "=" AND THEN THE ASCII BYTE JSR R5,O.PUTC MOV O.CAD,R0 CALL O.GTBT JSR R5,O.PUTC MOVB #40,R0 JSR R5,O.PUTC JMP O.DCD3 ;GO BACK TO DECODER .SBTTL O.PERI - DOT PROCESSOR O.PERI: MOV SP,R2 ;Set the 'number entered' flag MOV O.CAD,R4 ; and put the number where expected CLRB O.SMFD ;Reset 'semicolon seen' CLRB O.CMFD ; and 'comma seen' flags JMP O.SCAN ;Now continue scan .SBTTL O.EQUA - LOCATION EVALUATION PROCESSOR O.EQUA: MOVB #40,R0 ;Print delimiter JSR R5,O.PUTC MOV O.CAD,R0 ;Get current open address JSR R5,O.CADV ;Print it out JMP O.DCD3 ;Now continue command decode .SBTTL O.CRET - PROCESS CARRIAGE RETURN O.CRET: CALL O.CLSE ;CLOSE LOCATION MOV #20000+,DCDFLG ;Use instruction decode CLRB O.IRFG ;Reset internal register access flag O.DCDA: JMP O.DCD ;RETURN TO DECODER O.ERR3: JMP O.ERR ;INTERMEDIATE HELP .SBTTL O.OP1 - MODIFY, CLOSE, OPEN NEXT PROCESSOR O.OLD: INCB O.SEQ ;SET FLAG TO LATER RESTORE CAD O.OP1: TST O.BW ; RECEIVED O.ERR2: BEQ O.ERR3 ;ERROR IF NOTHING IS OPEN CALL O.CLSE ;CLOSE PRESENT CELL TSTB O.SEQ ;SHOULD CAD BE RESTORED? BEQ 1$ ;BRANCH IF NOT ;MG01; CMP O.CAD,O.DOT ;IS CURRENT ADDRESS = ORIGIN? ;DL01 ;MG01; BEQ 2$ ;PROCEED AS USUAL IF YES ;DL01 ;MG01; MOV #2,O.BW ;OTHERWISE BACK TO WORD MODE ;DL01 2$: MOV O.DOT,O.CAD ;RESTORE PREVIOUS SEQUENCE CLRB O.SEQ ;RESET FLAG; NO LONGER NEEDED 1$: ADD O.BW,O.CAD ;GENERATE NEW ADDRESS O.OP2: TSTB O.IRFG ;Internal register access? BEQ 10$ ;Nope... CMP O.CAD,#20000+ ;Below internal register space? BLO O.ERR3 ;Yep... CMP O.CAD,#20000+ ;Nope, above same? BHIS O.ERR3 ;Yep... 10$: MOV O.CAD,O.DOT ;INITIALIZE DOT O.OP2A: JSR R5,O.CRLF ; O.BPTS: CALL O.PMOD ;Print the previous mode ID MOV O.BW,-(SP) ;SAVE BW MOV #2,O.BW ;SET TO TYPE FULL WORD ADDRESS MOV O.CAD,R0 ;NUMBER TO TYPE JSR R5,O.RORA ; CHECK FORMAT MOV @SP,O.BW ;RESTORE BW MOV #"\/,R0 ;/ IN LOW BYTE ; \ IN HIGH BYTE ASR (SP)+ ;IS IT BYTE MODE? BCS 1$ ;YES... SWAB R0 ;TYPE A / 1$: JSR R5,O.PUTC ;TYPE THE LOW BYTE OF R0 TST DCDFLG ;Doing a special decode? BEQ. O.WRD1 ;Nope... ;;; MOV O.CAD,R0 ;;; CALL O.GTWD ;;; JSR R5,O.CADV ; and print it JMP @DCDFLG ;And dispatch to the special routine .SBTTL O.BACK - MODIFY, CLOSE, OPEN PREVIOUS LOCATION O.BACK: TST O.BW ; ^ RECEIVED BEQ O.ERR2 ;ERROR IF NOTHING OPEN CALL O.CLSE SUB O.BW,O.CAD ;GENERATE NEW ADDRESS BR O.OP2 ;GO DO THE REST .SBTTL O.BKPT - SET/REMOVE BREAKPOINT PROCESSOR ;+ ; ; O.BKPT ; Sets or removes breakpoints. ; ; ;B Removes all breakpoints ; ;nB Removes breakpoint n ; rexp;B Sets breakpoint (using available cell) ; rexp;nB Sets breakpoint n ; ;- .ENABL LSB O.BKPT: ASL R4 ;Shift any specified breakpoint number TST R3 ;Location specified? BEQ 40$ ;Nope, remove breakpoint ; Here to set a breakpoint TST R2 ;Was breakpoint specified? BNE 30$ ;Yep... CLR R4 ;Set to scan table 10$: CMP R4,#O.BKP ;End of table? BGT 80$ ;Yep, no cells free CMP O.ADR1+<20000-O..IDT>(R4),#40000+ ;Free cell? BNE 20$ ;Nope... CMP O.P2B+<20000-O..IDT>(R4),#200 ;Maybe, check bias BNE 20$ ;Nope... MOV R4,R0 ;R0 = Breakpoint table offset ASR R0 ;Shift for number 0-7 ADD #'0,R0 ;Make it printable JSR R5,O.PUTC ; and print it BR 30$ 20$: TST (R4)+ ;On to next breakpoint cell BR 10$ 30$: MOV R5,-(SP) ;Set to convert virtual address CALL O.CVTP ; to PAR2 bias and offset MOV (SP)+,O.P2B+<20000-O..IDT>(R4) ;Save the PAR2 bias MOV (SP)+,O.ADR1+<20000-O..IDT>(R4) ; and offset BR 70$ ;All done ; Reset breakpoints 40$: TST R2 ;Specific breakpoint? BEQ 50$ ;Nope, reset all breakpoints CALL 65$ ;Remove the specified breakpoint BR 70$ 50$: CLR R4 ;Set to reset breakpoint table 60$: CMP R4,#O.BKP ;End of table? BGT 70$ ;Yep... CALL 65$ ;Remove a breakpoint TST (R4)+ ;On to next cell BR 60$ 65$: MOV @#KISAR1,O.P2B+<20000-O..IDT>(R4) ; free the cell MOV #40000+,20000+(R4) ; ... CLR O.CT+<20000-O..IDT>(R4) ; and reset the count RETURN O.DCDB: 70$: JMP O.DCD ;Return to command scanner 80$: JMP O.ERR .DSABL LSB .SBTTL O.OFST - BRANCH OFFSET PROCESSOR O.OFST: CMP O.BW,#2 ;CHECK WORD MODE BNE O.ERR1 ;ERROR IF NOT CORRECT MODE MOVB #40,R0 ;TYPE ONE BLANK JSR R5,O.PUTC ; AS A SEPARATOR TST R3 ;WAS SEMI-COLON TYPED? BEQ O.ERR1 ;NO, CALL IT AN ERROR SUB O.CAD,R5 ;COMPUTE DEC R5 DEC R5 ; 16 BIT OFFSET MOV R5,R0 JSR R5,O.CADV ;NUMBER IN R0 - WORD MODE MOV R5,R0 ASR R0 ;DIVIDE BY TWO BCS 1$ ;ERROR IF ODD CMP R0,#-200 ;COMPARE WITH -200 BLE 1$ ;DO NOT TYPE IF OUT OF RANGE CMP R0,#177 ;COMPARE WITH +177 BGE 1$ ;DO NOT TYPE IF OUT OF RANGE DEC O.BW ;SET TEMPORARY BYTE MODE JSR R5,O.CADV ;NUMBER IN R0 - BYTE MODE INC O.BW ;RESTORE WORD MODE 1$: JMP O.DCD3 ;ALL DONE O.ERR1: JMP O.ERR ;INTERMEDIATE HELP .SBTTL O.EFF - EFFECTIVE ADDRESS SEARCH .SBTTL O.WSCH - WORD SEARCH ;+ ; ; Searches ; O.MSK = mask ($M) ; O.MSK+2 = starting address ; O.MSK+4 = ending address ; ;- O.EFF: INC R1 ;SET EFFECTIVE SEARCH BR O.WDS O.WSCH: CLR R1 ;SET WORD SEARCH O.WDS: TST R3 ;CHECK FOR OBJECT FOUND BEQ O.ERR1 ;ERROR IF NO OBJECT MOV #2,O.BW ;SET WORD MODE MOV O.MSK+2,R2 ;SET ORIGIN MOV O.MSK,R4 ;SET MASK COM R4 1$: CMP R2,O.MSK+4 ; IS THE SEARCH ALL DONE? BHI O.DCDB ; YES MOV R2,R0 CALL O.GTWD TST R1 ;NO BNE 4$ ;BRANCH IF EFFECTIVE SEARCH MOV R0,-(SP) MOV R5,R3 ;EXCLUSIVE OR BIC R5,R0 ; IS DONE BIC (SP)+,R3 ; IN A VERY BIS R0,R3 ; FANCY MANNER HERE BIC R4,R3 ;AND RESULT WITH MASK 2$: BNE 3$ ;RE-LOOP IF NO MATCH MOV R4,-(SP) ;REGISTERS R2,R4, AND R5 ARE SAFE MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) JSR R5,O.CRLF MOV R2,R0 ;GET READY TO TYPE JSR R5,O.RORA ; CHECK FORMAT MOVB #'/,R0 ;SLASH TO R0 JSR R5,O.PUTC ;TYPE IT MOV R2,R0 CALL O.GTWD JSR R5,O.CADV ; TYPE CONTENT MOV (SP)+,R3 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 MOV (SP)+,R4 ; RESTORE R4 JSR R5,O.CU ;HAS CTRL/U BEEN STRUCK? BCC O.DCDB ;YES...STOP SEARCH... 3$: TST (R2)+ ;INCREMENT TO NEXT CELL AND BR 1$ ; RETURN 4$: CMP R0,R5 ; IS (X)=K? BEQ 2$ ;TYPE IF EQUAL MOV R0,R3 ;(X) TO R3 ADD R2,R3 ;(X)+X INC R3 INC R3 ;(X)+X+2 CMP R3,R5 ;IS (X)+X+2=K? BEQ 2$ ;BRANCH IF EQUAL BIC #177400,R0 ;WIPE OUT EXTRANEOUS BITS MOVB R0,R0 CCC ASL R0 ;MULTIPLY BY TWO INC R0 INC R0 ADD R2,R0 ;ADD PC CMP R0,R5 ;IS THE RESULT A PROPER REL. BRANCH? BR 2$ .SBTTL O.GO - GO PROCESSOR O.GO: TSTB O.SMFD ;WAS ";" TYPED? BEQ O.ERR1 ;BR IF NOT TYPED TST R3 ;WAS K; TYPED? BEQ O.ERR1 ; TYPE ? IF NOT MOVB #O.BKP+3,O.P ;CLEAR PROCEED ASR R5 ;CHECK LOW ORDER BIT BCS O.ERR1 ;ERROR IF ODD NUMBER ASL R5 ;RESTORE WORD MOV R5,O.UPC ;SET UP NEW PC MOVB #PS.PR7,-(SP) ;SET HIGH PRIORITY CALL O.WST JSR R5,O.RSTT ;RESTORE TELETYPE O.TBIT: CLRB O.T ;CLEAR BIS #PS.T,O.UST ; BOTH T-BIT FLAGS TSTB O.S ;SEE IF WE NEED A T BIT BNE O.GO2 ;IF NOT GO NOW BIC #PS.T,O.UST ;SET TH T BIT JSR R5,O.RSB ;RESTORE BREAKPOINTS O.GO2: JSR R0,O.RSR ;Restore registers and stack MOV O.UST,-(SP) ;Put PS MOV O.UPC,-(SP) ; and PC back on kernel stack MOV O.UST,-(SP) ; MOV IN STATUS FIRST W/O T BIT BIC #PS.T,@SP ; SO INTERRUPTS CAN HAPPEN BEFORE CALL O.WST ; RTT TURNS ON THE T BIT. O.RTIT: MOV O..IDT,-(SP) ;Set to return to low-memory portion RETURN ; of breakpoint handler .SBTTL O.PROC - PROCEED PROCESSOR ; ONLY ALLOWED AFTER A BREAKPOINT O.PROC: TSTB O.SMFD ;WAS ";" TYPED? BEQ O.ERR1 ;BR IF NOT TYPED MOVB O.P,R0 ;Legal for proceed? BLT O.ERR1 ;Nope... TST R2 ;CHECK FOR ILLEGAL COUNT BNE. O.ERR1 ;JUMP IF ILLEGAL TST R3 ;WAS COUNT SPECIFIED? BEQ 1$ ;NO MOV R5,20000+(R0) ;YES, PUT AWAY COUNT 1$: MOVB #PS.PR7,-(SP) ;FORCE HIGH PRIORITY CALL O.WST JSR R5,O.RSTT ;RESTORE TTY O.C1: CMPB O.P,#O.BKP ;SEE IF A REAL ONE OR A FAKE BGT O.TBIT ;BRANCH IF FAKE TSTB O.S ;SEE IF SINGLE INSTRUCTION MODE BNE O.TBIT ;IF SO EXIT NOW MOVB #PS.PR7,-(SP) ;SET HIGH PRIORITY CALL O.WST INCB O.T ;SET T-BIT FLAG BIS #PS.T,O.UST ;SET T-BIT BR O.GO2 .SBTTL BREAKPOINT HANDLER O.BRKH: MOV (SP)+,O..IDT ;Save return address (and link ; to low-memory portion) MOV (SP)+,O.UPC ;PRIORITY IS 7 UPON ENTRY MOV (SP)+,O.UST ;SAVE STATUS AND PC MWLHCH O.$KP1,O.KP1 ;Get KISAR1 contents at BPT time MOVB #O.BKP+3,O.P ;TELL ;P THAT WE CAN CONTINUE JSR R0,O.SVR ;Save the registers MOV O..IDT,R0 ;R0 -> O.$DSP+4 ADD #,R0 ;R0 -> Debug terminal register table TST (R0) ;Debug terminal specified? BNE 10$ ;Yep... MOV @#SYSPTR,R0 ;Nope, use console terminal ADD #TTKS,R0 ;R0 -> Console terminal registers 10$: MOV #20000+,R1 ;R1 -> Local register table MOV (R0)+,(R1)+ ;Get keyboard CSR address TST (R1)+ ;Bypass CSR storage MOV (R0)+,(R1)+ ;Get keyboard buffer address MOV (R0)+,(R1)+ ;Get printer CSR address TST (R1)+ ;Bypass CSR storage MOV (R0),(R1) ;Get printer buffer address TSTB O.T ;CHECK FOR T-BIT SET BNE O.TBIT ;JUMP IF SET JSR R5,O.REM ;REMOVE BREAKPOINTS TSTB O.PRI ;CHECK IF PRIORITY BPL 1$ ; IS AS SAME AS USER PGM MOVB O.UST,R5 ;PICK UP USER UST IF SO BR 2$ 1$: MOVB O.PRI,R5 ;OTHERWISE PICK UP ACTUAL PRIORITY CCC ;CLEAR CARRY RORB R5 ;SHIFT LOW ORDER BITS RORB R5 ; INTO RORB R5 ; HIGH ORDER RORB R5 ; POSITION 2$: BIC #PS.T,R5 ;CLEAR POSSIBLE T BIT (S/I MODE) MOVB R5,-(SP) ;PUT THE STATUS AWAY WHERE IT BELONGS CALL O.WST MOV O.UPC,R5 ;GET PC, IT POINTS TO THE BPT TSTB O.S ;SEE IF IT WAS SINGLE INSTRUCTION FUN BMI 4$ ;IF SO HANDLE THERE TST -(R5) MOV R5,O.UPC MOV #O.BKP,R4 ;GET A COUNTER 3$: MOV R5,-(SP) ;Set virtual address CALL O.CVTP ;Convert to PAR2 bias and offset CMP 2(SP),20000+(R4) ;Offset match? BNE 35$ ;Nope... CMP (SP),20000+(R4) ;Yes, how about PAR bias? BNE 35$ CMP (SP)+,(SP)+ ;Discard stack BR 5$ 35$: CMP (SP)+,(SP)+ ;Discard stack DEC R4 DEC R4 BGE 3$ ;RE-LOOP UNTIL FOUND JSR R5,O.SVTT ;SAVE TELETYPE STATUS JSR R5,O.CRLF MOV #20000+,R4 ;R4 -> Start of unknown BPT string MOV #20000+,R3 ;R3 -> End of above-mentioned string JSR R5,O.TYPE ;Print the string TST (R5)+ ;Update the resume PC MOV R5,O.UPC MOV R5,R0 BR 6$ 4$: MOVB #O.BKP+2,R4 ;SET BREAK POINT HIGH + 1 MOV R5,-(SP) ;Get virtual address CALL O.CVTP ;Convert to PAR2 bias and offset MOV (SP)+,20000+(R4) ;Save PAR2 bias MOV (SP)+,20000+(R4) ; and offset 5$: MOVB R4,O.P ;ALLOW PROCEED DEC 20000+(R4) BGT. O.C1 ;JUMP IF REPEAT CLRB O.S MOV #1,20000+(R4) ;RESET COUNT TO 1 JSR R5,O.SVTT ;SAVE TELETYPE STATUS, R4 IS SAFE MOVB O.P,R0 ;R0 = Breakpoint number *2 ASR R0 ;Convert to number ADD #'0,R0 ;Make it printable ascii MOVB R0,O.BPT+3 ;Place it in the ID string MOV #20000+,R4 ;R4 -> Start of ID string MOV #20000+,R3 ;R3 -> End of ID string JSR R5,O.TYPE ;Print the string MOVB O.P,R4 ;R4 = Breakpoint number *2 MOV 20000+(R4),-(SP) ;Save PAR2 offset MOV 20000+(R4),-(SP) ; and bias CALL O.CPTV ;Convert to virtual address MOV (SP)+,R0 ;R0 = PC at breakpoint 6$: MOV R0,O.CAD ;Set the current address MOV #2,O.BW ; and word mode access MOV #20000+,DCDFLG ;Enable special decode CLRB O.IRFG ; and reset internal access flag CMPB O.P,#<8.*2> ;Trace trap BPT (single instruction)? BNE 7$ ;Nope... JMP O.BPTS ;Yes, display all the info 7$: CALL O.PMOD ;Display mode MOV O.CAD,R0 JSR R5,O.CADV ; and address JMP O.DCD ; then go to command scanner .SBTTL O.SVR - SAVE REGISTERS ;+ ; ; O.SVR ; Remove items from kernel stack, switch to debugger ; stack and save previous mode stack pointer as well ; as registers. ; ;- O.SVR: MOV (SP)+,O.XXX ;Move return address from kernel stack MFPD SP ;Get the previous mode stack pointer MOV (SP)+,O.USP ; and save it MOV SP,O.KSP ;Save kernel stack pointer MOV #20000+,SP ;Set to debugger stack MOV R5,-(SP) ;Save MOV R4,-(SP) ; general MOV R3,-(SP) ; registers MOV R2,-(SP) ; R0 MOV R1,-(SP) ; to MOV O.XXX,-(SP) ; R5 CLR -(SP) ;Now return to caller RTS R0 ; on the debugger stack .SBTTL O.RSR - RESTORE REGISTERS ;+ ; ; O.RSR: ; Restore registers from debugger space, restore previous ; mode stack pointer, then switch back to kernel stack. ; ;- O.RSR: TST (SP)+ ;Pop the extra cell MOV (SP)+,O.XXX ;Save return address MOV (SP)+,R1 ;Restore MOV (SP)+,R2 ; general MOV (SP)+,R3 ; registers MOV (SP)+,R4 ; R0 MOV (SP)+,R5 ; to MOV O.USP,-(SP) ;Restore the user stack pointer MTPD SP ; ... MOV O.KSP,SP ;Restore kernel stack pointer MOV O.XXX,-(SP) ; and return to caller RTS R0 ; on kernel stack .SBTTL O.RSB - RESTORE BREAKPOINTS 0-7 ;+ ; ; O.RSB ; Saves the current contents of up to 8 locations, replacing ; them with breakpoints. ; ;- O.RSB: MOV R0,-(SP) ;Save R0 for awhile CLR R0 ;Set to breakpoint 0 10$: CMP R0,#O.BKP ;Done with list? BGT 20$ ;Yep... CALL O.SETB ;No, set a breakpoint TST (R0)+ ;On to next entry BR 10$ 20$: MOV (SP)+,R0 ;Restore R0 RTS R5 .SBTTL O.SVTT - SAVE TELETYPE STATUS O.SVTT: MOV @O..TKS,O..TKS+2 ;Save receiver status BIC #^C,O..TKS+2 ; and turn off BIC #RC.IE,@O..TKS ; interrupts MOV @O..TPS,O..TPS+2 ;Save transmitter status BIC #^C,O..TPS+2 ; and turn off BIC #XC.IE,@O..TPS ; interrupts 1$: TSTB @O..TPS ;Now wait until printer is ready BPL 1$ ; ... RTS R5 .SBTTL O.RSTT - RESTORE TELETYPE STATUS O.RSTT: JSR R5,O.CRLF TSTB @O..TPS ;WAIT READY BPL .-4 ; ON PRINTER BIT #4000,@O..TKS ;CHECK BUSY FLAG BEQ 1$ ;SKIP READY LOOP IF NOT BUSY TSTB @O..TKS ;WAIT READY BPL .-4 ; ON READER 1$: BIS O..TKS+2,@O..TKS ;Restore input and BIS O..TPS+2,@O..TPS ; output interrupts RTS R5 .SBTTL O.REM - REMOVE BREAKPOINTS 0-7 ; IN THE OPPOSITE ORDER OF SETTING O.REM: TSTB O.S ;Single-instruction? BNE 30$ ;Yep... MOV R0,-(SP) ;Save R0 for awhile CLR R0 ;Set to access table 10$: CMP R0,#O.BKP ;End of table? BGT 20$ ;Yep... CALL O.RESB ;Nope, remove a breakpoint TST (R0)+ ;On to next entry BR 10$ 20$: MOV (SP)+,R0 ;Restore previously saved R0 30$: RTS R5 ; and return .SBTTL O.CADV - OCTAL OUTPUT WITH TRAILING SPACE ; WORD IS IN R0 ; Destroys R0 and R3 O.CADV: MOV #6,R3 ;R3 = 6 digits per word CMP O.BW,#1 ;But are we doing a word? BNE 10$ ;Yep... ASR R3 ;Nope, then 3 digits per byte BIC #^C<377>,R0 ; and strip to just the bits we want 10$: MOVB #40,-(SP) ;Place trailing space on stack BR 25$ ;Jump into middle of recursion 20$: MOV R0,-(SP) ;Save the current value BIC #^C<7>,@SP ;Strip all but a digit ADD #'0,@SP ;Make it printable ROR R0 ;Shift right ASR R0 ; 3 bits for ASR R0 ; next octal digit DEC R3 ;More characters to do? BLE 30$ ;Nope... 25$: JSR R5,20$ 30$: MOVB (SP)+,R0 ;Get a character BR O.PUTC ; and print it (letting O.PUTC ; unwind the recursion) .SBTTL O.CLRR - CLEAR RELOCATION REGISTERS ;+ ; ; O.CLRR CLEAR RELOCATION REGS ; I.E., SET THEM TO A HIGH MEM LOC. (-1) ; R1,R0 CLOBBERED ; ;- O.CLRR: MOV #20000+,R1 ;R1 -> Relocation register table MOV #8.,R0 ;R0 = Count of entries 10$: MOV #-1,(R1)+ ;Reset a relocation register DEC R0 ;More to do? BGT 10$ ;Yep... RTS R5 ;Nope, return to caller .SBTTL O.PUTC - SINGLE CHARACTER OUTPUT ; TYPE ONLY ONE CHARACTER (CONTAINED IN R0) O.PUTC: MOV R0,-(SP) ;Save character for awhile BIC #^C<177>,R0 ;Strip to 7-bit ascii BEQ 3$ ;s are easy to do CMPB R0,#33 ;Trying to echo an ape? BEQ 4$ ;Yes, then don't do it... CMPB R0,#10 ;If character is in range 1-10 BLOS 2$ CMPB R0,#16 ; or 16-37 BLO 3$ CMPB R0,#37 BLOS 2$ CMPB R0,#177 ; or is a 177 BNE 3$ 2$: MOVB #'?,R0 ;Print a '?' 3$: TSTB @O..TPS ;Ready? BPL .-4 ;Nope... MOVB R0,@O..TPB ;Yes, output the character 4$: MOV (SP)+,R0 ;RESTORE CHARACTER O.TYP1: RTS R5 .SBTTL O.GETC - SINGLE CHARACTER INTPUT ; CHARACTER INPUT GOES TO R0 O.GETC: TSTB @O..TKS ;Keyboard ready? BPL .-4 ;Nope...wait for it MOVB @O..TKB,R0 ;Yes, get the character BIC #^C<177>,R0 ;Strip to 7-bit ascii <06:00> BEQ O.GETC ;Ignore s CMPB R0,#3 ;Is character a ? BEQ 4$ ;Yes, don't echo it CMPB R0,#12 ;Is it a ? BEQ 4$ ;Yes, don't echo it 2$: CMPB R0,#'A+40 ;Is character lower case? BLO 3$ ;Nope... CMPB R0,#'Z+40 ;Maybe, check upper limit BHI 3$ ;Nope... BIC #40,R0 ;Yes, convert to upper case 3$: JSR R5,O.PUTC ;Echo the character CMPB R0,#40 ;Is character a ? BNE 4$ ;Nope... TSTB O.SCRN ;Yes, should it be passed? BEQ O.GETC ;Nope... 4$: RTS R5 .SBTTL O.TYPE - STRING OUTPUT ;+ ; ; ADDRESS OF FIRST BYTE IN R4, ; ADDRESS OF LAST BYTE IN R3, (R3)>(R4) ; EXPECTS LOCS 56,57 TO BE INITIALIZED BY MONITOR FOR FILL ; CHARACTERISTICS OF TERMINAL ; 56=CHAR TO BE FILLED AFTER ; 57=# OF NULLS TO FILL WITH ; ;- O.TYPE: CMP R3,R4 ;CHECK FOR COMPLETION BLO O.TYP1 ; EXIT WHEN DONE MOVB (R4)+,R0 ;GET A CHARACTER JSR R5,O.PUTC ;TYPE ONE CHARACTER CMPB R0,@#TTFILL ;COMPARE CHAR AGAINST FILL REQUIREMENT BNE O.TYPE ;NO FILL NEEDED MOVB @#TTNFIL,(PC)+ ;FILL COUNT INTO TEMP O.FTMP: .WORD 0 CLR R0 ;FILL WITH NULLS 1$: JSR R5,O.PUTC ;TYPE NULLS DEC O.FTMP ;DECREASE COUNT BGT 1$ ;BRANCH IF NOT DONE BR O.TYPE ;LOOP UNTIL DONE .SBTTL O.GTxx - Get word/byte contents ;+ ; ; O.GTWD ; Returns in R0 the contents of the word in previous address ; space pointed to by the contents of R0. ; ;- O.GTWD: TSTB O.IRFG ;Internal register access? BEQ 10$ ;Nope... MOV @R0,R0 ;Yes, get from debugger space BR 20$ 10$: ;;; CALL O.GTP1 ;Prepare for get from PAR1 MFPD @R0 ;Get a word MOV (SP)+,R0 ;Return it in R0 20$: RETURN ;+ ; ; O.GTBT ; Returns in R0, right-justified, the contents of the byte in ; previous address space pointed to by the contents of R0. ; ;- O.GTBT: TSTB O.IRFG ;Internal register access? BEQ 10$ ;Nope... MOVB @R0,R0 ;Yes, get from debugger space BR 30$ 10$: ;;; CALL O.GTP1 ;Prepare for get from PAR1 MFPD @R0 ;Get a word of data ASR R0 ;Was it high byte? BCC 20$ ;Nope... SWAB @SP ;Yes, reverse bytes 20$: MOVB (SP)+,R0 ;Return byte in R0 30$: RETURN .if eq 1 ;+ ; ; O.GTP1 ; Used to determine if the address to be referenced is in ; kernel PAR1 space, which is used to map the debugger. If ; so, we temporarily map it through PAR2. ; ;- O.GTP1: MOV @#PS,-(SP) ;Get PS contents BIC #^C,(SP)+ ;Previous mode kernel? BNE 10$ ;Nope... CMP R0,#20000 ;Yes, address in range of PAR1? BLO 10$ ;Nope... CMP R0,#40000 ;Maybe, check upper limit BHI 10$ ;Nope... MOV @SP,-(SP) ;Yes, shuffle stack MOV @#KISAR2,2(SP) ;Save PAR2 contents MWLHCH O.$KP1,@#KISAR2 ;Replace with PAR1 contents ADD #20000,R0 ; and move reference into PAR2 CALL @(SP)+ ;Co-routine call to caller MOV (SP)+,@#KISAR2 ;Restore kernel PAR2 10$: RETURN .endc ;eq 1 .SBTTL O.PTxx - Put word/byte contents ;+ ; ; O.PTWD ; Places a word in previous address space pointed to by the ; contents of R0. ; ;- O.PTWD: MOV 2(SP),-(SP) ;Reorder stack MOV 2(SP),4(SP) ; ... MOV (SP)+,@SP ; ... TSTB O.IRFG ;Internal register access? BEQ 10$ ;Nope... MOV (SP)+,@R0 ;Yes, move to current space BR 20$ 10$: ;;; CALL O.PTP1 MTPD @R0 ;Move (SP) to @R0 20$: RETURN ;+ ; ; O.PTBT ; Places a byte in previous address space pointed to by ; the contents of R0. ; ;- O.PTBT: MOV 2(SP),-(SP) ;Reorder stack MOV 2(SP),4(SP) ; ... MOV (SP)+,@SP ; ... TSTB O.IRFG ;Internal register access? BEQ 10$ ;Nope... MOVB (SP)+,@R0 ;Yes, move to current space BR 40$ 10$: ;;; CALL O.PTP1 MFPD @R0 ;Get old contents BIT #1,R0 ;Odd byte? BEQ 20$ ;Nope... SWAB @SP ;Yes, swap old contents 20$: MOVB 2(SP),@SP ;Replace byte BIT #1,R0 ;Odd byte? BEQ 30$ ;Nope... SWAB @SP ;Yes, restore correct order 30$: MOV (SP)+,@SP ;Reorder stack MTPD @R0 ;Move (SP) to @R0 40$: RETURN .if eq 1 ;+ ; ; O.PTP1 ; Used to determine if the address to be referenced is in ; kernel PAR1 space, which is used to map the debugger. If ; so, we temporarily map it through PAR2. ; ;- O.PTP1: MOV @#PS,-(SP) ;Get PS contents BIC #^C,(SP)+ ;Previous mode kernel? BNE 10$ ;Nope... CMP R0,#20000 ;Yes, referencing PAR1 space? BLO 10$ ;Nope... CMP R0,#40000 ;Maybe, check upper limit BHIS 10$ ;Nope... MOV @SP,-(SP) ;Yes, shuffle stack MOV 4(SP),2(SP) ; ... MOV @#KISAR2,4(SP) ;Save kernel PAR2 contents MWLHCH O.$KP1,@#KISAR2 ;Replace with PAR1 contents ADD #20000,R0 ; and shift reference into PAR2 CALL @(SP)+ ;Co-routine call to caller MOV (SP)+,@#KISAR2 ;Restore kernel PAR2 10$: RETURN .endc ;eq 1 .SBTTL ^U TEST ;+ ; ; CHECKS FOR ^U. IF PRESENT, ECHOS IT ; GOES TO COMMAND DECODER. STACK GETS INITIALIZED ; ;- .ENABL LSB O.CU: TSTB @O..TKS ;CHARACTER AVAILABLE? BPL 1$ ;NOPE... MOVB @O..TKB,R0 ;YES...GET IT... O.CU1: BIC #^C<177>,R0 ;Strip to 7-bit ascii CMPB R0,#'U-'@ ;IS CHARACTER A '^U'? BNE 1$ ;NOPE... MOVB #'^,R0 ;YES...PUT "^" IN R0 JSR R5,O.PUTC MOVB #'U,R0 ;PUT U IN R0 JSR R5,O.PUTC TST (PC)+ 1$: SEC RTS R5 .DSABL LSB .SBTTL O.RRST - READ PS (MACHINE INDEPENDENT) O.RRST: MOVB @#PS,O.UST ;STORE THE STATUS IN USER ; STATUS AREA.FOR AN LSI ; THIS IS CHANGED TO ; MFPS O.UST RETURN .SBTTL O.WST - WRITE PS (MACHINE INDEPENDENT) ; CALL ROUTINE WITH PS VALUE ON THE STACK O.WST: MOVB 2(SP),@#PS ;STORE NEW PS VALUE ; THIS INSTRUCTION IS CHANGED FOR LSI ; TO MTPS 2(SP) MOV (SP)+,@SP ;PUT RETURN PC OVER SUB. ARGUMENT RETURN ;TO RETURN WITHOUT IT ON THE STACK .SBTTL O.LOC - LOCATE RELOCATION REGISTER ;+ ; ; NEAREST BUT STILL ; BELOW THE ADDRESS IN R0. RETURNS WITH THE REGISTER ; NUMBER IN R0, AND WITH THE DISTANCE BETWEEN THE REGISTER ; AND (R0) IN O.XXY ; IF NO GOOD RELOC. REG. FOUND, R0 WILL = -1 ; ;- O.LOC: MOV R0,5$ ;PUT R0 IN WORKINK LOCATION. CLR R0 MOV #-1,O.XXX ;INITIALIZE RELOC. REG. INDEX MOV #177777,O.XXY ;INITIALIZE DISTANCE TO A HIGH VALUE 1$: CMP R0,#O.RLR ;ARE WE DONE COMPARING? BHI 3$ ;BRANCH IF DONE CMP 20000+(R0),5$ ;IS CURR. RELOC. BIAS > (O.CAD)? BHI 2$ ;YES -- DON'T SUBTRACT, GET NEXT MOV 5$,R1 ;OTHERWISE TAKE THE DIFFERENCE SUB 20000+(R0),R1 ; OF CURR. RELOC. REG. AND O.CAD CMP O.XXY,R1 ;IS THE RESULT THE SMALLEST SO FAR? BHI 4$ ;BRANCH IF YES (UNSIGNED CONDITIONAL) 2$: TST (R0)+ ;OTHERWISE, BUMP R0 FOR NEXT ; RELOCATION REGISTER BR 1$ ;LOOP BACK FOR NEXT COMPARISON 3$: MOV O.XXX,R0 ;PUT REG.# IN R0 RTS R5 ;JOB OVER, RETURN 4$: MOV R1,O.XXY ;REMEMBER SMALLEST DIFFERENCE IN O.XXY ASR R0 ;AND ASSOCIATED REGISTER NUMBER MOV R0,O.XXX ; IN O.XXX ASL R0 ;RESTORE R0 TO ORIGINAL VALUE BR 2$ ;GO FO NEXT COMPARISON. 5$: .WORD ;TEMP LOCATION. .SBTTL O.ST - INIT MEMORY ;+ ; ; SET A SEGMENT OF MEMORY TO A GIVEN VALUE. (ENTERED VIA R5) ; FIRST WORD OR BYTE ADDRESS IS IN R4, =TO R3 AT EXIT ; LAST WORD OR BYTE ADDRESS IS IN R3 ; BYTE OR WORD VALUE IS IN R0 ; BYTE OR WORD MODE IS SPECIFIED BY O.BW ; ;- O.ST: 1$: CMP O.BW,#1 ;IF NOT BYTE MODE, ASSUME WORD BEQ 3$ ;BRANCH IF BYTE MODE MOV R0,-(SP) MOV R0,-(SP) MOV R4,R0 CALL O.PTWD ADD #2,R4 MOV (SP)+,R0 2$: CMP R4,R3 ;ARE WE DONE? BLOS 1$ ;BRANCH IF NOT DONE RTS R5 ;OTHERWISE EXIT 3$: MOV R0,-(SP) MOV R0,-(SP) MOV R4,R0 CALL O.PTBT INC R4 MOV (SP)+,R0 BR 2$ ;GO TO TEST IF DONE .SBTTL O.CLSE - MODIFY, CLOSE LOCATION ;+ ; ; CLOSE WORD OR BYTE AND EXIT, ; UPON ENTERING, R2 HAS NUMERIC FLAG, R4 HAS CONTENTS ; ;- O.CLSE: TST R2 ;IF NO NUMBER WAS TYPED THERE IS BEQ 2$ ;NO CHANGE TO THE OPEN CELL CMP O.BW,#1 BEQ 1$ ;JUMP IF BYTE MODE BLO 2$ ;JUMP IF ALREADY CLOSED MOV R0,-(SP) MOV R4,-(SP) MOV O.CAD,R0 CALL O.PTWD MOV (SP)+,R0 BR 2$ 1$: MOV R0,-(SP) MOV R4,-(SP) MOV O.CAD,R0 CALL O.PTBT MOV (SP)+,R0 2$: RETURN O.CRLF: MOV #20000+,R3 ;LWA BR O.CRS O.CRLS: MOV #20000+,R3 ;LWA * O.CRS: MOV #20000+,R4 ;FWA JSR R5,O.TYPE ;TYPE SOMETHING RTS R5 .SBTTL O.RORA - DECODE RELATIVE OR ABS ADDRESS ;+ ; ; SUBROUTINE O.RORA ; FUNCTION: DECIDE IF AN ADDRESS IS ; TO BE PRINTED IN ABSOLUTE OR IN RELATIVE ; FORM. IF THE FLAG O.FORM=0 THEN PRINT ; IN RELATIVE FORM, OTHERWISE PRINT IN ABSOLUTE FORM. ; IF THE ADDRESS IS TO BE PRINTED IN RELATIVE FORM, ; THEN THE ADDRESS WILL BE PRINTED OUT ; RELATIVE TO A RELOCATION REGISTER NEAREST ; BUT STILL BELOW THE ADDRESS. IF NO SUCH ; RELOCATION REGISTER EXIST THEN THE ; ADDRESS WILL BE PRINTED IN ABSOLUTE FORM ; INPUT: THE ADDRESS TO BE PRINTED IS IN R0. ; DATA SAVED: R0 CONTAINING THE ADDRESS TO BE ; PRINTED, AND LOCATION O.CAD CONTAINING ; THE CURRENT ADDRESS WERE SAVED AND RESTORED. ; CALLED: JSR 5,O.RORA ; ;- O.RORA: TST O.FORM ;CHECK FORMAT BEQ 2$ ; GO TO 2$ IF RELATIVE 1$: JSR R5,O.CADV ;PRINT ABSOLUTE ADDRESS RTS R5 2$: MOV R0,O.TMP2 ;SAVE R0 JSR R5,O.LOC ; FIND BEST N TST R0 ;IF = -1, PRINT IN ABS. BLT 3$ ADD #'0,R0 ; CONVERT N TO ANSCII JSR R5,O.PUTC ; TYPE N MOVB #',,R0 ; PREPARE INPUT FOR O.PUTC JSR R5,O.PUTC ; TYPE COMMA MOV O.BW,-(SP) ; SAVE O.BW MOV #2,O.BW ;ARTIFICIALLY SET MODE FOR WORDS MOV O.XXY,R0 ;PREPARE INPUT FOR O.CADV JSR R5,O.CADV ;TYPE RELATIVE AMOUNT MOV (SP)+,O.BW ;RESTORE MODE MOV O.TMP2,R0 ; RESTORE R0 RTS R5 3$: MOV O.TMP2,R0 ;RESTORE R0,CAD BEFORE BR 1$ .SBTTL PACK00 - MOD40 PACK ;+ ; ; MOD40 PACK - ENTERED WITH JSR PC, PACK00 ; INPUT: R0=ADR OF MOD40 WORD (1 WORD) ; R1=ADR OF ASCII CHARACTERS (3 CHARS) ; OUTPUT: R1 POINTS ONE PAST END OF ASCII STRINT ; THE MOD40 WORD IS FORMED AS ; N=C1*40^2+C2*40+C3 ; R2,R3,R4 ARE CLOBBERED ; ;- PACK00: MOV #-3,R4 ;LOOP CT. CLR R2 ;0 SUM 1$: MOVB (R1)+,R3 ;GET NEXT ASCII CHAR. CMPB R3,#40 BEQ 2$ ;"BLANK" CMPB R3,#'$ BEQ 4$ ;"$" CMPB R3,#'A BLO 3$ ;"." OR "0-9" SUB #40,R3 ;"A-1" 2$: SUB #16,R3 3$: SUB #11,R3 4$: SUB #11,R3 ; MULT R2 BY 40. ASL R2 ;2*R2 ASL R2 ;4*R2 ASL R2 ;8*R2 MOV R2,-(SP) ;STACK 8*R2 ASL R2 ;16.*R2 ASL R2 ;32.*R2 ADD (SP)+,R2 ;40.*R2 ; INCLUDE CURRENT CHARACTER ADD R3,R2 INC R4 ;DONE 3 CHARS? BLT 1$ ;NO MOV R2,(R0)+ ;YES-STORE MOD40 WORD RETURN ;EXIT .SBTTL UNPA00 - MOD40 UNPACK ;+ ; ; MOD40 UNPACK - ENTERED VIA JSR PC,UNPA00 ; INPUT: R0=ADR OF MOD40 NUMBER (1 WORD) ; R1=ADR OF ASCII STRING (3 BYTES) ; OUTPUT: R1 POINTS ONE PAST LAST GENERATED CHARACTER ; ; IF N IS THE MOD40 NUMBER, THEN ; N=C1*50 ^ 2+C2*50+C3 ; THUS, N/50^2 IS C1 AND THE REMAINDER IS C2*50+C3 ; THE REMAINDER IS DIVIDED BY 50 TO GET C2 ETC. ; ;- UNPA00: MOV #-3,R5 ;MINOR LOOP COUNT CALL O.GTWD MOV #20000+,R2 ;R2 -> Coefficient table 1$: CLR R3 ;0 QUOTIENT ; DIVIDE BY COEFFICIENTS 2$: CMP R0,(R2) ;DONE WITH DIVIDE? BLO 3$ ;YES SUB (R2),R0 ;NO-SUBTRACT COEFF. INC R3 ;ADD 1 TO QUOTIENT BR 2$ ; DIVIDE DONE. QUOT IN R3, REMAINDER IN R0 ; CONVERT TO AN ASCII CHARACTER 3$: TSTB R3 BEQ 4$ ;"BLANK" CMPB R3,#33 BEQ 6$ ;"$" BGT 5$ ;"." OR "0-9" ADD #40,R3 ;"A-Z" 4$: ADD #16,R3 5$: ADD #11,R3 6$: ADD #11,R3 MOVB R3,(R1)+ ;STORE CHARACTER TST (R2)+ ;ADVANCE TO NEXT COEFF. INC R5 ;DONE 3 CHARS? BLT 1$ ;NO-DO MORE MOV @SP,R0 ;RESTORE ORIGINAL R0 AND TST (R0)+ ;MOVE TO NEXT WORD RETURN .SBTTL DEFINITIONS ; Feature tests .IIF NDF FT.EIS FT.EIS == 1 ;Extended instruction set .IIF NDF FT.FIS FT.FIS == 0 ;Floating instruction set .IIF NDF FT.FPP FT.FPP == 0 ;Floating point instruction set .IIF NDF FT.J11 FT.J11 == 0 ;J-11 multiprocessor instructions .SBTTL O.DCOD - PRIMARY DECODER AND DISPATCHER ;+ ; ; O.DCOD ; To place into a buffer the mnemonic form of a PDP-11 ; instruction ; ; INPUT: ; R4 -> Output buffer ; R5 -> First word of instruction to be decoded ; ; OUTPUT: ; R0 = Decoded instruction length in bytes ; R4 -> Character beyond last placed in buffer ; R5 -> First word of next instruction ; ; IMPLICIT OUTPUT: ; ; Decoded instruction in buffer pointed to by input R4 ; ;- O.OPCD:: .IRPC X,<1235> MOV R'X,-(SP) .ENDR MOV R5,R0 ;R0 = Address to fetch CALL O.GTWD ;Get its contents MOV R0,-(SP) MOV R0,R1 ADD #2,R5 CLRB BYTFLG ASL R1 ;STRIP OFF HIGH-ORDER BIT ADCB BYTFLG ; AND USE IT TO SET THE ROR R1 ; BYTE INSTRUCTION INDICATOR MOV #20000+,R2 ;R2->INSTRUCTION TABLE MOV #20000+,R3 ;R3->INSTRUCTION MNEMONICS STRING 1$: ADD #4,R2 ;BUMP POINTER TO NEXT ENTRY TST (R2) ;AT END OF TABLE? BEQ 3$ ;YES... CMP R1,(R2) ;NOPE...DOES INSTRUCTION FIT HERE? BLO 3$ ;YES... TST -(SP) ;BACK UP STACK POINTER 2$: CLR (SP) ;CLEAR WORD ON TOP OF STACK BISB -1(R2),(SP) ;GET LENGTH OF PREVIOUS MNEMONIC ADD (SP)+,R3 ;ADD TO RUNNING POINTER BR 1$ ;AND CONTINUE SCANNING TABLE 3$: MOV -2(R2),-(SP) ;GET INSTRUCTION DEFINITION CODE TSTB (SP) ;CAN THIS BE A BYTE INSTRUCTION? BMI 4$ ;YES... ASRB BYTFLG ;WAS BYTE INSTRUCTION INDICATOR SET? BCC 4$ ;NOPE...WE'RE OKAY THEN BIS #100000,R1 ;YES...RESTORE HIGH-ORDER BIT BR 2$ ;AND CONTINUE SCANNING TABLE 4$: MOV (SP),R1 ;GET MNEMONIC LENGTH CLRB R1 SWAB R1 BEQ 6$ ;NO MNEMONIC TO PRINT... 5$: MOVB (R3)+,(R4)+ ;PLACE A MNEMONIC CHARACTER IN BUFFER DEC R1 ;DE-BUMP LENGTH COUNTER BGT 5$ ;KEEP GOING IF COUNT>0 ASRB BYTFLG ;BYTE INSTRUCTION? BCC 6$ ;NOPE... MOVB #'B,(R4)+ ;YES...APPEND A 'B' 6$: MOV (SP)+,R0 ;R0=INSTRUCTION DEFINITION CODE BIC #177600,R0 ASL R0 ;SHIFT FOR BYTE OFFSET MOV (SP)+,R1 ;R1=INSTRUCTION BEING DECODED MOV DECTAB+<20000-O..IDT>(R0),R0 ; R0 = Offset to routine ADD #20000-O..IDT,R0 ;R0 -> Routine CALL @R0 ;Dispatch to routine MOV R5,R0 SUB (SP)+,R0 .IRPC X,<321> MOV (SP)+,R'X .ENDR DEC.XT: RETURN ;AND RETURN BYTFLG: .WORD 0 ;BYTE INSTRUCTION INDICATOR DECTAB: .WORD DEC.UN ;0 - Undefined .WORD DEC.XT ;1 - No operands .WORD DEC.R ;2 - Register .WORD DEC.N3 ;3 - 3-bit number .WORD DEC.CC ;4 - Condition codes .WORD DEC.O8 ;5 - Branch offset .WORD DEC.N6 ;6 - 6-bit number .WORD DEC.RO ;7 - Register, branch offset .WORD DEC.N8 ;10 - 8-bit number .WORD DEC.DD ;11 - Source/Destination .WORD DEC.RD ;12 - Register, destination .WORD DEC.RS ;13 - Register, source .WORD DEC.XT ;14 - reserved .WORD DEC.AS ;15 - AC, source .WORD DEC.AD ;16 - AC, destination .WORD DEC.SD ;17 - Source, destination .SBTTL DEC.R - REGISTER PRINTER ;+ ; ; THIS ROUTINE PRINTS A REGISTER NAME AS FOLLOWS: ; ; R0 R1 R2 R3 R4 R5 SP PC ; ;- DEC.R: MOVB #11,(R4)+ ROUT: BIC #177770,R1 ;STRIP TO REGISTER ASL R1 ;SHIFT FOR BYTE OFFSET ADD #20000+,R1 ;MAKE IT A POINTER MOVB (R1)+,(R4)+ ;FIRST CHARACTER TO BUFFER MOVB (R1),(R4)+ ; FOLLOWED BY SECOND CHARACTER RETURN ;RETURN REGLST: .ASCII /R0R1R2R3R4R5SPPC/ .EVEN .SBTTL AC PRINTER ;+ ; ; Prints a FPP accumulator name of the form ; ; ACn ; ;- DEC.A: MOVB #11,(R4)+ AOUT: MOVB #'A,(R4)+ MOVB #'C,(R4)+ BIC #^C<3>,R1 ADD #'0,R1 MOVB R1,(R4)+ RETURN .SBTTL DEC.N? - NUMBER PRINTER ;+ ; ; THIS ROUTINE IS USED TO PRINT ONE OF THE FOLLOWING: ; ; 3-BIT OCTAL NUMBER ; 6-BIT OCTAL NUMBER ; 8-BIT OCTAL NUMBER ; 16-BIT OCTAL NUMBER ; ; ALL WITH LEADING ZEROES SUPPRESSED ; ;- DEC.N3: BIC #177770,R1 ;STRIP TO BITS <2:0> DEC.N6: BIC #177700,R1 ;STRIP TO BITS <5:0> DEC.N8: BIC #177400,R1 ;STRIP TO BITS <7:0> O8OUT: MOVB #11,(R4)+ DEC.UN: MOV R1,R0 ;MOVE NUMBER TO R0 TOCTO: MOV R0,-(SP) ;SAVE CURRENT NUMBER BIC #177770,(SP) ;STRIP TO ONE OCTAL DIGIT ADD #60,(SP) ;MAKE IT PRINTABLE ROR R0 ;SHIFT FOR NEXT DIGIT ASR R0 ASR R0 BEQ 1$ ;IF =0 THEN START PRINTING CALL TOCTO ;OTHERWISE...RECURSE! 1$: MOVB (SP)+,(R4)+ ;PLACE A DIGIT IN THE BUFFER RETURN ;RETURN RECURSIVELY .SBTTL DEC.CC - CONDITION CODE PRINTER ;+ ; ; THIS ROUTINE IS USED TO PRINT THE CONDITION CODES AND ; ALL THEIR POSSIBLE COMBINATIONS. ; ; COMBINATIONS WILL BE OF THE FORM: ; ; (CL,SE)!(CL,SE)... ; ;- DEC.CC: MOV #20000+,R2 ;ASSUME CODE IS A 'CL' BIT #20,R1 ;ARE WE CORRECT? BEQ 1$ ;YES... ADD #4,R2 ;NOPE...IT'S A 'SE' 1$: MOV #20000+,R3 ;R3->CC BIT NAMES MOV #-1,2$ ;RESET 'OR' FLAG CALL (PC) ;DO FOLLOWING CODE 2 TIMES CALL (PC) ; ! CORRECTION ! - 4 TIMES ASR R1 ;IS BIT ON? BCC 3$ ;NOPE... MOV R2,-(SP) ;SAVE CURRENT PREFIX POINTER 15$: MOVB (R2)+,(R4)+ ;MOVE A BYTE OF THE PREFIX BPL 15$ ;KEEP GOING UNTIL <200> BYTE DEC R4 ;CORRECT R4 MOV (SP)+,R2 ; AND RESTORE R2 MOVB (R3),(R4)+ ;ADD THE BIT NAME INC (PC)+ ;BUMP 'OR' FLAG 2$: .BLKW BNE 3$ ;NOT FIRST TIME... DEC R2 ;BACK UP TO '!' 3$: INC R3 ;ON TO NEXT BIT NAME RETURN ;AND RETURN CLSTR: .ASCII /!CL/<200> SESTR: .ASCII /!SE/<200> CCSTR: .ASCII /CVZN/ .EVEN .SBTTL DEC.O8 - BRANCH OFFSET PRINTER ;+ ; ; THIS ROUTINE IS USED TO PRINT THE TARGET ADDRESS OF A BRANCH USING ; THE OFFSET AND THE CURRENT PC. ; ;- DEC.O8: MOVB #11,(R4)+ MOVB R1,R1 ;SIGN EXTEND OFFSET ROOUT: ASL R1 ;OFFSET*2 ADD R5,R1 ;ADD CURRENT PC CALLR DEC.UN ;AND PRINT IT .SBTTL DEC.RO - SOB PRINTER ;+ ; ; THIS ROUTINE PRINTS THE REGISTER,TARGET_ADDRESS PAIR ; FOR AN 'SOB' INSTRUCTION. ; ;- DEC.RO: MOV R1,-(SP) ;SAVE INSTRUCTION ASL R1 ;GET REGISTER ASL R1 SWAB R1 CALL DEC.R ;PRINT IT MOVB #',,(R4)+ ;DELIMITER MOV (SP)+,R1 ;GET INSTRUCTION BIC #177700,R1 ;STRIP TO OFFSET NEG R1 CALLR ROOUT ;AND PRINT IT .SBTTL DEC.DD - SOURCE OR DESTINATION PRINTER ;+ ; ; THIS ROUTINE PRINTS THE EFFECTIVE SOURCE OR DESTINATION ; USING THE BITS AS LISTED ON THE PDP-11 PROGRAMMING ; CARD. ; ;- DEC.DD: MOVB #11,(R4)+ DDOUT: BIC #177700,R1 ;STRIP TO MOV R1,-(SP) ;AND SAVE IT BIC #70,R1 ;STRIP TO REGISTER CMP R1,#7 ;REGISTER 7 (PC)? BNE 4$ ;NOPE... BIT #20,(SP) ;MODE 2,3,6 OR 7? BEQ 4$ ;NOPE... BIT #10,(SP) ;MODE 3 OR 7? BEQ 1$ ;NOPE... MOVB #'@,(R4)+ ;YES...DEFERRED MODE 1$: BIT #40,(SP) ;MODE 2 OR 3? BNE 2$ ;NOPE... MOVB #'#,(R4)+ ;YES...IMMEDIATE OR ABSOLUTE MODE 2$: MOV R5,R0 ADD #2,R5 CALL O.GTWD BIT #40,(SP)+ ;MODE 6 OR 7? BEQ 3$ ;NOPE... ADD R5,R0 ;YES...PC RELATIVE 3$: CALLR TOCTO ;PRINT IT 4$: BIT #10,(SP) ;MODE 1,3,5 OR 7? BEQ 5$ ;NOPE... CMP (SP),#30 ;MODE 3,5 OR 7? BLT 5$ ;NOPE... MOVB #'@,(R4)+ ;YES...DEFERRED MODE 5$: BIT #40,(SP) ;MODE 4,5,6 OR 7? BEQ 7$ ;NOPE... CMP (SP),#60 ;MODE 4 OR 5? BGE 6$ ;NOPE... MOVB #'-,(R4)+ ;YES...AUTO-DECREMENT MODE BR 7$ 6$: MOV R5,R0 ADD #2,R5 CALL O.GTWD CALL TOCTO ;PRINT IT OUT 7$: CMP (SP),#10 ;MODE 1-7? BLT 8$ ;NOPE... MOVB #'(,(R4)+ ;YES...REGISTER DEFERRED MODE START 8$: CALL ROUT ;PRINT REGISTER CMP (SP),#10 ;MODE 1-7? BLT 9$ ;NOPE... MOVB #'),(R4)+ ;YES...REGISTER DEFERRED MODE END 9$: BIT #20,(SP) ;MODE 2,3,6 OR 7? BEQ 10$ ;NOPE... CMP (SP),#40 ;YES...MODE 2 OR 3? BGE 10$ ;NOPE... MOVB #'+,(R4)+ ;YES...AUTO-INCREMENT MODE 10$: TST (SP)+ ;DISCARD INSTRUCTION RETURN ;AND RETURN .SBTTL DEC.RD - REG,DST PRINTER DEC.RD: MOVB #11,(R4)+ MOV R1,-(SP) ;SAVE INSTRUCTION ASL R1 ;SHIFT AND SWAB FOR REGISTER ASL R1 SWAB R1 CALL ROUT ;PRINT REGISTER MOVB #',,(R4)+ ;DELIMITER MOV (SP)+,R1 CALLR DDOUT .SBTTL DEC.RS - REG,SRC PRINTER DEC.RS: MOV R1,-(SP) ;SAVE INSTRUCTION CALL DEC.DD ;PRINT SOURCE MOVB #',,(R4)+ ;DELIMITER MOV (SP)+,R1 ;GET INSTRUCTION ASL R1 ;SHIFT AND SWAB FOR REGISTER ASL R1 SWAB R1 CALLR ROUT .SBTTL DEC.AS - AC, SRC PRINTER DEC.AS: MOV R1,-(SP) ;Save instruction CALL DEC.DD ;Print source MOVB #',,(R4)+ ;Delimiter MOV (SP)+,R1 ;Get instruction ASL R1 ;Shift and swab for AC ASL R1 SWAB R1 CALLR AOUT .SBTTL DEC.AD - AC,DST PRINTER DEC.AD: MOV R1,-(SP) ;Save instruction CALL DEC.A ;Print AC MOVB #',,(R4)+ ;Delimiter MOV (SP)+,R1 ;Get instruction CALLR DDOUT .SBTTL DEC.SD - SRC,DST PRINTER DEC.SD: MOV R1,-(SP) ;SAVE INSTRUCTION ASL R1 ;SHIFT AND SWAB FOR SOURCE ASL R1 SWAB R1 CALL DEC.DD ;PRINT SOURCE MOVB #',,(R4)+ ;DELIMITER MOV (SP)+,R1 CALLR DDOUT ;PRINT DESTINATION .SBTTL Instruction decode tables ; INSTRUCTION DEFINITION CODES UN = 0 ;1 WORD...UNDEFINED NO = 1 ;1 WORD...NO OPERANDS R = 2 ;1 WORD...REG <2:0> N3 = 3 ;1 WORD...3-BIT NUMBER <2:0> CC = 4 ;1 WORD...CONDITION CODES <3:0> O8 = 5 ;1 WORD...8-BIT OFFSET <7:0> N6 = 6 ;1 WORD...6-BIT NUMBER <5:0> RO6 = 7 ;1 WORD...REG,6-BIT OFFSET <8:6><5:0> N8 = 10 ;1 WORD...8-BIT NUMBER <7:0> DD = 11 ;1,2 WORD...DST <5:0> SS = DD ;1,2 WORD...SRC <5:0> RDD = 12 ;1,2 WORD...REG,DST <8:6><5:0> RSS = 13 ;1,2 WORD...REG,SRC <8:6><5:0> FS = DD ;1,2 WORD...FSRC <5:0> FD = DD ;1,2 WORD...FDST <5:0> AFS = 15 ;1,2 WORD...ACC,FSRC <7:6><5:0> AFD = 16 ;1,2 WORD...ACC,FDST <7:6><5:0> SD = 17 ;1,2,3 WORD...SRC,DST <11:6><5:0> BYTE = 200 ;BYTE INSTRUCTION ; INSTRUCTION TABLE BUILD MACRO .MACRO BLDTAB .MACRO TABBLD ; ; INSTRUCTION DEFINITION TABLE ; ; NAME BASE CODE ; ---- ---- ---- OPDEF HALT 000000 ;HALT processor OPDEF WAIT 000001 ;WAIT for interrupt OPDEF RTI 000002 ;ReTurn from Interrupt OPDEF BPT 000003 ;BreakPoint Trap OPDEF IOT 000004 ;Input-Output Trap OPDEF RESET 000005 ;RESET bus OPDEF RTT 000006 ;ReTurn from interrupt (T-bit set) OPDEF MFPT 000007 ;Move From Processor Type OPDEF ,000010 OPDEF JMP 000100 DD ;JuMP unconditionally OPDEF RTS 000200 R ;ReTurn from Subroutine (R0-SP) OPDEF RETURN 000207 ;RETURN from subroutine (PC) OPDEF ,000210 OPDEF SPL 000230 N3 ;Set processor Priority Level OPDEF NOP 000240 ;No OPeration OPDEF ,000241 CC ;Clear selected condition codes OPDEF CCC 000257 ;Clear Condition Codes OPDEF ,000260 ;(logical no-operation) OPDEF ,000261 CC ;Set selected condition codes OPDEF SCC 000277 ;Set Condition Codes OPDEF SWAB 000300 DD ;SWAp Bytes OPDEF BR 000400 O8 ;BRanch unconditionally OPDEF BNE 001000 O8 ;Branch if Not Equal OPDEF BEQ 001400 O8 ;Branch if EQual OPDEF BGE 002000 O8 ;Branch if Greater than or Equal OPDEF BLT 002400 O8 ;Branch if Less Than OPDEF BGT 003000 O8 ;Branch if Greater Than OPDEF BLE 003400 O8 ;Branch if Less than or Equal OPDEF JSR 004000 RDD ;Jump to SubRoutine (R0-SP) OPDEF CALL 004700 DD ;Jump to SubRoutine (PC) OPDEF CLR 005000 DD!BYTE ;CLeaR [Byte] OPDEF COM 005100 DD!BYTE ;COMplement [Byte] (1's complement) OPDEF INC 005200 DD!BYTE ;INCrement [Byte] OPDEF DEC 005300 DD!BYTE ;DECrement [Byte] OPDEF NEG 005400 DD!BYTE ;NEGate [Byte] (2's complement) OPDEF ADC 005500 DD!BYTE ;ADd Carry [Byte] OPDEF SBC 005600 DD!BYTE ;SuBtract Carry [Byte] OPDEF TST 005700 DD!BYTE ;TeST [Byte] OPDEF ROR 006000 DD!BYTE ;ROtate Right [Byte] OPDEF ROL 006100 DD!BYTE ;ROtate Left [Byte] OPDEF ASR 006200 DD!BYTE ;Arithmetic Shift Right [Byte] OPDEF ASL 006300 DD!BYTE ;Arithmetic Shift Left [Byte] OPDEF MARK 006400 N6 ;MARK OPDEF MFPI 006500 SS ;Move From Previous Instruction space OPDEF MTPI 006600 DD ;Move To Previous Instruction space OPDEF SXT 006700 DD ;Sign eXTend OPDEF ,007000 .IF NE FT.J11 OPDEF TSTSET 007200 DD ;TeST and SET OPDEF WRTLCK 007300 DD ;WRiTe interLoCKed OPDEF ,007400 .ENDC ;NE FT.J11 OPDEF MOV 010000 SD!BYTE ;MOVe [Byte] OPDEF CMP 020000 SD!BYTE ;CoMPare [Byte] OPDEF BIT 030000 SD!BYTE ;BIt Test [Byte] OPDEF BIC 040000 SD!BYTE ;BIt Clear [Byte] OPDEF BIS 050000 SD!BYTE ;BIt Set [Byte] OPDEF ADD 060000 SD ;ADD .IF EQ FT.EIS OPDEF ,070000 .IFF OPDEF MUL 070000 RSS ;MULtiply OPDEF DIV 071000 RSS ;DIVide OPDEF ASH 072000 RSS ;Arithmetic SHift OPDEF ASHC 073000 RSS ;Arithmetic SHift Combined OPDEF XOR 074000 RDD ;eXclusive OR .IF EQ FT.FIS OPDEF ,075000 .ENDC ;EQ FT.FIS .ENDC ;NE FT.EIS .IF NE FT.FIS OPDEF FADD 075000 R ;Floating ADD OPDEF FSUB 075010 R ;Floating SUBtract OPDEF FMUL 075020 R ;Floating MULtiply OPDEF FDIV 075030 R ;Floating DIVide OPDEF ,075040 .ENDC ;NE FT.EIS OPDEF SOB 077000 RO6 ;Subract One and Branch if not equal OPDEF BPL 100000 O8 ;Branch if PLus OPDEF BMI 100400 O8 ;Branch if MInus OPDEF BHI 101000 O8 ;Branch if HIgh OPDEF BLOS 101400 O8 ;Branch if LOwer or Same OPDEF BVC 102000 O8 ;Branch if oVerflow Clear OPDEF BVS 102400 O8 ;Branch if oVerflow Set OPDEF BCC 103000 O8 ;Branch if Carry Clear OPDEF BCS 103400 O8 ;Branch if Carry Set OPDEF EMT 104000 N8 ;EMulator Trap OPDEF TRAP 104400 N8 ;TRAP OPDEF ,105000 OPDEF MTPS 106400 SS ;Move To Processor Status OPDEF MFPD 106500 SS ;Move From Previous Data space OPDEF MTPD 106600 DD ;Move To Previous Data space OPDEF MFPS 106700 DD ;Move From Processor Status OPDEF ,107000 OPDEF SUB 160000 SD ;SUBtract .IF EQ FT.FPP OPDEF ,177777 .IFF OPDEF CFCC 170000 ;Copy Floating Condition Codes OPDEF SETF 170001 ;SET Floating mode OPDEF SETI 170002 ;SET Integer mode OPDEF ,170003 OPDEF SETD 170011 ;SET floating Double mode OPDEF SETL 170012 ;SET Long integer mode OPDEF ,170013 OPDEF LDFPS 170100 SS ;LoaD FPp prog Status OPDEF STFPS 170200 DD ;STore FPp prog Status OPDEF STST 170300 DD ;STore STatus (exe codes and adrs) OPDEF CLRF 170400 FD ;CLeaR Floating/double OPDEF TSTF 170500 FD ;TeST Floating/double OPDEF ABSF 170600 FD ;make ABSolute Floating/double OPDEF NEGF 170700 FD ;NEGate Floating/double OPDEF MULF 171000 AFS ;MULtiply Floating/double OPDEF MODF 171400 AFS ;Multiply and integerize OPDEF ADDF 172000 AFS ;Add floating/double OPDEF LDF 172400 AFS ;Load floating/double OPDEF SUBF 173000 AFS ;Subtract floating/double OPDEF CMPF 173400 AFS ;Compare floating/double OPDEF STF 174000 AFD ;Store floating/double OPDEF DIVF 174400 AFS ;Divide floating/double OPDEF STEXP 175000 AFD ;Store exponent OPDEF STCFI 175400 AFD ;Store and convert floating or double ; to integer or long integer OPDEF STCFD 176000 AFD ;Store and convert (double<->floating) OPDEF LDEXP 176400 AFS ;Load exponent OPDEF LDCIF 177000 AFS ;Load and convert integer or long ; integer to floating or double OPDEF LDCDF 177400 AFS ;Load and convert .ENDC ;EQ FT.FPP .ENDM TABBLD .MACRO OPDEF NAME,BASE,CODE .COD. = NO .NCHR .LEN. .IIF B .COD. = 0 .IIF NB .COD. = CODE .WORD BASE .BYTE .COD.,.LEN. .ENDM OPDEF OPTAB: TABBLD .WORD 0 .MACRO OPDEF NAME,BASE,CODE .IF NB .ASCII /'NAME/ .ENDC .ENDM OPDEF OPTXTB: TABBLD .EVEN .ENDM BLDTAB ; BUILD THE TABLES BLDTAB .SBTTL Command dispatch tables ; List of legal command characters ; ; *NOTE* The following list is order critical and must match the ; order of the processing routine table beginning with O.LGDR O.LGCH: .BYTE '; ; ; Command delimiter .BYTE '/ ; / Open location - word .BYTE '\ ; \ Open location - byte .BYTE 015 ; Close location .BYTE '$ ; $ Special register name .BYTE 'G ; G Go .BYTE 012 ; Close current, open next .BYTE '_ ; _ (BACK ARROW) .BYTE '< ; < .BYTE '^ ; ^ (UP ARROW) .BYTE ', ; , Expression delimiter .BYTE 'O ; O .BYTE 'W ; W .BYTE 'E ; E .BYTE 'B ; B .BYTE 'P ; P .BYTE '@ ; @ .BYTE '> ; > .BYTE 'S ; S .BYTE 'R ; R .BYTE 'C ; C .BYTE '- ; - Unary minus .BYTE 'F ; F .BYTE 'I ; I .BYTE '! ; ! .BYTE 'X ; X .BYTE '| ; | Instruction decode .BYTE 033 ; Single instruction execution .BYTE '. ; . Current location .BYTE '= ; = Evaluate current location .BYTE 'T ; T Set/display current terminal .BYTE '[ ; [ Open word sans decode O.CLGT = .-O.LGCH ;TABLE LENGTH .EVEN ; Table of command character processing routines ; ; *NOTE* The following list is order critical and must match the ; order of the command character list beginning with O.LGCH O.LGDR: .WORD O.SEMI ; ; Argument/operation delimiter .WORD O.WRD ; / Open word .WORD O.BYT ; \ Open byte .WORD O.CRET ; Modify, close location .WORD O.REGT ; $ Special registers .WORD O.GO ; G Execute from specified address .WORD O.OP1 ; Modify, close, open next .WORD O.ORPC ; _ Modify, close, open indexed ; from PC .WORD O.OLD ; < Return to previous sequence .WORD O.BACK ; ^ Modify, close, open previous .WORD O.COMM ; , Relocation register delimiter .WORD O.OFST ; O Offset .WORD O.WSCH ; W Search word .WORD O.EFF ; E Search effective address .WORD O.BKPT ; B [Re]Set breakpoints .WORD O.PROC ; P Proceed from breakpoint .WORD O.ORAB ; @ Open related, absolute .WORD O.ORRB ; > Open related, relative branch .WORD O.SNGL ; S Single instruction .WORD O.REL ; R Relocation register .WORD O.CNS ; C Constant register .WORD O.MIN ; - Unary minus .WORD O.FILL ; F Fill words from constant reg. .WORD O.INIT ; I Fill bytes from constant reg. .WORD O.RCMP ; ! Display current address in ; relative format (n,oooooo) .WORD O.MOD ; X Print and input RAD50 .WORD O.DCOD ; | Mnemonic instruction decode .WORD O.ESC ; Single instruction (shortform) .WORD O.PERI ; . Evaluate current location .WORD O.EQUA ; = Display current address in ; absolute format .WORD O.TTYC ; T Display/change debug terminal .WORD O.LBRA ; [ Open word sans decode O.LGL = .-O.LGDR ;LGL MUST EQUAL 2X CHLGT ALWAY ; Internal register name/access table O.IRTB: .WORD '0,O.UR0 ;General register 0 ($0) .WORD '1,O.UR0+2 ;General register 1 ($1) .WORD '2,O.UR0+4 ;General register 2 ($2) .WORD '3,O.UR0+6 ;General register 3 ($3) .WORD '4,O.UR0+10 ;General register 4 ($4) .WORD '5,O.UR0+12 ;General register 5 ($5) .WORD '6,O.UR0+14 ;User stack ($6) .WORD '7,O.UR0+16 ;User PC ($7) .WORD 'B,O.ADR1 ;Breakpoint table ($B) .WORD 'C,O.CNST ;Constant register ($C) .WORD 'F,O.FORM ;Format register ($F) .WORD 'K,O.KSP ;Kernel stack ($K) .WORD 'M,O.MSK ;Mask ($M) .WORD 'P,O.PRI ;Priority ($P) .WORD 'R,O.RELT ;Relocation registers ($R) .WORD 'S,O.UST ;User status ($S) .WORD 0 ; : Table fence .SBTTL Text impure area O.ALFE: .BYTE '= ;RAD50 pack/unpack storage O.ALF1: .BYTE 0 O.ALF2: .BYTE 0 O.ALF3: .BYTE 0 O.ALFS: .BYTE 40 O.BD: .ASCII "BE:" ;Unknown breakpoint string O.BDE = .-1 O.BPT: .ASCII /BPTx>/ ;Breakpoint ID string O.BPTE = .-1 O.MID: .ASCII /(x) / ;Mode identifier O.MIDE = .-1 O.TTY: .ASCII / CSR = / ;Terminal CSR string O.TTYE = .-1 O.CR: .BYTE 15,12 ;Debugger prompt .NLCSI TYPE=I,PART=NAME .ASCII />/ O.CRE = .-1 SYMBUF: .BLKB 40. ; : Disassembly buffer .EVEN .SBTTL Word data impure area O.BW: .WORD 0 ; =0 - ALL CLOSED ; =1 - BYTE OPEN, ; =2 - WORD OPEN COEFF: .WORD 50*50 ;Rad50 conversion table .WORD 50 .WORD 1 O.CAD: .WORD 0 ; : Current address O.DOT: .WORD 0 ; : Origin address O.XXX: .WORD 0 ; : Temporary storage O.XXY: .WORD 0 ; ... O.TMP1: .WORD 0 ; ... O.TMP2: .WORD 0 ; ... O.BIAS: .WORD 0 ; : Current relocation bias DCDFLG: .WORD 0 ; : Special decode flag O.TRTC: BPT ; : Breakpoint trap proto O..TKS: .BLKW ; : Address of keyboard status .BLKW ; : Saved keyboard interrupt enable O..TKB: .BLKW ; : Address of keyboard buffer O..TPS: .BLKW ; : Address of printer status .BLKW ; : Saved printer interrupt enable O..TPB: .BLKW ; : Address of printer buffer .SBTTL Byte data impure area O.SCRN: .BYTE 0 ;FLAG; 1=PASS SPACES ON FROM TTY ; ALSO, IF =1, IS ECHOED O.SEQ: .BYTE 0 ;CHANGE SEQUENCE INDICATOR O.S: .BYTE 0 ;SINGLE INSTRUCTION FLAG ; 0 IF NOT ACTIVE ; -1 IF ACTIVE ; NO BREAK BOINTS MAY BE SET WHILE IN ; SINGLE INSTRUCTION MODE O.T: .BYTE 0 ; T-BIT FLAG O.P: .BYTE 0 ;PROCEED FLAG = -2 IF MANUAL ENTRY ; -1 IF NO PROCEED ALLOWED ; 0-7 IF PCEED ALLOWED O.CMFD: .BYTE 0 ;COMMA FOUND SWITCH, =0 NO COMMA FOUND ; =1 COMMA FOUND O.SMFD: .BYTE 0 ;SEMICOLON FOUND SWITCH ; =0 NO SEMICOLON FOUND ; =1 SEMICOLON FOUND O.IRFG: .BYTE 0 ;Internal register access flag O.MINS: .BYTE 0 ;MINUS SIGN TYPED (SWITCH) ; 0=NO MINUS TYPED ; 1=MINUS SIGN TYPED .EVEN O...SZ = <.-OVRBK1>/2 .IIF GT <.-OVRBK1>-20000 .ERROR ;Debugger larger than one PAR .END