-- PcHot.mesa last edit, Bruce July 31, 1980 2:42 PM DIRECTORY Copier USING [Outer], DebugOps USING [ReadCodeWord, ShortREAD], DSyms USING [GFHandle, GFrameMdi], Frames USING [Invalid], Init USING [], Lf USING [GF, PC], MachineDefs USING [BYTE, FHandle, GFHandle, NullGF], Pc USING [BytePC, EVRange, NullPC], PcOps USING [BytePC, CacheBase, CacheCBtiCold, ConvertCbti, EpCold, EpToCBtiCold, FindUserCbti, Item, ItemNull, ParentCbtiCold], PrincOps USING [BytePC, EntryVectorItem, PrefixHeader, SVPointer], State USING [GetGS, GF, GSHandle, LF], Storage USING [Pages], Symbols USING [BTIndex, BTNull, CBTIndex, CBTNull, MDIndex, MDNull], SymbolTable USING [Base, Missing]; PcHot: PROGRAM IMPORTS Copier, DebugOps, DSyms, Frames, Lf, PcOps, State, Storage, SymbolTable EXPORTS Init, Pc, PcOps = BEGIN OPEN PcOps, PrincOps, Symbols; NoBti: ERROR = CODE; BadReason: ERROR = CODE; FHandle: TYPE = MachineDefs.FHandle; GFHandle: TYPE = MachineDefs.GFHandle; EVRange: TYPE = Pc.EVRange; data: State.GSHandle ← State.GetGS[]; cache: PUBLIC CacheBase ← Storage.Pages[1]; Head, Free: PUBLIC Item; Enumerate: PROC [proc: PROC [Item] RETURNS [BOOLEAN], gf: GFHandle] RETURNS [i: Item] = BEGIN next, last: Item; FOR i ← Head, cache[i].link UNTIL i = ItemNull DO IF cache[i].gf = gf AND proc[i] THEN BEGIN IF i = Head THEN RETURN; cache[last].link ← cache[i].link; cache[i].link ← Head; Head ← i; RETURN END; last ← i; ENDLOOP; IF Free # ItemNull THEN RETURN; FOR i ← Head, next UNTIL i = last DO IF (next ← cache[i].link) # last THEN LOOP; cache[i].link ← ItemNull; cache[last].link ← Free; Free ← next; RETURN[ItemNull]; ENDLOOP; END; FindEp: PUBLIC PROC [ep: EVRange, gf: GFHandle] RETURNS [Item] = BEGIN Find: PROC [i: Item] RETURNS [BOOLEAN] = {RETURN[ep = cache[i].ep]}; RETURN[Enumerate[Find, gf]]; END; FindUserCbti: PUBLIC PROC [gf: GFHandle, cbti: CBTIndex] RETURNS [Item] = { Find: PROC [i: Item] RETURNS [BOOLEAN] = { RETURN[gf = cache[i].gf AND cbti = cache[i].userCbti]}; RETURN[Enumerate[Find, gf]]}; FindPC: PROC [pc: BytePC, gf: GFHandle] RETURNS [Item] = BEGIN Find: PROC [i: Item] RETURNS [BOOLEAN] = BEGIN RETURN[ Card[pc] >= Card[cache[i].start] AND Card[pc] <= Card[cache[i].end]] END; RETURN[Enumerate[Find, gf]]; END; FindCbti: PUBLIC PROC [cbti: CBTIndex] RETURNS [i: Item] = BEGIN FOR i ← Head, cache[i].link UNTIL i = ItemNull DO IF cache[i].dCbti = cbti THEN RETURN; ENDLOOP; END; GetPc: PUBLIC PROC [gf: GFHandle, i: EVRange] RETURNS [pc: BytePC] = BEGIN OPEN PrincOps; -- CSegP: TYPE = POINTER TO MachineDefs.CSegPrefix; -- gf, LOOPHOLE[@LOOPHOLE[0,CSegP].entry[i].initialpc]]; InitialPcOffset: CARDINAL = 0; pc ← DebugOps.ReadCodeWord[ gf, SIZE[PrefixHeader]+i*SIZE[EntryVectorItem]+InitialPcOffset]; RETURN[[pc*2]]; END; EvalStackEmpty: PUBLIC PROCEDURE [sp: PrincOps.SVPointer ← NIL] RETURNS [BOOLEAN] = BEGIN SV: TYPE = RECORD [inst,ptr: MachineDefs.BYTE]; sv: SV; IF sp = NIL THEN sp ← data.StatePtr; IF sp = NIL THEN RETURN[TRUE]; sv ← DebugOps.ShortREAD[sp+8]; -- yech RETURN [sv.ptr = 0] END; Son: PUBLIC PROC [cbti: CBTIndex] RETURNS [BOOLEAN] = BEGIN i: Item ← FindCbti[cbti]; IF i = ItemNull THEN ERROR NoBti; RETURN [cache[i].hasSons]; END; Ep: PUBLIC PROC [pc: BytePC, gf: GFHandle] RETURNS [ep: EVRange, start: BytePC] = BEGIN old: Item ← FindPC[pc, gf]; IF old # ItemNull THEN {ep ← cache[old].ep; start ← cache[old].start} ELSE [ep,start] ← PcOps.EpCold[pc,gf]; RETURN; END; EpToCBti: PUBLIC PROC [ ep: EVRange, gf: GFHandle, start: BytePC ← Pc.NullPC] RETURNS [cbti: CBTIndex] = BEGIN old: Item = FindEp[ep, gf]; RETURN[IF old # ItemNull THEN cache[old].dCbti ELSE PcOps.EpToCBtiCold[ep,gf,start]]; END; CacheCBti: PUBLIC PROC [mdi: MDIndex, gf: GFHandle, cbti: CBTIndex] RETURNS [CBTIndex] = BEGIN i: Item = PcOps.FindUserCbti[gf,cbti]; IF i # ItemNull THEN RETURN[cache[i].dCbti]; RETURN[CacheCBtiCold[mdi,gf,cbti]]; END; Fixup: PROC [pc: BytePC, gf: GFHandle] RETURNS [BytePC, GFHandle] = BEGIN IF gf = NIL THEN gf ← State.GF[]; IF pc = Pc.NullPC THEN pc ← GetPc[gf,0]; RETURN[pc,gf]; END; ParentCbti: PUBLIC PROC [pc: BytePC, gf: GFHandle] RETURNS [old: Item, mdi: MDIndex] = BEGIN old ← FindPC[pc,gf]; mdi ← DSyms.GFrameMdi[gf ! SymbolTable.Missing, Frames.Invalid => GOTO noSyms]; IF old = ItemNull THEN old ← PcOps.ParentCbtiCold[pc,gf,mdi]; RETURN; EXITS noSyms => {mdi ← Symbols.MDNull; RETURN}; END; Bti: PUBLIC PROC [pc: BytePC ← Pc.NullPC, gf: GFHandle ← MachineDefs.NullGF] RETURNS [bti: BTIndex] = BEGIN mdi: MDIndex; lpc: BytePC; lgf: GFHandle; i: Item; ClosestBti: PROC [base: SymbolTable.Base] = { bti ← PcOps.ConvertCbti[bti,pc,cache[i].start,base]}; [lpc,lgf] ← Fixup[pc,gf]; [i,mdi] ← ParentCbti[lpc,lgf]; IF mdi = Symbols.MDNull OR i = ItemNull THEN RETURN[BTNull]; IF (bti ← cache[i].userCbti) = BTNull THEN RETURN; IF ~cache[i].hasSons THEN RETURN; Copier.Outer[mdi,ClosestBti]; END; CBti: PUBLIC PROC [ pc: BytePC ← Pc.NullPC, gf: GFHandle ← MachineDefs.NullGF] RETURNS [cbti: CBTIndex] = BEGIN lpc: BytePC; lgf: GFHandle; i: Item; [lpc,lgf] ← Fixup[pc,gf]; IF (i ← ParentCbti[lpc, lgf].old) = ItemNull THEN RETURN[CBTNull]; RETURN[cache[i].dCbti]; END; EntryPC: PUBLIC PROC [ep: EVRange, gf: GFHandle, noSyms: BOOLEAN ← FALSE] RETURNS [pc: BytePC] = BEGIN pc ← GetPc[gf,ep]; END; ExitPC: PUBLIC PROC [cbti: CBTIndex] RETURNS [BytePC] = { i: Item = FindCbti[cbti]; IF i # ItemNull THEN RETURN[cache[i].end] ELSE ERROR SymbolTable.Missing[NIL]}; CbtiItem: PROC [f: FHandle, pc: BytePC] RETURNS [Item, BytePC] = BEGIN SELECT TRUE FROM f = NIL => BEGIN f ← State.LF[]; pc ← Lf.PC[f] END; pc = Pc.NullPC => pc ← Lf.PC[f]; ENDCASE; RETURN[FindCbti[CBti[pc, Lf.GF[f]]], pc]; END; Entry: PUBLIC PROCEDURE [ f: FHandle ← NIL, pc: BytePC ← Pc.NullPC] RETURNS [BOOLEAN] = BEGIN i: Item; [i,pc] ← CbtiItem[f,pc]; IF i = ItemNull THEN ERROR SymbolTable.Missing[NIL]; RETURN[(cache[i].start = pc) OR (cache[i].inner AND Card[cache[i].start]+2 = Card[pc])]; END; Exit: PUBLIC PROCEDURE [ f: FHandle ← NIL, pc: BytePC ← Pc.NullPC] RETURNS [BOOLEAN] = BEGIN i: Item; [i,pc] ← CbtiItem[f,pc]; IF i = ItemNull THEN ERROR SymbolTable.Missing[NIL]; RETURN[cache[i].end = pc]; END; Card: PROC [pc: BytePC] RETURNS [CARDINAL] = INLINE {RETURN[LOOPHOLE[pc]]}; END.