<> <> 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; <> <> <> <<++RuntimeInternal.++StartTrace: PUBLIC PROC [>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<++RuntimeInternal.++StopTrace: PUBLIC PROC = {continueTracing _ FALSE};>> Initialize: PROC = <<(This code only needs to be initially resident.)>> 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.