file: CSegDebugContents.mesa
Last Edited by: Sweet, July 31, 1984 3:11:28 pm PDT
DIRECTORY
Ascii,
Basics,
Convert,
CSegDebugDefs,
ListerUtils,
PrincOps,
RESOut,
Rope,
ViewerTools;
CSegDebugContents: CEDAR PROGRAM
IMPORTS
Basics, Convert, CSegDebugDefs, ListerUtils, RESOut, Rope, ViewerTools
EXPORTS CSegDebugDefs =
BEGIN OPEN RESOut, CSegDebugDefs;
BYTE: TYPE = CSegDebugDefs.BYTE;
ROPE: TYPE = Rope.ROPE;
GFH: TYPE = PrincOps.GlobalFrameHandle;
RopeForEsc: PUBLIC PROC [alpha: BYTE] RETURNS [r: ROPE] = {};
RopeForSdName: PUBLIC PROC [op: BYTE] RETURNS [r: ROPE] = {};
ShortREAD: PROC [addr: POINTER] RETURNS [UNSPECIFIED] = TRUSTED {
RETURN [addr^]};
ReadCodeWord: PROC [gf: GFH, delta: INTEGER] RETURNS [UNSPECIFIED] = TRUSTED {
code: PrincOps.FrameCodeBase ← gf.code;
code.out ← FALSE;
RETURN[(LOOPHOLE[code, LONG POINTER TO UNSPECIFIED]+delta)^]};
EscName: PROC [handle: Handle, alpha: BYTE] = {
esc: ROPE = RopeForEsc[alpha];
eLength: CARDINAL = Rope.Length[esc];
IF eLength < 8 THEN THROUGH [eLength..8) DO PChar[handle, Ascii.SP] ENDLOOP
ELSE PChar[handle, Ascii.SP];
PRope[handle, esc]};
SdName: PROC [handle: Handle, op: BYTE] = {
s: ROPE = RopeForSdName[op];
sLength: CARDINAL = Rope.Length[s];
IF sLength < 8 THEN THROUGH [sLength..8) DO PChar[handle, Ascii.SP] ENDLOOP
ELSE PChar[handle, Ascii.SP];
PRope[handle, s]};
GetByte: PROC [handle: Handle, gf: GFH] RETURNS [b: BYTE] =
BEGIN
w: RECORD [high, low: BYTE] = GetWord[handle, handle.offset, gf];
b ← IF handle.byte = 0 THEN w.high ELSE w.low;
handle.byte ← 1 - handle.byte;
IF handle.byte = 0 THEN handle.offset ← handle.offset + 1;
END;
GetWord: PROC [handle: Handle, delta: INTEGER, gf: GFH] RETURNS [UNSPECIFIED] =
BEGIN
RETURN [ReadCodeWord[gf, delta]];
END;
PutAsCode: PUBLIC PROCEDURE [handle: Handle] =
BEGIN
nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal];
handle.shortfall ← PutCodeBytes[handle, nBytes];
handle.bytesShown ← nBytes - handle.shortfall;
END;
PutAsOctal: PUBLIC PROCEDURE [handle: Handle] =
BEGIN
nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal];
bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal];
handle.offset ← bytePC/2;
handle.byte ← bytePC MOD 2;
IF handle.byte # 0 THEN handle.offset ← handle.offset + 1;
PutOctalWords[handle, nBytes];
handle.bytesShown ← 2*nBytes + handle.byte;
END;
PutAsAscii: PUBLIC PROCEDURE [handle: Handle] =
BEGIN
nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal];
bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal];
handle.offset ← bytePC/2;
handle.byte ← bytePC MOD 2;
PutAsciiText[handle, nBytes];
handle.bytesShown ← nBytes;
END;
PutAsBytes: PUBLIC PROCEDURE [handle: Handle] =
BEGIN
nBytes: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.nVal];
bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal];
handle.offset ← bytePC/2;
handle.byte ← bytePC MOD 2;
PutOctalBytes[handle, nBytes];
handle.bytesShown ← nBytes;
END;
DisplayPrefix: PUBLIC PROC [handle: Handle] =
BEGIN
csp: REF PrincOps.CSegPrefix;
gfo: REF PrincOps.GlobalFrame;
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
PCr[handle];
gfo ← ReadGFrame[handle, gf];
PRope[handle, "Frame - gfi: "];
POctal[handle, gfo.gfi];
PrintCodeBase[handle, gfo.code];
IF gfo.codelinks THEN PNext[handle, "codelinks"];
IF gfo.started THEN PNext[handle, "started"];
IF gfo.copied THEN PNext[handle, "copied"];
IF gfo.alloced THEN PNext[handle, "alloced"];
IF gfo.shared THEN PNext[handle, "shared"];
IF gfo.trapxfers THEN PNext[handle, "trapxfers"];
PCr[handle];
PRope[handle, "Code - "];
csp ← ReadPrefix[handle, gf];
PRope[handle, "ngfi: "]; POctal[handle, csp.header.info.ngfi];
PNextUnsigned[handle, "nlinks", csp.header.info.nlinks];
IF csp.header.info.stops THEN PNext[handle, "stops"];
IF csp.header.swapinfo # 0 THEN PNextUnsigned[handle, "swapinfo", csp.header.swapinfo];
END;
PrintCodeBase: PROC [handle: Handle, code: PrincOps.FrameCodeBase] =
BEGIN
wasOut: BOOLEAN = code.out;
code.out ← FALSE;
PNextLongOctal[handle, "code base", code.longbase] ;
IF wasOut THEN PNext[handle, "out"];
END;
ReadPrefix: PROC [handle: Handle, gf: GFH] RETURNS [csp: REF PrincOps.CSegPrefix] =
TRUSTED BEGIN
code: PrincOps.FrameCodeBase ← gf.code;
ph: LONG POINTER TO PrincOps.CSegPrefix;
code.out ← FALSE;
ph ← LOOPHOLE[code];
csp ← NEW[PrincOps.CSegPrefix ← ph^];
END;
ReadGFrame: PROC [handle: Handle, gf: GFH] RETURNS [gfRef: REF PrincOps.GlobalFrame] =
procedural so could work across worlds some day (requires further work)
TRUSTED BEGIN
IF gf = PrincOps.NullGlobalFrame THEN Complain[handle, "not a valid global frame"];
gfRef ← NEW [PrincOps.GlobalFrame ← gf^];
END;
GoToLf: PUBLIC PROC [handle: Handle, lf: PrincOps.FrameHandle] = {
OPEN PrincOps;
overhead: POINTER TO Frame;
following relies on same world debugger
TRUSTED {
overhead ← LOOPHOLE[lf, POINTER TO Frame.local];
ViewerTools.SetContents [
handle.cmd.gfVal,
Convert.RopeFromInt[from: LOOPHOLE[overhead.accesslink, CARDINAL], base: 8, showRadix: TRUE]];
ViewerTools.SetContents [
handle.cmd.bpcVal,
Convert.RopeFromInt[from: LOOPHOLE[overhead.pc, CARDINAL], base: 8, showRadix: TRUE]]};
};
DspLf: PUBLIC PROC [handle: Handle, lf: PrincOps.FrameHandle] = {
OPEN PrincOps;
overhead: POINTER TO Frame;
nlocals: CARDINAL;
fsi: CARDINAL;
PCr[handle];
PRope[handle, "Local Frame: "];
POctal[handle, lf];
IF LOOPHOLE[lf, CARDINAL] MOD 4 # 0 THEN {
PRope[handle, " -- not 0 mod 4"]; RETURN};
following relies on same world debugger
TRUSTED {
fsi ← LOOPHOLE[lf-1, POINTER TO CARDINAL]^;
overhead ← LOOPHOLE[lf, POINTER TO Frame.local];
PNextUnsigned[handle, "fsi", fsi];
PNextOctal[handle, "ret", overhead.returnlink];
PNextOctal[handle, "gf", overhead.accesslink];
PNextOctal[handle, "pc", overhead.pc]};
nlocals ← IF fsi IN FrameSizeIndex THEN FrameVec[fsi] - localbase ELSE 0;
PCr[handle];
TRUSTED {FOR i: CARDINAL IN [0..nlocals) DO
val: CARDINAL = ShortREAD[lf + localbase + i];
cols: CARDINAL ← Log8[val];
IF val > 7 THEN cols ← cols + 1;
IF i # 0 AND MakeRoom[handle, cols+2, 0] THEN PRope[handle, ", "]
ELSE {PRope[handle, "local("]; POctal[handle, i]; PRope[handle, "): "]};
POctal[handle, val];
ENDLOOP}};
PutEntryItem: PUBLIC PROC [handle: Handle, epi: CARDINAL] =
BEGIN
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
epc: PrincOps.EntryVectorItem = GetEntryItem[handle, epi, gf];
PCr[handle];
PRope[handle, "ep["]; POctal[handle, epi]; PRope[handle, "] = bpc: "];
POctal[handle, epc.initialpc*2];
PNextUnsigned[handle, "fsi", epc.info.framesize];
IF epc.info.nparams # 0 THEN PNextUnsigned[handle, "nparams", epc.info.nparams];
IF epc.info.defaults THEN PNext[handle, "defaults"];
END;
GetEntryItem: PROC [handle: Handle, epi: CARDINAL, gf: GFH] RETURNS [evi: PrincOps.EntryVectorItem] =
TRUSTED BEGIN
offset: CARDINAL = LOOPHOLE [
@LOOPHOLE[1, POINTER TO PrincOps.CSegPrefix].entry[epi], CARDINAL] - 1;
p: POINTER TO CARDINAL = LOOPHOLE[@evi];
FOR i: CARDINAL IN [0..SIZE[PrincOps.EntryVectorItem]) DO
(p+i)^ ← GetWord[handle, offset+i, gf];
ENDLOOP;
END;
FindEP: PUBLIC PROC [handle: Handle, pc: CARDINAL] =
TRUSTED BEGIN
bestPc: CARDINAL ← 0;
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
wpc: CARDINAL = pc/2;
bestI: INTEGER ← -1;
csp: REF PrincOps.CSegPrefix;
csp ← ReadPrefix[handle, gf];
FOR i: CARDINAL IN [0..PrincOps.EPRange*csp.header.info.ngfi) DO
epOffset: CARDINAL = LOOPHOLE [
@LOOPHOLE[1, POINTER TO PrincOps.CSegPrefix].entry[i],
CARDINAL] - 1;
evi: PrincOps.EntryVectorItem ← GetEntryItem[handle, i, gf];
IF evi.initialpc <= epOffset THEN EXIT; -- ran off the end
IF evi.initialpc IN (bestPc..wpc] THEN
{bestI ← i; bestPc ← evi.initialpc};
ENDLOOP;
PCr[handle];
PRope[handle, "pc = "]; POctal[handle, pc];
IF bestI = -1 THEN PRope[handle, " not found"]
ELSE {PRope[handle, " closest to ep "]; POctal[handle, bestI]; PutEntryItem[handle, bestI]};
END;
PutLink: PUBLIC PROC [handle: Handle, lki: PUBLIC CARDINAL] =
TRUSTED BEGIN
codeLinks: BOOLEAN;
link: PrincOps.ControlLink;
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
gfo: REF PrincOps.GlobalFrame;
gfo ← ReadGFrame[handle, gf];
codeLinks ← gfo.codelinks;
link ← IF codeLinks THEN GetWord[handle, -1-lki, gf]
ELSE ShortREAD[
LOOPHOLE[gf - SIZE[PrincOps.GlobalFrame]-1-lki]];
PCr[handle];
PRope[handle, SELECT TRUE FROM
codeLinks => "(code",
ENDCASE => "(frame"];
PRope[handle, ")link["]; POctal[handle, lki]; PRope[handle, "] = "];
POctal[handle, link];
IF link.proc THEN {
PRope[handle, " = ["]; POctal[handle, link.gfi]; PChar[handle, ',];
POctal[handle, link.ep]; PChar[handle, ',]; POctal[handle, link.tag]; PChar[handle, ']];};
END;
PutAsProcDesc: PUBLIC PROC [handle: Handle, desc: UNSPECIFIED] =
BEGIN
link: PrincOps.ControlLink = desc;
PCr[handle];
POctal[handle, desc]; PRope[handle, " = "];
SELECT TRUE FROM
link.proc => {
PChar[handle, '[]; POctal[handle, link.gfi]; PChar[handle, ',];
POctal[handle, link.ep]; PChar[handle, ',]; POctal[handle, link.tag]; PChar[handle, ']];};
link.indirect => PRope[handle, " (indirect)"];
ENDCASE => PRope[handle, " (frame)"];
END;
PrintPos: PROC [handle: Handle, word, bytepc: BOOLEANFALSE, delta: CARDINAL ← 1] =
BEGIN
parity: ARRAY [0..1] OF ROPE = [",E", ",O"];
pc: CARDINAL ← 2*handle.offset + handle.byte - delta;
wo: CARDINAL ← pc / 2;
bo: CARDINAL ← pc MOD 2;
IF word THEN POctal[handle, wo];
IF word AND bytepc THEN {PRope[handle, parity[bo]]; PChar[handle, Ascii.TAB]};
IF bytepc THEN POctal[handle, pc];
PChar[handle, ':]; PChar[handle, Ascii.TAB];
END;
PutCodeBytes: PROC [handle: Handle, n: CARDINAL] RETURNS [unused: CARDINAL] =
{
bytePC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal];
RETURN[GenOperations[handle, bytePC, PutInstLine, n!
UNWIND => handle.bytesShown ← handle.bytesSeen]]};
GenOperations: PUBLIC PROC [handle: Handle, startPC: CARDINAL,
Action: PROC [handle: Handle, pc: CARDINAL, op: Operation] RETURNS [BOOLEAN],
n: CARDINAL] RETURNS [unused: CARDINAL] =
BEGIN
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
--op: Operation;
il: [0..3];
pc: CARDINAL;
inst: BYTE;
total: CARDINAL = n;
IF handle.opData = NIL THEN TRUSTED {handle.opData ← ListerUtils.GetOpCodeArray[]};
handle.offset ← startPC/2;
handle.byte ← startPC MOD 2;
WHILE n > 0 DO
ENABLE UNWIND => handle.bytesSeen ← total - n;
pc ← handle.offset*2+handle.byte;
inst ← GetByte[handle, gf];
il ← MAX[handle.opData[inst].length, 1];
IF il > n THEN RETURN[n];
{op: Operation ← [inst: inst, params: il-1];
SELECT il FROM
1 => NULL;
2 => op.param[1] ← GetByte[handle, gf];
3 => {op.param[1] ← GetByte[handle, gf]; op.param[2] ← GetByte[handle, gf]};
ENDCASE;
n ← n - il;
IF Action[handle, pc, op] THEN EXIT;
};
ENDLOOP;
RETURN[0];
END;
PutInstLine: PROC [handle: Handle, pc: CARDINAL, op: Operation]
RETURNS [stop: BOOLEANFALSE] =
BEGIN
parity: ARRAY [0..1] OF ROPE = [",E", ",O"];
oper: Operation = op; -- PrincOps has an op defined in it
PutPair: PROC [handle: Handle, alpha: CARDINAL] =
BEGIN
a: CARDINAL = alpha/16;
b: CARDINAL = alpha MOD 16;
PChar[handle, '[];
POctal[handle, a];
PChar[handle, ',];
POctal[handle, b];
PChar[handle, ']];
RETURN
END;
PCr[handle];
POctal[handle, pc/2];
PRope[handle, parity[pc MOD 2]]; PChar[handle, Ascii.TAB];
POctal[handle, pc]; PChar[handle, ':]; PChar[handle, Ascii.TAB];
PRope[handle, RopeForMop[handle, oper.inst]];
SELECT oper.params FROM
0 => IF oper.inst IN JumpOp THEN {
PChar[handle, Ascii.TAB]; PutJumpAddress[handle, op.inst, 0]};
1 =>
BEGIN OPEN PrincOps;
PChar[handle, Ascii.TAB];
SELECT oper.inst FROM
zRILP, zWILP, zRXLP, zWXLP, zRIGP,
zRXLPL, zWXLPL, zRXGPL, zWXGPL,
zRILPL, zWILPL, zRIGPL, zWIGPL => PutPair[handle, oper.param[1]];
ENDCASE => POctal[handle, oper.param[1]];
IF oper.inst IN JumpOp THEN PutJumpAddress[handle, oper.inst, oper.param[1]];
SELECT oper.inst FROM
zMISC => EscName[handle, oper.param[1]];
zKFCB => SdName[handle, oper.param[1]];
ENDCASE;
END;
2 =>
BEGIN OPEN PrincOps;
PChar[handle, Ascii.TAB];
SELECT oper.inst FROM
zRF, zWF, zWSF, zRFC, zRFL, zWFL =>
BEGIN
POctal[handle, oper.param[1]];
PRope[handle, ", "];
PutPair[handle, oper.param[2]];
END;
ENDCASE =>
BEGIN
POctal[handle, oper.wparam];
END;
SELECT oper.inst FROM
zJIB, zJIW => NULL;
IN JumpOp => PutJumpAddress[handle, oper.inst, oper.wparam];
ENDCASE;
END;
ENDCASE;
END;
JumpOp: TYPE = [PrincOps.zJ2..PrincOps.zJIW];
BackupPc: PUBLIC PROC [handle: Handle] =
BEGIN
oldPC: CARDINAL = CSegDebugDefs.CellCard[handle, handle.cmd.bpcVal];
delta: CARDINALMIN[oldPC, 10];
DoNothing: PROC [handle: Handle, pc: CARDINAL, op: Operation] RETURNS [BOOLEAN] = {
RETURN[FALSE]};
WHILE delta # 0 DO
IF GenOperations[handle, oldPC - delta, DoNothing, delta] = 0 THEN EXIT;
delta ← delta - 1;
ENDLOOP;
ViewerTools.SetContents [
handle.cmd.bpcVal,
Convert.RopeFromInt[from: oldPC - delta, base: 8, showRadix: TRUE]];
END;
PutJumpAddress: PROC [handle: Handle, jop: BYTE, arg: INTEGER] =
BEGIN OPEN PrincOps;
d: RECORD [SELECT OVERLAID * FROM
word => [i: INTEGER],
bytes => [b1, b2: CSegDebugDefs.BYTE],
nibbles => [fill: CSegDebugDefs.BYTE, n1, n2: [0..16)],
ENDCASE] = [word[arg]];
SELECT handle.opData[jop].length FROM
1 =>
SELECT jop FROM
IN [zJ2..zJ9] => arg ← jop - zJ2 + 2;
IN [zJEQ2..zJEQ9] => arg ← jop - zJEQ2 + 2;
IN [zJNE2..zJNE9] => arg ← jop - zJNE2 + 2;
ENDCASE => ERROR;
2 =>
BEGIN
IF arg > 177B THEN arg ← Basics.BITOR[arg, 177400B];
arg ← arg - 1;
END;
ENDCASE => arg ← arg - 2;
PRope[handle, " ("];
POctal[handle, 2*handle.offset+handle.byte-1+LOOPHOLE[arg, CARDINAL]];
PChar[handle, ')];
END;
Octal0: NumberFormat =
[base: 8, unsigned: TRUE, zerofill: FALSE, columns: 0];
Decimal0: NumberFormat =
[base: 10, unsigned: TRUE, zerofill: FALSE, columns: 0];
PutOctalWords: PUBLIC PROC [handle: Handle, count: CARDINAL] =
BEGIN
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
cols, val: CARDINAL;
PCr[handle];
FOR i: CARDINAL IN [0..count) DO
ENABLE UNWIND => handle.bytesShown ← i*2; -- could be "off" by 1
val ← GetWord[handle, handle.offset, gf]; handle.offset ← handle.offset + 1;
cols ← Log8[val];
IF val > 7 THEN cols ← cols + 1;
IF i # 0 AND MakeRoom[handle, cols+2, 0] THEN PRope[handle, ", "]
ELSE PrintPos[handle: handle, word: TRUE, delta: 2];
POctal[handle, val];
ENDLOOP;
END;
PutOctalBytes: PUBLIC PROC [handle: Handle, count: CARDINAL] =
BEGIN
cols, val: CARDINAL;
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
PCr[handle];
FOR i: CARDINAL IN [0..count) DO
ENABLE UNWIND => handle.bytesShown ← i;
val ← GetByte[handle, gf];
cols ← Log8[val];
IF val > 7 THEN cols ← cols + 1;
IF i # 0 AND MakeRoom[handle, cols+2, 0] THEN PRope[handle, ", "]
ELSE PrintPos[handle, TRUE, TRUE];
POctal[handle, val];
ENDLOOP;
END;
PutAsciiText: PUBLIC PROC [handle: Handle, count: CARDINAL] =
BEGIN
cols: CARDINAL;
ch: CHARACTER;
gf: GFH = LOOPHOLE[CSegDebugDefs.CellCard[handle, handle.cmd.gfVal]];
PCr[handle];
FOR i: CARDINAL IN [0..count) DO
ENABLE UNWIND => handle.bytesShown ← i;
ch ← LOOPHOLE[GetByte[handle, gf]];
cols ← SELECT ch FROM
Ascii.CR, Ascii.SP => 4,
Ascii.TAB, Ascii.ESC, Ascii.NUL, Ascii.DEL => 5,
< 40C => 2,
> 200C => 5,
ENDCASE => 1;
IF i = 0 OR ~MakeRoom[handle, cols, 0] THEN PrintPos[handle, TRUE, TRUE];
SELECT ch FROM
Ascii.SP => PRope[handle, "<SP>"];
Ascii.CR => PRope[handle, "<CR>"];
Ascii.TAB => PRope[handle, "<TAB>"];
Ascii.ESC => PRope[handle, "<ESC>"];
Ascii.NUL => PRope[handle, "<NUL>"];
Ascii.DEL => PRope[handle, "<DEL>"];
< 40C => {PChar[handle, '^]; PChar[handle, ch + 100B]};
> 200C => {PChar[handle, '<]; PNumber[handle, ch, Octal0]; PChar[handle, '>]};
ENDCASE => PChar[handle, ch];
ENDLOOP;
END;
END.