-- FramesXD.Mesa  Edited by: Sandman  July 22, 1980  4:28 PM
--		  Edited by: Bruce  Oct 10, 1980 11:47 AM

DIRECTORY
  DebugOps USING [Lengthen, LongREAD, ShortCopyREAD, ShortREAD],
  Frames USING [PreDeclared],
  Gf USING [CodeBase, Handle],
  Init USING [bootLoaded],
  Inline USING [LowHalf],
  MachineDefs USING [ControlLink, FSHandle, GFHandle, GFT, GFTIndex, PageSize],
  PrincOps USING [ControlLink, FrameCodeBase],
  SegmentDefs USING [FileSegmentObject],
  State USING [GetGS, GSHandle];
  
FramesXD: PROGRAM
  IMPORTS DebugOps, Frames, Init, Gf, Inline, State
  EXPORTS Gf, MachineDefs =
  BEGIN OPEN Gf, MachineDefs;
  
  data: State.GSHandle = State.GetGS[];
  
  GfiToFrame: PUBLIC PROC [gfi: GFTIndex] RETURNS [GFHandle] = {
    RETURN[DebugOps.ShortREAD[@MachineDefs.GFT[gfi].frame]]};
    
  GfiToOffset: PUBLIC PROC [gfi: GFTIndex] RETURNS [CARDINAL] = {
    RETURN[DebugOps.ShortREAD[@MachineDefs.GFT[gfi].epbase]]};
    
  OldLink: PUBLIC PROC [ncl: PrincOps.ControlLink]
    RETURNS [ocl: MachineDefs.ControlLink] =
    BEGIN
    IF Frames.PreDeclared[ncl] THEN RETURN[LOOPHOLE[ocl]];
    IF ncl.proc THEN
      BEGIN
      ocl.gfi ← ncl.gfi; ocl.ep ← ncl.ep;
      ocl.tag ← IF ncl.gfi = 0 THEN unbound ELSE procedure;
      END
    ELSE ocl ← LOOPHOLE[ncl];
    END;
    
  SameModule: PUBLIC PROC [gf1, gf2: Handle] RETURNS [BOOLEAN] =
    BEGIN
    code1: PrincOps.FrameCodeBase = CodeBase[gf1];
    code2: PrincOps.FrameCodeBase = CodeBase[gf2];
    seg1, seg2: POINTER;
    o1, o2: CARDINAL;
    IF code1.out AND code2.out THEN RETURN[code1.handle = code2.handle];
    IF code1.highByte = 0 AND code2.highByte = 0 THEN
      RETURN[code1.longbase = code2.longbase];
    IF Init.bootLoaded THEN RETURN[FALSE];
    [seg1, o1] ← MungeCodeBase[code1];
    [seg2, o2] ← MungeCodeBase[code2];
    RETURN[seg1 = seg2 AND o1 = o2];
    END;
    
  MungeCodeBase: PROC [code: PrincOps.FrameCodeBase]
      RETURNS [seg: POINTER, o: CARDINAL] =
    BEGIN
    SELECT TRUE FROM
      code.out => {code.out ← FALSE; o ← code.offset; seg ← code.handle};
      code.highByte # 0 => {
	o ← code.shortbase - UserFileSegmentAddress[code.handle];
	seg ← code.handle};
      ENDCASE => {
	seg ← SegFromPage[bank: code.otherByte, p: code.offset/MachineDefs.PageSize];
	o ← Inline.LowHalf[code.longbase - UserLongFileSegmentAddress[seg]]};
    END;
    
  SegFromPage: PROCEDURE [bank, p: CARDINAL] RETURNS [POINTER] = INLINE {
    RETURN[DebugOps.LongREAD[LP[p, bank]]]};
    
  LP: PROCEDURE [low, high: CARDINAL] RETURNS [LONG POINTER] =
    MACHINE CODE BEGIN END;
    
  UserFileSegmentAddress: PROC [seg: MachineDefs.FSHandle] RETURNS [POINTER] =
    BEGIN OPEN DebugOps, SegmentDefs;
    lseg: FileSegmentObject;
    ShortCopyREAD[from: seg, to: @lseg, nwords: SIZE[FileSegmentObject]];
    RETURN[LOOPHOLE[lseg.VMpage*MachineDefs.PageSize]]
    END;
    
  UserLongFileSegmentAddress: PROC [seg: MachineDefs.FSHandle] RETURNS [LONG POINTER] =
    BEGIN OPEN DebugOps, SegmentDefs;
    lseg: FileSegmentObject;
    ShortCopyREAD[from: seg, to: @lseg, nwords: SIZE[FileSegmentObject]];
    RETURN[LOOPHOLE[LONG[lseg.VMpage]*MachineDefs.PageSize]]
    END;
    
  END.