DIRECTORY Environment USING [Byte], Frame USING [Free, GetReturnFrame, GetReturnLink, MyLocalFrame, SetReturnFrame, SetReturnLink], Mopcodes USING [zDESCBS, zLDIV, zPORTI, zPORTO, zSFC], ProcessorFace USING [SetMP], PilotMP USING [cEarlyTrap, Code], PrincOps USING [ AV, AVHandle, ControlLink, ControlModule, Frame, FrameCodeBase, FrameHandle, GlobalFrameHandle, LargeReturnSlot, MainBodyIndex, NullControl, NullFrame, NullGlobalFrame, Port, PortHandle, PrefixHandle, StateVector, SVPointer], PrincOpsRuntime USING [GetFrame, GFT], Runtime USING [ValidateGlobalFrame], RuntimeInternal USING [Codebase], RuntimePrograms USING [], SDDefs USING [ sBoundsFault, sControlFault, SD, sDivideCheck, sError, sHardwareError, sPointerFault, sRestart, sSignal, sStackError, sStart, sSwapTrap, sUnbound, sWakeupError, sZeroDivisor], Trap USING [ReadOTP]; Traps: PROGRAM IMPORTS Frame, PrincOpsRuntime, ProcessorFace, RuntimeInternal, Trap, Runtime EXPORTS Runtime, RuntimePrograms = BEGIN ControlLink: TYPE = PrincOps.ControlLink; FrameHandle: TYPE = PrincOps.FrameHandle; GlobalFrameHandle: TYPE = PrincOps.GlobalFrameHandle; StateVector: TYPE = PrincOps.StateVector; AV: PrincOps.AVHandle = PrincOps.AV; LargeReturnSlot: CARDINAL = PrincOps.LargeReturnSlot; 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; CodeBytesPtr: TYPE = LONG POINTER TO PACKED ARRAY [0..0) OF Environment.Byte; BumpPC: PROCEDURE [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 BEGIN Mopcodes.zDESCBS, PrincOps.MainBodyIndex END; --RuntimePrograms.--Restart: PUBLIC PROC [dest: GlobalFrameHandle] = BEGIN stops: BOOLEAN; frame: FrameHandle; IF dest = PrincOps.NullGlobalFrame THEN ERROR StartFault[LOOPHOLE[dest, PROGRAM]]; IF ~dest.started THEN Start[[frame[dest]]]; stops _ LOOPHOLE[RuntimeInternal.Codebase[LOOPHOLE[dest, PROGRAM]], LONG PrincOps.PrefixHandle].header.info.stops; IF ~stops THEN ERROR StartFault[LOOPHOLE[dest, PROGRAM]]; IF (frame _ dest.global[0]) # PrincOps.NullFrame THEN BEGIN frame.returnlink _ Frame.GetReturnLink[]; Frame.SetReturnFrame[frame] END END; --RuntimePrograms.--Start: PUBLIC PROCEDURE [cm: PrincOps.ControlModule] = BEGIN CM: PROGRAM; FramesStarted: PROCEDURE RETURNS [BOOLEAN] = INLINE BEGIN OPEN PrincOpsRuntime; dest: ControlLink = LOOPHOLE[Runtime.ValidateGlobalFrame]; RETURN[GetFrame[GFT[dest.gfi]].started]; END; state: StateVector; state _ STATE; CM _ LOOPHOLE[cm]; IF ~cm.multiple THEN BEGIN OPEN f: cm.frame; IF @f = PrincOps.NullGlobalFrame OR f.started THEN ERROR StartFault[CM]; IF FramesStarted[] THEN Runtime.ValidateGlobalFrame[@f]; 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]; END ELSE BEGIN StartCM[cm, NIL, NIL]; IF state.stkptr # 0 THEN SIGNAL StartFault[CM]; END; RETURN END; StartCM: PROCEDURE [ cm: PrincOps.ControlModule, frame: GlobalFrameHandle, state: PrincOps.SVPointer] = BEGIN Call: PROCEDURE [ControlLink] = MACHINE CODE BEGIN Mopcodes.zSFC END; SELECT TRUE FROM cm = PrincOps.NullControl => RETURN; cm.multiple => BEGIN 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; Frame.Free[cm.list]; END; cm.frame.started => RETURN; ENDCASE => BEGIN control: PrincOps.ControlModule _ cm.frame.global[0]; IF control # cm THEN StartCM[control, frame, state]; IF ~cm.frame.started THEN BEGIN cm.frame.started _ TRUE; IF frame # cm.frame THEN Call[MainBody[cm.frame]] ELSE StartWithState[frame, state]; END; END; RETURN END; StartWithState: PROC [frame: GlobalFrameHandle, state: PrincOps.SVPointer] = BEGIN s: StateVector _ state^; retFrame: FrameHandle _ Frame.GetReturnLink[].frame; s.dest _ MainBody[frame]; Frame.SetReturnLink[s.source _ retFrame.returnlink]; -- allows stack trace if RETURN WITH s faults. Frame.Free[retFrame]; RETURN WITH s; END; BoundsFaultTrap: PROC = BEGIN frame: PrincOps.FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ Frame.GetReturnFrame[]]]; BumpPC[frame, 1]; state.v.stkptr _ state.v.stkptr - 1; ERROR BoundsFault; -- pc is advanced on this trap END; CodeTrap: PROC = BEGIN OPEN PrincOpsRuntime; dest: ControlLink; state: StateVector; frame: GlobalFrameHandle; state _ STATE; dest _ Trap.ReadOTP[]; state.dest _ Frame.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 END; DivideCheckTrap: PROC = BEGIN frame: PrincOps.FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ Frame.GetReturnFrame[]]]; BumpPC[frame, 1]; state.v.stkptr _ state.v.stkptr - 2; SIGNAL DivideCheck; -- pc is advanced on this trap RETURN WITH state.v END; HardwareErrorTrap: PROC = BEGIN state: RECORD [a, b: UNSPECIFIED, v: StateVector]; state.v _ STATE; ERROR HardwareError END; PointerFaultTrap: PROC = BEGIN frame: PrincOps.FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ Frame.GetReturnFrame[]]]; BumpPC[frame, 1]; ERROR PointerFault; -- pc is advanced on this trap END; StackErrorTrap: PROC = BEGIN 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 END; 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 = BEGIN sourceOp: Environment.Byte; frame: PrincOps.FrameHandle; dest: ControlLink; state: StateVector; state _ STATE; dest _ Trap.ReadOTP[]; state.dest _ ControlLink[frame[frame _ Frame.GetReturnFrame[]]]; BumpPC[frame, OpcodeLengths[sourceOp _ GetCodeBytes[frame][frame.pc]]]; IF sourceOp = Mopcodes.zSFC OR sourceOp = Mopcodes.zPORTO THEN state.stkptr _ state.stkptr - 1; [] _ SIGNAL UnboundProcedure[dest]; RETURN WITH state END; WakeupErrorTrap: PROC = BEGIN state: RECORD [a, b: UNSPECIFIED, v: StateVector]; state.v _ STATE; ERROR WakeupError END; ZeroDivisorTrap: PROC = BEGIN frame: PrincOps.FrameHandle; state: RECORD [a: UNSPECIFIED, v: StateVector]; state.v _ STATE; state.v.dest _ ControlLink[frame[frame _ Frame.GetReturnFrame[]]]; state.v.stkptr _ state.v.stkptr - (IF GetCodeBytes[frame][frame.pc] = Mopcodes.zLDIV THEN 2 ELSE 1); BumpPC[frame, 1]; SIGNAL ZeroDivisor; -- pc is advanced on this trap RETURN WITH state.v END; ControlFaultTrap: PROC = BEGIN errorStart, savedState: StateVector; sourceOp: Environment.Byte; PORTI: PROC = MACHINE CODE BEGIN Mopcodes.zPORTI END; p, q: PrincOps.PortHandle; sourceFrame, self: FrameHandle; source: ControlLink; savedState _ STATE; self _ Frame.MyLocalFrame[]; sourceFrame _ self.returnlink.frame; source _ Trap.ReadOTP[]; sourceOp _ GetCodeBytes[sourceFrame][sourceFrame.pc]; BumpPC[sourceFrame, OpcodeLengths[sourceOp]]; IF sourceOp = Mopcodes.zPORTO THEN BEGIN savedState.stkptr _ savedState.stkptr - 1; p _ source.port; q _ p.dest.port; IF q = NIL THEN errorStart.stk[0] _ LinkageFault ELSE BEGIN q^ _ PrincOps.Port[links[PrincOps.NullFrame, [indirect[port[p]]]]]; errorStart.stk[0] _ PortFault END; errorStart.stk[1] _ 0; -- message errorStart.instbyte _ 0; errorStart.stkptr _ 2; errorStart.source _ sourceFrame.returnlink; errorStart.dest _ SDDefs.SD[SDDefs.sError]; IF savedState.stkptr = 0 THEN RETURN WITH errorStart -- RESPONDING port ELSE BEGIN 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 END END ELSE -- not a port call BEGIN Punt: PROC [c: PilotMP.Code] = INLINE BEGIN ProcessorFace.SetMP[c]; DO ENDLOOP END; IF sourceOp = Mopcodes.zSFC THEN savedState.stkptr _ savedState.stkptr - 1; IF SDDefs.SD[SDDefs.sSignal] = 0 THEN Punt[PilotMP.cEarlyTrap]; savedState.dest _ ControlLink[frame[sourceFrame]]; [] _ SIGNAL ControlFault[sourceFrame]; RETURN WITH savedState -- to press on END END; Initialize: PROC = BEGIN OPEN SDDefs; 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; END; Initialize[]; END. ΒTraps.mesa last edited by Levin on March 11, 1983 4:43 pm Non-trap type procedures: don't start trap module Frames early!! 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) lets UNWIND skip trapping frame avoid loop XFER break tracing implementation: The following code is thought not to work. Furthermore, we do not want it permanently resident. Thus it is retired, at least for now. continueTracing: BOOLEAN; ++RuntimeInternal.++StartTrace: PUBLIC PROC [ loc: POINTER, val: UNSPECIFIED, mask: WORD, equal: BOOLEAN] = BEGIN state: PrincOps.StateVector; lval: UNSPECIFIED; continueTracing _ TRUE; state _ STATE; state.dest _ Frame.GetReturnLink[]; SDDefs.SD[SDDefs.sXferTrap] _ state.source _ Frame.MyLocalFrame[]; ProcessInternal.DisableInterrupts[]; DO lval _ Inline.BITAND[loc^, mask]; IF (IF equal THEN val = lval ELSE val # lval) THEN RuntimeInternal.WorryCallDebugger["TraceTrap"L]; IF ~continueTracing THEN { SDDefs.SD[SDDefs.sXferTrap] _ 0; ProcessInternal.EnableInterrupts[]; RETURN WITH state} ELSE { XferTrap.WriteXTS[skip1]; ProcessInternal.EnableInterrupts[]; TRANSFER WITH state}; ProcessInternal.DisableInterrupts[]; state _ STATE; XferTrap.WriteXTS[off]; state.dest _ Frame.GetReturnLink[]; state.source _ 0; ENDLOOP END; ++RuntimeInternal.++StopTrace: PUBLIC PROC = {continueTracing _ FALSE}; (This code only needs to be initially resident.) Main body ΚB– "Cedar" style˜Jšœ ™ J™.J˜šΟk ˜ Jšœ œ˜šœœ&˜1J˜-—Jšœ œ(˜6Jšœœ ˜Jšœœ˜!šœ œ˜Jšœ˜J˜1J˜2J˜.J˜2—Jšœœ œ˜&Jšœœ˜$Jšœœ ˜!Jšœœ˜šœœ˜Jšœœ6˜UJ˜Y—Jšœœ ˜J˜—šœ˜JšœF˜MJšœ˜"J˜—Jš˜J˜J˜Jšœ œ˜)Jšœ œ˜)Jšœœ˜5Jšœ œ˜)J˜Jšœœ˜$J˜Jšœœ˜5J˜J˜Jšœ œœœ˜!Jš œœœœœ˜OJš œ œœœœ˜'Jšœœœœ˜$Jšœœœœ˜"Jšœœœœ˜"Jšœ œœœ˜Jš œ œœœœ˜1Jšœ œœœ˜ šœœœœ˜KJšœ˜—Jšœ œœ˜Jš œ œœœœ˜'J˜Jšœœœœœœœœ˜MJ˜J˜Jšœ™J˜J˜JšΟnœ œœœ˜LJ˜J˜šž œœœœ˜IJšœœ#˜2J˜J˜—š žœœœœ˜GJšœ*œ˜3J˜J˜J˜—šΟcžœœœ˜DJš˜Jšœœ˜J˜Jš œ!œœ œœ˜RJšœœ˜+šœœœœ˜CJšœ*˜.—Jš œœœ œœ˜9šœ/˜5Jš˜J˜)J˜Jš˜—Jšœ˜J˜J˜J˜—šŸžœœ œ˜JJš˜Jšœœ˜ š ž œ œœœ˜3Jšœœ˜Jšœœ˜:Jšœ œ˜(Jšœ˜—J˜Jšœœ˜Jšœœ˜šœ˜Jšœœ ˜Jš œœ œœ œ˜HJšœ&™&Jšœœ!˜8J˜!Jšœ œœ˜CJš œœœœ œ˜4Jš˜—š˜Jš˜Jšœ œœ˜Jšœœœ œ˜/Jšœ˜—Jš˜Jšœ˜J˜J˜J˜—šžœ œ˜J˜RJš˜Jš žœ œœœœœ˜Ešœœ˜Jšœœ˜$˜Jš˜Jšœœ˜Jšœœ˜Jšœ!œœ˜/J˜šœœœ ˜!Jšœ3œ˜;—J˜Jšœ˜—Jšœœ˜šœ˜ Jš˜J˜5Jšœœ ˜4šœ˜Jš˜Jšœœ˜Jšœœ˜1Jšœ˜"Jšœ˜—Jšœ˜——Jš˜Jšœ˜J˜J˜J˜—šžœœ8˜LJš˜J˜J˜4J˜Jšœ6Ÿ.˜dJ˜Jšœœ˜Jšœ˜J˜J˜J˜—Jšœ™J˜J˜J˜šžœœ˜Jš˜J˜Jšœœ œ˜/Jšœ œ˜J˜BJ˜J˜$JšœŸ˜2Jšœ™Jšœ˜J˜J˜J˜—šžœœ˜Jšœœ˜J˜J˜J˜Jšœœ˜J˜J˜#š˜Jšœ œœ œ˜9š˜Jšœœ˜'Jšœ!œŸ˜4J˜—Jšœ˜—Jšœœ˜-Jšœœ˜Jšœœ˜Jšœ˜J˜J˜J˜—šžœœ˜Jš˜J˜Jšœœ œ˜/Jšœ œ˜J˜BJ˜J˜$JšœŸ˜2Jšœœ˜Jšœ˜J˜J˜J˜—šžœœ˜Jš˜Jšœœ œ˜2Jšœ œ˜Jšœ˜Jšœ˜J˜J˜J˜—šžœœ˜Jš˜J˜Jšœœ œ˜/Jšœ œ˜J˜BJ˜JšœŸ˜2Jšœ™Jšœ˜J˜J˜J˜—šžœœ˜Jš˜Jšœœ œ˜/Jšœœ˜ Jšœ œ˜JšœœŸA˜MJšœ"™"Jšœ7™7Jšœœœ ˜Jšœ˜J˜J˜J˜—šœœœ œ ˜0˜NJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜JJ˜J˜J˜J˜——šžœœ˜Jš˜J˜J˜J˜J˜Jšœœ˜J˜J˜@J˜Gšœœ˜>J˜ —Jšœœ˜#Jšœœ˜Jšœ˜J˜J˜J˜—šžœœ˜Jš˜Jšœœ œ˜2Jšœ œ˜Jšœ ˜Jšœ˜J˜J˜J˜—šžœœ˜Jš˜J˜Jšœœ œ˜/Jšœ œ˜J˜B˜˜Jšœœ0œœ˜B——J˜JšœŸ˜2Jšœœ˜Jšœ˜J˜J˜J˜—šžœœ˜Jš˜J˜$J˜Jš œœœœœœ˜5J˜J˜J˜J˜Jšœ œ˜J˜J˜$J˜J˜5J˜-šœ˜"Jš˜J˜*J˜J˜Jšœœœ!˜0š˜Jš˜J˜CJ˜Jšœ˜—JšœŸ ˜!J˜J˜J˜+Jšœ™Jšœœ˜+Jš œœœœ Ÿ˜HJ˜š˜Jš˜J˜Jšœœ ˜Jšœ˜J˜˜'J˜3—J˜=Jšœœ ˜Jš˜—Jš˜—šœŸ˜Jš˜šžœœ˜%Jšœœœœ˜-—Jšœœ+˜KJšœœœ˜?Jšœ ™ J˜2Jšœœ˜&Jšœœ Ÿ˜%J˜Jš˜—Jšœ˜J˜J˜J˜—Jšœ"™"J˜Jšœ‡™‡J˜Jšœ™J˜J˜J˜Jšœ-™-Jšœ=™=Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ#™#JšœB™BJšœ$™$Jšœ™Jšœ!™!Jšœ2™2Jšœ0™0Jšœ™Jšœ ™ Jšœ#™#Jšœ™Jšœ™Jšœ™Jšœ#™#Jšœ™Jšœ$™$Jšœ™Jšœ™Jšœ#™#Jšœ™Jšœ™Jšœ™J˜JšœG™GJ˜J˜J˜šž œœ˜Jšœ0™0Jšœœ˜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˜J˜J˜J˜J˜—…—(`