	.title	trace	Profile support entry module (with trace) for ast's
	.ident	"V2.0"
;+
;
; Index		Profile support module (with trace) for ast's
;
; Usage
;
;	#include <stdio.h>
;	extern	FILE	*$$flow;
;
;	$$flow = fopen("trace.out", "w");
;
;	/* or $$flow = stderr; to trace to the console	*/
;	...
;	$$flow = NULL;		/* Turn off flow trace	*/
;
; Internal
;
;	jsr	r5,pcsv$
;	.word	name		; Pointer to name
;
;	Where name has the structure:
;
;	name:	.word	0	; Counter
;		.asciz	/name/	; function name
;
; Description
;
;	This module is called whenever a function that was compiled
;	with the profile option is executed.  It checks that the
;	stack will remain above 600 octal when the function executes
;	and optionally prints a flow-trace.  It is a modified version
;	of the pcsv() function in the DECUS C library which saves R0
;	so that C routines may be used as RSX-11 AST service routines.
;
;	For more information on C AST service routines, see the astset()
;	documentation and the AST usage information in the CX library
;	manual.
;
;	If $$flow is set to a file descriptor, the function name,
;	location the function is called from, and the calling environment,
;	are printed on each call to a function compiled with the profile
;	option.
;
;	The output format is:
;
;		function_name<TAB>caller<TAB>environment
;
;	Where function_name is the name of the function being called,
;	caller is the address of the calling program (actually,
;	the return address), and environment is the R5 argument
;	pointer (for local addressing within the routine being called).
;	The information will be written to $$flow with a newline before
;	and after.
;
;	If profiling has been enabled and the program exits via
;	error() or via an operating-system trap (such as an illegal
;	memory reference), a register dump and subroutine trace
;	will be written to stderr.
;
;	See the description of calltrace() for details.
;
; Internal
;
;	See acsv$ for details of the calling environment.
;
;	When this routine is entered for the first time, it sets
;	up to intercept synchronous system traps, and loads the
;	error exit address and profile pointer. The trap service
;	routines are in the "traps" module. See the description there
;	for more information.
;
; Bugs
;
; [end]
;-
;
; Edit history
; V2.0 19-Oct-82 RBD	Re-baseline for new C kit release.
;
	.enabl	gbl,lc
	.psect	C$DATA

$$flow::			; set FILE *$$flow for tracing
	.word	0
format:	.byte	12
	.ascii	"%s"
	.byte	11
	.ascii	"%06o"
	.byte	11
	.ascii	"%06o"
	.byte	12,0

die:	.byte	15,12
	.asciz	/-IO-TRACE-stack below 600 octal at/
onesht:	.byte	1		;set to zero when one-shot done
	.even

	.psect	C$CODE
;
; Set up SST intercept first time through.
;
pcsv$::
	asrb	onesht		;Setup code executed?
	bcc	8$		;Yes, skip setup code
	.mcall	SVTK$S		;One shot deserves $S form.
	SVTK$S	#$$sstt,#10	;Table is in "traps" module
; Set up special profile and exit pointers
	mov	#$$prof,$$pptr	;Profile pointer
	mov	#$$ctra,$$errx	;Error exit
;
; Warning, this code must match the standard C save sequence.
;
8$:
	sub	#10,sp
	mov	r5,(sp)
	mov	sp,r5
	tst	(r5)+
	mov	r2,(r5)+
	mov	r3,(r5)+
	mov	r4,(r5)+
	mov	(sp),r4		;r4 -> profile word
	inc	@(r4)+		;bump profile count
	mov	r1,-(sp)	;save the rest
	mov	r0,-(sp)	;of the registers
;
; Trace the call
;
	mov	$$flow,r1	;Get flow file pointer
	beq	10$		;None, just check stack overflow
	mov 	r5,-(sp)	;frame pointer
	mov	2(r5),-(sp)	;caller
	mov	-(r0),-(sp)	;(sp) -> pcsv buffer
	add	#2,(sp)		;(sp) -> function name
	mov	#format,-(sp)	;format
	mov	r1,-(sp)	;$$flow
	jsr	pc,fprintf	;print it
	add	#<5.*2>,sp	;drop arguments
;
10$:	mov	sp,r0		;new stack pointer
	cmp	(r4),(pc)+	;Is first subroutine instruction
	sub	(pc)+,sp	;get auto memory?
	bne	20$		;no, just check current frame pointer
	sub	2(r4),r0	;yes, do the subtract
	bcs	30$		;Death if it underflowed
20$:	cmp	r0,#600		;Got enough room?
	blo	30$		;br if not
	mov	(sp)+,r0	;restore registers
	mov	(sp)+,r1	;both of them
	jsr	pc,(r4)		;tst -(sp); jmp (r4) -- Ok exit
;
30$:
	mov	#die,-(sp)	;Sorry about that
	jsr	pc,msg		;Inform the user
	mov	-(r4),(sp)	;Function name
	add	#2,(sp)		;onto stack
	jsr	pc,msg		;Print it
	jmp	$$exit		;Can't do more
;
	.end
