:TITLE[Ustats.0mc, August 11, 1982  3:30 PM, van Melle];

:IF[StatsMode];

onpage[pgFrame3];
FNStat:		* Come here on function call when lspStatsPtr is on
	lspL2 ← T;				* Nargs
	T ← lspIfuBr, loadpage[pgStats];	* fnheader lo
	lspL3 ← T, UseCTask, call[EmitStats1];	* put out stats
	T ← lspNargs, goto[FNStatDone];		* Restore state we entered in

onpage[pgJump];		* Tail of return is on pgJump for ifu refill
ReturnStat:		* Come here when we are about to return to someone
			* returnstat is just like fncall, but Nargs = 77
	T ← lspIfuBr;				* fnheader lo
	lspL3 ← T, loadpage[pgStats];
	T ← AllOnes, call[EmitStats];		* Nargs = all ones
	goto[ReturnStatDone];

onpage[pgLisp0];
SubrStat:		* Come here on subrcall.  Subr# in ac2, Nargs in ac3
	lspIfuBrHi ← Zero;			* Clear fn header hi
	T ← AC2;				* "fn header" lo = punt#
	lspL3 ← T, loadpage[pgStats];
	T ← AC3, call[EmitStats];		* Nargs
	T ← (StatsPointerLocation);
	PStore1[MDS, lspStatsPtr], goto[SubrStatDone];
		* Make stats pointer up to date, since going to bcpl now

onpage[pgJump];
CheckStatOvfl:				* have we overflowed?
	lu ← (lspStatsPtr) - (StatsBufferBoundary), goto[nxiLBL, R<0];
	goto[StatsPunt, alu>=0];
	  goto[nxiLBL];



onpage[pgStats];
EmitStats:		* Come here with T = nargs, L3 = fn addr lo,
			* IfuBrHi = fn addr hi to emit a 4-word function stat

	lspL2 ← T, UseCTask;		* L2 ← Nargs
EmitStats1:
	T ← APCTask&APC;		* return link
	lspL5 ← T;			* save it
	T ← rhmask[lspIfuBrHi];		* hiloc of fnheader
	lspL2← (lsh[lspL2, 10]) or T;	* Nargs in left half
	lspL2← (lspL2) or (140000c);	* Top two bits mean function event
	T ← lspStatsPtr, goto[Emit2, R Even];
	  PStore1[MDS, RZero];		* filler word; even placement
	  T ← lspStatsPtr← (lspStatsPtr) + 1;	* Doubleword align pointer
Emit2:	PStore2[MDS, lspL2];	* Store nargs,,fnheader hi,, Fnheader lo
	call[GetTime];			* Get time in L2,3
	T ← lspStatsPtr ← (lspStatsPtr) + (2c);
	PStore2[MDS, lspL2];		* store time
	APCTask&APC ← lspL5;		* restore link & return
	lspStatsPtr ← (lspStatsPtr) + (2c), return;


:ENDIF;

onpage[pgStats];

* RCLK subroutine.  Returns time left justified in L2, L3

GetTime:
	T ← (R400) + (30c);		* Alto RTC
	PFetch1[MDS, lspL2];		* Fetch high half of clock
	lspL3 ← IP[RTCLow]c;
	T ← (SStkP&NStkp) xor (377c);
	Stkp ← lspL3, lspL3 ← T, NoRegILockOK;
	T ← (Stack) and not (77c);	* fetch most of low clock
	Stkp ← lspL3, lspL3 ← T, NoRegILockOK, return;

*
* If we absolutely place one instruction in Timer.mc, we could
* get the time instead by doing (saving net 5 instructions)
*
*	loadpageExternal[XMiscPage];
*	T ← (R400) + (30c), callExternal[MXRclkLoc];
*


* RCLK -- store 32-bit processor clock @TOS

@RCLK:	loadpage[pgSetBase], opcode[167];
	call[lspSetBase];		* Setup lspGenBr for store
	loadpage[pgStats];
	call[GetTime];			* Get clock in L2,3
	PStore2[lspGenBr, lspL2, 0], goto[nxiLBL];	* Store it


:END[Ustats];