;---------------------------------------------------------------------------
; m16.profile - by Mike Hibbetts
;
;  created	2/24/89	MRH
;  updated	2/28/89	MRH (silly notational change)
;	3/1/89	KAW changed profiling routines to use jsr/rts instead
;	    	of jsl/rtl when Profile='s'
;	   	added call counts
;	    	added optional suffix to allow multiple copies
;	9/29/89	KAW changed ProfileData to interleave values.
;
;	The following macros aid in profiling code on the Apple IIGS by using
;	tick counts to determine the amount of time that is spent in a routine.
;	The macros will generate code only if the symbol 'Profile' is defined
;	and has a non-zero value.  (You can asmiigs with the '-d Profile'
;	option to create the symbol, or define the symbol in the source.)
;
;	If multiple copies of the profiling code are required (e.g. two modules
;	each with profiling code, to be linked together), an optional suffix
;	argument may be provided to each of the following macros.  The suffix,
;	which must the same in each case, will distinguish between copies of
;	the profiling code
;
;
; Macros:
;
;  ProfileData m[,suffix]
;	- This needs to be placed in the code exactly once.
;	  3*(m+1) long words will be reserved in the code at that
;	  location.  m is the number of indices desired.
;	  The first long for each index is the total tick count,
;	  the second is the number of calls, the third is workspace.
;	  Indices 0Ém are valid.
;
;  ProfileCode [suffix]
;	- This needs to be placed in the code exactly once.
;	  It contains the routines needed by the profiling macros.
;
;  ProfileInit [suffix]
;	- This needs to be executed after the tools have been
;	  loaded and started, but before either of the following
;	  macros is executed.  After this macro is executed, the
;	  information in ProfileData is zero-ed out, but may be
;	  executed as many times as is desired.
;
;  ProfileIn n[,suffix]
;	- These two macros need to come in pairs for meaningful
;	  results. ProfileIn takes the current tick count and puts
;	  it in the workspace for index n.  It also increments
;	  the call count for index n.  [ 0 ˛ n ˛ m ]
;
;  ProfileOut n[,suffix]
;	- ProfileOut subtracts the tick count saved by ProfileIn
;	  from the current tick count, and adds that to the total
;	  accumulated for index n.  ProfileIn and ProfileOut may
;	  be nested with different indices.  [ 0 ˛ n ˛ m ]

;	The routines ProfileIn&suffix and ProfileOut&suffix each have a block
;	of spare space at the end.  This makes a handy location for punching
;	code during debugging.


  IF &Type('Profile') = 'UNDEFINED ' THEN	; A space is really there!
Profile	equ	0
  ENDIF
;-------------------------------------
	MACRO
	ProfileData	&NumSlots,&suffix
	IF Profile THEN

ProfileData&suffix	PROC	EXPORT
	EXPORT	ProfileSize&suffix
	EXPORT	ProfileCount&suffix
	EXPORT	ProfileWS&suffix
ProfileSize&suffix	equ	&NumSlots
	DS.L	1
ProfileCount&suffix
	DS.L	1
ProfileWS&suffix
	DS.L	1

	DS.L	(ProfileSize&suffix*3)
	ENDP

	ENDIF
	MEND
;-------------------------------------
	MACRO
	ProfileCode	&suffix
  IF Profile THEN

ProfileIn&suffix	PROC	EXPORT
	EXPORT	ProfTick1&suffix
	EXPORT	ProfTick2&suffix
	IMPORT	ProfileCount&suffix
	IMPORT	ProfileWS&suffix

ProfTick1&suffix
	lda	>000000	; TickCount
	sta	>ProfileWS&suffix,x
ProfTick2&suffix
	lda	>000000	; TickCount+2
	sta	>ProfileWS&suffix+2,x

	lda	>ProfileCount&suffix,x
	ina
	sta	>ProfileCount&suffix,x
	bne	@1
	lda	>ProfileCount&suffix+2,x
	ina
	sta	>ProfileCount&suffix+2,x
@1
    IF Profile='s' THEN
	rts
    ELSE
	rtl
    ENDIF
	DS.B	256	; space
	ENDP


ProfileOut&suffix PROC	EXPORT
	EXPORT	ProfTick3&suffix
	EXPORT	ProfTick4&suffix
	IMPORT	ProfileData&suffix
	IMPORT	ProfileWS&suffix

ProfTick3&suffix
	lda	>000000	; TickCount
	sec
	sbc	>ProfileWS&suffix,x
	sta	>ProfileWS&suffix,x
ProfTick4&suffix
	lda	>000000	; TickCount+2
	sbc	>ProfileWS&suffix+2,x
	sta	>ProfileWS&suffix+2,x

	lda	>ProfileWS&suffix,x
	clc
	adc	>ProfileData&suffix,x
	sta	>ProfileData&suffix,x
	lda	>ProfileWS&suffix+2,x
	adc	>ProfileData&suffix+2,x
	sta	>ProfileData&suffix+2,x
    IF Profile='s' THEN
	rts
    ELSE
	rtl
    ENDIF
	DS.B	256	; space
	ENDP

  ENDIF
	MEND

;-------------------------------------
	MACRO
	ProfileInit	&suffix
  IF Profile THEN

	IMPORT	ProfileSize&suffix
	IMPORT	ProfileData&suffix
	IMPORT	ProfTick1&suffix
	IMPORT	ProfTick2&suffix
	IMPORT	ProfTick3&suffix
	IMPORT	ProfTick4&suffix

	ldx	#(ProfileSize&suffix*4)*3
	lda	#0

profileInitLoop&suffix
	dex
	dex
	sta	>ProfileData&suffix,x
	bne	profileInitLoop&suffix

	pha
	pha
	pea	5
	_GetAddr
	lda	1,s
	sta	>ProfTick1&suffix+1
	sta	>ProfTick3&suffix+1

	lda	2,s
	sta	>ProfTick1&suffix+2
	sta	>ProfTick3&suffix+2

	lda	1,s
	clc
	adc	#2
	sta	1,s
	sta	>ProfTick2&suffix+1
	sta	>ProfTick4&suffix+1
	bcc	incHighByte&suffix

	lda	3,s
	inc	a
	sta	3,s

incHighByte&suffix
	lda	2,s
	sta	>ProfTick2&suffix+2
	sta	>ProfTick4&suffix+2

	pla
	pla

  ENDIF
	MEND
;-------------------------------------
	MACRO
	ProfileIn	 &Slot,&suffix
  IF Profile THEN

	IMPORT	ProfileIn&suffix

	ldx	#&Slot*4*3
    IF Profile='s' THEN
	jsr	ProfileIn&suffix
    ELSE
	jsl	ProfileIn&suffix
    ENDIF

  ENDIF
	MEND
;-------------------------------------
	MACRO
	ProfileOut &Slot,&suffix
  IF Profile THEN

	IMPORT	ProfileOut&suffix

	ldx	#&Slot*4*3
    IF Profile='s' THEN
	jsr	ProfileOut&suffix
    ELSE
	jsl	ProfileOut&suffix
    ENDIF

  ENDIF
	MEND