-- 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...