InsertResetPointer:
PUBLIC
PROC [resetVector:
CARD32] ~ {
Insert by hand the instruction ba resetVector followed by nop
instruction: CARD32 ← 10800000H; -- ba 0
IF resetVector >= 1000000H THEN ERROR; -- verify max offest
instruction ← instruction + resetVector/4; -- add offsett
DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2, Basics.HighHalf[instruction]];
DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 1, Basics.LowHalf[instruction]];
instruction ← 01000000H; -- nop
DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 2, Basics.HighHalf[instruction]];
DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 3, Basics.LowHalf[instruction]];
};
SparcSoftcardLoaderProc: Commander.CommandProc ~ {
GetLong:
PROC [byteAddress:
CARD16]
RETURNS [result:
CARD32] = {
IF (byteAddress MOD 4) # 0 THEN ERROR;
result ← buffer[byteAddress/2] * 65536 + buffer[byteAddress/2 + 1];
};
SetOneMoreMapPage:
PROC ~ {
backdoorEntry.virtualAddressByte ← SparcSoftcard.cedarBackDoorBaseByte;
Always on the same backdoor page
superTextEntry.virtualAddressByte ← loadAddress;
superDataEntry.virtualAddressByte ← loadAddress;
backdoorEntry.realAddressByte ← loadAddress + SparcSoftcard.cedarMemoryExtensionSizeByte;
superTextEntry.realAddressByte ← loadAddress + SparcSoftcard.cedarMemoryExtensionSizeByte;
superDataEntry.realAddressByte ← loadAddress + SparcSoftcard.cedarMemoryExtensionSizeByte;
SparcSoftcardOps.WriteMapEntry[backdoorEntry];
SparcSoftcardOps.WriteMapEntry[superTextEntry];
SparcSoftcardOps.WriteMapEntry[superDataEntry];
};
in: IO.STREAM ← IO.RIS[cmd.commandLine];
fileName: ROPE ← GetCmdToken[in];
inputFile: IO.STREAM ← FS.StreamOpen[fileName: fileName, accessOptions: $read];
startAddress, loadAddress, bssSize: CARD32;
backdoorEntry, superTextEntry, superDataEntry: SparcSoftcardOps.MapEntry;
backdoorPointerWord16: CARD32;
bufSize:
NAT = 1000H;
Maximum size allowed by the compiler
buffer: ARRAY [0..bufSize/2) OF CARD16;
block: Basics.UnsafeBlock;
readSize: CARD16;
Reads first the beginning of the file to check the header and find out the loading address
TRUSTED {
block ← [base: @buffer, count: bufSize];
readSize ← IO.UnsafeGetBlock[inputFile, block];
};
IF readSize # bufSize
THEN
ERROR;
File way too small
IF GetLong[aDotOutIdentificationByte] # aDotOutIdentificationValue
THEN
ERROR;
Bad magic number or tool version
startAddress ← GetLong[aDotOutEntryPointByte];
IF (startAddress
MOD SparcSoftcard.softcardPageSizeByte) # aDotOutHeaderSizeByte
THEN
ERROR;
Probably bad linking. The entry point has to be the first effective instruction.
loadAddress ← startAddress - aDotOutHeaderSizeByte;
bssSize ← GetLong[aDotOutBssSizeByte];
Reset the Sparc and the cache
SparcSoftcardOps.SparcReset[];
SparcSoftcardOps.SparcCacheDisable[];
Set the first map pages
backdoorEntry.vMSpace.name ← cP;
superTextEntry.vMSpace.name ← sparcSuperProgram;
superDataEntry.vMSpace.name ← sparcSuperData;
backdoorEntry.virtualAddressByte ← SparcSoftcard.cedarBackDoorBaseByte;
backdoorEntry.realAddressByte ← SparcSoftcard.cedarMemoryExtensionSizeByte;
SparcSoftcardOps.WriteMapEntry[backdoorEntry];
The first page of backdoor points to the begining of free memory
superTextEntry.virtualAddressByte ← 0;
superTextEntry.realAddressByte ← SparcSoftcard.cedarMemoryExtensionSizeByte;
SparcSoftcardOps.WriteMapEntry[superTextEntry];
The first page of sparcSuperProgram points to the begining of free memory
superDataEntry.virtualAddressByte ← 0;
superDataEntry.realAddressByte ← SparcSoftcard.cedarMemoryExtensionSizeByte;
SparcSoftcardOps.WriteMapEntry[superDataEntry];
The first page of sparcSuperData points to the begining of free memory
Insert the reset pointer
InsertResetPointer[startAddress];
Transfert the data and set additional map pages if needed
WHILE readSize = bufSize
DO
IF (loadAddress
MOD SparcSoftcard.softcardPageSizeByte) = 0
THEN {
Set one more map page.
SetOneMoreMapPage[];
backdoorPointerWord16 ← SparcSoftcard.cedarBackDoorBaseByte/2;
};
FOR i:
NAT
IN [0..bufSize/2)
DO
DoveInputOutput.Poke[backdoorPointerWord16, buffer[i]];
backdoorPointerWord16 ← backdoorPointerWord16 + 1;
ENDLOOP;
TRUSTED {
readSize ← IO.UnsafeGetBlock[inputFile, block];
};
loadAddress ← loadAddress + bufSize;
ENDLOOP;
IF readSize # 0
THEN
ERROR;
the file has an odd length (ie non multiple of softcardPageSizeByte)
Zero bss
WHILE bssSize > 0
DO
IF (loadAddress
MOD SparcSoftcard.softcardPageSizeByte) = 0
THEN {
Set one more map page.
SetOneMoreMapPage[];
backdoorPointerWord16 ← SparcSoftcard.cedarBackDoorBaseByte/2;
};
FOR i:
NAT
IN [0..bufSize/2)
DO
DoveInputOutput.Poke[backdoorPointerWord16, 0];
backdoorPointerWord16 ← backdoorPointerWord16 + 1;
ENDLOOP;
loadAddress ← loadAddress + bufSize;
bssSize ← bssSize - bufSize;
ENDLOOP;
IF bssSize # 0
THEN
ERROR;
the bss has an odd length (ie non multiple of softcardPageSizeByte)
For debug replace the first page of backdoor to the begining of free memory
backdoorEntry.virtualAddressByte ← SparcSoftcard.cedarBackDoorBaseByte;
backdoorEntry.realAddressByte ← SparcSoftcard.cedarMemoryExtensionSizeByte;
SparcSoftcardOps.WriteMapEntry[backdoorEntry];
Start the sparc
SparcSoftcardOps.SparcResetAndStart[];