DIRECTORY DragomanPrivate, DragomanRefTab, BasicTime, PrincOps, PrincOpsUtils; DragomanXfer: CEDAR PROGRAM IMPORTS DragomanRefTab, RI: DragomanPrivate, BasicTime, PrincOpsUtils EXPORTS DragomanPrivate = { OPEN PrincOps; Value: TYPE = RI.Value; DValue: TYPE = RI.DValue; Ptr1: TYPE = RI.Ptr1; Ptr2: TYPE = RI.Ptr2; LPtr1: TYPE = RI.LPtr1; LPtr2: TYPE = RI.LPtr2; Machine: TYPE = RI.Machine; Byte: TYPE = RI.Byte; Bytes: TYPE = RI.Bytes; Pair: TYPE = RI.Pair; FieldDescriptor: TYPE = PrincOps.FieldDescriptor; LCB: TYPE = RI.LCB; RestartInterpreter: PUBLIC SIGNAL [iFrame: FrameHandle] RETURNS [uFrame: FrameHandle] = CODE; FetchLink: PUBLIC PROC [m: Machine, lki: CARDINAL] RETURNS [ControlLink] = TRUSTED { codeLinks: BOOLEAN; RI.ReadAtAddress[m, LONG[m.g]]; codeLinks _ LOOPHOLE[m.g, GlobalFrameHandle].codelinks; IF codeLinks THEN { cp: LONG POINTER _ LOOPHOLE[m.cb - (lki+1)*SIZE[ControlLink]]; RETURN[LOOPHOLE[RI.Read[m, cp]]]} ELSE { cps: POINTER _ LOOPHOLE[m.g - (lki+1)*SIZE[ControlLink]]; RETURN[LOOPHOLE[RI.Read[m, LONG[cps]]]]} }; MakeProcDesc: PUBLIC PROC [m: Machine, gf: GlobalFrameHandle, entry: CARDINAL] RETURNS [ControlLink] = TRUSTED { gfi: GFTIndex; RI.ReadAtAddress[m, LONG[gf]]; gfi _ gf.gfi; RETURN [[procedure[gfi: gfi + entry / EPRange, ep: entry MOD EPRange, tag: TRUE]]]}; Xfer: PUBLIC PROC [m: Machine, dst, src: ControlLink, push: BOOL _ TRUE, free: BOOL _ FALSE] = TRUSTED { nlf: FrameHandle; nPc: CARDINAL; GF: GlobalFrameHandle; CB: FrameCodeBase; nDst: ControlLink _ dst; -- final destination GFTFrame: PROC [gfti: GFTItem] RETURNS [GlobalFrameHandle] = TRUSTED { gfti.epbias _ 0; RETURN [gfti.framePtr]}; ControlLinkType: PROC [link: ControlLink] RETURNS [ControlLinkTag] = TRUSTED { SELECT TRUE FROM link.proc => RETURN [procedure]; link.indirect => RETURN [indirect]; ENDCASE => RETURN [frame]}; CBRep: TYPE = MACHINE DEPENDENT RECORD [ lo(0:0..14): [0..77777B], out(0:15..15): BOOL, hi(1): CARDINAL]; WHILE ~nDst.proc AND nDst.indirect DO nDst _ LOOPHOLE[RI.Read[m, LOOPHOLE[LONG[nDst.link]]]]; ENDLOOP; SELECT ControlLinkType[nDst] FROM procedure => { evi: CARDINAL; ev: EntryVectorItem; gfti: GFTItem; IF ~m.interestingGfi[nDst.gfi] THEN { CallDirectly[m, nDst]; RETURN}; RI.ReadAtAddress[m, LONG[@GFT[nDst.gfi]]]; gfti _ GFT[nDst.gfi]; m.g _ LOOPHOLE[GF _ GFTFrame[gfti]]; IF GF = NIL THEN RI.UnboundProcTrap[m, dst]; RI.DoubleReadAtAddress[m, LONG[@GF.code]]; CB _ GF.code; IF LOOPHOLE[CB, CBRep].out THEN { LOOPHOLE[CB, CBRep].out _ FALSE; START LOOPHOLE[GF, PROGRAM]}; -- let the start code run in microcode m.cb _ LOOPHOLE[CB]; evi _ gfti.epbias * EPRange + nDst.ep; RI.DoubleReadAtAddress[m, @LOOPHOLE[CB, LCB].entry[evi]]; ev _ LOOPHOLE[CB, LCB].entry[evi]; nPc _ ev.initialpc * 2; IF nPc = 0 THEN RI.UnboundProcTrap[m, dst]; nlf _ RI.AllocFrame[ev.info.framesize]; RI.WriteAtAddress[m, LONG[@nlf.accesslink]]; nlf.accesslink _ GF; RI.WriteAtAddress[m, LONG[@nlf.returnlink]]; nlf.returnlink _ src; nlf.pc _ [nPc+1]; -- to make display lf get the right procedure }; frame => { IF nDst = LOOPHOLE[0] THEN RI.ControlTrap[m, src]; nlf _ LOOPHOLE[nDst]; RI.ReadAtAddress[m, LONG[@nlf.accesslink]]; m.g _ LOOPHOLE[GF _ nlf.accesslink]; RI.DoubleReadAtAddress[m, LONG[@GF.code]]; m.cb _ GF.code.longbase; RI.ReadAtAddress[m, LONG[@nlf.pc]]; nPc _ nlf.pc; IF nPc = 0 THEN RI.UnboundProcTrap[m, dst]; }; ENDCASE; IF push THEN { RI.Push[m, LOOPHOLE[dst]]; RI.Push[m, LOOPHOLE[src]]; m.sd _ m.sd - 2}; IF free THEN RI.FreeFrame[LOOPHOLE[m.l]]; m.l _ LOOPHOLE[nlf]; RI.SetPc[m, nPc]; }; Pulses: PROC RETURNS [BasicTime.Pulses] = {RETURN [BasicTime.GetClockPulses[]]}; lastPulse: BasicTime.Pulses = LAST [BasicTime.Pulses]; -- 2**32 -1 DragomanRefTabSize: CARDINAL _ 101; CallDirectly: PROC [m: Machine, proc: ControlLink] = TRUSTED { m.outCalls _ m.outCalls + 1; IF m.flushOnCall THEN RI.FlushAllCaches[m]; IF m.recordXferOut THEN { lc: DragomanRefTab.Ref _ LOOPHOLE[m.xferData]; found: BOOLEAN; val: DragomanRefTab.Val; IF lc = NIL THEN { m.xferData _ lc _ DragomanRefTab.Create[DragomanRefTabSize]; found _ FALSE} ELSE [found, val] _ DragomanRefTab.Fetch[lc, [link: proc]]; IF found THEN {val.lCount _ val.lCount + 1; val.time _ val.time + (lastPulse - Pulses[]) + 1} ELSE [] _ DragomanRefTab.Store[lc, [link: proc], NEW [DragomanRefTab.ValRec _ [lCount: 1, time: (lastPulse - Pulses[]) + 1]]]; }; CallFromSimulatedStack[m, proc]; Xfer[m: m, dst: [frame[LOOPHOLE[m.l]]], src: NullLink, push: FALSE]; -- simulate return from called proc IF m.recordXferOut THEN { lc: DragomanRefTab.Ref _ LOOPHOLE[m.xferData]; found: BOOLEAN; val: DragomanRefTab.Val; [found, val] _ DragomanRefTab.Fetch[lc, [link: proc]]; val.time _ val.time + Pulses[]; }; RETURN; }; CallFromSimulatedStack: PROC [m: Machine, proc: ControlLink] = TRUSTED { actualReturn: ControlLink _ PrincOpsUtils.GetReturnLink[]; LF: FrameHandle _ RI.FH[m.l]; PrincOpsUtils.SetReturnLink[[frame[LF]]]; -- to make signaller work DoDirectCall[m, proc ! UNWIND => { m.sd _ 0; -- after the unwind, stack should be empty LOOPHOLE[m.l, FrameHandle] _ SIGNAL RestartInterpreter[LOOPHOLE[actualReturn]]}]; PrincOpsUtils.SetReturnLink[actualReturn]; RETURN; }; DoDirectCall: PROC [m: Machine, proc: ControlLink] = TRUSTED { extrajunk: INT _ 0; -- to move state vector to reasonable place args, results: StateVector; args _ [ stk: NULL, instbyte: 0, stkptr: m.sd, data: lst[dest: proc, source: [frame[PrincOpsUtils.MyLocalFrame[ ]]]]]; FOR i: CARDINAL IN [0..MIN[m.sd+2, 14]) DO args.stk[i] _ m.stack[i]; ENDLOOP; TRANSFER WITH args; results _ STATE; -- could use same state vector once debugged FOR i: CARDINAL IN [0..MIN[results.stkptr+2, 14]) DO m.stack[i] _ LOOPHOLE[results.stk[i]]; ENDLOOP; m.sd _ results.stkptr; RETURN; }; LoadState: PUBLIC PROC [m: Machine, free: BOOL] = TRUSTED { alpha: CARDINAL _ RI.NextOpByte[m]; st: POINTER TO StateVector = LOOPHOLE[m.l + alpha]; FOR i: CARDINAL IN [0..MIN[st.stkptr+2, 14]) DO RI.ReadLocal[m, alpha+i]; m.stack[i] _ LOOPHOLE[st.stk[i]]; ENDLOOP; RI.ReadLocal[m, alpha+PrincOps.stackDepth]; m.sd _ st.stkptr; IF ~free THEN { RI.WriteAtAddress[m, LONG[@LOOPHOLE[m.l, FrameHandle].pc]]; LOOPHOLE[m.l, FrameHandle].pc _ [m.pc]}; RI.ReadLocal[m, alpha+PrincOps.stackDepth+1]; RI.ReadLocal[m, alpha+PrincOps.stackDepth+2]; Xfer[m: m, dst: st.dest, src: st.source, push: FALSE, free: free]}; }. @DragomanXfer.mesa Last Edited by: Sweet, March 5, 1985 8:52:56 am PST Bertrand Serlet July 27, 1985 11:12:08 pm PDT Types and Global Data copied pretty much from PrincOps document version3.0c don't bother to record references for Alloc since Dragon uses other scheme IF LOOPHOLE[CB, CBRep].out THEN CodeTrap[dst] ΚΟ˜šœ™J™3Icode™-—J˜šΟk ˜ J˜Jšœ˜Jšœ#˜#J˜—šœ œ˜Jšœ@˜GJšœ˜Jšœ ˜šœ™Jšœœ ˜Jšœœ Οc˜Jšœœ ˜Jšœœ ˜Jšœœ ˜Jšœœ ˜J˜šœ œ˜J˜—Jšœœ ˜Jšœœ ˜Jšœœ ˜Jšœœ˜1šœœœ˜J˜—Jš œœœœœ˜]J˜—š Οn œœœœœœ˜TJšœ œ˜Jšœœ˜Jšœ œ#˜7šœ œ˜Jš œœœ œœ˜>Jšœœœ˜!—šœ˜Jšœœœœ˜9Jšœœœ œ ˜(—J˜J˜—š Ÿ œœœ,œœœ˜pJ˜Jšœœ˜J˜ Jšœ3œœ˜T—˜J˜—šŸœœœ+œœœœœ˜hJšœ5™5J˜Jšœœ˜Jšœ˜Jšœ˜J˜-š ŸœœΠfkΟfœœ˜FJšœœ˜)—šŸœœœœ˜Nšœœ˜Jšœ œ ˜ Jšœœ ˜#Jšœœ ˜——š œœœ œœ˜(Jšœ)œ œ˜@—J˜šœ œ˜%Jš œœœ œœ˜7Jšœ˜—šœ˜!˜Jšœœ˜Jšœ˜J˜šœœ˜%J˜Jšœ˜—Jšœœœ ˜*Jšœœ ˜Jšœœœ˜$Jš œœœœœ˜,Jšœœœ˜*Jšœœ˜ šœœœ œ˜!Jšœœœ˜ Jšœœ œž&˜D—Jšœœœ˜J˜&Jšœœœœ˜9Jšœœœœ ˜"J˜Jšœ œœ˜+JšœJ™JJ˜'Jšœœ˜,Jšœœ˜Jšœœ˜,J˜Jšœž-˜?J˜—˜ Jšœœœœ˜2Jšœœ˜Jšœœ˜+Jšœœœ˜$Jšœœ ˜*Jšœœ˜Jšœ-™-Jšœœ ˜#Jšœ ˜ Jšœ œœ˜+J˜—Jšœ˜—šœœ˜Jšœ œ˜Jšœ œ˜Jšœ˜—Jšœœœ˜)Jšœœ˜Jšœ˜Jšœ˜—J˜JšŸœœœœ˜PJšœœž ˜BJ˜Jšœœ˜#šŸ œœ#œ˜>J˜Jšœœœ˜+šœœ˜Jšœœ ˜.Jšœœ˜Jšœœ˜šœœœ˜Jšœ<˜Jšœ œž+˜?J˜šœ˜Jšœœ˜ Jšœ ˜ Jšœ˜JšœG˜G—š œœœœ˜*J˜Jšœ˜—Jšœœ˜Jšœ œž,˜=š œœœœ˜4Jšœ œ˜&Jšœ˜—Jšœ˜Jšœ˜J˜J˜—š Ÿ œœœœœ˜;Jšœœ˜#Jšœœœœ˜3š œœœœ˜/Jšœ˜Jšœ œ ˜!Jšœ˜—Jšœ)˜+Jšœ˜šœœ˜Jšœœœ˜;Jšœ ˜(—Jšœ+˜-Jšœ+˜-Jšœ/œ˜CJ˜—J˜——…—Κ"Ω