-- Faults.mesa; edited by Sandman, August 1, 1980 10:45 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoDefs USING [BYTE], ControlDefs USING [ ControlLink, FrameHandle, GlobalFrameHandle, InstWord, NullFrame, Port, PortHandle, StateVector, SVPointer], CoreSwapDefs USING [], FrameDefs USING [SwapInCode], FrameOps USING [GetReturnFrame, MyLocalFrame, ReleaseCode], Mopcodes USING [zPORTI, zRBL], NucleusOps USING [], Resident USING [CSPort, MemorySwap, WBPort], Runtime USING [], SDDefs USING [sCoreSwap, SD, sError], SDOps USING [], SegmentDefs USING [memConfig], TrapDefs USING [], TrapOps USING [ReadOTP]; Faults: PROGRAM IMPORTS FrameDefs, FrameOps, ResidentPtr: Resident, SegmentDefs, TrapOps EXPORTS NucleusOps, Runtime, SDOps, TrapDefs SHARES ControlDefs, Resident =PUBLIC BEGIN OPEN ControlDefs; -- Traps StackError: ERROR = CODE; StackErrorTrap: PROCEDURE = BEGIN state: StateVector; foo: BOOLEAN; state _ STATE; foo _ TRUE; IF foo THEN ERROR StackError; END; GenericFault: PROCEDURE [state: SVPointer, signal: SIGNAL] = BEGIN frame: FrameHandle _ FrameOps.GetReturnFrame[]; SIGNAL signal; state.source _ frame; state.dest _ frame.returnlink; RETURN END; PointerFault: SIGNAL = CODE; PointerFaultTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; IF SegmentDefs.memConfig.AltoType IN [AltoI..AltoIIXM] THEN state.stkptr _ state.stkptr + 1; GenericFault[@state, PointerFault]; RETURN WITH state; END; BoundsFault: SIGNAL = CODE; BoundsFaultTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; GenericFault[@state, BoundsFault]; RETURN WITH state; END; ZeroDivisor: SIGNAL = CODE; ZeroDivisorTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; GenericFault[@state, ZeroDivisor]; RETURN WITH state; END; DivideCheck: SIGNAL = CODE; DivideCheckTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; GenericFault[@state, DivideCheck]; RETURN WITH state; END; UnimplementedInst: SIGNAL = CODE; UnimplementedInstTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; GenericFault[@state, UnimplementedInst]; RETURN WITH state; END; WakeupError: SIGNAL = CODE; WakeupErrorTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; GenericFault[@state, WakeupError]; RETURN WITH state; END; PageFault: SIGNAL [page: CARDINAL] = CODE; PageFaultTrap: PROCEDURE = BEGIN state: StateVector; foo: BOOLEAN; page: CARDINAL; state _ STATE; page _ LOOPHOLE[TrapOps.ReadOTP[]]; foo _ TRUE; IF foo THEN ERROR PageFault[page]; END; WriteProtectFault: SIGNAL [page: CARDINAL] = CODE; WriteProtectFaultTrap: PROCEDURE = BEGIN state: StateVector; foo: BOOLEAN; page: CARDINAL; state _ STATE; page _ LOOPHOLE[TrapOps.ReadOTP[]]; foo _ TRUE; IF foo THEN ERROR WriteProtectFault[page]; END; HardwareError: SIGNAL = CODE; HardwareErrorTrap: PROCEDURE = BEGIN state: StateVector; state _ STATE; GenericFault[@state, HardwareError]; RETURN WITH state; END; NullPort: PortHandle = LOOPHOLE[0]; PortFault: ERROR = CODE; LinkageFault: ERROR = CODE; ControlFault: SIGNAL [source: FrameHandle] RETURNS [ControlLink] = CODE; PORTI: PROCEDURE = MACHINE CODE BEGIN Mopcodes.zPORTI END; ControlFaultTrap: PROCEDURE = BEGIN errorStart, savedState: StateVector; p, q: PortHandle; sourceFrame, self: FrameHandle; savedState _ STATE; self _ FrameOps.MyLocalFrame[]; IF PortCall[self.returnlink] THEN BEGIN p _ self.returnlink.port; q _ p.dest.port; sourceFrame _ p.frame; IF q = NullPort THEN errorStart.stk[0] _ LinkageFault ELSE BEGIN q^ _ Port[links[NullFrame, [indirect[port[p]]]]]; errorStart.stk[0] _ PortFault; END; errorStart.stk[1] _ 0; 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.source _ p; savedState.dest _ p.dest; RETURN WITH savedState; END; END ELSE BEGIN savedState.source _ self.returnlink; savedState.dest _ SIGNAL ControlFault[savedState.source]; RETURN WITH savedState END; END; PortCall: PROCEDURE [source: ControlLink] RETURNS [BOOLEAN] = BEGIN portcall: BOOLEAN _ FALSE; WHILE source.tag = indirect DO source _ source.link^; ENDLOOP; IF source.tag = frame AND ReturnByte[source.frame, 0] = Mopcodes.zPORTI THEN portcall _ TRUE; RETURN[portcall] END; ReadLongInstWord: PROCEDURE [LONG POINTER] RETURNS [InstWord] = MACHINE CODE BEGIN Mopcodes.zRBL, 0 END; ReturnByte: PROCEDURE [frame: FrameHandle, byteoffset: INTEGER] RETURNS [byte: AltoDefs.BYTE] = BEGIN g: GlobalFrameHandle = frame.accesslink; bytePC: CARDINAL = byteoffset + (IF frame.pc < 0 THEN 2*(-frame.pc) + 1 ELSE 2*frame.pc); FrameDefs.SwapInCode[g]; IF g.code.highByte = 0 THEN BEGIN iw: InstWord _ ReadLongInstWord[g.code.longbase + bytePC/2]; byte _ IF bytePC MOD 2 # 0 THEN iw.oddbyte ELSE iw.evenbyte; END ELSE BEGIN iw: POINTER TO InstWord _ g.code.shortbase + bytePC/2; byte _ IF bytePC MOD 2 # 0 THEN iw.oddbyte ELSE iw.evenbyte; END; FrameOps.ReleaseCode[g]; RETURN END; InitSwapPorts: PROCEDURE = BEGIN OPEN SDDefs; sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED _ SD; resident: POINTER TO FRAME[Resident] _ ResidentPtr; BEGIN OPEN resident; LOOPHOLE[CSPort, Port].in _ MemorySwap; LOOPHOLE[CSPort, Port].out _ @WBPort; sd[sCoreSwap] _ LOOPHOLE[WBPort, Port].out _ @CSPort; WBPort[NIL]; END; END; END...