DIRECTORY Basics USING [BYTE], MesaRuntimeInit USING [], PrincOps USING [ ControlLink, ControlModule, Frame, FrameCodeBase, FrameHandle, GFT, GFTItem, GlobalFrameHandle, MainBodyIndex, NullControl, NullFrame, NullGlobalFrame, Port, PortHandle, PrefixHandle, sBoundsFault, sControlFault, SD, sDivideCheck, sError, sHardwareError, sPointerFault, sRestart, sStackError, sStart, sSwapTrap, StateVector, sUnbound, SVPointer, sWakeupError, sZeroDivisor, zAND, zDESCBS, zLDIV, zPORTI, zPORTO, zSFC], PrincOpsUtils USING [ Codebase, Free, GetReturnFrame, GetReturnLink, MyLocalFrame, ReadOTP, SetReturnFrame, SetReturnLink], RuntimeError USING []; TrapsImpl: PROGRAM IMPORTS PrincOpsUtils EXPORTS MesaRuntimeInit, RuntimeError = BEGIN OPEN PrincOps; CodeBytesPtr: TYPE = LONG POINTER TO PACKED ARRAY [0..0) OF Basics.BYTE; BoundsFault: PUBLIC ERROR = CODE; ControlFault: PUBLIC SIGNAL [source: FrameHandle] RETURNS [ControlLink] = CODE; DivideCheck: PUBLIC SAFE SIGNAL = CODE; HardwareError: PRIVATE ERROR = CODE; LinkageFault: PUBLIC ERROR = CODE; PointerFault: PUBLIC ERROR = CODE; PortFault: PUBLIC ERROR = CODE; StartFault: PUBLIC SIGNAL [dest: PROGRAM] = CODE; StackError: PUBLIC ERROR = CODE; UnboundProcedure: PUBLIC SIGNAL [dest: ControlLink] RETURNS [ControlLink] = CODE; WakeupError: ERROR = CODE; ZeroDivisor: PUBLIC SAFE SIGNAL = CODE; Start: PUBLIC PROC [cm: PrincOps.ControlModule] = { CM: PROGRAM _ LOOPHOLE[cm]; state: StateVector; state _ STATE; IF ~cm.multiple THEN { OPEN f: cm.frame; IF @f = NullGlobalFrame OR f.started THEN ERROR StartFault[CM]; StartCM[f.global[0], @f, @state]; IF ~f.started THEN {f.started _ TRUE; StartWithState[@f, @state]} ELSE IF state.stkptr ~= 0 THEN SIGNAL StartFault[CM]; } ELSE { StartCM[cm, NIL, NIL]; IF state.stkptr ~= 0 THEN SIGNAL StartFault[CM]; }; }; Restart: PUBLIC PROC [dest: GlobalFrameHandle] = { stops: BOOLEAN; frame: FrameHandle; IF dest = NullGlobalFrame THEN ERROR StartFault[LOOPHOLE[dest, PROGRAM]]; IF ~dest.started THEN Start[[frame[dest]]]; stops _ LOOPHOLE[PrincOpsUtils.Codebase[dest], LONG PrefixHandle].header.info.stops; IF ~stops THEN ERROR StartFault[LOOPHOLE[dest, PROGRAM]]; IF (frame _ dest.global[0]) ~= NullFrame THEN { frame.returnlink _ PrincOpsUtils.GetReturnLink[]; PrincOpsUtils.SetReturnFrame[frame] } }; StartCM: PROC [cm: ControlModule, frame: GlobalFrameHandle, state: SVPointer] = { Call: PROC [ControlLink] = MACHINE CODE {zSFC}; SELECT TRUE FROM cm = NullControl => RETURN; cm.multiple => { length: CARDINAL; cm.multiple _ FALSE; IF (length _ cm.list.nModules) = 0 THEN RETURN; cm.list.nModules _ 0; FOR i: CARDINAL IN [0..length) DO StartCM[[frame[cm.list.frames[i]]], frame, state]; ENDLOOP; PrincOpsUtils.Free[cm.list]; }; cm.frame.started => RETURN; ENDCASE => { control: ControlModule _ cm.frame.global[0]; IF control ~= cm THEN StartCM[control, frame, state]; IF ~cm.frame.started THEN { cm.frame.started _ TRUE; IF frame ~= cm.frame THEN Call[MainBody[cm.frame]] ELSE StartWithState[frame, state]; }; }; }; StartWithState: PROC [frame: GlobalFrameHandle, state: PrincOps.SVPointer] = { s: StateVector _ state^; retFrame: FrameHandle _ PrincOpsUtils.GetReturnLink[].frame; s.dest _ MainBody[frame]; PrincOpsUtils.SetReturnLink[s.source _ retFrame.returnlink]; -- allows stack trace if RETURN WITH s faults. PrincOpsUtils.Free[retFrame]; RETURN WITH s }; BoundsFaultTrap: PROC = { frame: FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ PrincOpsUtils.GetReturnFrame[]]]; BumpPC[frame, 1]; state.v.stkptr _ state.v.stkptr - 1; ERROR BoundsFault; -- pc is advanced on this trap }; CodeTrap: PROC = { dest: ControlLink; state: StateVector; frame: GlobalFrameHandle; state _ STATE; dest _ PrincOpsUtils.ReadOTP[]; state.dest _ PrincOpsUtils.GetReturnLink[]; DO IF dest.proc THEN {frame _ GetFrame[GFT[dest.gfi]]; EXIT} ELSE IF dest.indirect THEN dest _ dest.link^ ELSE {frame _ dest.frame.accesslink; EXIT}; -- frame ENDLOOP; IF ~frame.started THEN Start[[frame[frame]]]; frame.code.out _ FALSE; RETURN WITH state }; DivideCheckTrap: PROC = { frame: FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ PrincOpsUtils.GetReturnFrame[]]]; BumpPC[frame, 1]; state.v.stkptr _ state.v.stkptr - 2; SIGNAL DivideCheck; -- pc is advanced on this trap RETURN WITH state.v }; HardwareErrorTrap: PROC = { state: RECORD [a, b: UNSPECIFIED, v: StateVector]; state.v _ STATE; ERROR HardwareError }; PointerFaultTrap: PROC = { frame: FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ PrincOpsUtils.GetReturnFrame[]]]; BumpPC[frame, 1]; ERROR PointerFault; -- pc is advanced on this trap }; StackErrorTrap: PROC = { state: RECORD [a: UNSPECIFIED, v: StateVector]; foo: BOOLEAN; state.v _ STATE; foo _ TRUE; -- The garbage with foo is so all the code for the next statement IF foo THEN ERROR StackError }; OpcodeLengths: PACKED ARRAY [0..255] OF [0..3] = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 2, 3, 0, 0, 0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 3, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 3, 2, 3, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 0, 2, 2, 1, 0]; UnboundProcedureTrap: PROC = { sourceOp: Basics.BYTE; frame: FrameHandle; dest: ControlLink; state: StateVector; state _ STATE; dest _ PrincOpsUtils.ReadOTP[]; state.dest _ ControlLink[frame[frame _ PrincOpsUtils.GetReturnFrame[]]]; BumpPC[frame, OpcodeLengths[sourceOp _ GetCodeBytes[frame][frame.pc]]]; IF sourceOp = zSFC OR sourceOp = zPORTO THEN state.stkptr _ state.stkptr - 1; [] _ SIGNAL UnboundProcedure[dest]; RETURN WITH state }; WakeupErrorTrap: PROC = { state: RECORD [a, b: UNSPECIFIED, v: StateVector]; state.v _ STATE; ERROR WakeupError }; ZeroDivisorTrap: PROC = { frame: FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ PrincOpsUtils.GetReturnFrame[]]]; state.v.stkptr _ state.v.stkptr - (IF GetCodeBytes[frame][frame.pc] = zLDIV THEN 2 ELSE 1); BumpPC[frame, 1]; SIGNAL ZeroDivisor; -- pc is advanced on this trap RETURN WITH state.v }; ControlFaultTrap: PROC = { errorStart, savedState: StateVector; sourceOp: Basics.BYTE; PORTI: PROC = MACHINE CODE {zPORTI}; p, q: PortHandle; sourceFrame, self: FrameHandle; source: ControlLink; savedState _ STATE; self _ PrincOpsUtils.MyLocalFrame[]; sourceFrame _ self.returnlink.frame; source _ PrincOpsUtils.ReadOTP[]; sourceOp _ GetCodeBytes[sourceFrame][sourceFrame.pc]; BumpPC[sourceFrame, OpcodeLengths[sourceOp]]; IF sourceOp = zPORTO THEN { savedState.stkptr _ savedState.stkptr - 1; p _ source.port; q _ p.dest.port; IF q = NIL THEN errorStart.stk[0] _ LinkageFault ELSE { q^ _ Port[links[NullFrame, [indirect[port[p]]]]]; errorStart.stk[0] _ PortFault }; errorStart.stk[1] _ 0; -- message errorStart.instbyte _ 0; errorStart.stkptr _ 2; errorStart.source _ sourceFrame.returnlink; errorStart.dest _ SD[sError]; IF savedState.stkptr = 0 THEN RETURN WITH errorStart -- RESPONDING port ELSE { p.frame _ self; TRANSFER WITH errorStart; PORTI[]; p.frame _ sourceFrame; savedState.stk[savedState.stkptr + 1] _ savedState.source _ ControlLink[indirect[port[p]]]; savedState.stk[savedState.stkptr] _ savedState.dest _ p.dest; RETURN WITH savedState } } ELSE {-- not a port call IF sourceOp = zSFC THEN savedState.stkptr _ savedState.stkptr - 1; savedState.dest _ ControlLink[frame[sourceFrame]]; [] _ SIGNAL ControlFault[sourceFrame]; RETURN WITH savedState -- to press on } }; BumpPC: PROC [f: FrameHandle, i: INTEGER] = INLINE {f.pc _ [f.pc + i]}; GetCodeBytes: PROC [frame: FrameHandle] RETURNS [CodeBytesPtr] = INLINE { RETURN[LOOPHOLE[frame.accesslink.code.longbase]]}; MainBody: PROC [GlobalFrameHandle] RETURNS [ControlLink] = MACHINE CODE {zDESCBS, MainBodyIndex}; GetFrame: PROC [g: GFTItem] RETURNS [GlobalFrameHandle] = INLINE { And: PROC [g: GFTItem, mask: GFTItem] RETURNS [GlobalFrameHandle] = MACHINE CODE {zAND}; maskFrame: GFTItem = [ep[data: 37777B, epbias: 0]]; RETURN[And[g, maskFrame]] }; Initialize: PROC = { pSD: POINTER TO ARRAY [0..0) OF UNSPECIFIED _ SD; pSD[sBoundsFault] _ BoundsFaultTrap; pSD[sControlFault] _ ControlFaultTrap; pSD[sDivideCheck] _ DivideCheckTrap; pSD[sHardwareError] _ HardwareErrorTrap; pSD[sPointerFault] _ PointerFaultTrap; pSD[sRestart] _ Restart; pSD[sStackError] _ StackErrorTrap; pSD[sStart] _ Start; pSD[sSwapTrap] _ CodeTrap; pSD[sUnbound] _ UnboundProcedureTrap; pSD[sWakeupError] _ WakeupErrorTrap; pSD[sZeroDivisor] _ ZeroDivisorTrap; }; Initialize[]; END. lTrapsImpl.mesa last edited by Levin on September 20, 1983 11:12 am Types and Related Declarations Exported to RuntimeError Exported to MesaRuntimeInit Language support routines Internal Procedures to support language support routines Trap Handlers RETURN WITH state.v RETURN WITH state.v looks like it is in this procedure to the debugger (when it looks in the fine grain table) The following should be exported by InstructionsImpl, or, in Trinity, the ProcessorFace. lets UNWIND skip trapping frame Assert: there is a (possibly stubbed) signaller Internal procedures to support trap handlers Initialization Κ 0– "Cedar" style˜Jšœ™J™3J˜šΟk ˜ Jšœœœ˜Jšœœ˜šœ œ˜Jšœ?œ“œΛ˜’—šœœ˜Jšœe˜e—Jšœ œ˜J˜—šœ ˜Jšœ˜Jšœ ˜'J˜—Jš˜J˜Jšœ ˜J˜J˜J™J˜Jšœœœœœœœœœ˜HJ˜J˜Jšœ™J˜Jšœ œœœ˜!Jš œœœœœ˜OJš œ œœœœ˜'Jšœœœœ˜$Jšœœœœ˜"Jšœœœœ˜"Jšœ œœœ˜Jš œ œœœœ˜1Jšœ œœœ˜ Jš œœœœœ˜QJšœ œœ˜Jš œ œœœœ˜'J˜J™Jšœ™J˜šΟnœœœ!˜3Jšœœœ˜Jšœ˜Jšœœ˜šœœ˜Jšœ ˜Jš œœ œœ œ˜?J˜!Jšœ œœ˜AJš œœœœ œ˜5Jšœ˜—šœ˜Jšœ œœ˜Jšœœœ œ˜0Jšœ˜—Jšœ˜J˜J˜J˜—J™J˜šžœœœ˜2Jšœœ˜J˜Jš œœœ œœ˜IJšœœ˜+Jšœœœ!˜TJš œœœ œœ˜9šœ'œ˜/Jšœ1˜1Jšœ#˜#Jšœ˜—Jšœ˜J˜J˜—J˜JšΟc8™8J™šžœœD˜QJšžœœœœ˜/šœœ˜Jšœœ˜˜Jšœœ˜Jšœœ˜Jšœ!œœ˜/J˜šœœœ ˜!Jšœ2˜2Jšœ˜—J˜Jšœ˜—Jšœœ˜šœ˜ J˜,Jšœœ ˜5šœœ˜Jšœœ˜Jšœœ˜2Jšœ˜"Jšœ˜—Jšœ˜——Jšœ˜J˜J˜J˜—šžœœ:˜NJ˜J˜Ÿ.˜lJšœ˜Jšœœ˜ Jšœ˜J˜—™J˜—Jšœ ™ J˜J˜šžœœ˜J˜Jšœœ œ˜/Jšœ œ˜J˜JJ˜J˜$JšœŸ˜2Jšœ™Jšœ˜J˜—šžœœ˜J˜J˜J˜Jšœœ˜J˜J˜+š˜Jšœ œœ œ˜9š˜Jšœœ˜'Jšœ!œŸ˜4—Jšœ˜—Jšœœ˜-Jšœœ˜Jšœœ˜Jšœ˜J˜—šžœœ˜J˜Jšœœ œ˜/Jšœ œ˜J˜JJ˜J˜$JšœŸ˜2Jšœœ˜Jšœ˜J˜—šžœœ˜Jšœœ œ˜2Jšœ œ˜Jšœ˜Jšœ˜J˜—šžœœ˜J˜Jšœœ œ˜/Jšœ œ˜J˜JJ˜JšœŸ˜2Jšœ™Jšœ˜J˜—šžœœ˜Jšœœ œ˜/Jšœœ˜ Jšœ œ˜JšœœŸA˜MJšœ"™"Jšœ7™7Jšœœœ ˜Jšœ˜J˜—JšœX™XJ™šœœœ œ ˜0˜NJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜J˜——šžœœ˜Jšœœ˜J˜J˜J˜Jšœœ˜J˜J˜HJ˜GJšœœœ!˜MJšœœ˜#Jšœœ˜Jšœ˜J˜—šžœœ˜Jšœœ œ˜2Jšœ œ˜Jšœ ˜Jšœ˜J˜—šžœœ˜J˜Jšœœ œ˜/Jšœ œ˜J˜JJšœ#œ'œœ˜[J˜JšœŸ˜2Jšœœ˜Jšœ˜J˜—šžœœ˜J˜$Jšœœ˜Jšœœœœ ˜$J˜J˜J˜Jšœ œ˜J˜$J˜$J˜!J˜5J˜-šœœ˜J˜*J˜J˜Jšœœœ!˜0šœ˜J˜1J˜Jšœ˜—JšœŸ ˜!J˜J˜J˜+Jšœ™Jšœœ ˜Jš œœœœ Ÿ˜Hšœ˜J˜Jšœœ ˜Jšœ˜J˜J˜[J˜=Jšœœ ˜Jšœ˜—Jšœ˜—šœŸ˜Jšœœ+˜BJšœ/™/J˜2Jšœœ˜&Jšœœ Ÿ˜%Jšœ˜—Jšœ˜J˜J˜J˜—J™,J˜J˜Jšžœœœœ˜GJ˜J˜šž œœœœ˜IJšœœ#˜2J˜J˜—šžœœœ˜:Jšœœ˜&—J˜šžœœœœ˜Bšžœœœ˜DJšœœ˜—J˜3Jšœ˜J˜J˜—J˜Jšœ™J™šž œœ˜Jš œœœœœ œœ˜1J˜$J˜&J˜$J˜(J˜&J˜J˜"J˜J˜J˜%J˜$J˜$Jšœ˜J˜J˜—J˜ J˜J˜Jšœ˜J˜J˜J˜J˜J˜—…—#ϊ1–