<> <> <> <> <> <<>> <> <<>> DIRECTORY Basics USING [Card32FromF, HighHalf, LowHalf, UnsafeBlock], Commander USING [CommandProc, Register], DoveInputOutput USING [ Peek, Poke ], FS USING [ Error, FileInfo, StreamOpen ], IO USING [ CharClass, EndOfStream, GetFWord, GetTokenRope, PutF, RIS, rope, GetIndex, SetIndex, STREAM, UnsafeGetBlock, Reset], RefTab USING [Ref, Create, Pairs, EachPairAction, Store, Delete], Rope USING [Cat, ROPE], SparcSoftcardLoaderOps, SparcSoftcardMap, SparcSoftcardOps, SparcSoftcard; SparcSoftcardLoader: CEDAR PROGRAM IMPORTS Basics, Commander, DoveInputOutput, FS, IO, RefTab, Rope, SparcSoftcardMap, SparcSoftcardOps EXPORTS SparcSoftcardLoaderOps ~ BEGIN ROPE: TYPE ~ Rope.ROPE; LoadInfoRep: TYPE ~ RECORD [ startAddress: CARD32, memTrapStart: CARD32, memCommStart: CARD32, commLength: CARD32, fileTextStart: CARD32, memTextStart: CARD32, textLength: CARD32, fileDataStart: CARD32, memDataStart: CARD32, dataLength: CARD32, memBssStart: CARD32, bssLength: CARD32, fileSymbolStart: CARD32, memSymbolStart: CARD32, symbolLength: CARD32 ]; LoadInfo: TYPE ~ REF LoadInfoRep; bufSize: NAT = 1000H; <> <<>> aDotOutIdentificationByte: CARD16 ~ 0; aDotOutTextSizeByte: CARD16 ~ 04H; aDotOutDataSizeByte: CARD16 ~ 08H; aDotOutBssSizeByte: CARD16 ~ 0CH; aDotOutSymbolSizeByte: CARD16 ~ 10H; aDotOutEntryPointByte: CARD16 ~ 14H; 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]; }; MyPokeLong: PROC [byteAddress: CARD32, word: CARD32] ~ { IF (byteAddress MOD 4) # 0 THEN ERROR; DoveInputOutput.Poke[(SparcSoftcard.cedarBackDoorBaseByte + byteAddress)/2, Basics.HighHalf[word]]; DoveInputOutput.Poke[(SparcSoftcard.cedarBackDoorBaseByte + byteAddress)/2 + 1, Basics.LowHalf[word]]; }; InsertResetPointer: PUBLIC PROC [resetVector: CARD32] ~ { <> instruction: CARD32 _ 10800000H; -- ba 0 IF resetVector >= 800000H THEN ERROR; -- verify max offest instruction _ instruction + resetVector/4; -- add offsett MyPokeLong[0, instruction]; instruction _ 01000000H; -- nop MyPokeLong[4, instruction]; }; InsertInfo: PUBLIC PROC [loadInfo: LoadInfo] ~ { MapPageZero[0]; InsertResetPointer[loadInfo.startAddress]; MyPokeLong[08h, loadInfo.startAddress]; MyPokeLong[0ch, loadInfo.memTrapStart]; MyPokeLong[10h, loadInfo.memCommStart]; MyPokeLong[14h, loadInfo.commLength]; MyPokeLong[18h, loadInfo.memTextStart]; MyPokeLong[1ch, loadInfo.textLength]; MyPokeLong[20h, loadInfo.memDataStart]; MyPokeLong[24h, loadInfo.dataLength]; MyPokeLong[28h, loadInfo.memBssStart]; MyPokeLong[2ch, loadInfo.bssLength]; MyPokeLong[30h, loadInfo.memSymbolStart]; MyPokeLong[34h, loadInfo.symbolLength]; }; SetCommunicationMap: PROC [start, length: CARD32] ~ { <> address: CARD32; iteration: NAT; IF (start MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; IF (length MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; <> address _ start; iteration _ length / SparcSoftcard.softcardPageSizeByte; FOR i: NAT IN [0..iteration) DO MapOnePage[address, TRUE]; <> address _ address + SparcSoftcard.softcardPageSizeByte; ENDLOOP; }; 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; }; GetLoadInfo: PROC [stream: IO.STREAM] RETURNS [loadInfo: LoadInfo] = { startAddress, bssLength, roundedBssLength: CARD32; symbolLength, roundedSymbolLength: CARD32; loadInfo _ NEW[LoadInfoRep]; IF GetLong[stream, aDotOutIdentificationByte] # aDotOutIdentificationValue THEN ERROR; <> startAddress _ GetLong[stream, aDotOutEntryPointByte]; IF (startAddress MOD SparcSoftcard.softcardPageSizeByte) # aDotOutHeaderSizeByte THEN ERROR; <> loadInfo.startAddress _ GetLong[stream, aDotOutEntryPointByte]; loadInfo.memTrapStart _ SparcSoftcard.softcardPageSizeByte; -- TBR in page one loadInfo.memCommStart _ loadInfo.memTrapStart + SparcSoftcard.softcardPageSizeByte; loadInfo.fileTextStart _ 0; loadInfo.memTextStart _ startAddress - aDotOutHeaderSizeByte; loadInfo.commLength _ loadInfo.memTextStart - loadInfo.memCommStart; loadInfo.textLength _ GetLong[stream, aDotOutTextSizeByte]; loadInfo.fileDataStart _ loadInfo.textLength; loadInfo.memDataStart _ loadInfo.memTextStart + loadInfo.textLength; loadInfo.dataLength _ GetLong[stream, aDotOutDataSizeByte]; loadInfo.memBssStart _ loadInfo.memDataStart + loadInfo.dataLength; bssLength _ GetLong[stream, aDotOutBssSizeByte]; roundedBssLength _ ((bssLength + SparcSoftcard.softcardPageSizeByte - 1) / SparcSoftcard.softcardPageSizeByte) * SparcSoftcard.softcardPageSizeByte; <> loadInfo.bssLength _ roundedBssLength; loadInfo.fileSymbolStart _ loadInfo.fileDataStart + loadInfo.dataLength; loadInfo.memSymbolStart _ loadInfo.memBssStart + loadInfo.bssLength; symbolLength _ GetLong[stream, aDotOutSymbolSizeByte]; roundedSymbolLength _ ((symbolLength + SparcSoftcard.softcardPageSizeByte - 1) / SparcSoftcard.softcardPageSizeByte) * SparcSoftcard.softcardPageSizeByte; <> loadInfo.symbolLength _ roundedSymbolLength; }; LoadSegment: PROC [stream: IO.STREAM, fileStart, memStart, length: CARD32] = { loadAddress, backdoorPointerWord16: CARD32; buffer: ARRAY [0..bufSize/2) OF CARD16; block: Basics.UnsafeBlock; readSize: CARD16; iteration: NAT; IF (fileStart MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; IF (memStart MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; IF (length MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; <> iteration _ length / bufSize; IO.SetIndex[stream, fileStart]; loadAddress _ memStart; TRUSTED { block _ [base: @buffer, count: bufSize]; }; FOR i: NAT IN [0..iteration) DO IF (loadAddress MOD SparcSoftcard.softcardPageSizeByte) = 0 THEN { MapPageZero[loadAddress]; backdoorPointerWord16 _ SparcSoftcard.cedarBackDoorBaseByte/2; }; TRUSTED { readSize _ IO.UnsafeGetBlock[stream, block]; }; IF readSize # bufSize THEN ERROR; <> <> <> <> <> TRUSTED { ptr: LONG POINTER TO CARD16 _ @buffer[0]; limit: LONG POINTER TO CARD16 _ ptr + bufSize/2; DO IF ptr = limit THEN EXIT; DoveInputOutput.Poke[backdoorPointerWord16, ptr^]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ptr _ ptr + SIZE[CARD16]; DoveInputOutput.Poke[backdoorPointerWord16, ptr^]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ptr _ ptr + SIZE[CARD16]; DoveInputOutput.Poke[backdoorPointerWord16, ptr^]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ptr _ ptr + SIZE[CARD16]; DoveInputOutput.Poke[backdoorPointerWord16, ptr^]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ptr _ ptr + SIZE[CARD16]; ENDLOOP; }; loadAddress _ loadAddress + bufSize; ENDLOOP; MapPageZero[0]; }; SetBssMap: PROC [memStart, length: CARD32] = { iteration: NAT; IF (memStart MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; IF (length MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; <> iteration _ length / SparcSoftcard.softcardPageSizeByte; FOR i: NAT IN [0..iteration) DO MapPageZero[memStart]; memStart _ memStart + SparcSoftcard.softcardPageSizeByte; ENDLOOP; MapPageZero[0]; }; MapPageZero: PROC [sparcVMAddress: CARD32]= { backdoorEntry, superTextEntry, superDataEntry, dMAEntry: SparcSoftcardMap.MapEntry; IF (sparcVMAddress MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; <> backdoorEntry.vMSpace.name _ cP; superTextEntry.vMSpace.name _ sparcSuperProgram; superDataEntry.vMSpace.name _ sparcSuperData; dMAEntry.vMSpace.name _ dMA; backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte; superTextEntry.virtualAddressByte _ sparcVMAddress; superDataEntry.virtualAddressByte _ sparcVMAddress; dMAEntry.virtualAddressByte _ sparcVMAddress; backdoorEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; superTextEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; superDataEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; dMAEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; TRUSTED { SparcSoftcardMap.WriteMapEntry[backdoorEntry]; SparcSoftcardMap.WriteMapEntry[superTextEntry]; SparcSoftcardMap.WriteMapEntry[superDataEntry]; SparcSoftcardMap.WriteMapEntry[dMAEntry]; }; }; MapOnePage: PROC [sparcVMAddress: CARD32, nonCachable: BOOLEAN _ FALSE]= { backdoorEntry, superTextEntry, superDataEntry, dMAEntry: SparcSoftcardMap.MapEntry; IF (sparcVMAddress MOD SparcSoftcard.softcardPageSizeByte) # 0 THEN ERROR; <> superTextEntry.flags.nonCachable _ nonCachable; superDataEntry.flags.nonCachable _ nonCachable; backdoorEntry.vMSpace.name _ cP; superTextEntry.vMSpace.name _ sparcSuperProgram; superDataEntry.vMSpace.name _ sparcSuperData; dMAEntry.vMSpace.name _ dMA; backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte + sparcVMAddress; superTextEntry.virtualAddressByte _ sparcVMAddress; superDataEntry.virtualAddressByte _ sparcVMAddress; dMAEntry.virtualAddressByte _ sparcVMAddress; backdoorEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; superTextEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; superDataEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; dMAEntry.realAddressByte _ sparcVMAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; TRUSTED { SparcSoftcardMap.WriteMapEntry[backdoorEntry]; SparcSoftcardMap.WriteMapEntry[superTextEntry]; SparcSoftcardMap.WriteMapEntry[superDataEntry]; SparcSoftcardMap.WriteMapEntry[dMAEntry]; }; }; GetLong: PROC [in: IO.STREAM, byteAddress: CARD16] RETURNS [result: CARD32] = { IF (byteAddress MOD 4) # 0 THEN ERROR; IO.SetIndex[in, byteAddress]; result _ Basics.Card32FromF[IO.GetFWord[in]]; }; startTable: RefTab.Ref _ RefTab.Create[]; StartAll: PROC [inputFile: IO.STREAM] ~ { StartOne: RefTab.EachPairAction ~ { sProc: PROC[inputFile: IO.STREAM] _ NARROW[val, REF PROC [inputFile: IO.STREAM]]^; IO.Reset[inputFile]; sProc[inputFile]; }; index: INT _ IO.GetIndex[inputFile]; -- save the stream status [] _ RefTab.Pairs[startTable, StartOne]; IO.SetIndex[inputFile, index]; -- restore the stream }; RegisterStartProc: PUBLIC PROC [ref: REF, sProc: PROC [inputFile: IO.STREAM]] ~ { IF sProc=NIL THEN [] _ RefTab.Delete[startTable, ref] ELSE [] _ RefTab.Store[startTable, ref, NEW[PROC[inputFile: IO.STREAM] _ sProc]]; }; SparcSoftcardLoaderProc: Commander.CommandProc ~ { FileExistence: PROC [fileName: ROPE] RETURNS [found: BOOLEAN _ TRUE] ~ { [] _ FS.FileInfo[fileName ! FS.Error => { IF error.group = user THEN { found _ FALSE; CONTINUE; }; }]; }; in: IO.STREAM _ IO.RIS[cmd.commandLine]; fileName, longFileName: ROPE; inputFile: IO.STREAM; loadInfo: LoadInfo; fileName _ GetCmdToken[in]; longFileName _ fileName; IF NOT FileExistence[fileName] THEN { longFileName _ Rope.Cat[fileName, ".out"]; }; IF NOT FileExistence[longFileName] THEN { IO.PutF[cmd.out, "Cannot find file %g\n", IO.rope[fileName]]; } ELSE { inputFile _ FS.StreamOpen[fileName: longFileName, accessOptions: $read]; <> TRUSTED { SparcSoftcardOps.SparcReset[]; SparcSoftcardOps.SparcCacheDisable[]; SparcSoftcardOps.SetDMAMode[display]; SparcSoftcardOps.SetDMAState[active]; SparcSoftcardOps.SetDMAState[inactive]; }; <> loadInfo _ GetLoadInfo[inputFile]; <> SetCommunicationMap[loadInfo.memCommStart, loadInfo.commLength]; StartAll[inputFile]; <> LoadSegment[inputFile, loadInfo.fileTextStart, loadInfo.memTextStart, loadInfo.textLength]; LoadSegment[inputFile, loadInfo.fileDataStart, loadInfo.memDataStart, loadInfo.dataLength]; SetBssMap[loadInfo.memBssStart, loadInfo.bssLength]; LoadSegment[inputFile, loadInfo.fileSymbolStart, loadInfo.memSymbolStart, loadInfo.symbolLength]; <> MapOnePage[SparcSoftcard.softcardPageSizeByte]; <<>> <> InsertInfo[loadInfo]; <<>> <> TRUSTED {SparcSoftcardOps.SparcResetAndStart[];}; }; }; <> Commander.Register[ key: "SparcSoftcardLoader", proc: SparcSoftcardLoaderProc, doc: "Loads a a.out file into the SparcSoftcard memory"]; <<>> <<>> END.