-- XMDebug.Mesa -- Edited by: -- Levin on November 16, 1978 11:21 AM DIRECTORY AltoDefs: FROM "altodefs" USING [PageSize, wordlength], BitBltDefs: FROM "BitBltDefs" USING [BBptr, BBTable], BootDefs: FROM "bootdefs" USING [BusyPage, FreePage, PageMap, SystemTableHandle], ControlDefs: FROM "controldefs" USING [GetReturnLink, GlobalFrameHandle, InstWord, Lreg, StateVector], DebugData: FROM "debugdata" USING [ESV], DebugUsefulDefs: FROM "debugusefuldefs" USING [CopyRead, CopyWrite, SREAD], DebugUtilityDefs: FROM "debugutilitydefs" USING [AllocOnDrum, RemoveFromDrum, MapUserSegment], DebugXMDefs: FROM "debugxmdefs", GlobalFrameDefs: FROM "globalframedefs" USING [FrameCodeBase, GlobalFrameHandle], InlineDefs: FROM "InlineDefs" USING [DIVMOD], Mopcodes: FROM "Mopcodes" USING [zADD, zAND, zDUP, zLI1], NovaOps: FROM "NovaOps" USING [NovaJSR], ProcessDefs: FROM "ProcessDefs" USING [DisableInterrupts, EnableInterrupts], SDDefs: FROM "SDDefs" USING [SD], SegmentDefs: FROM "segmentdefs" USING [DeleteFileSegment, FileSegmentAddress, FileSegmentHandle, FileSegmentObject, SegmentHandle, SegmentObject, SwapIn, Unlock], XMESA: FROM "xmesaprivatedefs" USING [Bank1X, Bank2X, Bank3X, InUseSeal, XFileSegmentHandle, XFileSegmentObject, XMremote, XSegInfo], XMesaDefs: FROM "xmesadefs" USING [BankIndex, HighHalfPtr, LowHalfPtr, sXCOPY, XCOPY]; XMDebug: PROGRAM IMPORTS DDptr: DebugData, DebugUsefulDefs, DebugUtilityDefs, SegmentDefs, XMesaDefs EXPORTS DebugXMDefs, XMesaDefs SHARES XMESA, SegmentDefs = BEGIN GFH: TYPE = ControlDefs.GlobalFrameHandle; SH: TYPE = SegmentDefs.SegmentHandle; SO: TYPE = SegmentDefs.SegmentObject; FSH: TYPE = SegmentDefs.FileSegmentHandle; FSO: TYPE = SegmentDefs.FileSegmentObject; XFSH: TYPE = XMESA.XFileSegmentHandle; XFSO: TYPE = XMESA.XFileSegmentObject; XSegInfo: TYPE = XMESA.XSegInfo; -- Utilities XMRead: PUBLIC PROCEDURE [from: LONG POINTER] RETURNS [data: UNSPECIFIED] = BEGIN XMesaDefs.XCOPY[from: from, to: LONG[@data], nwords: 1]; RETURN END; XMWrite: PUBLIC PROCEDURE [to: LONG POINTER, data: UNSPECIFIED] = BEGIN seg: SH; SegObj: SO; XMesaDefs.XCOPY[from: LONG[@data], to: to, nwords: 1]; -- check for codesegment and write on Drum seg ← SegmentFromLongPointer[to]; IF seg = BootDefs.BusyPage OR seg = BootDefs.FreePage THEN RETURN; DebugUsefulDefs.CopyRead[to: @SegObj, from: seg, nwords: SIZE[SO]]; WITH s: seg SELECT FROM file => IF s.class = code THEN BEGIN pi: POINTER TO ControlDefs.InstWord; chocolate: XFSH = @cSegObj; vanilla: FSH = @vSegObj; cSegObj: XFSO; vSegObj: FSO; xs: XSegInfo; dseg: FSH; ChocolateToVanilla[chocolate, vanilla, @s]; dseg ← DebugUtilityDefs.MapUserSegment[@s]; SegmentDefs.SwapIn[dseg]; dseg.write ← TRUE; WITH c: chocolate SELECT FROM remote => BEGIN IF c.proc # XMESA.XMremote THEN ERROR; DebugUsefulDefs.CopyRead[to: @xs, from: c.info, nwords: SIZE[XSegInfo]]; IF xs.seal # XMESA.InUseSeal THEN ERROR; END; ENDCASE => ERROR; pi ← SegmentDefs.FileSegmentAddress[dseg]+ (LOOPHOLE[XMesaDefs.LowHalfPtr[to], CARDINAL] - xs.XMpage*AltoDefs.PageSize); pi↑ ← data; SegmentDefs.Unlock[dseg]; SegmentDefs.DeleteFileSegment[dseg]; VanillaToChocolate[vanilla, chocolate, @s]; END; ENDCASE; RETURN END; XMAllocOnDrum: PUBLIC PROCEDURE[g: GFH] RETURNS[p: POINTER] = BEGIN chocolate: XFSH = @cSegObj; vanilla: FSH = @vSegObj; cSegObj: XFSO; vSegObj: FSO; seg: FSH; seg ← SegmentFromFrame[g]; ChocolateToVanilla[chocolate, vanilla, seg]; p ← DebugUtilityDefs.AllocOnDrum[seg !UNWIND => VanillaToChocolate[vanilla, chocolate, seg]]; VanillaToChocolate[vanilla, chocolate, seg]; RETURN END; XMFreeOnDrum: PUBLIC PROCEDURE[g: GFH] = BEGIN chocolate: XFSH = @cSegObj; vanilla: FSH = @vSegObj; cSegObj: XFSO; vSegObj: FSO; seg: FSH; seg ← SegmentFromFrame[g]; ChocolateToVanilla[chocolate, vanilla, seg]; DebugUtilityDefs.RemoveFromDrum[seg !UNWIND => VanillaToChocolate[vanilla, chocolate, seg]]; VanillaToChocolate[vanilla, chocolate, seg]; END; ChocolateToVanilla: PROCEDURE [chocolate: XFSH, vanilla: FSH, seg: FSH] = BEGIN xs: XSegInfo; DebugUsefulDefs.CopyRead[to: chocolate, from: seg, nwords: SIZE[XFSO]]; vanilla↑ ← LOOPHOLE[chocolate↑]; WITH c: chocolate SELECT FROM remote => BEGIN IF c.proc # XMESA.XMremote THEN ERROR; DebugUsefulDefs.CopyRead[to: @xs, from: c.info, nwords: SIZE[XSegInfo]]; IF xs.seal # XMESA.InUseSeal THEN ERROR; END; ENDCASE => ERROR; vanilla.location ← disk[xs.hint]; DebugUsefulDefs.CopyWrite[to: seg, from: vanilla, nwords: SIZE[FSO]]; END; VanillaToChocolate: PROCEDURE [vanilla: FSH, chocolate: XFSH, seg: FSH] = BEGIN xs: XSegInfo; DebugUsefulDefs.CopyRead[to: vanilla, from: seg, nwords: SIZE[FSO]]; chocolate.file ← vanilla.file; chocolate.base ← vanilla.base; chocolate.pages ← vanilla.pages; chocolate.lock ← vanilla.lock; WITH v: vanilla SELECT FROM disk => WITH c: chocolate SELECT FROM remote => BEGIN DebugUsefulDefs.CopyRead[to: @xs, from: c.info, nwords: SIZE[XSegInfo]]; IF xs.seal # XMESA.InUseSeal THEN ERROR; xs.hint ← v.hint; DebugUsefulDefs.CopyWrite[to: c.info, from: @xs, nwords: SIZE[XSegInfo]]; END; ENDCASE => ERROR; ENDCASE => ERROR; DebugUsefulDefs.CopyWrite[to: seg, from: chocolate, nwords: SIZE[XFSO]]; END; SegmentFromFrame: PROCEDURE [g: GFH] RETURNS [FSH] = BEGIN seg: SH; segment: SO; c: GlobalFrameDefs.FrameCodeBase; DebugUsefulDefs.CopyRead[from: @LOOPHOLE[g, GlobalFrameDefs.GlobalFrameHandle].code, to: @c, nwords: SIZE[GlobalFrameDefs.FrameCodeBase]]; IF c.highByte # 0 THEN RETURN[c.handle]; seg ← SegmentFromLongPointer[c.codebase]; IF seg = BootDefs.FreePage OR seg = BootDefs.BusyPage THEN ERROR; DebugUsefulDefs.CopyRead[from: seg, to: @segment, nwords: SIZE[SO]]; WITH segment SELECT FROM file => RETURN[LOOPHOLE[seg]]; ENDCASE => ERROR END; SegmentFromLongPointer: PROCEDURE [p: LONG POINTER] RETURNS [seg: SH] = BEGIN bank: XMesaDefs.BankIndex; page: [0..256); table: BootDefs.SystemTableHandle = DDptr.ESV.tables; bank ← XMesaDefs.HighHalfPtr[p]; IF bank ~ IN XMesaDefs.BankIndex THEN ERROR; page ← LOOPHOLE[XMesaDefs.LowHalfPtr[p], CARDINAL]/AltoDefs.PageSize; IF table # NIL THEN BEGIN OPEN DebugUsefulDefs; page0map: POINTER TO BootDefs.PageMap ← SREAD[@table.pagemap]; pagemap: POINTER TO BootDefs.PageMap; pagemap ← SELECT bank FROM 1 => SREAD[@page0map[XMESA.Bank1X]], 2 => SREAD[@page0map[XMESA.Bank2X]], 3 => SREAD[@page0map[XMESA.Bank3X]], ENDCASE => page0map; IF pagemap = NIL THEN ERROR; RETURN[SREAD[@pagemap[page]]] END ELSE ERROR END; -- here follows the code for XCOPY NovaBBArgBlock: TYPE = MACHINE DEPENDENT RECORD [ fill: [0..37777B], bank: XMesaDefs.BankIndex, bbt: BitBltDefs.BBptr ]; XCOPYProc: TYPE = PROCEDURE [from, to: LONG POINTER, nwords: CARDINAL]; -- Constants maxRasterWidth: CARDINAL = 3777B; initialBBT: BitBltDefs.BBTable = [ pad: 0, sourcealt: FALSE, destalt: FALSE, sourcetype: block, function: replace, unused: 0, dbca: NIL, -- will be filled in dbmr: maxRasterWidth, dlx: 0, dty: 0, dw: 0*AltoDefs.wordlength, -- will be filled in dh: 0, -- will be filled in sbca: NIL, -- will be filled in sbmr: maxRasterWidth, slx: 0, sty: 0, gray0: 0, gray1: 0, gray2: 0, gray3: 0 ]; -- Global Frame Data bbTable: ARRAY [0..SIZE[BitBltDefs.BBTable]+1) OF UNSPECIFIED; arg: NovaBBArgBlock; NovaCode: ARRAY [0..16) OF CARDINAL ← [ 54415B, -- STA 3 saveret 115000B, -- MOV 0 3 AC3: @arg 22415B, -- LDA 0 @bankno 40413B, -- STA 0 savebank savebank ← EmulatorBankRegister 21400B, -- LDA 0 0,3 42412B, -- STA 0 @bankno EmulatorBankRegister ← arg.bank 31401B, -- LDA 2 1,3 AC2: arg.bbt 126400B, -- SUB 1 1 AC1: 0 61024B, -- BITBLT 20405B, -- LDA 0 savebank 42405B, -- STA 0 @bankno EmulatorBankRegister ← savebank 34402B, -- LDA 3 saveret 1400B, -- JMP 0 3 0B, -- saveret: 0 0B, -- savebank: 0 177740B -- bankno: 177740 ]; -- Signals InvalidXCOPY: PUBLIC ERROR = CODE; -- Code XCOPYSaysBadArgs: PROCEDURE = BEGIN ERROR XMesaDefs.InvalidXCOPY END; MakeItEven: PROCEDURE[arg: POINTER] RETURNS[POINTER] = MACHINE CODE BEGIN Mopcodes.zDUP; Mopcodes.zLI1; Mopcodes.zAND; Mopcodes.zADD END; XCOPYproc: PROCEDURE RETURNS[XCOPYProc] = BEGIN OPEN XMESA; fromBank, toBank: XMesaDefs.BankIndex; nwords: CARDINAL; bbt: BitBltDefs.BBptr; state: ControlDefs.StateVector; state ← STATE; ProcessDefs.DisableInterrupts[]; state.dest ← ControlDefs.GetReturnLink[]; state.stkptr ← 1; state.stk[0] ← REGISTER[ControlDefs.Lreg]; -- first time return LocalFrameHandle bbt ← MakeItEven[@bbTable]; arg ← [fill: 0, bank: 0, bbt: bbt]; DO ProcessDefs.EnableInterrupts[]; TRANSFER WITH state; -- Enter here from KFCB sXCOPY ProcessDefs.DisableInterrupts[]; state ← STATE; state.dest ← state.source; state.stkptr ← 0; bbt↑ ← initialBBT; fromBank ← state.stk[1]; bbt.sbca ← state.stk[0]; toBank ← state.stk[3]; bbt.dbca ← state.stk[2]; nwords ← state.stk[4]; BEGIN -- for error exit IF fromBank = 0 THEN IF toBank = 0 THEN GO TO BogusArguments -- "impossible" in the debugger ELSE BEGIN arg.bank ← toBank; bbt.destalt ← TRUE END ELSE BEGIN arg.bank ← fromBank; SELECT toBank FROM = 0 => bbt.sourcealt ← TRUE; = fromBank => bbt.sourcealt ← bbt.destalt ← TRUE; ENDCASE => GO TO BogusArguments; END; -- BitBlt legal and necessary state.source ← 0; IF nwords > maxRasterWidth THEN BEGIN -- large segment requires 2 BitBlts rem: [0..maxRasterWidth); wordsInFirstBitBlt: CARDINAL; bbt.dw ← maxRasterWidth*AltoDefs.wordlength; [bbt.dh, rem] ← InlineDefs.DIVMOD[nwords, maxRasterWidth]; wordsInFirstBitBlt ← nwords-rem; [] ← NovaOps.NovaJSR[code: JSR, address: @NovaCode, arg: @arg]; IF (nwords ← rem) # 0 THEN BEGIN bbt.dbca ← bbt.dbca + wordsInFirstBitBlt; bbt.sbca ← bbt.sbca + wordsInFirstBitBlt END ELSE LOOP END; bbt.dw ← nwords*AltoDefs.wordlength; bbt.dh ← 1; [] ← NovaOps.NovaJSR[code: JSR, address: @NovaCode, arg: @arg]; EXITS BogusArguments => state.dest ← XCOPYSaysBadArgs; END; ENDLOOP; END; -- of XCOPYproc -- Main Body SDDefs.SD[XMesaDefs.sXCOPY] ← XCOPYproc[]; END...