-- MesaRuntime>PilotNub.mesa (May 11, 1983 2:45 pm by Levin)
DIRECTORY
Boot USING [ReadMDS],
BootSwap USING [InLoad, OutLoad, Teledebug],
CPSwapDefs USING [
BBArray, BBHandle, CallDP, DebugParameter, ExternalStateVector, SwapInfo,
StartDP, SwapReason, UBBPointer, UserBreakBlock, VersionID],
DebuggerSwap USING [canSwap, parameters],
DeviceCleanup USING [Item, Linkage, Perform, Reason],
Environment USING [Byte, maxPagesInMDS, PageCount, PageNumber],
Frame USING [
GetReturnFrame, GetReturnLink, MyLocalFrame, SetReturnFrame,
SetReturnLink],
Inline USING [HighHalf, LowHalf],
KeyboardFace USING [keyboard],
Keys USING [DownUp, KeyBits],
Mopcodes USING [zDUP, zRFS],
PilotMP USING [cCantSwap, cCleanup, cClient, cHang, Code],
PilotSwitches USING [switches--.h, .i, .r--],
PrincOps USING [
ControlLink, FieldDescriptor, FrameHandle, GlobalFrameHandle, NullFrame,
NullLink, Port, StateVector, SVPointer],
Process USING [GetPriority, Priority, SetPriority, SetTimeout, Ticks],
ProcessInternal USING [DisableInterrupts, EnableInterrupts],
ProcessOperations USING [HandleToIndex, IndexToHandle, ReadPSB, ReadPTC,
ReadWDC, WritePSB, WritePTC, WriteWDC],
ProcessPriorities USING [priorityRealTime],
ProcessorFace USING [BootButton, GetClockPulses,
microsecondsPerHundredPulses, SetMP],
PSB USING [PDA],
Runtime USING [Interrupt],
RuntimeInternal USING [],
RuntimePrograms USING [],
SDDefs USING [
sAlternateBreak, sBreak, sBreakBlock, sBreakBlockSize, sCallDebugger,
sCoreSwap, SD, sInterrupt, sProcessBreakpoint, sUncaughtSignal,
sWorryCallDebugger, sXferTrap],
XferTrap USING [ReadXTS, Status, WriteXTS];
PilotNub: MONITOR -- for CheckInterrupt, DeviceCleanup.Install
IMPORTS
Boot, BootSwap, DebuggerSwap, DeviceCleanup, Frame, Inline, KeyboardFace,
PilotSwitches, Process, ProcessInternal, ProcessOperations, ProcessorFace,
Runtime, XferTrap
EXPORTS DeviceCleanup, RuntimeInternal, RuntimePrograms
SHARES DeviceCleanup =
BEGIN
-- This module is the debugger's representative in the client world.
loadStatePage: PUBLIC Environment.PageNumber; -- exported to RuntimeInternal
CAbort: PUBLIC SIGNAL = CODE;
CantSwap: PUBLIC SIGNAL = CODE;
KillThisTurkey: SIGNAL = CODE;
Quit: SIGNAL = CODE;
--
-- Breakpoints
numberBlocks: CARDINAL = 5; -- number of break blocks
BreakBlocks: TYPE = MACHINE DEPENDENT RECORD [
header(0): CPSwapDefs.BBArray, -- length plus (zero-length) array of blocks
body(1): ARRAY [0..numberBlocks) OF CPSwapDefs.UserBreakBlock];
breakBlocks: BreakBlocks;
InitBreakBlocks: PROC =
BEGIN OPEN SDDefs;
SD[sBreakBlock] ← Inline.LowHalf[LONG[@breakBlocks]];
-- mds relative (should really be long pointer)
SD[sBreakBlockSize] ← SIZE[BreakBlocks];
breakBlocks.header.length ← 0;
END;
Break: PROC = -- executed by (non-worry) BRK instruction
BEGIN
state: RECORD [
padding: ARRAY [0..2) OF UNSPECIFIED, v: PrincOps.StateVector];
state.v ← STATE;
state.v.dest ← Frame.GetReturnLink[];
state.v.source ← PrincOps.NullLink;
ProcessBreakpoint[@state.v]; -- isn't this supposed to go through SD[sProcessBreakpoint]?
IF XferTrap.ReadXTS[] = on THEN XferTrap.WriteXTS[skip1];
RETURN WITH state.v;
END;
ProcessBreakpoint: PROC [s: PrincOps.SVPointer] =
BEGIN
inst: Environment.Byte;
swap: BOOLEAN;
[inst, swap] ← DoBreakpoint[s];
IF swap THEN CoreSwap[breakpoint, s]
ELSE s.instbyte ← inst -- replant the instruction and go on
END;
-- make this INLINE someday??
DoBreakpoint: PROC [s: PrincOps.SVPointer]
RETURNS [Environment.Byte, BOOLEAN] =
BEGIN
bba: CPSwapDefs.BBHandle = SDDefs.SD[SDDefs.sBreakBlock];
l: PrincOps.FrameHandle ← LOOPHOLE[s.frame];
FOR i: CARDINAL IN [0..bba.length) DO
ubb: CPSwapDefs.UBBPointer = @bba.blocks[i];
IF ubb.frame = l.accesslink AND ubb.pc = CARDINAL[l.pc] THEN
IF TrueCondition[ubb, l, s] THEN EXIT ELSE RETURN[ubb.inst, FALSE]
ENDLOOP;
RETURN[0, TRUE]
END;
-- decide whether to take the breakpoint
TrueCondition: PROC [
ubb: CPSwapDefs.UBBPointer, base: POINTER, s: PrincOps.SVPointer]
RETURNS [BOOLEAN] =
INLINE BEGIN
ReadField: PROC [POINTER, PrincOps.FieldDescriptor] RETURNS [UNSPECIFIED] =
MACHINE CODE BEGIN Mopcodes.zRFS END;
fd: PrincOps.FieldDescriptor;
locL, locR: POINTER;
left, right: UNSPECIFIED;
IF ubb.counterL THEN RETURN[(ubb.ptrL ← ubb.ptrL + 1) = ubb.ptrR];
locL ← SELECT TRUE FROM
ubb.stackRelative => @s.stk[LOOPHOLE[ubb.ptrL, CARDINAL]],
ubb.localL => base + LOOPHOLE[ubb.ptrL, CARDINAL],
ENDCASE => ubb.ptrL;
fd ← [offset: 0, posn: ubb.posnL, size: ubb.sizeL];
left ← ReadField[locL, fd];
IF ~ubb.immediateR THEN
BEGIN
fd ← [offset: 0, posn: ubb.posnR, size: ubb.sizeR];
locR ← IF ubb.localR THEN base + LOOPHOLE[ubb.ptrR, CARDINAL] ELSE ubb.ptrR;
right ← ReadField[locR, fd]
END
ELSE right ← ubb.ptrR;
RETURN[
SELECT ubb.relation FROM
lt => left < right, gt => left > right, eq => left = right,
ne => left # right, le => left <= right, ge => left >= right,
ENDCASE => FALSE]
END;
-- executed by worry-mode BRK instruction
WorryBreaker: PROC RETURNS [PrincOps.FrameHandle] =
BEGIN OPEN PrincOps;
state: RECORD [padding: ARRAY [0..2) OF UNSPECIFIED, v: StateVector];
state.v.instbyte ← 0;
state.v.stkptr ← 1;
state.v.stk[0] ← Frame.MyLocalFrame[];
state.v.dest ← Frame.GetReturnLink[];
state.v.source ← PrincOps.NullLink;
ProcessInternal.DisableInterrupts[];
DO
IF XferTrap.ReadXTS[] = on THEN XferTrap.WriteXTS[skip1];
ProcessInternal.EnableInterrupts[];
TRANSFER WITH state.v;
ProcessInternal.DisableInterrupts[];
state.v ← STATE;
state.v.dest ← Frame.GetReturnLink[];
state.v.source ← PrincOps.NullLink;
swapInfo.state ← @state.v;
swapInfo.reason ← worrybreak; -- set mds too
ToDebugger[@swapInfo];
ENDLOOP;
END;
--
-- Uncaught signals
Catcher: PROC [msg, signal: UNSPECIFIED, frame: PrincOps.FrameHandle] =
BEGIN
Punt: PROC [c: PilotMP.Code] = INLINE
{ProcessorFace.SetMP[c]; DO ENDLOOP};
SignallerGF: PrincOps.GlobalFrameHandle;
state: PrincOps.StateVector;
f: PrincOps.FrameHandle;
state.stk[0] ← msg;
state.stk[1] ← signal;
state.stkptr ← 0;
-- The call stack below here is: Signaller, [Signaller,] offender
f ← Frame.GetReturnFrame[];
SignallerGF ← f.accesslink;
f ← LOOPHOLE[state.dest ← f.returnlink, PrincOps.FrameHandle];
IF f.accesslink = SignallerGF THEN state.dest ← f.returnlink;
IF signal = CantSwap THEN Punt[PilotMP.cCantSwap];
CoreSwap[uncaughtsignal, @state ! CAbort => GOTO abort];
EXITS
abort =>
IF signal = ABORTED THEN {BackStop[frame]; ERROR KillThisTurkey}
ELSE ERROR ABORTED;
END;
BackStop: PROC [root: PrincOps.FrameHandle] =
BEGIN
endProcess: PrincOps.ControlLink = root.returnlink;
Caller: PROC = LOOPHOLE[Frame.GetReturnLink[]];
root.returnlink ← [frame[Frame.MyLocalFrame[]]];
Frame.SetReturnFrame[PrincOps.NullFrame];
Caller[ ! KillThisTurkey => CONTINUE];
Frame.SetReturnLink[endProcess];
END;
--~~~~~~~~~ Interrupts (e.g. CTRL-SWAT) ~~~~~~~~~
wakeup: CONDITION;
ticksPerWakeup: Process.Ticks = 1;
CheckInterrupt: ENTRY PROC = -- default CTRL-SWAT watcher
BEGIN
interruptState: Keys.DownUp ← up;
pKeys: LONG POINTER TO Keys.KeyBits = LOOPHOLE[KeyboardFace.keyboard];
DO --FOREVER--
ENABLE ABORTED => CONTINUE;
WAIT wakeup;
IF pKeys[Spare3]=down AND pKeys[Ctrl]=down AND pKeys[LeftShift]=up
AND interruptState = up
AND LOOPHOLE[PSB.PDA.available, CPSwapDefs.SwapInfo]
.externalStateVector ~= NIL THEN
{ interruptState ← down; Runtime.Interrupt[] }
ELSE interruptState ← up;
ENDLOOP;
END;
Interrupt: PROC = -- implementation of Runtime.Interrupt
BEGIN
state: RECORD [a, b: UNSPECIFIED, v: PrincOps.StateVector];
state.v ← STATE;
state.v.dest ← LOOPHOLE[Frame.MyLocalFrame[], PrincOps.ControlLink];
CoreSwap[interrupt, @state.v]
END;
InitializeInterrupt: PUBLIC PROC =
-- Initialize Pilot's CTRL-SWAT watcher (if one was requested).
-- Must not be invoked until KeyboardFace has been initialized.
BEGIN
IF PilotSwitches.switches.i = down THEN
BEGIN
throwAway: PROCESS;
priorityPrev: Process.Priority = Process.GetPriority[];
Process.SetTimeout[@wakeup, ticksPerWakeup];
Process.SetPriority[ProcessPriorities.priorityRealTime];
throwAway ← FORK CheckInterrupt[]; -- (no profit in Detaching)
Process.SetPriority[priorityPrev];
END;
END;
--
-- Miscellaneous Runtime, RuntimeInternal items
CallDebugger: PROC [s: STRING] =
-- Runtime.CallDebugger is KFCB[sCallDebugger]
BEGIN
state: RECORD [a, b: UNSPECIFIED, v: PrincOps.StateVector];
state.v ← STATE;
state.v.stk[0] ← s;
state.v.stkptr ← 1;
state.v.dest ← Frame.GetReturnLink[];
CoreSwap[explicitcall, @state.v]
END;
worryCallIndirect: PORT;
WorryCallDebugger: PROC RETURNS [PrincOps.FrameHandle] =
BEGIN OPEN PrincOps;
state: RECORD [padding: ARRAY [0..2) OF UNSPECIFIED, v: StateVector];
state.v.instbyte ← 0;
state.v.stkptr ← 1;
-- The following dance is needed because fixed frame procedures that are not
-- called as trap handlers don't have source & destination links put on the
-- stack. We insert an indirect link to force them to be put there.
LOOPHOLE[worryCallIndirect, PrincOps.Port].frame ← Frame.MyLocalFrame[];
state.v.stk[0] ← @worryCallIndirect;
state.v.dest ← Frame.GetReturnLink[];
state.v.source ← PrincOps.NullLink;
ProcessInternal.DisableInterrupts[];
DO --FOREVER--
IF XferTrap.ReadXTS[] = on THEN XferTrap.WriteXTS[skip1];
ProcessInternal.EnableInterrupts[];
TRANSFER WITH state.v;
ProcessInternal.DisableInterrupts[];
state.v ← STATE;
state.v.dest ← state.v.stk[state.v.stkptr + 1];
Frame.SetReturnLink[state.v.dest];
state.v.source ← PrincOps.NullLink;
swapInfo.state ← @state.v;
swapInfo.reason ← worrycall;
ToDebugger[@swapInfo];
ENDLOOP
END;
CleanMapLog: PUBLIC PROC =
BEGIN
state: RECORD [a, b: UNSPECIFIED, v: PrincOps.StateVector];
state.v ← STATE;
state.v.stkptr ← 0;
state.v.dest ← Frame.GetReturnLink[];
CoreSwap[cleanmaplog, @state.v]
END;
-- Procedures that cause swap to debugger
swapInfo: CPSwapDefs.ExternalStateVector; -- nub-debugger communication area
parmstring: STRING = [40];
GetMDS: PROC RETURNS [Environment.PageNumber] =
BEGIN RETURN[Boot.ReadMDS[]*Environment.maxPagesInMDS] END;
CoreSwap: PROC [why: CPSwapDefs.SwapReason, sp: PrincOps.SVPointer] =
BEGIN
DP: CPSwapDefs.DebugParameter;
decode: PROC RETURNS [proceed: BOOLEAN] = -- decode the SwapReason
BEGIN
f: PrincOps.GlobalFrameHandle;
lsv: PrincOps.StateVector;
SELECT swapInfo.reason FROM
proceed, resume => RETURN[TRUE];
call =>
BEGIN
lsv ← LOOPHOLE[swapInfo.parameter, CPSwapDefs.CallDP].sv;
lsv.source ← LOOPHOLE[Frame.MyLocalFrame[], PrincOps.ControlLink];
TRANSFER WITH lsv;
lsv ← STATE;
LOOPHOLE[swapInfo.parameter, CPSwapDefs.CallDP].sv ← lsv;
why ← return
END;
start =>
BEGIN
f ← LOOPHOLE[swapInfo.parameter, CPSwapDefs.StartDP].frame;
IF ~f.started THEN START LOOPHOLE[f, PROGRAM] ELSE RESTART f;
why ← return
END;
quit => SIGNAL Quit;
ENDCASE => RETURN[TRUE];
RETURN[FALSE]
END; --decode--
-- Body of CoreSwap:
-- IF ~DebuggerSwap.canSwap THEN SIGNAL CantSwap;
swapInfo.state ← sp;
DP.string ← parmstring;
swapInfo.parameter ← @DP;
-- versionident, debuggee, lspages, fill, mapLog set by Initialize
-- level, loadstatepage set by MemorySwap
swapInfo.mds ← GetMDS[];
DO
swapInfo.reason ← why;
ProcessInternal.DisableInterrupts[];
ToDebugger[@swapInfo];
ProcessInternal.EnableInterrupts[];
BEGIN
IF decode[
! CAbort => IF swapInfo.level > 0 THEN {why ← return; CONTINUE};
Quit => GOTO abort] THEN EXIT
EXITS abort => SIGNAL CAbort
END
ENDLOOP
END;
-- Serious swapper
level: INTEGER ← -1;
ToDebugger: PORT [POINTER TO CPSwapDefs.ExternalStateVector]; -- formerly WBPort
FromPilot: PORT RETURNS [POINTER TO CPSwapDefs.ExternalStateVector]; -- formerly CSPort
pulsesPerTwentySeconds: LONG CARDINAL;
MemorySwap: PROC [pESV: POINTER TO CPSwapDefs.ExternalStateVector] =
BEGIN
PKeys: PROC RETURNS [LONG POINTER TO Keys.KeyBits] = INLINE
{RETURN[LOOPHOLE[KeyboardFace.keyboard]]};
SwapIt: PROC = INLINE
BEGIN
savewdc, saveptc: UNSPECIFIED;
xferTrapStatus: XferTrap.Status = XferTrap.ReadXTS[];
xferTrapHandler: UNSPECIFIED = SDDefs.SD[SDDefs.sXferTrap];
pESV.level ← level;
pESV.loadstatepage ← loadStatePage; -- (possibly updated by loader)
pESV.mds ← Inline.HighHalf[LONG[LOOPHOLE[1, POINTER]]]; -- ("1" since
-- 0 collides with NIL.)
pESV.psb ← ProcessOperations.HandleToIndex[ProcessOperations.ReadPSB[]];
SDDefs.SD[SDDefs.sXferTrap] ← Frame.MyLocalFrame[]; -- in case we are restarted in trap mode
XferTrap.WriteXTS[off];
-- Save processor state not captured in PDA:
saveptc ← ProcessOperations.ReadPTC[];
savewdc ← ProcessOperations.ReadWDC[];
-- Manually save the state of the current process so that Copilot
-- will be able to examine it just as if we were waiting:
PSB.PDA.block[pESV.psb].link.vector ← FALSE;
PSB.PDA.block[pESV.psb].context.frame ← Frame.MyLocalFrame[];
DeviceCleanup.Perform[turnOff]; -- turn all devices off
IF PilotSwitches.switches.h = down THEN
BEGIN
AddToStack: PROC [BOOLEAN] = MACHINE CODE BEGIN END;
GetTOS: PROC RETURNS [BOOLEAN] = MACHINE CODE BEGIN Mopcodes.zDUP; END;
RemoveFromStack: PROC RETURNS [BOOLEAN] = MACHINE CODE BEGIN END;
AddToStack[TRUE];
ProcessorFace.SetMP[PilotMP.cHang];
WHILE GetTOS[] DO ENDLOOP;
[] ← RemoveFromStack[];
END
ELSE IF ~DebuggerSwap.canSwap OR PilotSwitches.switches.r = down THEN
BEGIN
ProcessorFace.SetMP[PilotMP.cCantSwap];
BootSwap.Teledebug[@DebuggerSwap.parameters.locDebugger];
END
-- OutLoad onto swatee, then boot Debugger.
ELSE IF BootSwap.OutLoad[@DebuggerSwap.parameters.locDebuggee, restore] =
outLoaded THEN
BEGIN OPEN DebuggerSwap, parameters;
-- The next line should be in BootSwap.InLoad but blows up the compiler
IF pMicrocodeCopy ~= NIL THEN DeviceCleanup.Perform[kill];
BootSwap.InLoad[pMicrocodeCopy, pGermCopy, nGerm, @locDebugger]
-- never returns
END;
-- Restore processor state not captured in PDA:
ProcessOperations.WriteWDC[savewdc];
ProcessOperations.WritePTC[saveptc];
-- Restore process state not captured in PDA:
ProcessOperations.WritePSB[ProcessOperations.IndexToHandle[pESV.psb]];
DeviceCleanup.Perform[turnOn]; -- turn devices back on
level ← pESV.level;
XferTrap.WriteXTS[xferTrapStatus];
SDDefs.SD[SDDefs.sXferTrap] ← xferTrapHandler;
ProcessorFace.SetMP[PilotMP.cClient]; -- announce our return
END;
DO
pESV ← FromPilot[];
-- Set our return link so Display Stack will work:
Frame.SetReturnLink[LOOPHOLE[FromPilot, PrincOps.Port].dest.link↑];
DO
SwapIt[];
SELECT pESV.reason FROM
kill => ProcessorFace.BootButton[];
showscreen =>
BEGIN
pulsesThen: LONG CARDINAL = ProcessorFace.GetClockPulses[];
prevSpare3: Keys.DownUp ← PKeys[][Spare3];
DO
IF (ProcessorFace.GetClockPulses[] - pulsesThen)
> pulsesPerTwentySeconds THEN EXIT;
IF prevSpare3=down THEN prevSpare3 ← PKeys[][Spare3]
ELSE IF PKeys[][Spare3]=down THEN
{WHILE PKeys[][Spare3]=down DO --snoore-- ENDLOOP; EXIT}
ELSE NULL -- both up
ENDLOOP;
END;
ENDCASE => EXIT;
pESV.reason ← return;
ENDLOOP
ENDLOOP
END;
--
-- DeviceCleanup implementation
linkage: PUBLIC DeviceCleanup.Linkage;
InitializeDeviceCleanup: PROC =
BEGIN
reason: DeviceCleanup.Reason;
pItem: POINTER TO Item;
LOOPHOLE[AwaitPerform, PrincOps.Port].dest ← Frame.GetReturnLink[];
linkage.Perform ← LOOPHOLE[@AwaitPerform];
DO
linkage.Await ← LOOPHOLE[Install];
reason ← AwaitPerform[];
ProcessorFace.SetMP[PilotMP.cCleanup];
linkage.Await ← LOOPHOLE[Frame.MyLocalFrame[]];
FOR pItem ← pItemFirst, pItem.pItemNext WHILE pItem ~= NIL DO
[] ← pItem.Procedure[reason] -- value should be pItem
ENDLOOP
ENDLOOP
END;
AwaitPerform: PORT RETURNS [reason: DeviceCleanup.Reason];
Install: ENTRY PROC [pItem: POINTER TO Item] =
BEGIN
fCaller: PrincOps.FrameHandle = Frame.GetReturnFrame[]; -- cleanup procedure
pItem↑ ← [pItemNext: pItemFirst, Procedure: LOOPHOLE[fCaller]];
pItemFirst ← pItem;
Frame.SetReturnLink[fCaller.returnlink]
END;
Item: PUBLIC TYPE = RECORD [
pItemNext: POINTER TO Item,
Procedure: PROC [DeviceCleanup.Reason] RETURNS [POINTER TO Item] ← NULL];
pItemFirst: POINTER TO Item ← NIL; -- list of waiting cleanup procedures
--
-- Initialization
InitializePilotNub: PUBLIC PROC [
pageLoadState: Environment.PageNumber,
countLoadState: Environment.PageCount,
pVMMapLog: LONG POINTER --TO VMMMapLog.Descriptor--] =
BEGIN
InitializeDeviceCleanup[];
loadStatePage ← pageLoadState;
-- swapInfo.state set in caller of MemorySwap
-- (e.g. CoreSwap, WorryBreaker, WorryCallDebugger)
-- swapInfo.reason set in caller of MemorySwap
-- (e.g. CoreSwap, WorryBreaker, WorryCallDebugger)
-- swapInfo.level set in MemorySwap
-- swapInfo.parameter set by debugger and obeyed by CoreSwap
swapInfo.versionident ← CPSwapDefs.VersionID;
-- swapInfo.loadstatepage set in MemorySwap
swapInfo.lspages ← countLoadState;
swapInfo.mapLog ← pVMMapLog;
swapInfo.mds ← GetMDS[]; -- delete this when WorryBreak, etc. set the field
swapInfo.fill ← ALL[0];
LOOPHOLE[PSB.PDA.available, CPSwapDefs.SwapInfo].externalStateVector
← @swapInfo;
InitBreakBlocks[];
BEGIN OPEN SDDefs;
pSD: POINTER TO ARRAY [0..0) OF UNSPECIFIED = SD;
pSD[sProcessBreakpoint] ← ProcessBreakpoint;
pSD[sUncaughtSignal] ← Catcher;
pSD[sInterrupt] ← Interrupt;
pSD[sCallDebugger] ← CallDebugger;
pSD[sBreak] ← Break;
pSD[sAlternateBreak] ← WorryBreaker[];
pSD[sWorryCallDebugger] ← WorryCallDebugger[];
pulsesPerTwentySeconds ←
LONG[20]*1000000*100/ProcessorFace.microsecondsPerHundredPulses;
LOOPHOLE[ToDebugger, PrincOps.Port].out ← @FromPilot;
-- connect ToDebugger to FromPilot
LOOPHOLE[FromPilot, PrincOps.Port].out ← @ToDebugger;
-- connect FromPilot to ToDebugger
pSD[sCoreSwap] ← @FromPilot;
LOOPHOLE[FromPilot, PrincOps.Port].in ← MemorySwap;
ToDebugger[NIL]; -- allocate frame for MemorySwap
END;
END;
END.
LOG
(For earlier log entries see Pilot 4.0 archive version.)
April 29, 1980 9:50 PM Forrest Move in Memory swap stuff from Traps
May 3, 1980 2:29 PM Forrest Mesa 6.0
June 23, 1980 6:26 PM McJones Fix WorryCallDebugger bug; OISProcessorFace=>ProcessorFace; make TrueCondition INLINE; allocate break blocks in global frame
July 28, 1980 6:46 PM McJones New KeyboardFace, Keys
July 31, 1980 7:21 PM Forrest Implement Hang switch
August 28, 1980 2:59 PM McJones Merge InterruptKey with PilotNub; timeout userscreen after twenty seconds; SetMP[cCleanup]
August 27, 1980 4:00 PM McJones New PSB, ProcessOperations, XferTrap
October 3, 1980 1:30 PM Forrest Reverse sense of i switch; add code to dally during userscreen as long as swat held down; Jim Sandman fixed conditional Break logic
December 10, 1980 9:58 AM Knutsen New PDA layout. externalStateVector now not defined in PSB.mesa.
January 19, 1981 5:03 PM Knutsen Twiddle process priorities.
January 30, 1981 5:35 PM Luniewski Make conditional breakpoints at procedure entry/exit work.
February 4, 1981 11:51 AM Knutsen PrincOps fields changed names.
25-Feb-81 16:24:10 Gobbel Make Interrupt use correct SwapReason.
31-Mar-81 11:41:06 Sandman Correct XferTrapStatus check and BreakPoints.
March 31, 1981 12:46 PM Luniewski State vectors can't be in local 0 or 1.
June 16, 1982 5:35 pm Levin WorryCallDebugger indirection to get links pushed on stack.
May 11, 1983 2:41 pm Birrell SwapIt clears link.vector; no indirect return link in call stack.