-- MMSignals.Mesa Edited by Sandman on May 7, 1979 7:08 PM
DIRECTORY
AltoDefs: FROM "altodefs" USING [BYTE],
ControlDefs: FROM "controldefs" USING [
ControlLink, Frame, FrameHandle, GlobalFrameHandle, InstWord,
localbase, NullFrame, StateVector, WordPC],
FrameOps: FROM "frameops" USING [
Alloc, Free, GetReturnFrame, GetReturnLink, MyGlobalFrame,
MyLocalFrame, SetReturnLink],
ImageDefs: FROM "imagedefs" USING [PuntMesa],
MMInit: FROM "MMInit",
MMSDEntries: FROM "MMSDEntries",
Mopcodes: FROM "mopcodes" USING [
zCATCH, zJ2, zJ9, zJB, zJW, zKFCB, zNOOP, zPORTI, zSLB],
SDDefs: FROM "sddefs" USING [SD, sUncaughtSignal],
TrapDefs: FROM "trapdefs";
MMSignals: PROGRAM
IMPORTS FrameOps, ImageDefs EXPORTS MMInit, MMSDEntries = PUBLIC
BEGIN OPEN ControlDefs;
BYTE: TYPE = AltoDefs.BYTE;
CatchPointer: TYPE = POINTER TO catch Frame;
CatchCall: TYPE = PROCEDURE [SIGNAL] RETURNS [ActionCode];
CatchContinue: TYPE = PROCEDURE;
ActionCode: TYPE = INTEGER;
reject: ActionCode = 0;
resume: ActionCode = 1;
exit: ActionCode = -1;
SendMsgSignal: PUBLIC SIGNAL RETURNS [UNSPECIFIED, UNSPECIFIED] = CODE;
signalling: CARDINAL = 177777B;
notSignalling: CARDINAL = 0;
MarkSignalFrame: PROCEDURE [value: CARDINAL] =
MACHINE CODE BEGIN Mopcodes.zSLB, 3 --OFFSET[mark]-- END;
SignalHandler: PROCEDURE [signal: SIGNAL, message: UNSPECIFIED] =
BEGIN
SignalFrame: TYPE = POINTER TO FRAME[SignalHandler];
frame, nextFrame: FrameHandle;
target, nextTarget: FrameHandle;
self: FrameHandle = FrameOps.MyLocalFrame[];
start: FrameHandle;
catchFrame: CatchPointer;
action: ActionCode;
unwinding: BOOLEAN;
catchPhrase: BOOLEAN;
catchFSIndex: BYTE;
catchPC, exitPC: WordPC;
catchState: ControlDefs.StateVector;
MarkSignalFrame[signalling]; unwinding ← FALSE;
start ← GetFrame[self.returnlink]; target ← NullFrame;
DO
nextFrame ← start;
UNTIL nextFrame = target DO
frame ← nextFrame;
IF frame.accesslink = FrameOps.MyGlobalFrame[] AND frame.mark THEN
BEGIN
OPEN thisSignaller: LOOPHOLE[frame, SignalFrame];
IF unwinding THEN
BEGIN
IF signal = thisSignaller.signal THEN
nextTarget ← IF thisSignaller.unwinding
THEN thisSignaller.nextTarget
ELSE thisSignaller.nextFrame;
IF thisSignaller.unwinding THEN
BEGIN
IF thisSignaller.frame = LOOPHOLE[frame.returnlink] THEN
frame.returnlink ← [frame[thisSignaller.nextFrame]];
FrameOps.Free[thisSignaller.frame];
END;
nextFrame ← GetFrame[frame.returnlink];
END
ELSE
nextFrame ← IF signal # thisSignaller.signal
THEN
IF thisSignaller.unwinding
THEN thisSignaller.nextFrame
ELSE GetFrame[frame.returnlink]
ELSE
IF thisSignaller.unwinding
THEN thisSignaller.nextTarget
ELSE thisSignaller.nextFrame;
END
ELSE nextFrame ← GetFrame[frame.returnlink];
IF unwinding AND nextTarget = frame THEN nextTarget ← nextFrame;
[catchPhrase, catchFSIndex, catchPC] ← CheckCatch[frame];
IF catchPhrase
THEN
BEGIN
catchFrame ← FrameOps.Alloc[catchFSIndex];
catchFrame↑ ← Frame[
accesslink: frame.accesslink,
pc: catchPC,
returnlink: [frame[self]],
extensions: catch[unused: ,
staticlink: frame+localbase, messageval: message]];
action ← LOOPHOLE[catchFrame, CatchCall]
[IF unwinding THEN LOOPHOLE[UNWIND] ELSE signal
! SendMsgSignal => RESUME[message, signal]];
catchState ← STATE;
SELECT action FROM
reject => NULL;
resume =>
IF unwinding
THEN ERROR ResumeError
ELSE
BEGIN
catchState.dest ← FrameOps.GetReturnLink[];
catchState.source ← 0;
RETURN WITH catchState;
END;
exit =>
BEGIN
-- catchFrame is waiting to execute its exit jump
exitPC ← catchFrame.pc;
FrameOps.Free[catchFrame];
target ← LOOPHOLE[catchState.stk[0]-ControlDefs.localbase];
nextTarget ← nextFrame;
unwinding ← TRUE; message ← NIL;
GO TO StartUnwind;
END;
ENDCASE;
END;
IF unwinding
THEN
BEGIN
IF frame = start THEN start ← nextFrame;
IF frame = LOOPHOLE[self.returnlink]
THEN self.returnlink ← [frame[nextFrame]];
FrameOps.Free[frame];
END;
REPEAT
StartUnwind => NULL;
FINISHED => EXIT
ENDLOOP;
ENDLOOP;
IF unwinding THEN target.pc ← exitPC
ELSE
BEGIN
IF SDDefs.SD[SDDefs.sUncaughtSignal] = 0 THEN ImageDefs.PuntMesa[];
UncaughtSignal[message, signal, frame];
END;
RETURN
END;
CheckCatch: PROCEDURE [frame: FrameHandle]
RETURNS [catchPhrase: BOOLEAN, fsIndex: BYTE, pc: WordPC] =
BEGIN OPEN Mopcodes;
codeWords: ARRAY [0..3) OF InstWord; -- worst case is XFER NOOP CATCH 0
code: POINTER TO ARRAY [0..3) OF InstWord ← @codeWords;
p: POINTER TO InstWord;
c: [0..3);
inst: [0..377B];
g: GlobalFrameHandle ← frame.accesslink;
parity: {even, odd};
MarkSignalFrame[notSignalling];
pc ← [ABS[frame.pc]];
p ← pc + g.code.shortbase;
code[0] ← p↑;
code[1] ← (p+1)↑;
code[2] ← (p+2)↑;
c ← 0;
parity ← IF frame.pc < 0 THEN odd ELSE even;
DO
inst ← IF parity = even THEN code[c].evenbyte ELSE code[c].oddbyte;
SELECT inst FROM
zCATCH => BEGIN catchPhrase ← parity = even; EXIT END;
zPORTI,zNOOP =>
IF parity=even THEN parity ← odd
ELSE BEGIN c ← c + 1; parity ← even; END;
ENDCASE => BEGIN catchPhrase ← FALSE; EXIT END;
ENDLOOP;
IF catchPhrase
THEN
BEGIN -- [c, parity] points at zCatch (note: parity must be even)
pc ← WordPC[pc+c+1];
fsIndex ← code[c].oddbyte;
SELECT code[c+1].evenbyte FROM
zJB =>
BEGIN pc ← [pc + 1]; GO TO evenPC END;
IN [zJ2..zJ9] => GO TO oddPC;
zJW => -- always padded !
BEGIN pc ← [pc + 2]; GO TO evenPC END;
ENDCASE;
EXITS
evenPC => NULL;
oddPC => pc ← [-pc];
END;
RETURN
END;
GetFrame: PROCEDURE [link: ControlLink] RETURNS [FrameHandle] =
BEGIN
-- MarkSignalFrame[notSignalling];
DO
WITH cl: link SELECT link.tag FROM
frame => RETURN [cl.frame];
indirect => link ← cl.link↑;
ENDCASE => RETURN[NullFrame];
ENDLOOP;
END;
Signal: PROCEDURE [signal: SIGNAL, message: UNSPECIFIED] = SignalHandler;
SignalList: PROCEDURE [signal: SIGNAL, message: POINTER TO UNSPECIFIED] =
BEGIN
MarkSignalFrame[notSignalling];
SignalHandler[signal, message !
UNWIND => FrameOps.Free[message]];
FrameOps.Free[message];
RETURN
END;
ResumeError: PUBLIC SIGNAL = CODE;
Error: PROCEDURE [signal: SIGNAL, message: UNSPECIFIED] =
BEGIN
MarkSignalFrame[notSignalling];
SignalHandler[signal, message];
ERROR ResumeError
END;
ErrorList: PROCEDURE [signal: SIGNAL, message: POINTER TO UNSPECIFIED] =
BEGIN
MarkSignalFrame[notSignalling];
SignalHandler[signal, message !
UNWIND => FrameOps.Free[message]];
FrameOps.Free[message];
ERROR ResumeError
END;
ReturnError: PROCEDURE [signal: SIGNAL, message: UNSPECIFIED] =
BEGIN
caller: FrameHandle = FrameOps.GetReturnFrame[];
FrameOps.SetReturnLink[caller.returnlink];
MarkSignalFrame[notSignalling];
SignalHandler[signal, message !
UNWIND => FrameOps.Free[caller]];
FrameOps.Free[caller];
ERROR ResumeError
END;
ReturnErrorList: PROCEDURE [signal: SIGNAL, message: POINTER TO UNSPECIFIED] =
BEGIN
caller: FrameHandle = FrameOps.GetReturnFrame[];
FrameOps.SetReturnLink[caller.returnlink];
MarkSignalFrame[notSignalling];
SignalHandler[signal, message !
UNWIND =>
BEGIN
FrameOps.Free[caller];
FrameOps.Free[message];
END];
FrameOps.Free[caller];
FrameOps.Free[message];
ERROR ResumeError
END;
UnnamedError: PROCEDURE =
BEGIN
MarkSignalFrame[notSignalling];
SignalHandler[LOOPHOLE[-1], -1];
ERROR ResumeError
END;
UncaughtSignal: PROCEDURE [msg, signal: UNSPECIFIED, frame: FrameHandle] =
MACHINE CODE BEGIN Mopcodes.zKFCB, SDDefs.sUncaughtSignal END;
END.