:TITLE[Fvarlookup.0mc, October 23, 1983 4:48 PM, van Melle]; onpage[pgFvar]; RM[FVep, IP[lspDefx1]]; RM[Cnt, IP[lspDefx0]]; RM[NamePtr, IP[lspGenBr]]; RM[NamePtrHi, IP[lspGenBrHi]]; * * Called with name (litatom) to lookup in FVarName * Returns in FVarBinding/Hi a binding pointer * Important that FVarName ne 0 !! * FVarLookupName: T ← (lspEp) - (12c); FVep ← T, UseCtask; * FVep ← current FX T ← APC&APCTask; :IF[FvarStatsMode]; lspStatsPtr, goto[FvStartStat, R>=0]; :ENDIF; FVarReturnAddress ← T; * save return link NewFrame: T ← (FVep) + (1c); PFetch1[lspStkBr, FVep], task; * FVep ← FVep:#Alink FVep ← (FVep) - (12c); T ← FVep ← (FVep) and not (1c); * FVep ← FX base goto[EndOfStack, alu=0]; PFetch1[lspStkBr, Cnt]; * get frame flags,,usecount lu ← (Cnt) and (10000c); * Test F bit lu ← (Cnt) and (1000c), skip[alu=0]; * test V = nametab valid bit goto[NewFrame]; * skip frame if binds no vars T ← (FVep) + (2c), skip[alu=0]; * T ← offset of Fnheader (V=0) T ← (FVep) + (6c); * T ← offset of name table (V=1) PFetch2[lspStkBr, NamePtr]; * get one or the other T ← rhmask[NamePtrHi]; NamePtrHi ← (lsh[NamePtrHi, 10]) or T; * why bother putting it in both halves? T ← Cnt ← 10c; * Offset of names in nametable SearchLoop: PFetch4[NamePtr, xBuf], call[retLBL]; * Fetch next 4 words of nametable T ← FVarName; * Name to compare against * Now compare T against each item in xBuf * DispTable arrangement is for Dispatch * following PVar1, which dispatches to the * odd locations Look0: lu ← (xBuf) xor T, disptable[10]; * [0] Look1: lu ← (xBuf1) xor T, dblgoto[Look2, Found0, alu#0]; * [1] Found0: T ← Cnt, goto[Found]; * [2] Look2: lu ← (xBuf2) xor T, dblgoto[Look3, Found1, alu#0]; * [3] Found1: T ← Cnt ← (Cnt) + (1c), goto[Found]; * [4] Look3: lu ← (xBuf3) xor T, dblgoto[Look4, Found2, alu#0]; * [5] Found2: T ← Cnt ← (Cnt) + (2c), goto[Found]; * [6] Look4: lu ← xBuf3, dblgoto[EndTest, Found3, alu#0]; * [7] Found3: T ← Cnt ← (Cnt) + (3c), goto[Found]; EndTest: T ← Cnt ← (Cnt) + (4c), dblgoto[SearchLoop, NewFrame, alu#0]; * Nametable ends in zeroes Found: PFetch1[NamePtr, lspL4, 6], call[retLBL]; * L4 ← NTSIZE, * avoiding passaround failure T ← (lspL4) + T; * offset of second NT slot PFetch1[NamePtr, lspL4]; * L4 ← flag,,offset T ← rhmask[lspL4]; * offset of var wherever lspL4 ← (lspL4) + T, goto[FoundAsIVar, R>=0]; * word offset FPvar: * L4[0:1] = 10 or 11 T ← (FVep) + (12c); * Find start of Pvars T ← (rhmask[lspL4]) + T; * Look at Nth Pvar PFetch2[lspStkBr, FVarBinding]; * Fetch pvar value or fvar binding lu ← (lspL4) and (40000c); * which are we looking at? goto[FoundAsPVar, alu=0]; lu ← FVarBinding, goto[FoundVal, R Even]; * has been looked up * May want to create chain goto[NewFrame]; FoundAsPVar: * fetched FVarBinding out of a PVAR slot lu ← FVarBinding, goto[FailedAsPVar, R<0]; * unbound if high bit on FVarBinding ← T, goto[LookStackPtr]; * return ptr to this binding FailedAsPVar: * unbound pvar--loop, since there may be a bound one in same frame * Need to get back into the main loop where we left off. Cnt is * offset of this instance of FVarName. We shift Cnt left one and * dispatch to 1 + that value of Cnt; e.g., if Cnt mod 4 = 2, then * go to Look3. T ← (lsh[Cnt, 1]) + 1; lspL4 ← T; Cnt ← (Cnt) and not (3c); * Restore Cnt mod 4 Dispatch[lspL4, 15, 3]; * Always odd T ← FVarName, disp[Look0]; * Note that alu#0, so the first goto works right FoundAsIVar: T ← (FVep) - 1; PFetch1[lspStkBr, FVarBinding]; * Fetch ptr to Ivar start T ← rhmask[lspL4]; * Add in offset FVarBinding ← (FVarBinding) + T; LookStackPtr: T ← FVarBindingHi ← (StackSpaceR); LookPtrHi: FVarBindingHi ← (lsh[FVarBindingHi, 10]) or T, goto[FoundVal]; EndOfStack: * stack exhausted, point at value cell T ← lsh[FVarName, 1], goto[EOSBig, r<0]; * atomnumber * 2 FVarBinding ← T; T ← FVarBindingHi ← (VALspaceR), goto[LookPtrHi]; EOSBig: FVarBinding ← T; * value cell in second segment T ← FVarBindingHi ← (VALspace2R), goto[LookPtrHi]; :IF[FvarStatsMode]; FoundVal: lspStatsPtr, goto[FVExitStat, R>=0]; APC&APCTask ← FVarReturnAddress; :ELSE; FoundVal: APC&APCTask ← FVarReturnAddress; :ENDIF; FVLookupExit: T ← SavedFvarOffset, return; * T for benefit of FVar and FVar← * Eval, op 54 Eval: call[lspTyp], opcode[54]; * get type in LN, pop TOS into L3,2 loadpage[pgEval]; T ← (lspType) - (listType); * is it Listp? onpage[pgEval]; FreezeResult, goto[EvalList, alu=0]; * yes, do evalform skip[alu<0], lu ← (lspType) - (atomType); * is TOS atom or less? lspUFN ← 54c, goto[ufnLBL]; * types greater than listp punt T ← lspL2, skip[alu=0]; * Skip if type atom NextOpCode; * Smallp, fixp, floatp eval to self * TOS is atom. Thus L3=0, L2 = atom# lu ← (lspL2) - (KtVal), skip[alu#0]; NextOpCode; * NIL evals to self skip[alu#0]; NextOpCode; * so does T loadpage[pgFvar]; FVarName ← T, callp[FVarLookupName]; * Returns FVarBinding = binding slot PFetch2[FVarBinding, lspL2, 0]; T ← lspL2; * test L2,3 = NOBIND lu ← (lspL3) - (atomNOBIND), goto[EvalOk, alu#0]; skip[alu#0]; lspUFN ← (54c), goto[ufnLBL]; * punt if var's value is NOBIND * Note this is not right if var is * actually BOUND to NOBIND, but who cares? nop; * allocation constraint EvalOk: Stack&-1 ← T; * = L2, hi half of value T ← lspL3; Stack&+1 ← T, goto[nxiLBL]; EvalList: * Eval a list. Do this by calling a * special fn, rather than normal ufn, thus * saving a frame in the interpreter. * T is conveniently zero from previous lu lspDefx1 ← atomEVALFORM; lspDefx0 ← T, loadpage[pgFrame]; * ← 0 lspNargs ← 1c, gotop[lspCallFn]; * StkScan, op 57: TOS -> binding pointer of TOS StkScan: T ← Stack&-1, opcode[057]; lu ← Stack&-1, goto[StkScanNil, alu=0]; skip[alu=0]; * Is hiloc of TOS zero? lspUFN ← 57c, goto[ufnLBL]; * no, punt loadpage[pgFvar]; FVarName ← T, callp[FVarLookupName]; T ← rsh[FVarBindingHi, 10]; * hiloc of binding ptr Stack&+1 ← T; T ← FVarBinding; StkScanPush: Stack&+1 ← T, goto[nxiLBL]; StkScanNil: Stack&+1 ← (ValSpaceR), goto[StkScanPush]; * Note that T = 0 :END[Fvarlookup];