DIRECTORY Basics USING [BYTE, RawBytes], 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 Basics.RawBytes; BoundsFault: PUBLIC ERROR = CODE; ControlFault: PUBLIC SIGNAL [source: ControlLink] 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[LOOPHOLE[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: BOOL; frame: FrameHandle; IF dest = NullGlobalFrame THEN ERROR StartFault[LOOPHOLE[dest, PROGRAM]]; IF ~dest.started THEN Start[[frame[dest]]]; stops _ PrincOpsUtils.Codebase[dest].header.info.stops; IF ~stops THEN ERROR StartFault[LOOPHOLE[dest, PROGRAM]]; IF (frame _ LOOPHOLE[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 _ LOOPHOLE[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: WORD, 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}; IF NOT dest.indirect THEN {frame _ dest.frame.accesslink; EXIT}; dest _ dest.link^; ENDLOOP; IF ~frame.started THEN Start[[frame[frame]]]; frame.code.out _ FALSE; RETURN WITH state }; DivideCheckTrap: PROC = { frame: FrameHandle; state: RECORD [a: WORD, 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: WORD, v: StateVector]; state.v _ STATE; ERROR HardwareError }; PointerFaultTrap: PROC = { frame: FrameHandle; state: RECORD [a: WORD, 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: WORD, v: StateVector]; foo: BOOL; 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: WORD, v: StateVector]; state.v _ STATE; ERROR WakeupError }; ZeroDivisorTrap: PROC = { frame: FrameHandle; state: RECORD [a: WORD, 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] _ LOOPHOLE[LinkageFault] ELSE { q^ _ Port[links[NullFrame, [indirect[port[p]]]]]; errorStart.stk[0] _ LOOPHOLE[PortFault]; }; errorStart.stk[1] _ 0; -- message errorStart.instbyte _ 0; errorStart.stkptr _ 2; errorStart.source _ sourceFrame.returnlink; errorStart.dest _ LOOPHOLE[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] _ LOOPHOLE[savedState.source _ ControlLink[indirect[port[p]]]]; savedState.stk[savedState.stkptr] _ LOOPHOLE[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[LOOPHOLE[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 NAT OF PROC ANY RETURNS ANY _ LOOPHOLE[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. ΞTrapsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Levin on September 20, 1983 11:12 am Russ Atkinson (RRA) February 19, 1985 1:18:43 pm PST 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 Κ {– "Cedar" style˜codešœ™Kšœ Οmœ1™ .˜lKšœ˜Kšžœžœ˜ Kšœ˜K˜—Kšœ ™ K˜šŸœžœ˜K˜Kšœžœžœ˜(Kšœ žœ˜K˜JK˜K˜$Kšžœ ˜2Kšœ™Kšœ˜K˜—šŸœžœ˜K˜K˜K˜Kšœžœ˜K˜K˜+šž˜Kšžœ žœžœ žœ˜:Kšžœžœžœ!žœ˜@Kšœ˜Kšžœ˜—Kšžœžœ˜-Kšœžœ˜Kšžœžœ˜Kšœ˜K˜—šŸœžœ˜K˜Kšœžœžœ˜(Kšœ žœ˜K˜JK˜K˜$Kšžœ ˜2Kšžœžœ˜Kšœ˜K˜—šŸœžœ˜Kšœžœžœ˜+Kšœ žœ˜Kšžœ˜Kšœ˜K˜—šŸœžœ˜K˜Kšœžœžœ˜(Kšœ žœ˜K˜JK˜Kšžœ ˜2Kšœ™Kšœ˜K˜—šŸœžœ˜Kšœžœžœ˜(Kšœžœ˜ Kšœ žœ˜Kšœžœ A˜MKšœ"™"Kšœ7™7Kšžœžœžœ ˜Kšœ˜K˜—KšœX™XK™šœžœžœ žœ ˜2Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ/˜/Kšœ0˜0K˜—šŸœžœ˜Kšœžœ˜K˜K˜K˜Kšœžœ˜K˜K˜HK˜GKšžœžœžœ!˜MKšœžœ˜#Kšžœžœ˜Kšœ˜K˜—šŸœžœ˜Kšœžœžœ˜+Kšœ žœ˜Kšžœ ˜Kšœ˜K˜—šŸœžœ˜K˜Kšœžœžœ˜(Kšœ žœ˜K˜JKšœ#žœ'žœžœ˜[K˜Kšžœ ˜2Kšžœžœ˜Kšœ˜K˜—šŸœžœ˜K˜$Kšœžœ˜Kšžœžœžœžœ ˜$K˜K˜K˜Kšœ žœ˜K˜$K˜$K˜!K˜5K˜-šžœ˜šžœ˜K˜*K˜K˜šžœž˜ Kšžœžœ˜/šžœ˜K˜1Kšœžœ ˜(Kšœ˜——Kšœ  ˜!K˜K˜K˜+Kšœ™Kšœžœžœ ˜'Kš žœžœžœžœ  ˜Hšžœ˜K˜Kšžœžœ ˜Kšžœ˜K˜Kšœ(žœ5˜eKšœ$žœ˜GKšžœžœ ˜Kšœ˜—Kšœ˜—šžœ ˜Kšžœžœ+˜BKšœ/™/K˜2Kšœžœžœ˜0Kšžœžœ  ˜%Kšœ˜——Kšœ˜K˜—™,K˜KšŸœžœžœžœ˜GK˜šŸ œžœžœžœ˜IKšžœžœ#˜2K˜—šŸœžœžœ˜:Kšžœžœ˜&—K˜šŸœžœžœžœ˜BšŸœžœžœ˜DKšžœžœ˜—K˜3Kšžœ˜K˜—K˜—šœ™K™šŸ œžœ˜Kšœžœžœžœžœžœžœžœžœžœžœžœ˜AK˜$K˜&K˜$K˜(K˜&K˜K˜"K˜K˜K˜%K˜$K˜$šœ˜K˜——K˜ K˜—Kšžœ˜K˜K˜K˜K˜K˜—…—#ζ2/