<> <> <> <<>> <> <<>> DIRECTORY <> Basics USING [HighHalf, LowHalf, UnsafeBlock], Commander USING [CommandProc, Register], DoveInputOutput USING [ Peek, Poke ], FS USING [ StreamOpen ], IO USING [ CharClass, EndOfStream, GetTokenRope, RIS, STREAM, UnsafeGetBlock], Rope USING [ROPE], SparcSoftcardOps, SparcSoftcard; SparcSoftcardLoader: CEDAR PROGRAM IMPORTS Basics, Commander, DoveInputOutput, FS, IO, SparcSoftcardOps ~ BEGIN ROPE: TYPE ~ Rope.ROPE; aDotOutIdentificationByte: CARD16 ~ 0; aDotOutEntryPointByte: CARD16 ~ 14H; aDotOutBssSizeByte: CARD16 ~ 0CH; aDotOutHeaderSizeByte: CARD16 ~ 20H; aDotOutIdentificationValue: CARD32 ~ 0103010BH; MyPeek: PROC [address: CARD32] RETURNS [word: UNSPECIFIED] ~ { word _ DoveInputOutput.Peek[address]; }; MyPoke: PROC [address: CARD32, word: UNSPECIFIED] ~ { DoveInputOutput.Poke[address, word]; }; InsertResetPointer: PUBLIC PROC [resetVector: CARD32] ~ { <> 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]]; }; <> <> <> <> <<};>> <<>> CmdTokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ THEN RETURN [break]; IF char = ' OR char = '\t OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE] = { rope _ NIL; rope _ stream.GetTokenRope[CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; }; 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; <> 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; <> buffer: ARRAY [0..bufSize/2) OF CARD16; block: Basics.UnsafeBlock; readSize: CARD16; <> TRUSTED { block _ [base: @buffer, count: bufSize]; readSize _ IO.UnsafeGetBlock[inputFile, block]; }; IF readSize # bufSize THEN ERROR; <> IF GetLong[aDotOutIdentificationByte] # aDotOutIdentificationValue THEN ERROR; <> startAddress _ GetLong[aDotOutEntryPointByte]; IF (startAddress MOD SparcSoftcard.softcardPageSizeByte) # aDotOutHeaderSizeByte THEN ERROR; <> loadAddress _ startAddress - aDotOutHeaderSizeByte; bssSize _ GetLong[aDotOutBssSizeByte]; <> SparcSoftcardOps.SparcReset[]; SparcSoftcardOps.SparcCacheDisable[]; <> backdoorEntry.vMSpace.name _ cP; superTextEntry.vMSpace.name _ sparcSuperProgram; superDataEntry.vMSpace.name _ sparcSuperData; backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte; backdoorEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[backdoorEntry]; <> superTextEntry.virtualAddressByte _ 0; superTextEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[superTextEntry]; <> superDataEntry.virtualAddressByte _ 0; superDataEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[superDataEntry]; <> <> <<>> InsertResetPointer[startAddress]; <<>> <<>> <> WHILE readSize = bufSize DO IF (loadAddress MOD SparcSoftcard.softcardPageSizeByte) = 0 THEN { <> 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; <> <<>> <> <<>> WHILE bssSize > 0 DO IF (loadAddress MOD SparcSoftcard.softcardPageSizeByte) = 0 THEN { <> 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; <> <<>> <> <<>> backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte; backdoorEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[backdoorEntry]; <<>> <> <<>> SparcSoftcardOps.SparcResetAndStart[]; }; <<>> <<>> <> Commander.Register[ key: "SparcSoftcardLoader", proc: SparcSoftcardLoaderProc, doc: "Loads a a.out file into the SparcSoftcard memory"]; <<>> <<>> END.