:TITLE[Ustats.0mc, October 23, 1983 4:48 PM, van Melle]; :IF[StatsMode]; mc[FVStartStatEventR, 375]; mc[FVExitStatEvent, lshift[376,10]]; onpage[pgFrame3]; FNStat: * Come here on function call when lspStatsPtr is on lspL2 ← T, loadpage[pgStats]; * Nargs lspL2 ← (lspL2) or (300c), call[EmitFnStats]; 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 loadpage[pgStats]; lspL2 ← (377c), call[EmitFnStats]; * Nargs = all ones goto[ReturnStatDone]; onpage[pgLisp0]; SubrStat: * Come here on subrcall. Subr# in ac2, Nargs in ac3 T ← (AC3) or (300c); * Nargs lspL2 ← T, loadpage[pgStats]; lspL2 ← lsh[lspL2, 10], call[SubrStat1]; 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]; :IF[FvarStatsMode]; onpage[pgFVar]; FvStartStat: FVarReturnAddress ← T, loadpage[pgStats]; * save return link lspL2 ← (FVStartStatEventR), call[EmitFnStats]; goto[NewFrame]; FVExitStat: T ← rsh[FVarBindingHi, 10]; * Hiloc of binding pointer lspL2 ← T; T ← FVarName, loadpage[pgStats]; * Name we looked up lspL2 ← (lspL2) or (FVExitStatEvent), call[EmitStatsCommon]; APC&APCTask ← FVarReturnAddress, goto[FVLookupExit]; :ENDIF; onpage[pgStats]; SubrStat1: T ← AC2, goto[EmitStatsCommon]; * "fn header" lo = punt# EmitFnStats: * Come here with L2 = desired hi byte. rh[L2] and L3 * will be filled from IfuBr/Hi to produce a 4-word stat T ← rhmask[lspIfuBrHi]; * hiloc of fnheader lspL2 ← (lsh[lspL2, 10]) or T; * Nargs in left half T ← lspIfuBr; * fnheader lo EmitStatsCommon: lspL3 ← T, UseCTask; T ← APCTask&APC; * return link lspL5 ← T; * save it 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];