-- XCoreMap.Mesa
-- Edited by Levin on October 16, 1978 3:37 PM
DIRECTORY
AltoDefs: FROM "altodefs" USING [PageSize],
BcdDefs: FROM "bcddefs" USING [MTHandle, MTIndex, NameRecord, NameString],
BootDefs: FROM "bootdefs" USING [BusyPage, FreePage, PageMap, SystemTableHandle],
ControlDefs: FROM "controldefs" USING [GFT, GlobalFrameHandle],
DebugData: FROM "debugdata" USING [debugPilot, ESV],
DebugMiscDefs: FROM "debugmiscdefs" USING [CommandNotAllowed, ControlDEL],
DebugUsefulDefs: FROM "debugusefuldefs" USING [AddCommand, AREAD, MREAD, SREAD],
DebugUtilityDefs: FROM "debugutilitydefs" USING [LoadStateInvalid],
GlobalFrameDefs: FROM "globalframedefs" USING [FrameCodeBase, GlobalFrameHandle],
InlineDefs: FROM "inlinedefs" USING [BITAND],
IODefs: FROM "iodefs" USING [CR, NumberFormat, Rubout, SP, WriteChar, WriteLine, WriteNumber,
WriteOctal, WriteString],
LoaderBcdUtilDefs: FROM "loaderbcdutildefs" USING [BcdBase, EnumerateModuleTable, ReleaseBcdSeg,
SetUpBcd],
LoadStateDefs: FROM "loadstatedefs" USING [BcdAddress, BcdSegFromLoadState, ConfigIndex,
EnumerateLoadStateBcds, FileSegmentHandle, InitializeRelocation, InputLoadState,
ReleaseLoadState, ReleaseRelocation, Relocation],
SegmentDefs: FROM "segmentdefs" USING [FileSegmentHandle, PageCount, PageNumber, SegmentHandle],
StreamDefs: FROM "streamdefs" USING [ControlDELtyped],
StringDefs: FROM "stringdefs" USING [AppendSubString, SubStringDescriptor],
SystemDefs: FROM "systemdefs" USING [AllocateHeapNode, AllocateHeapString, AllocateSegment,
FreeHeapNode, FreeHeapString, FreeSegment, PruneHeap],
XMESA: FROM "XMesaPrivateDefs" USING [Bank1X, Bank2X, Bank3X, XMremote, XSegInfo, XSegmentHandle,
XSegmentObject],
XMesaDefs: FROM "XMesaDefs" USING [BankIndex, HighHalfPtr, LowHalfPtr, MaxXPage, PagesPerBank];
DEFINITIONS FROM AltoDefs, SystemDefs, IODefs, SegmentDefs;
XCoreMap: PROGRAM
IMPORTS DDptr: DebugData, DebugMiscDefs, DebugUsefulDefs, DebugUtilityDefs, LoadStateDefs,
IODefs, SystemDefs, StringDefs, StreamDefs, LoaderBcdUtilDefs
SHARES XMESA, SegmentDefs =
BEGIN
byte: NumberFormat = NumberFormat[8,FALSE,TRUE,3];
pageNF: NumberFormat = NumberFormat[8,FALSE,TRUE,4];
word: NumberFormat = NumberFormat[8,FALSE,TRUE,6];
CopyRead: PROCEDURE [from, to: POINTER, nwords: CARDINAL] =
BEGIN
i: CARDINAL;
FOR i IN [0..nwords) DO
(to+i)↑ ← DebugUsefulDefs.SREAD[from+i];
ENDLOOP;
RETURN
END;
PrintPages: PROCEDURE [
page:PageNumber, count:PageCount, state:PageState] =
BEGIN
WriteNumber[page,pageNF]; WriteChar[SP];
WriteLongPointer[LongAddressFromPage[page]];
WriteString[" "L];
WriteNumber[count,pageNF];
WriteLine[SELECT state FROM
free => " free"L,
data => " data"L,
file => " file"L,
busy => " busy"L,
ENDCASE => " ?"L];
RETURN
END;
WriteLongPointer: PROCEDURE [p: LONG POINTER] =
BEGIN
i: CARDINAL = (IF LOOPHOLE[XMesaDefs.LowHalfPtr[p], CARDINAL] > 77777B THEN 1 ELSE 0)
+ 2*XMesaDefs.HighHalfPtr[p];
WriteChar[IF i = 0 THEN ' ELSE '0 + i];
WriteNumber[InlineDefs.BITAND[LOOPHOLE[XMesaDefs.LowHalfPtr[p], WORD], 77777B],[8,i # 0,TRUE,5]];
RETURN
END;
LongAddressFromPage: PROCEDURE [page: PageNumber] RETURNS [LONG POINTER] =
BEGIN
RETURN[LOOPHOLE[LONG[page]*PageSize]]
END;
BaseFromSeg: PROCEDURE [seg: XMESA.XSegmentHandle] RETURNS [p: PageNumber] =
BEGIN
WITH s: seg SELECT FROM
data => RETURN[IF s.VMpage= 0 THEN s.XMpage ELSE s.VMpage];
file =>
WITH xs: s SELECT FROM
disk => RETURN[xs.VMpage];
remote =>
IF xs.proc = XMESA.XMremote THEN
BEGIN
info: XMESA.XSegInfo;
CopyRead[to: @info, from: xs.info, nwords: SIZE[XMESA.XSegInfo]];
RETURN[info.XMpage]
END
ELSE RETURN[xs.VMpage];
ENDCASE;
ENDCASE
END;
PrintSegment: PROCEDURE [seg: XMESA.XSegmentHandle] RETURNS [state: PageState, size: PageCount] =
BEGIN
copiedSeg: XMESA.XSegmentObject;
segBase: PageNumber;
CopyRead[to: @copiedSeg, from: seg, nwords: SIZE[ XMESA.XSegmentObject]];
segBase ← BaseFromSeg[@copiedSeg];
WITH s: copiedSeg SELECT FROM
data => BEGIN PrintPages[segBase, s.pages, data]; RETURN[data, s.pages] END;
file =>
BEGIN
WriteNumber[segBase,pageNF]; WriteChar[SP];
WriteLongPointer[LongAddressFromPage[segBase]]; WriteChar[SP];
WriteNumber[s.base,byte]; WriteChar[SP];
WriteNumber[s.pages,pageNF]; WriteChar[SP];
WriteString["SN"L];
WriteOctal[DebugUsefulDefs.AREAD[@s.file.fp.serial.part2]];
SELECT s.class FROM
code => WriteString[" code"L];
ENDCASE;
IF s.read OR s.write THEN WriteChar[' ];
IF s.read THEN WriteChar['R];
IF s.write THEN WriteChar['W];
WITH xs: s SELECT FROM
remote => IF xs.proc = XMESA.XMremote THEN WriteChar['X] ELSE WriteString[" remote"L];
ENDCASE;
IF s.lock > 0 THEN
BEGIN
WriteString[" lock="L];
WriteOctal[s.lock];
END;
SELECT s.class FROM
code => PrintFileName[LOOPHOLE[seg]];
ENDCASE;
WriteChar[CR];
RETURN[file, s.pages]
END;
ENDCASE
END;
PrintFileName: PROCEDURE [seg: FileSegmentHandle] =
BEGIN
node: POINTER TO NameItem;
found: BOOLEAN ← FALSE;
FOR node ← NameList, node.next UNTIL node = NIL DO
IF node.code = seg THEN
BEGIN
WriteChar[SP];
WriteString[node.module];
found ← TRUE;
END;
ENDLOOP;
RETURN
END;
NameItem: TYPE = RECORD [
next: POINTER TO NameItem,
code: FileSegmentHandle,
module: STRING];
NameList: POINTER TO NameItem ← NIL;
SegmentFromFrame: PROCEDURE [g: ControlDefs.GlobalFrameHandle]
RETURNS [seg: FileSegmentHandle] =
BEGIN
c: GlobalFrameDefs.FrameCodeBase;
CopyRead[from: @LOOPHOLE[g, GlobalFrameDefs.GlobalFrameHandle].code,
to: @c, nwords: SIZE[GlobalFrameDefs.FrameCodeBase]];
seg ← SegmentFromCodePointer[c];
IF seg = BootDefs.FreePage OR seg = BootDefs.BusyPage THEN ERROR;
RETURN
END;
SegmentFromCodePointer: PROCEDURE [c: GlobalFrameDefs.FrameCodeBase]
RETURNS [seg: FileSegmentHandle] =
BEGIN
bank: XMesaDefs.BankIndex;
page: [0..256);
table: BootDefs.SystemTableHandle = DDptr.ESV.tables;
IF c.highByte # 0 THEN RETURN[c.handle];
bank ← c.highHalf;
IF bank ~ IN XMesaDefs.BankIndex THEN ERROR;
page ← LOOPHOLE[c.shortCodebase, CARDINAL]/AltoDefs.PageSize;
IF table # NIL THEN
BEGIN OPEN DebugUsefulDefs;
page0map: POINTER TO BootDefs.PageMap ← SREAD[@table.pagemap];
pagemap: POINTER TO BootDefs.PageMap;
pagemap ←
SELECT bank FROM
1 => SREAD[@page0map[XMESA.Bank1X]],
2 => SREAD[@page0map[XMESA.Bank2X]],
3 => SREAD[@page0map[XMESA.Bank3X]],
ENDCASE => page0map;
IF pagemap = NIL THEN ERROR;
RETURN[SREAD[@pagemap[page]]]
END
ELSE ERROR
END;
FindFrameNames: PROCEDURE =
BEGIN OPEN LoaderBcdUtilDefs, DebugUsefulDefs, LoadStateDefs;
bcd: BcdBase;
proc: PROCEDURE [config: ConfigIndex, bcdAddr: BcdAddress]
RETURNS [BOOLEAN] =
BEGIN
rel: Relocation ← InitializeRelocation[config];
bcdseg: FileSegmentHandle ← BcdSegFromLoadState[config];
code: FileSegmentHandle;
FindNames: PROCEDURE [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [BOOLEAN] =
BEGIN OPEN ControlDefs;
frame: GlobalFrameHandle ← MREAD[@GFT[rel[mth.gfi]].frame];
code ← SegmentFromFrame[frame];
AddName[code, bcd, mth.name];
RETURN[FALSE];
END;
[] ← EnumerateModuleTable[bcd ← SetUpBcd[bcdseg],FindNames];
ReleaseRelocation[rel];
ReleaseBcdSeg[bcdseg];
RETURN[FALSE];
END;
BEGIN
[] ← InputLoadState[ ! DebugUtilityDefs.LoadStateInvalid => GOTO noNames];
[] ← EnumerateLoadStateBcds[recentfirst,proc];
ReleaseLoadState[];
EXITS
noNames => NULL;
END;
END;
AddName: PROCEDURE [code: FileSegmentHandle, bcd: LoaderBcdUtilDefs.BcdBase,
name: BcdDefs.NameRecord] =
BEGIN
ssb: BcdDefs.NameString = LOOPHOLE[bcd+bcd.ssOffset];
ss: StringDefs.SubStringDescriptor ←
[base: @ssb.string, offset: name, length: ssb.size[name]];
s: STRING ← SystemDefs.AllocateHeapString[ssb.size[name]];
node: POINTER TO NameItem ← AllocateHeapNode[SIZE[NameItem]];
StringDefs.AppendSubString[s, @ss];
node↑ ← [next: NameList, code: code, module: s];
NameList ← node;
END;
FreeNames: PROCEDURE =
BEGIN
node: POINTER TO NameItem;
FOR node ← NameList, NameList UNTIL node = NIL DO
NameList ← node.next;
SystemDefs.FreeHeapString[node.module];
SystemDefs.FreeHeapNode[node];
ENDLOOP;
[] ← SystemDefs.PruneHeap[];
END;
PageState: TYPE = {free,data,file,busy};
PageMap: DESCRIPTOR FOR ARRAY OF XMESA.XSegmentHandle ← DESCRIPTOR[NIL,XMesaDefs.MaxXPage+1];
StateFromPage: PROCEDURE [p: PageNumber] RETURNS [XMESA.XSegmentHandle, PageState] =
BEGIN
RETURN[
PageMap[p],
SELECT LOOPHOLE[PageMap[p], SegmentHandle] FROM
BootDefs.FreePage => free,
BootDefs.BusyPage => busy,
ENDCASE => data] -- well it doesn't really matter
END;
CopyPageMap: PROCEDURE [map: POINTER, start: PageNumber] =
BEGIN
i: PageNumber;
IF map = NIL THEN
FOR i IN [0..XMesaDefs.PagesPerBank) DO PageMap[start+i] ← LOOPHOLE[BootDefs.BusyPage] ENDLOOP
ELSE
CopyRead[from: map, to: @PageMap[start], nwords: XMesaDefs.PagesPerBank];
END;
xcoremap: PUBLIC PROCEDURE =
BEGIN
seg: XMESA.XSegmentHandle;
i: XMesaDefs.BankIndex;
segSize: PageCount;
count: PageCount ← 0;
page, hole: PageNumber ← 0;
state, next: PageState ← free;
table: BootDefs.SystemTableHandle = DDptr.ESV.tables;
pagemap: POINTER TO BootDefs.PageMap ← DebugUsefulDefs.SREAD[@table.pagemap];
IF DDptr.debugPilot THEN
BEGIN
IODefs.WriteString["Debugging Pilot--"];
SIGNAL DebugMiscDefs.CommandNotAllowed;
END;
PageMap ← DESCRIPTOR [AllocateSegment[LENGTH[PageMap]], LENGTH[PageMap]];
BEGIN ENABLE UNWIND =>
BEGIN
FreeSegment[BASE[PageMap]];
FreeNames[];
END;
CopyRead[from:@pagemap[0], to: @PageMap[0], nwords: XMesaDefs.PagesPerBank];
FOR i IN [1..LAST[XMesaDefs.BankIndex]] DO
CopyPageMap[DebugUsefulDefs.SREAD[@pagemap[XMESA.Bank1X+i-1]], i*XMesaDefs.PagesPerBank];
ENDLOOP;
FindFrameNames[];
WriteChar[CR]; page ← 0;
UNTIL page >= LENGTH[PageMap] DO
ENABLE Rubout => EXIT;
[seg, next] ← StateFromPage[page];
IF next # state AND count#0 THEN
BEGIN
PrintPages[hole,count,state];
hole ← hole + count; count ← 0;
END;
segSize ← 1;
SELECT next FROM
free => state ← free;
busy => state ← busy;
ENDCASE => [state, segSize] ← PrintSegment[seg];
page ← page + segSize;
SELECT state FROM
data, file => hole ← page;
ENDCASE => count ← count+1;
IF StreamDefs.ControlDELtyped[] THEN SIGNAL DebugMiscDefs.ControlDEL;
REPEAT
FINISHED => IF count#0 THEN
PrintPages[hole,count,state];
ENDLOOP;
END;
FreeSegment[BASE[PageMap]];
FreeNames[];
WriteChar[CR];
RETURN
END;
DebugUsefulDefs.AddCommand["XCoreMap", xcoremap];
END...