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. ΌSparcSoftcardLoader.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Created by J-C Cuenod, September 29, 1988 1:36:45 pm PDT Christian Le Cocq October 25, 1988 5:23:32 pm PDT Christophe Cuenod October 7, 1988 2:49:01 pm PDT Loads a single a.out file into the SparcSoftcard Maximum size allowed by the compiler Insert by hand the instruction ba resetVector followed by nop The communication package uses a part of backdoor. Alignement error The communication area is non cachable Bad magic number or tool version Probably bad linking. The entry point has to be the first effective instruction. Extend size to the nearest page bondary. Extend size to the nearest page bondary. Alignement error File too small FOR j: NAT IN [0..bufSize/2) DO DoveInputOutput.Poke[backdoorPointerWord16, buffer[j]]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ENDLOOP; Alignement error Alignement error Alignement error Reset the Sparc, the cache and the DMA. Get Load info about the field length Set the communication map and restart communication package Load different segments; Sets the map for the trap page (page 1) Insert the reset pointer and layout info Start the sparc Registration Κ0˜code•Mark outsideHeaderšœ™Kšœ<™Kšœ%˜%K˜—K˜šžœœ œ œ˜5Kšœ$˜$K˜—K˜šž œœœœ˜8Jšœœœœ˜&Kšœc˜cKšœf˜fK˜—K˜šžœœœœ˜9Kšœ=™=Kšœ œΟc˜(KšœœœŸ˜;Kšœ+Ÿ˜9Jšœ˜KšœŸ˜ Kšœ˜K˜K˜—šž œœœ˜0J˜J˜J˜Jšœ*˜*J˜Jšœ'˜'Jšœ'˜'Jšœ'˜'Jšœ%˜%Jšœ'˜'Jšœ%˜%Jšœ'˜'Jšœ%˜%Jšœ&˜&Jšœ$˜$Jšœ)˜)Jšœ'˜'K˜K˜—šžœœœ˜5J™2Jšœ œ˜Jšœ œ˜Jšœœ)œœ˜Ašœ œ)œœ˜BJ™—Jšœ˜Jšœ8˜8šœœœ˜šœœ˜J™&—Jšœ7˜7Jšœ˜—J˜K˜—– "cedar" styleš ž œœœœœ˜;Kšœ œœ ˜!Kšœ œ œ œ œ œœ˜VKšœ ˜Kšœ˜K˜—– "cedar" styleš ž œœ œœœœ˜>K– "cedar" stylešœœ˜ K– "cedar" stylešœ+œœ˜MKšœ˜—K– "cedar" style˜– "cedar" styleš ž œœ œœœ˜FK˜Kšœ+œ˜2Kšœ#œ˜*Kšœ œ˜šœIœœ˜VJ™ —Jšœ6˜6šœœ=œœ˜\J™P—Jšœ?˜?J˜Jšœ<Ÿ˜NJ˜JšœS˜SJ˜Jšœ˜Jšœ=˜=JšœD˜DJšœ;˜;J˜Jšœ-˜-JšœD˜DJšœ;˜;J˜JšœC˜CJšœ0˜0šœ”˜”Jšœ)™)—Jšœ&˜&K˜KšœH˜HKšœD˜DKšœ6˜6šœš˜šJšœ)™)—Kšœ,˜,Kšœ˜—K– "cedar" style˜– "cedar" styleš ž œœ œœœ˜NK˜Jšœ$œ˜+Jšœœœœ˜'Jšœ˜Jšœ œ˜Jšœ œ˜Jšœ œ)œœ˜EJšœ œ)œœ˜Dšœ œ)œœ˜BJ™—Jšœ˜Jšœ˜Jšœ˜šœ˜ Jšœ(˜(K˜—šœœœœ˜ šœœ)œ˜BJšœ˜Jšœ>˜>Jšœ˜—Jšœœ"˜9šœœœ˜!K™—šœœœ™Jšœ7™7Jšœ2™2Jšœ™—šœ˜ Jš œœœœœ˜)Jš œœœœœ˜0š˜Jšœ œœ˜Jšœ2˜2Jšœ2˜2Jšœ œœ˜Jšœ2˜2Jšœ2˜2Jšœ œœ˜Jšœ2˜2Jšœ2˜2Jšœ œœ˜Jšœ2˜2Jšœ2˜2Jšœ œœ˜Jšœ˜—Jšœ˜—Jšœ$˜$Jšœ˜—Jšœ˜Kšœ˜—K– "cedar" style˜– "cedar" stylešž œœœ˜.K˜Jšœ œ˜Jšœ œ)œœ˜Dšœ œ)œœ˜BJ™—Jšœ8˜8šœœœœ˜ Jšœ˜Jšœ9˜9Jšœ˜—Jšœ˜Kšœ˜—K– "cedar" style˜– "cedar" stylešž œœœ˜-KšœS˜Sšœœ)œœ˜JK™—Kšœ ˜ Kšœ0˜0Kšœ-˜-Kšœ˜K˜KšœG˜GKšœ3˜3Kšœ3˜3Kšœ-˜-K˜Kšœ\˜\Kšœ]˜]Kšœ]˜]KšœW˜Wšœ˜ Kšœ.˜.Kšœ/˜/Kšœ/˜/Kšœ)˜)K˜—Kšœ˜—K– "cedar" style˜– "cedar" styleš ž œœœœœ˜JKšœS˜Sšœœ)œœ˜JK™—Kšœ/˜/Kšœ/˜/K˜Kšœ ˜ Kšœ0˜0Kšœ-˜-Kšœ˜K˜KšœX˜XKšœ3˜3Kšœ3˜3Kšœ-˜-K˜Kšœ\˜\Kšœ]˜]Kšœ]˜]KšœW˜WK˜šœ˜ Kšœ.˜.Kšœ/˜/Kšœ/˜/Kšœ)˜)K˜—Kšœ˜—K– "cedar" style˜– "cedar" stylešžœœœœœœ œ˜OJšœœœœ˜&Jšœ˜Jšœœ˜-Kšœ˜—K˜šœ)˜)K˜—šžœœ œœ˜)šžœ˜#Kšœœ œœœœœ œœ˜RKšœ˜Kšœ˜K˜—K•StartOfExpansion2[x: RefTab.Ref, action: RefTab.EachPairAction]šœœœŸ˜>Kšœ(˜(KšœŸ˜4K˜K˜—šžœœœœ œ œœ˜QKšœœœ$˜5Kš œ$œœ œœ ˜QK˜K˜—šžœ˜2K˜š ž œœ œœ œœ˜Hšœœœ ˜*šœœ˜Jšœœ˜Jšœ˜ J˜—Jšœ˜—K˜—K˜Kš œœœœœ˜(Kšœœ˜Jšœ œœ˜Jšœ˜Jšœœ˜Jšœ œ ˜šœœœ˜&Kšœ*˜*K˜—šœœœ˜)Jšœ(œ˜=J˜—šœ˜Jšœ œ:˜HJ˜šœ#œ™'šœ˜ Kšœ˜Kšœ%˜%Kšœ%˜%Kšœ%˜%Kšœ'˜'K˜—K˜—™$Jšœ"˜"—J˜™;Kšœ@˜@Kšœ˜—J˜™Kšœ[˜[Kšœ[˜[Kšœ4˜4Kšœa˜a—J˜J˜™'Jšœ/˜/—J™™(Jšœ˜—J™™Jšœ*˜1—Kšœ˜—˜K˜———head™ šœ˜Jšœt˜tK™K™——K˜Kšœ˜J˜—…—/ΆC’