Types
MapEntry: TYPE ~ SparcSoftcardMap.MapEntry;
Exact layout of the bits inside a map entry:
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
];
Map Access
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];
Store window number
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];
Store window number
PokeAtByteAd[entryAddressHighByte, Basics.Card16FromH[mapEntryConcrete.hi]];
Store high part of the entry
PokeAtByteAd[entryAddressLowByte, Basics.Card16FromH[mapEntryConcrete.lo]];
Store low part of the entry
};
ComputeEntryAddress:
PROC [ mapEntry: SparcSoftcardMap.MapEntry ]
RETURNS [windowNumber:
CARD16, entryAddressHighByte, entryAddressLowByte:
CARD32]~ {
mapEntryNumber: CARD16;
windowOffset: CARD16;
Computes the entry number into the map
SELECT mapEntry.vMSpace.name
FROM
Sets the base of mapEntryNumber
= dMA => {
mapEntryNumber ← 0E000H;
IF mapEntry.virtualAddressByte >= 4000000H
THEN
ERROR;
Address range limited to 64 Meg.
};
= iOP => {
mapEntryNumber ← 0A000H;
IF mapEntry.virtualAddressByte >= 1000000H
THEN
ERROR;
Address range limited to 16 Meg.
};
= cP => {
mapEntryNumber ← 0A000H + 1000000H/SparcSoftcard.softcardPageSizeByte;
CP is in the same VM than IOP but 16 Meg farther.
IF mapEntry.virtualAddressByte >= 400000H
THEN
ERROR;
Address range limited to 4 Meg.
};
= 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;
The supervisor address range is limited to 64 Meg.
};
= sparcSuperProgram => {
mapEntryNumber ← 0C000H;
IF mapEntry.virtualAddressByte >= 4000000H
THEN
ERROR;
The supervisor address range is limited to 64 Meg.
};
ENDCASE => ERROR;
mapEntryNumber ← mapEntryNumber + Basics.LongDiv[mapEntry.virtualAddressByte, SparcSoftcard.softcardPageSizeByte];
Adds the offset.
windowNumber ← mapEntryNumber / SparcSoftcard.mapEntriesPerWindow;
windowOffset ← mapEntryNumber MOD SparcSoftcard.mapEntriesPerWindow;
Computes addresses
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]
};
}.