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