.TITLE TRACK - F4P INSTRUCTION TRACKER .SBTTL TRACK - TITLE PAGE .IDENT /V00.01/ ; ; This module counts each instruction executed and stores the results ; by the name of the current Fortran subroutine. It also counts the ; number of times each subroutine is called. ; ; Macro Library Calls: ; .MCALL SVDB$S ; ; Global Declarations: ; .GLOBL TRKBEG ;Start subroutine tracking .GLOBL TRKEND ;End subroutine tracking ; ; Global References: ; .GLOBL $OTSV ;Fortran work area pointer .SBTTL TRACK - LOCAL DATA ; ; Local Symbols: ; TR.BEG = 1 ;Start of subroutine TR.END = 2 ;End of subroutine ; EM.ENA = 1 ;Enable tracking EM.DIS = 2 ;Disable tracking ; C.NAME = 0 ;Subroutine name C.CALL = 4 ;Number times called C.INSX = 10 ;Number instructions C.SIZE = 14 ;Size of cell ; ; Local Data: ; TRKSST:: ;Ref. label .WORD 0 ;Odd address .WORD 0 ;Memory protect .WORD TRKCNT ;T-bit trap .WORD 0 ;IOT instruction .WORD 0 ;Reserved instruction .WORD TRKCTL ;Non-RSX EMT TRKSIZ = <.-TRKSST>/2 ; FLAG: .WORD 0 ;Tracking mask NAME: .WORD 0 ;Current subroutine name .WORD 0 ; second part of name COUNT: .WORD 0 ;Instruction counts .WORD 0 ; second part of counts CELSIZ: .WORD 0 ;Number of counter cells CELBUF: .WORD 0 ;Address of counter buffer OVRBUF: .WORD 0 ;Address of overflow buffer .SBTTL TRKCNT * COUNT INSTRUCTIONS ; ;+ ; This subroutine counts an instruction. It also checks the FLAG mask ; word and performs start and stop of subroutine operations. ; ; INPUT: ; ; Called by T-bit SST. Called with stack as follows: ; ; (SP)+00 = PC OF TRAP ; (SP)+02 = PS OF TRAP ; ; OUTPUT: ; ; Instruction counted and RTT executed. If start of subroutine, ; initialize counters and name. If end of subroutine, store ; values and reset for next routine. ; ; ; REGISTERS: USES R0,R1 SAVES R0-R5 ; ;- ; TRKCNT: ;Ref. label TST FLAG ;Is a trace control instruction? BNE 1000$ ; If NE - yes, process ; ; Count instruction and return. ; ADD #1,COUNT+0 ;Count instruction ADC COUNT+2 ; Count overflow RTT ;Return to caller ; ; Process subroutine control. Save working registers. ; 1000$: MOV R0,-(SP) ;Save R0 MOV R1,-(SP) ;Save R1 CMP #TR.BEG,FLAG ;Is this start of trace? BNE 2000$ ; If NE - no, skip ; ; Process start of subroutine. Add counts to previous subroutine ; and count call of new subroutine. At this point, stack is assumed ; to have the following: ; ; (SP)+00 = Saved R0 ; (SP)+02 = Saved R1 ; (SP)+04 = PC of trap ; (SP)+06 = PS of trap ; (SP)+10 = First part of routine name (RAD50) ; (SP)+12 = Second part of routine name (RAD50) ; ; NAME is assumed to have calling subroutine name. ; CALL TRKFND ;Find current name cell SUB #3,COUNT+0 ;Correct count for NAM$ call SBC COUNT+2 ; In double precesion ADD COUNT+0,(R0)+ ;Add current instruction counts ADC (R0) ; in double precesion ADD COUNT+2,(R0)+ ; add high part of counts MOV 10(SP),NAME+0 ;Store new name MOV 12(SP),NAME+2 ; store high part MOV #3,COUNT+0 ;Count NAM$ call CLR COUNT+2 ; in double precesion CALL TRKFND ;Find current name cell INC -4(R0) ;Count subroutine call ADC -2(R0) ; in double precesion BR 3000$ ;And exit control ; ; Check for end of a subroutine. ; 2000$: CMP #TR.END,FLAG ;IS THIS END OF TRACE? BNE 3000$ ; IF NE - NO, SKIP ; ; Process end of subroutine. Add counts to current subroutine and ; reset name of previous subroutine. At this point, stack is assumed ; to have the following: ; ; (SP)+00 = Saved R0 ; (SP)+02 = Saved R1 ; (SP)+04 = PC of trap ; (SP)+06 = PS of trap ; ; NAME is assumed to have calling subroutine name. ; ; R4 = OTS pointer. second word is address of next traceback ; cell. Use this to reset NAME. ; CALL TRKFND ;Find current name cell ADD #1,COUNT+0 ;Count return from NAM$ ADC COUNT+2 ; in double precision ADD COUNT+0,(R0)+ ;Add current instruction counts ADC (R0) ; in double precesion ADD COUNT+2,(R0)+ ; add high part of counts MOV 2(R4),R0 ;Get previous name traceback MOV 4(R0),NAME+0 ;Store previous name MOV 6(R0),NAME+2 ; store high part MOV #-1,COUNT+0 ;Reset counter (for return from NAM$) MOV #-1,COUNT+2 ; in double precision ; ; Exit trace control. Restore registers, zero flag, and zero counter. ; 3000$: MOV (SP)+,R0 ;Restore R0 MOV (SP)+,R1 ;Restore R1 CLR FLAG ;Clear traceback flag RTT ;Return to caller .SBTTL TRKFND * FIND TRACKING CELL ; ;+ ; This subroutine finds a tracking cell. It searches the cell ; buffer for the current value stored in 'NAME'. If found, R0 ; is returned as the cell. If not found and an empty cell is ; available, 'NAME' is stored and the cell returned. Otherwise, ; a pointer is returned to the overflow area. ; ; INPUT: ; ; NAME = RAD50 name of subroutine to find ; ; CELSIZ = Number of cells ; CELBUF = Address of cell buffer ; OVRBUF = Address of overflow buffer ; ; OUTPUT: ; ; R0 = Cell to use (indexed to instruction counts). ; ; ; REGISTERS: USES R0,R1 SAVES R2-R5 ; ;- ; TRKFND: ;Ref. label MOV CELSIZ,R1 ;Get number of cells MOV CELBUF,R0 ;Get address of cell buffer 1000$: CMP NAME+0,(R0) ;Is this a match BNE 2000$ ; If NE - no CMP NAME+2,2(R0) ;Is this a match BEQ 3100$ ; If EQ - yes, continue 2000$: TST (R0) ;Is cell free? BNE 2100$ ; If NE - no TST 2(R0) ;Is cell free? BEQ 3000$ ; If NE - no 2100$: ADD #C.SIZE,R0 ;Advance to next cell SOB R1,1000$ ; and loop to next ; ; Not found and no free cell, count as overflow. ; MOV OVRBUF,R0 ;Get address of overflow ; ; Get found cell, set subroutine name and return. ; 3000$: MOV NAME+0,(R0) ;Store subroutine name MOV NAME+2,2(R0) ; store high part 3100$: ADD #10,R0 ;Skip instruction counters RETURN ;Return to caller .SBTTL TRKBEG * ENABLE TRACKING ; ;+ ; This subroutine enables instruction tracking. ; ; INPUT: ; ; Call from Fortran statement as follows: ; ; CALL TRKBEG (A,B,C) ; ; A = Number of cells ; B = Address of cell array (one cell is 6 words) ; C = Address of overflow array (6 words) ; ; OUTPUT: ; ; Cell size and counter array address are stored and array's ; are initialized. Note, if predefined subroutine names are ; wanted, initialize the first two words of each cell to the ; RAD50 subroutine name. Otherwise, leave as zero. ; ; ; REGISTERS: USES R0,R1,R5 SAVES R2-R4 ; ;- ; TRKBEG:: ;Ref. label TST (R5)+ ;Skip number of arguments MOV @(R5)+,CELSIZ ;Store number of cells MOV (R5)+,CELBUF ;Store address of cell array MOV (R5)+,OVRBUF ;Store address of overflow array MOV @#$OTSV,R0 ;Get OTS pointer MOV 2(R0),R0 ;Get name block pointer MOV 4(R0),NAME+0 ;Store program name MOV 6(R0),NAME+2 ; store second part CLR FLAG ;Clear flag SVDB$S #TRKSST,#TRKSIZ ;Declare SST table ; ; Issue EMT 1 to start tracing. ; EMT EM.ENA ;Enable tracing RETURN ;Return to caller .SBTTL TRKEND * DISABLE TRACKING ; ;+ ; This subroutine disables instruction tracking. ; ; INPUT: ; ; Call from Fortran statement as follows: ; ; CALL TRKEND ; ; OUTPUT: ; ; Instruction tracing is disabled. Current count are updated. ; ; ; REGISTERS: USES R0,R1,R5 SAVES R2-R4 ; ;- ; TRKEND:: ;Ref. label ; ; Get current totals stored away (T-bit trap will occur). ; MOV #TR.END,FLAG ;Store current counts ; ; Issue EMT 2 to disable tracing and disable SST's. ; EMT EM.DIS ;Disable tracing SVDB$S #0,#0 ;Disable SST'S RETURN ;Return to caller .SBTTL TRKCTL * CONTROL TRACING ; ;+ ; This subroutine enables or disable tracing. It is called by an ; EMT 1 or 2 and manipulates the T-bit of the PSW. ; ; INPUT: ; ; Called by NON-RSX SST. Called with stack as follows: ; ; (SP)+00 = EMT op-code (times 2) ; (SP)+02 = PC of trap ; (SP)+04 = PS of trap ; ; OUTPUT: ; ; T-bit in PSW set or cleared according to EMT 1 or 2. ; ; ; REGISTERS: USES R0 SAVES R1-R5 ; ;- ; TRKCTL: ;Ref. label MOV (SP)+,R0 ;Get operand code CMP #EM.ENA*2,R0 ;Is this enable tracing? BNE 1000$ ; If NE - no BIS #020,2(SP) ;Set T-bit RTT ; And return 1000$: CMP #EM.DIS*2,R0 ;Is this disable tracing? BNE 2000$ ; If NE - no BIC #020,2(SP) ;Clear T-bit RTT ; and return 2000$: HALT ;Not expected, halt. .SBTTL NAM$ - TRACEBACK NAME ROUTINE ;+ ; This routine is a version of DIGITAL'S NAM$ routine. It performs ; the same function but also flags the start and end of routines. ; ; INPUT: ; ; (SP)+00 = First part of name (RAD50) ; (SP)+02 = Second part of name (RAD50) ; ; R4 = Return address. ; ; OUTPUT: ; ; Name trace block setup. On final return, previous ; chain setup. ;- NAM$:: ;Ref. label MOV #TR.BEG,FLAG ;Flag start of subroutine MOV @#$OTSV,R3 ;Get OTS pointer MOV (R3)+,-(SP) ;Old sequence number MOV @R3,-(SP) ;Old name pointer MOV SP,@R3 ;New name pointer CLR -(R3) ;Init sequence number CALL @R4 ;Call caller back ; ; R0-R3 are untouched for return since they may contain function value. ; MOV @#$OTSV,R4 ;Get OTS pointer MOV (SP)+,2(R4) ;W.NAMC MOV (SP)+,@R4 ;W.SEQC CMP (SP)+,(SP)+ ;Clean stack MOV #TR.END,FLAG ;Flag end of subroutine RETURN ;Take final return .END