-- 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.