-- MesaDebug.Mesa  edited by Sandman on May 21, 1980  11:52 AM
-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  ControlDefs USING [
    ControlLink, EPRange, FrameHandle, NullFrame, StateVector, TraceNext,
    TraceOff, TrapParameter, TrapStatus],
  FrameDefs USING [MakeCodeResident, UnlockCode],
  FrameOps USING [
    Free, GetReturnLink, MyGlobalFrame, MyLocalFrame, SetReturnFrame,
    SetReturnLink],
  InlineDefs USING [BITAND],
  MiscDefs USING [WorryCallDebugger],
  NucleusOps USING [],
  ProcessDefs USING [DisableInterrupts, EnableInterrupts],
  SDDefs USING [SD, sXferTrap],
  TrapDefs USING [],
  TrapOps USING [ReadXTP, ReadXTS, WriteXTS];

MesaDebug: PROGRAM
  IMPORTS FrameDefs, FrameOps, InlineDefs, MiscDefs, ProcessDefs, TrapOps
  EXPORTS NucleusOps, TrapDefs =
  BEGIN

  continueTracing: BOOLEAN;

  StartTrace: PUBLIC PROCEDURE [
    loc: POINTER, val: UNSPECIFIED, mask: WORD, equal: BOOLEAN] =
    BEGIN OPEN ControlDefs;
    state: StateVector;
    trapParam: TrapParameter;
    status: TrapStatus ← TraceOff;
    frame: FrameHandle;
    ep: CARDINAL;
    lval: UNSPECIFIED;
    FrameDefs.MakeCodeResident[FrameOps.MyGlobalFrame[]];
    continueTracing ← TRUE;
    state ← STATE;
    state.dest ← FrameOps.GetReturnLink[];
    SDDefs.SD[SDDefs.sXferTrap] ← state.source ← FrameOps.MyLocalFrame[];
    ProcessDefs.DisableInterrupts[];
    ProcessDefs.DisableInterrupts[];
    DO
      lval ← InlineDefs.BITAND[loc↑, mask];
      IF (IF equal THEN val = lval ELSE val # lval) THEN
	MiscDefs.WorryCallDebugger["Trap"L];
      IF status.reason = return THEN
	BEGIN FrameOps.Free[frame]; state.source ← NullFrame; END;
      IF ~continueTracing THEN
	BEGIN
	ProcessDefs.EnableInterrupts[];
	ProcessDefs.EnableInterrupts[];
	RETURN WITH state;
	END
      ELSE
	BEGIN
	TrapOps.WriteXTS[TraceNext];
	ProcessDefs.EnableInterrupts[];
	ProcessDefs.EnableInterrupts[];
	TRANSFER WITH state;
	END;
      ProcessDefs.DisableInterrupts[];
      ProcessDefs.DisableInterrupts[];
      state ← STATE;
      trapParam ← TrapOps.ReadXTP[];
      status ← TrapOps.ReadXTS[];
      TrapOps.WriteXTS[TraceOff];
      SELECT status.reason FROM
	other =>
	  FrameOps.SetReturnLink[
	    IF state.source = NullFrame THEN trapParam.link ELSE state.source];
	localCall =>
	  BEGIN
	  ep ← (trapParam.ep - 2)/2;
	  frame ← state.source;
	  trapParam.link ← ControlLink[
	    procedure[
	    tag: procedure, gfi: frame.accesslink.gfi + ep/EPRange,
	    ep: ep MOD EPRange]];
	  FrameOps.SetReturnFrame[frame];
	  END;
	return =>
	  BEGIN
	  frame ← trapParam.frame - 6;
	  trapParam.link ← frame.returnlink;
	  FrameOps.SetReturnFrame[frame];
	  END;
	ENDCASE;
      state.dest ← trapParam.link;
      ENDLOOP;
    END;

  StopTrace: PUBLIC PROCEDURE =
    BEGIN
    continueTracing ← FALSE;
    FrameDefs.UnlockCode[FrameOps.MyGlobalFrame[]];
    RETURN
    END;

  -- Main Body;


  END.