-- PrincOps.Mesa  Edited by Johnsson on Feb 3, 1981 10:04 AM

PrincOps: DEFINITIONS =
  BEGIN

  BYTE: TYPE = [0..377B];

  -- control link definitions

  ControlLinkTag: TYPE = {frame, procedure, indirect, rep};

  ControlLink: TYPE = MACHINE DEPENDENT RECORD [
    SELECT OVERLAID ControlLinkTag FROM
      frame => [frame: FrameHandle],
      procedure => [gfi: GFTIndex, ep: EPIndex, tag: BOOLEAN],
      indirect => [
	SELECT OVERLAID * FROM
	  port => [port: PortHandle],
	  link => [link: POINTER TO ControlLink],
	  ENDCASE],
      rep => [fill: [0..37777B], indirect: BOOLEAN, proc: BOOLEAN],
      ENDCASE];

  ProcDesc, SignalDesc: TYPE = procedure ControlLink;

  TrapLink, NullLink: ControlLink = ControlLink[frame[NullFrame]];
  UnboundLink: ControlLink = ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]];

  PortHandle: TYPE = POINTER TO Port;

  Port: TYPE = MACHINE DEPENDENT RECORD [
    SELECT OVERLAID * FROM
      representation => [in, out: UNSPECIFIED],
      links => [frame: FrameHandle, dest: ControlLink],
      ENDCASE];

  -- frame definitions

  MaxFrameSize: CARDINAL = 4096 - 4;
  MaxSmallFrameIndex: CARDINAL = 17;

  FrameVec: ARRAY FrameSizeIndex OF [0..MaxFrameSize] =
    [7, 11, 15, 19, 23, 27, 31, 39, 47, 55, 67, 79, 95, 111, 127, 147, 171, 203,
      252, 508, 764, 1020, 1276, 1532, 1788, 2044, 2554, 3068, 3580, 4092];

  FrameClass: TYPE = {global, local, signal, catch, dying};

  Frame: TYPE = MACHINE DEPENDENT RECORD [
    accesslink: GlobalFrameHandle,
    pc: BytePC,
    returnlink: ControlLink,
    extensions:
      SELECT OVERLAID FrameClass FROM
	local => [unused: UNSPECIFIED, local: ARRAY [0..0) OF UNSPECIFIED],
	signal => [mark: BOOLEAN, unused: [0..77777B]],
	catch => [
	  unused: UNSPECIFIED, staticlink: FrameHandle, messageval: UNSPECIFIED],
	dying => [state: {dead, alive}, unused: [0..77777B]],
	ENDCASE];

  FrameHandle: TYPE = POINTER TO Frame;
  NullFrame: FrameHandle = LOOPHOLE[0];

  GlobalFrame: TYPE = MACHINE DEPENDENT RECORD [
    gfi: GFTIndex,
    copied, alloced, shared, started: BOOLEAN,
    trapxfers, codelinks: BOOLEAN,
    code: FrameCodeBase,
    global: ARRAY [0..0) OF UNSPECIFIED];

  FrameCodeBase: TYPE = MACHINE DEPENDENT RECORD [
    SELECT OVERLAID * FROM
      long => [longbase: LONG POINTER],
      short => [shortbase: POINTER, handle: POINTER],
      offset => [offset: CARDINAL, highHalf: UNSPECIFIED],
      either => [fill: [0..77777B], out: BOOLEAN, highByte, otherByte: BYTE],
      ENDCASE];

  GlobalFrameHandle: TYPE = POINTER TO GlobalFrame;
  NullGlobalFrame: GlobalFrameHandle = LOOPHOLE[0];

  -- The following offsets are used by the compiler and MUST
  -- reflect the field offsets in the definitions of Frame
  -- local frames

  accessOffset: CARDINAL = 0;
  pcOffset: CARDINAL = 1;
  returnOffset: CARDINAL = 2;

  -- global frames

  gfiOffset: CARDINAL = 0;
  codebaseOffset: CARDINAL = 1;

  -- efficiently addressable portion of frames

  globalbase: CARDINAL = SIZE[GlobalFrame];
  localbase: CARDINAL = SIZE[local Frame];
  framelink: CARDINAL = localbase;

  -- code segments

  BytePC: TYPE = RECORD [CARDINAL];

  InstWord: TYPE = MACHINE DEPENDENT RECORD [evenbyte, oddbyte: BYTE];

  FieldDescriptor: TYPE = MACHINE DEPENDENT RECORD [
    offset: BYTE, posn: [0..16), size: [1..16]];

  EPRange: CARDINAL = 32;
  EPIndex: TYPE = [0..EPRange);

  -- Global frame size preceeds body zero

  CSegPrefix: TYPE = MACHINE DEPENDENT RECORD [
    header: PrefixHeader, entry: ARRAY [0..0) OF EntryVectorItem];

  PrefixHandle: TYPE = POINTER TO CSegPrefix;

  PrefixHeader: TYPE = MACHINE DEPENDENT RECORD [
    swapinfo: WORD, info: PrefixInfo];

  PrefixInfo: TYPE = MACHINE DEPENDENT RECORD [
    stops: BOOLEAN,
    altoCode: BOOLEAN,
    fill: [0..17B],
    ngfi: [1..MaxNGfi],
    nlinks: [0..MaxNLinks]];

  EntryVectorItem: TYPE = MACHINE DEPENDENT RECORD [
    initialpc: BytePC,  -- (currently implemented as WordPC)
    info: EntryInfo];

  EntryInfo: TYPE = MACHINE DEPENDENT RECORD [
    defaults: BOOLEAN, nparams: [0..177B], framesize: [0..377B]];

  MaxNLinks: CARDINAL = 255;
  MainBodyIndex: CARDINAL = 0;

  -- Global Frame Table definitions

  MaxNGfi: CARDINAL = 4;

  --  GFTHandle: TYPE = POINTER TO ARRAY [0..0) OF GFTItem;
  --  GFT: GFTHandle = LOOPHOLE[1400B];
  --  GFTItem: TYPE = MACHINE DEPENDENT RECORD [
  --    frame: GlobalFrameHandle,
  --    epbase: CARDINAL];

  GFTIndex: TYPE = [0..1777B];
  GFTNull: GFTIndex = 0;

  --  NullEpBase: CARDINAL = LAST[CARDINAL];
  --  MaxGFTSize: CARDINAL = (LAST[GFTIndex]+1)*SIZE[GFTItem];

  -- system frame allocation vector

  AllocTag: TYPE = {frame, empty, indirect, enable};

  AVItem: TYPE = MACHINE DEPENDENT RECORD [
    SELECT OVERLAID * FROM
      data => [fsi: [0..37777B], tag: AllocTag],
      link => [link: POINTER TO AVItem],
      frame => [frame: FrameHandle],
      ENDCASE];

  AllocationVectorSize: CARDINAL = 40B;
  LastAVSlot: CARDINAL = AllocationVectorSize - 3;
  FrameSizeIndex: TYPE = [0..LastAVSlot];
  AllocationVector: TYPE = ARRAY [0..AllocationVectorSize) OF AVItem;
  AVHandle: TYPE = POINTER TO AllocationVector;
  AV: AVHandle = LOOPHOLE[1000B];

  --The following frame sizes are not generated by the Compiler
  LargeReturnSlot: CARDINAL = AllocationVectorSize - 2;
  SpecialReturnSlot: CARDINAL = AllocationVectorSize - 1;

  -- control module stuff

  ControlModule: TYPE = MACHINE DEPENDENT RECORD [
    SELECT OVERLAID * FROM
      frame => [frame: GlobalFrameHandle],
      list => [list: POINTER TO FrameList],
      tag => [fill: [0..77777B], multiple: BOOLEAN],
      ENDCASE];

  FrameList: TYPE = MACHINE DEPENDENT RECORD [
    nModules: CARDINAL, frames: ARRAY [0..0) OF GlobalFrameHandle];

  NullControl: ControlModule = [frame[NullGlobalFrame]];

  -- control registers
  -- known by the microcode

  PSBreg: CARDINAL = 0; -- current process

  WDCreg: CARDINAL = 1; -- wakeup disable counter

  XTSreg: CARDINAL = 2; -- xfer trap status

  -- 3, 4, 5 unused

  MDSreg: CARDINAL = 6; -- main data space

  PDAreg: CARDINAL = 7; -- process data area

  PTCreg: CARDINAL = 8; -- process tick count

  SVPointer: TYPE = POINTER TO StateVector;

  stackDepth: CARDINAL = 14;

  StateVector: TYPE = MACHINE DEPENDENT RECORD [
    stk(0): ARRAY [0..stackDepth) OF UNSPECIFIED,
    instbyte(stackDepth:0..7): BYTE,
    stkptr(stackDepth:8..15): BYTE, -- 0 => empty stack
    data(stackDepth+1): SELECT OVERLAID * FROM
      dst => NULL,
      lst => [dest(stackDepth+1), source(stackDepth+2): PrincOps.ControlLink],
      fault => [
	frame(stackDepth+1): POINTER TO local Frame,
	faultData(stackDepth+2): SELECT OVERLAID * FROM
	  allocFault => [fsi(stackDepth+2): FrameSizeIndex],
	  memFault => [memPointer(stackDepth+2): LONG POINTER],
	  otherFault => [dataArray(stackDepth+2): ARRAY [0..0) OF UNSPECIFIED],
	  ENDCASE],
      ENDCASE];

  MaxParamsInStack: CARDINAL = stackDepth - 3;

  END.