.TITLE DDTKNL .IDENT /820819/;GCE ;UPDATES: ; I/D SPACE SUPPORT ; L$URK TO LET TASK START AT ONCE... INVISIBLE DEBUGGER ; DDTTnn TASK NAME SUPPORT FOR DEBUGGER TASK .IF EQ,1 This program is a tiny kernel for use with DDT22 and DDTMU in RSX or IAS systems. It allows a task to communicate with DDT running in another task using the DDT facility of mapping to other physical machine addresses. This is rather strange, but works in the following way: 1. The user links DDT22 and DDTMU together, assembling DDT22 with MU$DBG defined (and DDTMU that way too) and with at least $VMEM defined and with DDT having access to the I/O page at least via a device common. He then types $G to start the program in DDTMU. At this point, that main program is awaiting a message from the task linked with this program, DDTKNL, giving the start address of this program. 2. The user then fixes the program to be debugged, or otherwise ensures that it CANNOT MOVE in physical memory during the debug. This normally means the shuffler must not be able to move it as well as not checkpointing it and will often require a quiescent system. Now the user runs his program, which has been linked with DDTKNL as a Debug Aid. DDTKNL gains initial control with R0=the task start address. It declares a SVDB$ debug trap to control selected vectors (which must include BPT) and sends a message to the DDT task which MUST BE NAMED DDT22M. It then suspends itself and awaits being resumed by DDT. 3. At this point, DDT gets the message, sets up pointers to the task's addresses and start addresses, and does a BPT there to get back to DDT command mode. Now the user issues commands to get DDT to map to the other task. This involves the UL'tasknam' command under RSX11M (and maybe M+) or setting virtual APRs PAR0 thru PAR7 to point at the task for IAS. The UM command turns on using those APRs. Now DDT is addressing the task target. The user now types commands to enter breakpoints or single stepping. Finally he types a G command to get DDT to go. NOTE: IAS now uses same task map commands as RSX11M and M+. (To try to avoid problems where the task being debugged moves, DDTMU may be assembled with R$XMDB defined in which case it will call the DDT task mapping routine to locate the task at every breakpoint. This is a bandaid and will not work in IAS, but should reduce the liklihood of errors in the debugging since the task may then legally move between breakpoints and still be debugged correctly. If it moves while the user is typing DDT commands before proceeding, the debugging will still work wrongly even so. Caution is needed for use of the tool. DDT can locate tasks at all references, which closes most of this window, but at considerable CPU expense. The use of pure messages closes the window completely; runs slower, but with no worry about what gets shuffled/checkpointed when. This is the preferred mode for IAS. 4. DDT now saves the instructions in any breakpoint locations in the task being addressed and inserts BPTs (as normal), then sends a message to the task of a PC/PS pair to use for start and then resumes the task. DDT itself then goes into an idle loop awaiting receive-data ASTs from the task. 5. The task reads the message from DDT, then restores registers it has saved at any BPT from dedicated core slots, then issues a fake RTT to execute the next instruction (and possibly trap again). It goes on in this way. DDT addresses the register save area directly so the registers, f.p. accumulators, etc., are stored purely locally in dedicated cells. Thus the 13 word intertask messages convey ample information to let DDT debug them. 6. At the next BPT, the task sends a message to DDT giving the PC, PS, and some other info on the trap type, which DDT decodes and gets back to command mode with via the BPT entry. The task suspends itself as before until DDT sends a reply with a new PC/PS pair to use in resumption. This proceeds until debug is complete. This logic is now added to by allowing messages to contain instructions concocted for DDTKNL by DDTMU which execute MOV or MOVB to send or receive task context a word at a time. Where I/D space mapping is enabled, the instructions cannot execute out of the message buffer, so there is a built-in emulator that can execute MOV or MOVB (but nothing else) from the message buffer's instructions. The flag at SNDDAT+26 in DDTMU is set for this. Bit meanings are 1 1 for I space, 0 for D space 2 Instruction sent in buffer if set 4 Instruction is reading task context if set 10 Instruction is setting task context if set. This is done to allow this program, which is small compared to DDT or even ODT, to be linked with programs of nearly 32K and allow them to be symbolically debugged. There is a problem in loading registers (i.e. modifying them in task context) with this logic. This is solved by having DDTMU determine whether the location to be altered is a register and changing the instruction in that case to a MOV to a register; otherwise the location containing the saved register would be written over before it could be read. Where RSX11M+ V2 I/D support is used, only immediate MOVs are supported but the registers are restored after the simulated instruction to avoid the error. Present implementation requires at least 128 words (decimal) if no floating point support exists or at least 196 if it does in DDTKNL. Options for such things as saving target AST enabled state and for finding the current TI: terminal number to allow DDT22M to be installed as ...DDT and the one at the current terminal to be used by DDTKNL add space. The I/D space version is larger too since it cannot just execute instructions in task space ($X fails in I/D space mode too...). Glenn C. Everhart .ENDC .IF DF,MPV2. .IF DF,..MVTS .IF NDF,..MVRL MV.TUI=0 ;MOVE TO USER I MV.TUD=1 ;MOVE TO USER D FROM VALUE ARG MV.TSI=2 ;MOVE TO SUPER I FROM VALUE ARG MV.TSD=3 ;MOVE TO SUPER D MV.FUI=4 ;MOVE FROM USER I SPACE TO BUF (SAME OFSET AS 3RD ARG) MV.FUD=5 ;MOVE FROM USER D SPACE MV.FSI=6 ;MOVE FROM SUPER I MV.FSD=7 ;MOVE FROM SUPER D SPACE ;DUMMY MACRO FOR TESTING, ASSUMES NO I/D SPACE AND ONLY MV.TUI AND MV.FUI .MACRO MVTS$S ACTION,ADDR,VAL,?A,?B CMP ACTION,#MV.TUI BNE A MOV VAL,@ADDR BR B A: CMP ACTION,#MV.FUI BNE B MOV @ADDR,@VAL B: .ENDM .IFF ; DEFINITION OF MVTS$S MACRO .MCALL MVTS$S,MVTS$ .IF EQ,1 .MACRO MVTS$S ACTION,ADDR,VAL .IF B,VAL CLR -(SP) .IFF MOV VAL,-(SP) ;VALUE TO PUT IN OR BUF TO GET DATA .ENDC MOV ADDR,-(SP) ;WHERE IN "SOME" SPACE TO ACCESS MOV ACTION,-(SP) ;SYMBOLIC ACTION MOV (PC)+,-(SP) .BYTE 203.,4 ;DIRECTIVE CODE EMT 377 ;CALL RSX ;DEFINITIONS OF CODES - NOT CORRECT UNLESS BY ACCIDENT MV.TUI=0 ;MOVE TO USER I MV.TUD=1 ;MOVE TO USER D FROM VALUE ARG MV.TSI=2 ;MOVE TO SUPER I FROM VALUE ARG MV.TSD=3 ;MOVE TO SUPER D MV.FUI=4 ;MOVE FROM USER I SPACE TO BUF (SAME OFSET AS 3RD ARG) MV.FUD=5 ;MOVE FROM USER D SPACE MV.FSI=6 ;MOVE FROM SUPER I MV.FSD=7 ;MOVE FROM SUPER D SPACE .ENDM .ENDC ;EQ,1 .ENDC .ENDC ;IF MPV2. IS DEFINED, WE ASSUME DDT IS FOR USE IN I/D SPACE ENABLED ;ENVIRONMENTS AND USE THE MVTS$ action,address,val/buf directive with ;MV.TUI OR MV.FUI TO ACCESS USER MODE I SPACE. IN THIS CASE THE RESUME ;PSW WILL RETURN WITH THE HIGH BYTE SET AS FOLLOWS: ; BIT 1 - I SPACE ACCESS ; BIT 2 - EXECUTE INSTRUCTION OUT OF RCV BUFFER (CAN'T DO) ; BIT 4 - GET DATA FROM ADDRESS IN BUFFER FOR DDT22M ; BIT 10 - PUT DATA IN BUFFER INTO PGM SPACE .MCALL MVTS$S .PSECT .DK.D,RW,D ;DDTKNL DATA AREA MV.D: MV.DAT: .WORD 0 ;DATA FOR MVTS$S CALL ;NOTE WE USE THE DIRECTIVE ONLY FOR I SPACE; DIRECT ACCESS IS OK FOR D SPACE ;SO WE NEED ONLY THE I SPACE ACCESS. THE INSTRUCTION WILL BE MOV OR MOVB ;WHERE VALID. NOTE THIS MAKES DDTKNL CONSIDERABLY LARGER THAN WITH THE NORMAL ;CODE. .ENDC ;If the M$CRDB conditional is defined, DDTKNL will not use the task name ;DDT22M for its debugger task, but will issue a GLUN$ on .ODTL1 to ;locate its TI: and compute the Tnn part of tis task name. It will ;then use the task name DDTTnn so computed, permitting DDT22M to be ;installed as ...DDT and run first from a given terminal .IF DF,M$CRDB .MCALL GLUN$S,ALUN$S .ODTL1:: .WORD 0 ;FILLED IN BY TKB WITH LUN FOR ODT TERMINAL .ENDC .IF DF,L$URK ; IF L$URK IS DEFINED AND D.LURK CONTAINS NONZERO, DDTKNL WILL JUST ; START THE TASK IMMEDIATELY AND NOT SEND ANY PACKETS TO DDT22M (OR ; DDTTNN) UNLESS OR UNTIL IT GETS A TRAP. THIS WILL NOT ALLOW DDT22M TO ; SET UP A NEW BREAKPOINT TABLE (SINCE THE STARTUP PACKET WILL NOT BE ; THERE), BUT WILL ALLOW DDT TO BE USED TO MONITOR A TASK EVEN IF ; THE SYSTEM IS A PRODUCTION (OR NEAR-PRODUCTION) ONE. .IIF NDF,L$$UR,L$$UR=0 D.LURK:: .WORD L$$UR .ENDC .IF DF, X$AST ASTST: .WORD 0 ;$DSW ON AST DISABLE .ENDC ;D.BGNA: .WORD 0 ;D.TNM: .WORD 0,0 .MCALL SVDB$S,SPND$S,RCVD$S,SDAT$ SNDBUF: SDAT$ DDT22M,SNDDAT STTT=SNDBUF+S.DATN ;NOTE INITIAL START CODE IS 16 OCTAL, USED BY DDT22M TO INITIALIZE FOR TASK .IF NDF,D$XIT. ;NORMAL SNDDAT: .WORD 16 ;CODE (SPECIAL START CODE=16) .IFF SNDDAT: .WORD 1 ;SPECIAL CODE TO GET DDT22M TO EXIT .ENDC .WORD 0 ;PC .WORD REGS ;REG SAVE AREA .IIF NDF,$D$FPU, FPSTAT=0 .WORD FPSTAT ;FP REG AREA .WORD 0 ;PSW ;SNDDAT+6 ; .BLKW 9. ;REST RCVBUF:; .BLKW 15. ;RCV DATA AREA .WORD 0,0 ;(TASK NAME HERE FROM DDT22M) SBF: .WORD 0,0 ;PC,PS HERE FROM DDT22M ;RCVBUF+6 BPVL: .WORD 0 ;FLAG FOR BPT FROM DDT22M (NORMALLY 0) LUNBF: .BLKW 10. ;REST. MAY INCLUDE INSTRUCTION IF $X. ;SBF+26 IS FLAG AREA FOR POSSIBLE I/D SPACE ;note the above overlaps the send and receive areas. ; *** N.B. ***** ; REGISTERS MUST APPEAR IN ORDER R0-R7 FOR DDT USE. ; ALSO, FOR CORRECT OPERATION OF $X, IT IS NECESARY THAT REGS ;FOLLOW THE RECEIVE BUFFER IMMEDIATELY, SO RCVBUF MAY BE ;COMPUTED BY DDT. REGS: .WORD 0,0,0,0,0,0,0,0 ;R0-R5, SP, PC .WORD 0 ;PSW .IF NDF,X$DSW DSWSV: .WORD 0 ;$DSW SAVE AREA .ENDC .MCALL RCVD$ RCVX: RCVD$ DDT22M,RCVBUF ;RCV DATA RTTT=RCVX+R.VDTN DTSZZ=. .PRINT DTSZZ ;SIZE OF DDTKNL DATA AREA .PSECT .DKNL.,I .IF DF,$XOK ;THE ONLY ADDITION TO DDTKNL TO SUPPORT INSTRUCTION$X IMMEDIATE INSTRUCTION ;EXECUTION IS BELOW. DDTMU WILL SEND 0 AS THE VALUE OF BPVL NORMALLY ;UNLESS THE INSTRUCTION IS $X TYPE. THIS MEANS THE FOLLOWING ;BPT MAY RESPOND WITH A TYPE 20 RESPONSE WHICH DDTMU WILL INTERPRET ;AS A WAY FOR DDT22M TO PROCEED. NOTE THAT 5 WORDS OF THE RECEIVE ;BUFFER ARE USED (1 FOR THE FLAG, 3 FOR THE INSTRUCTION, AND 1 FOR ;A BPT TO FOLLOW THE INSTRUCTION). A TYPE 20 RESPONSE WILL ;USE THE WORD AFTER THE FLAG TO INDICATE THE SAVED PC VALUE TO ;RE-INSERT IN DDT AT D.SVR7. D.BP: MOV BPVL,-(SP) ;GET CODE, USUALLY 0 EXCEPT FOR $X .IFF D.BP: CLR -(SP) .ENDC BR D.DSPA D.OD: MOV #2,-(SP) BR D.DSPA D.ILL: MOV #4,-(SP) BR D.DSPA ;TRAP CATCHERS ;IF EMT OR TRAP IS TO BE INTERCEPTED, ;UNCOMMENT THE CODE AND COMMENT OUT THE D.EMT=0 ETC LOGIC BELOW. ;THE FORTRAN OTS (AND MANY OTHERS) USE EMT OR TRAP TO COMMUNICATE ;SO IN GENERAL CATCHING THOSE INSTRUCTIONS IS NOT A GOOD IDEA. ;D.EMT: MOV #6,(SP) ;NOTE STACK IS LEFT CODE,PC,PSW ALWAYS ; BR D.DSPA D.EMT=0 ;D.TRP: MOV #10,(SP) ;NOTE KLUDGE DUE TO RSX STACK MUCKUP ; BR D.DSPA D.TRP=0 ;D.IOT: MOV #12,-(SP) ; BR D.DSPA D.IOT=0 D.SEG: CMP (SP)+,(SP)+ ;PASS SAVED STUFF ON STACK MOV #14,(SP) BR D.DSPA ;COMMENT OUT UNCAUGHT TRAPS .PSECT .DK.D,RW,D ;DDTKNL DATA AREA DBTBL: .WORD D.OD,D.SEG,D.BP,D.IOT,D.ILL,D.EMT,D.TRP .PSECT .DKNL.,I DDTKNL:: ; MOV R0,D.BGNA ;SAVE TSK START ADDR ; MOV R1,D.TNM ; MOV R2,D.TNM+2 ;SAVE TSK NAME TOO. MOV R0,SNDDAT+2 ;SEND START PC (USED BY DDT22M) .IIF DF,$$DBG,MOV R0,SNDDAT+12 ;EXTRA COPY OF START PC SVDB$S #DBTBL,#7 .MCALL DIR$ .IF DF,M$CRDB ;LOCATE OUR TERMINAL (IN .ODTL1) AND FIND DEBUGGER'S TASK NAME ALUN$S .ODTL1,#"TI,#0 ;ASSIGN LUN TO TI: GLUN$S .ODTL1,#LUNBF ;GET LUN INFO. USE RCV BUFFER FOR ;LUN BUFFER (SPACE REUSED LATER) MOVB LUNBF+2,R1 ;FILL IN NUMBER IN OCTAL ASCII MOV #LUNBF+1,R0 ;WHERE TO STORE IT CLRB LUNBF+1 ;ZERO OLD STUFF (LEAVE INITIAL T OF TI:) CLR LUNBF+2 ;ONLY NEED COMPUTE THE "TNN" PART OF NAME. DDT IS OK AS IS. CLR R2 ;FORGET LEADING 0S. LEFT JUSTIFY. JSR PC,$CBOMG ;CONVERT NUMBER TO ASCII ;NOW CONVERT TNN FORM TO RAD50 MOV #LUNBF,R0 ;CONVERT CLR R1 ;(NO PERIODS) JSR PC,$CAT5 ;GET RAD50 ;R1 RETURNS AS NAME PART MOV R1,STTT+2 ;FILL IN 2ND HALF OF TASK NAME MOV R1,RTTT+2 ;FOR BOTH SEND AND RECEIVE .ENDC CMP -(SP),-(SP) ;SET STACK AS IF A "TRAP" WAS SEEN MOV SP,REGS+14 ;SAVE SP .IF DF,L$URK TST D.LURK ;SHOULD WE JUST START UP NOW? BEQ 17$ ;IF NOT, BRANCH...NORMAL MOV SNDBUF+2,RCVBUF+4 ;COPY START PC MOV #174000,RCVBUF+6 ;START PSW TOO BR D.RESM ;RECEIVE WILL FAIL AND START AT PC 17$: .ENDC DIR$ #SNDBUF ;EMIT THE DATA .IF NDF,D$XIT. ;NORMAL SPND$S ;SUSPEND OURSELVES .IFF .MCALL EXIT$S ;IF WE ARE JUST TRYING TO GET DDT TO EXIT EXIT$S .ENDC ;JUST EXIT OURSELVES TOO. BR D.RESM D.DSPA: MOV R0,REGS MOV #REGS+2,R0 MOV R1,(R0)+ MOV R2,(R0)+ MOV R3,(R0)+ MOV R4,(R0)+ ;SAVE REGS, SP, PC, PSW MOV R5,(R0)+ MOV (SP)+,SNDDAT ;SAVE CODE IN MSG MOV SP,(R0)+ MOV (SP),(R0)+ MOV (SP),SNDDAT+2 ;SAVE PC VALUE MOV 2(SP),(R0) ;SAVE PSW MOV (R0)+,SNDDAT+10 ;BOTH PLACES .IIF NDF,X$DSW, MOV @#$DSW,@R0 ;SAVE $DSW AT BREAK .IIF DF,$D$FPU, JSR PC,FSAV ;SAVE F.P. REGS .MCALL ENAR$S,DSAR$S .IIF DF,X$AST, DSAR$S ;PREVENT ANY AST'S HERE .IIF DF,X$AST, MOV @#$DSW,ASTST ;SAVE DSW ERRS FOR IN CASE ASTS WERE OFF DIR$ #SNDBUF ;TELL DDT ABOUT OUR TRAP SPND$S ;SUSPEND OURSELVES. ;ON RESUMPTION FROM DDT READ ITS CMD D.RESM: DIR$ #RCVX ;GET DATA FROM DDT .IF NDF,X.SYNC .MCALL WSIG$S TSTB @#$DSW ;ANY ERROR ON RECEIVE? BPL 475$ ;IF NOT, PROCEED WSIG$S BR D.RESM ;ELSE WAIT, THEN RETRY 475$: .ENDC ;NORMALLY NOT DEFINED SO CODE INCLUDED NORMALLY .IF DF,X$AST CMPB ASTST,#IE.ITS ;WERE ASTS OFF BEFORE? BEQ 75$ ;IF SO DONT ENABLE ENAR$S 75$: ;REF LABEL .ENDC ; RCVD$S ,#RCVBUF ;BUFFER GETS PC, PS TO USE .IIF DF,$D$FPU, JSR PC,FRST ;RESTORE FPU REGS IF THERE MOV #REGS+2,R0 ;GET BACK REGS MOV (R0)+,R1 MOV (R0)+,R2 MOV (R0)+,R3 MOV (R0)+,R4 MOV (R0)+,R5 MOV (R0)+,SP .IIF NDF,X$DSW, MOV DSWSV,@#$DSW ;RESTORE DSW FROM BREAK MOV REGS,R0 ;RESTORES REGS & STACK CMP (SP)+,(SP)+ ;POP OLD PS/PC PAIR FROM SST MOV RCVBUF+4+2,-(SP) ;PUSH PSW TO USE .IF DF,MPV2. ;Instruction emulator. This section executes any MOV or MOVB instructions ;sent in the receive buffer on behalf of DDT22M. This should ONLY be done ;to support I/D space code in RSX11M+ V2 and later (if there is a later for ;RSX11M+). BITB #2,SBF+26 ;TEST FOR INSTRUCTION .IF EQ,1 BNE 338$ ; IF FOUND ONE USE IT BITB #2,(SP) ;ANY INSTRUCTION HERE? BEQ 38$ ;IF EQ NO, JUST RETURN NORMALLY 338$: .IFF ;ALWAYS 1 NE 0 BEQ 38$ ; SKIP NON INSTRUCTIONS .ENDC ;EQ 1 ;INSTRUCTION IS IN BUFFER. CAN'T EXECUTE IT THERE SO EMULATE IT. THEN DO A ;BPT TO GO ON. MOV R0,(SP) ;SAVE A REGISTER ON NOW-SPACE STACK CELL ;(DON'T NEED PSW HERE...) MOV RCVBUF+4,R0 ;INSTRUCTION BITB #4,SBF+26 ;SEE IF THIS IS TO GET DATA FROM SOMEWHERE BEQ 36$ ;IF EQ NO ;GET DATA (READ DATA) BITB #1,SBF+26 ;I SPACE ACCESS? BNE 40$ ;IF NE YES, USE DIRECTIVE ;D SPACE ACCESS TO READ DATA ;D SPACE ACCESS TO WRITE DATA 42$: BIT #100000,@R0 ;IS IT A MOVB? BNE 51$ ;IF NE YES MOV @2(R0),@4(R0) ;DO THE MOV BR 37$ 51$: MOVB @2(R0),@4(R0) ;DO THE MOVB BR 37$ ;DONE GRABBING USER D SPACE DATA NOW ;I SPACE ACCESS TO READ CODE 40$: MOV R1,-(SP) MOV 2(R0),R1 BIC #1,R1 ;ENWORD THE ADDRESS ;R1 = ADDRESS IN I SPACE TO GRAB. FILLS IN MV.D LOCATION... MVTS$S #MV.FUI,R1,#MV.D ;GET THE DATA TO D SPACE MOV 2(R0),R1 ;NOW GET IN ADDRESS AGAIN BIC #^C1,R1 ;GET BYTE NO BIS #MV.D,R1 ;GET DATA ADDRESS NOW MOV R1,2(R0) ;FILL IN ADDRESS AS WE NEED MOV (SP)+,R1 ;RESTORE R1 NOW BR 42$ ;GO PARASITE MOV/MOVB TEST CODE FOR SPACE 36$: BITB #10,SBF+26 ;IS THIS TO PUT DATA SOMEWHERE? BEQ 37$ ;IF EQ NO ;PUT DATA ; NOTE: MUST READ FIRST SINCE WE MAY HAVE TO WRITE A BYTE ONLY BITB #1,SBF+26 ;THIS AN I SPACE ACCESS? BEQ 42$ ;IF EQ NO, JUST DO MOVE OR MOVB ;PUT INSTRUCTION DATA ;MUST BE ABLE TO DO BYTE ACCESS TOO, SO READ OLD DATA FIRST 60$: MOV R1,-(SP) MOV 4(R0),R1 ;GET ADDRESS BIC #1,R1 ;MAKE IT VALID WORD ADDRESS MVTS$S #MV.FUI,R1,#MV.D ;GET DATA TO MV.D MOV 4(R0),R1 ;GET DEST ADDRESS AGAIN BIC #^C1,R1 ;MAKE BYTE OFFSET BIS #MV.D,R1 ;POINT AT CORRECT BYTE OF DEST ;R1 NOW POINTS AT ONE BYTE OF MV.D BIT #100000,@R0 ;IS THE INSTRUCTION A MOVB? BEQ 62$ MOVB @2(R0),@R1 ;FILL IN MV.D BYTE BR 63$ 62$: MOV @2(R0),@R1 ;FILL IN MV.D WORD 63$: MOV 4(R0),R1 ;GET ADDRESS AGAIN TO STORE DATA BIC #1,R1 ;AND MAKE A WORD AGAIN ;CORRECT SINCE MVTS$ PASSES VALUE ON MOVE TO ;CORRECTION BY CHANGING #MV.D TO MV.D MVTS$S #MV.TUI,R1,MV.D ;SHOVE MV.D TO USER I SPACE MOV (SP)+,R1 ;RESTORE R1 ;COMMON EXIT 37$: MOV (SP)+,R0 ;REPLACE R0 NOW .IF NDF,XR$EG$ ;PERFORM ANOTHER RESTORE OF REGISTERS TO ENSURE THAT ANY INSTRUCTIONS ;THAT MODIFY REGISTERS HAVE THE DESIRED EFFECT. MOV #REGS+2,R0 ;GET BACK REGS MOV (R0)+,R1 MOV (R0)+,R2 MOV (R0)+,R3 MOV (R0)+,R4 MOV (R0)+,R5 MOV REGS,R0 ;RESTORE SAVED REGISTERS TOO .ENDC BPT ;NOW TRAP BACK ;NOTICE WE DON'T EXECUTE INSTRUCTION GENERALLY IF IN DATA BUFFER ;WHERE I/D SPACE IS ENABLED, SINCE THEY ARE LIKELY TO BE DISTINCT. 38$: .ENDC ;NOTE: WE CANNOT HANDLE MODS TO REGISTERS HERE VERY WELL. MUST DO ;SO IN DDTMU BY SENDING MOVS TO REGS, NOT TO LOCATIONS. IN THE ;M+ I/D CASE ONLY WE CAN RESTORE REGS FOR DESIRED EFFECT OF MODS ;TO A REG FROM THE OTHER TASK. HOWEVER, IN THAT CASE THE ; MOV #NNN,RM$X COMMAND WILL FAIL, SO THIS IS FAIR... MOV RCVBUF+4,-(SP) ;PUSH PC TO USE RTT ;EXIT THIS TRAP .IF DF,$D$FPU ;F.P.U. SAVE/RESTORE ROUTINES ;LEAVE REGS ALONE IN ALL CASES. AC0=%0 AC1=%1 AC2=%2 AC3=%3 AC4=%4 AC5=%5 ;DEFINE FLOATING REGS ;FPCTL: .WORD $D$FPU ;CONTROL. SAVE/RESTORE FP REGS IF NONZERO .PSECT .DK.D,RW,D ;DDTKNL DATA AREA FPSTAT: .WORD 40000 ;FPU STATUS. SET INITIAL INTERRUPT DISABLE. FPAC0: .WORD 0,0,0,0 FPAC1: .WORD 0,0,0,0 FPAC2: .WORD 0,0,0,0 FPAC3: .WORD 0,0,0,0 FPAC4: .WORD 0,0,0,0 FPAC5: .WORD 0,0,0,0 ;FP AC STORAGE .PSECT .DKNL.,I FSAV: STFPS FPSTAT ;SAVE FP STATUS LDFPS #40200 ;SET DBL PREC SHORT INT NO INTS ;R0 IS FREE AT THESE CALLS... NO NEED TO ALTER IT. ; MOV R0,-(SP) ;PRESERVE R0 MOV #FPAC0,R0 ;SET UP SAVE STF AC0,(R0)+ STF AC1,(R0)+ STF AC2,(R0)+ STF AC3,(R0)+ ;SAVE EASY AC'S LDF AC4,AC0 ;GET AC4 TO AC0 STF AC0,(R0)+ LDF AC5,AC0 ;COPY AC5 TO AC0 STF AC0,(R0)+ LDF FPAC0,AC0 ;RESTORE AC0 TO OLD VALUE ; MOV (SP)+,R0 ;RESTORE R0 FROM CALL RTS PC ;THEN BACK ;RESTORE F.P. HARDWARE TO VALUE AT FSAV CALL ;NOTE R0 FREE HERE AND F.P. STATUS SHOULD STILL BE AS LEFT BY FSAV. FRST:; LDFPS #40200 ;SET STATUS TO DBL PREC NO INTERRUPTS ; MOV R0,-(SP) ;NEED A GEN'L REG MOV #FPAC1,R0 LDF (R0)+,AC1 LDF (R0)+,AC2 LDF (R0)+,AC3 LDF (R0)+,AC0 ;GET AC4 DATA STF AC0,AC4 ;AND PUT THERE LDF (R0)+,AC0 ;GET AC5 DATA STF AC0,AC5 ;AND PUT THERE LDF FPAC0,AC0 ;RESTORE AC0 TO OLD VALUE LDFPS FPSTAT ; MOV (SP)+,R0 ;GET BACK CALL R0 RTS PC .ENDC DDIII=. .PRINT DDIII ;SIZE OF DDTKNL INSTRUCTION AREA .END DDTKNL