<> <> <> <> <> <<>> DIRECTORY Basics USING [ FWORD, Card16FromH, HFromCard16, DoubleShiftRight, LongDiv, LongMult ], DoveInputOutput USING [ Peek, Poke ], SparcSoftcard, SparcSoftcardMap; <> <<>> SparcSoftcardMapImpl: PROGRAM IMPORTS Basics, DoveInputOutput EXPORTS SparcSoftcardMap ~ { <> MapEntry: TYPE ~ SparcSoftcardMap.MapEntry; <<>> <> <<>> MapEntryConcrete: TYPE = MACHINE DEPENDENT RECORD [ dirty: BOOLEAN, referenced: BOOLEAN, readOnly: BOOLEAN, nonCachable: BOOLEAN, interrupt: BOOLEAN, task: BYTE, virtualPageHiHi: [0..7H], -- 3 bits, virtualPageHiLow: [0..3H], -- 2 bits, trash: BOOL, realPage: [0..1FFFH] -- 13 bits ]; <> PeekAtByteAd: PROC [byteAd: CARD32] RETURNS [content: CARD16] ~ { wordAd: CARD32 _ Basics.DoubleShiftRight[[lc [byteAd]], 1].lc; -- /2 content _ DoveInputOutput.Peek[wordAd]; }; PokeAtByteAd: PROC [byteAd: CARD32, content: CARD16] ~ { wordAd: CARD32 _ Basics.DoubleShiftRight[[lc [byteAd]], 1].lc; -- /2 DoveInputOutput.Poke[wordAd, content]; }; <> ReadMapEntry: PUBLIC PROC [ mapEntry: MapEntry ] RETURNS [ oldMapEntry: MapEntry ] ~ { windowNumber: CARD16; entryAddressHighByte, entryAddressLowByte: CARD32; oldMapEntryConcrete: Basics.FWORD; [windowNumber, entryAddressHighByte, entryAddressLowByte] _ ComputeEntryAddress[mapEntry]; PokeAtByteAd[SparcSoftcard.mapWindowIndexRegisterByte, windowNumber]; <> oldMapEntryConcrete.hi _ Basics.HFromCard16[PeekAtByteAd[entryAddressHighByte]]; oldMapEntryConcrete.lo _ Basics.HFromCard16[PeekAtByteAd[entryAddressLowByte]]; oldMapEntry _ EntryFromConcrete[oldMapEntryConcrete]; oldMapEntry.vMSpace.name _ mapEntry.vMSpace.name; oldMapEntry.virtualAddressByte _ mapEntry.virtualAddressByte; -- for now, see EntryFromConcrete }; WriteMapEntry: PUBLIC PROC [ mapEntry: SparcSoftcardMap.MapEntry ] ~ { windowNumber: CARD16; entryAddressHighByte, entryAddressLowByte: CARD32; mapEntryConcrete: Basics.FWORD; [windowNumber, entryAddressHighByte, entryAddressLowByte] _ ComputeEntryAddress[mapEntry]; mapEntryConcrete _ ConcreteFromEntry[mapEntry]; PokeAtByteAd[SparcSoftcard.mapWindowIndexRegisterByte, windowNumber]; <> PokeAtByteAd[entryAddressHighByte, Basics.Card16FromH[mapEntryConcrete.hi]]; <> PokeAtByteAd[entryAddressLowByte, Basics.Card16FromH[mapEntryConcrete.lo]]; <> }; ComputeEntryAddress: PROC [ mapEntry: SparcSoftcardMap.MapEntry ] RETURNS [windowNumber: CARD16, entryAddressHighByte, entryAddressLowByte: CARD32]~ { mapEntryNumber: CARD16; windowOffset: CARD16; <> <<>> SELECT mapEntry.vMSpace.name FROM <> = dMA => { mapEntryNumber _ 0E000H; IF mapEntry.virtualAddressByte >= 4000000H THEN ERROR; <
> }; = iOP => { mapEntryNumber _ 0A000H; IF mapEntry.virtualAddressByte >= 1000000H THEN ERROR; <
> }; = cP => { mapEntryNumber _ 0A000H + 1000000H/SparcSoftcard.softcardPageSizeByte; <> IF mapEntry.virtualAddressByte >= 400000H THEN ERROR; <
> }; = sparcUserData => { mapEntryNumber _ 0; IF mapEntry.virtualAddressByte >= 8000000H THEN ERROR; <<***>> <<*** In this first implementation the address range is limited to 128 Meg. >> <<*** Only task 0 is implemented. >> <<***>> }; = sparcUserProgram => { mapEntryNumber _ 4000H; IF mapEntry.virtualAddressByte >= 8000000H THEN ERROR; <<***>> <<*** In this first implementation the address range is limited to 128 Meg.>> <<*** Only task 0 is implemented. >> <<***>> }; = sparcSuperData => { mapEntryNumber _ 8000H; IF mapEntry.virtualAddressByte >= 4000000H THEN ERROR; <> }; = sparcSuperProgram => { mapEntryNumber _ 0C000H; IF mapEntry.virtualAddressByte >= 4000000H THEN ERROR; <> }; ENDCASE => ERROR; mapEntryNumber _ mapEntryNumber + Basics.LongDiv[mapEntry.virtualAddressByte, SparcSoftcard.softcardPageSizeByte]; <> windowNumber _ mapEntryNumber / SparcSoftcard.mapEntriesPerWindow; windowOffset _ mapEntryNumber MOD SparcSoftcard.mapEntriesPerWindow; <> entryAddressHighByte _ SparcSoftcard.mapWindowBaseByte + SparcSoftcard.mapEntryHighByteOffset + windowOffset * SparcSoftcard.mapEntrySizeByte; entryAddressLowByte _ SparcSoftcard.mapWindowBaseByte + SparcSoftcard.mapEntryLowByteOffset + windowOffset * SparcSoftcard.mapEntrySizeByte; }; ConcreteFromEntry: PROC [ mapEntry: SparcSoftcardMap.MapEntry ] RETURNS [mapEntryConcreteFW: Basics.FWORD] ~ { mapEntryConcrete: MapEntryConcrete; mapEntryConcrete.readOnly _ mapEntry.flags.readOnly; mapEntryConcrete.referenced _ mapEntry.flags.referenced; mapEntryConcrete.dirty _ mapEntry.flags.dirty; mapEntryConcrete.nonCachable _ mapEntry.flags.nonCachable; mapEntryConcrete.interrupt _ mapEntry.flags.interrupt; mapEntryConcrete.task _ 0; <<***>> <<*** Now only task 0 is implemented>> <<***>> mapEntryConcrete.virtualPageHiHi _ 0; mapEntryConcrete.virtualPageHiLow _ 0; <<***>> <<*** Now only 128 Meg of VM>> <<***>> mapEntryConcrete.realPage _ Basics.LongDiv[mapEntry.realAddressByte, SparcSoftcard.softcardPageSizeByte]; mapEntryConcreteFW _ LOOPHOLE[mapEntryConcrete]; }; EntryFromConcrete: PROC [ mapEntryConcreteFW: Basics.FWORD ] RETURNS [mapEntry: SparcSoftcardMap.MapEntry] ~ { mapEntryConcrete: MapEntryConcrete _ LOOPHOLE[mapEntryConcreteFW]; mapEntry.flags.readOnly _ mapEntryConcrete.readOnly; mapEntry.flags.referenced _ mapEntryConcrete.referenced; mapEntry.flags.dirty _ mapEntryConcrete.dirty; mapEntry.flags.nonCachable _ mapEntryConcrete.nonCachable; mapEntry.flags.interrupt _ mapEntryConcrete.interrupt; IF mapEntryConcrete.task#0 THEN ERROR; -- Now only task 0 is implemented mapEntry.vMSpace.task _ mapEntryConcrete.task; IF mapEntryConcrete.virtualPageHiHi*4+mapEntryConcrete.virtualPageHiLow#0 THEN ERROR; --Now only 128 Meg of VM mapEntry.virtualAddressByte _ 0; mapEntry.realAddressByte _ Basics.LongMult[mapEntryConcrete.realPage, SparcSoftcard.softcardPageSizeByte] }; }.