: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];