<> <> <> <<>> <> <<>> DIRECTORY Basics USING [BITAND, BITNOT, HighHalf, LowHalf, UnsafeBlock], Commander USING [CommandProc, Register], DoveInputOutput USING [ Poke ], IO USING [ CharClass, EndOfStream, GetTokenRope, RIS, STREAM], RedBlackTree USING [LookupNode], Rope USING [ROPE], SparcSoftcardOps USING [SparcCacheDisable, SparcCacheFlushAndEnable, SparcReset, SparcResetAndStart], SparcSoftcardVM USING [pageSiz, SegmentType, SetPageValue, SparcPageValue], SunADotOut USING [Module, ModuleFromFile], SunADotOutPrivate USING [ ModuleObject, Segment, Symbol ]; BasicLoader: CEDAR PROGRAM IMPORTS Basics, Commander, DoveInputOutput, IO, RedBlackTree, SparcSoftcardOps, SparcSoftcardVM, SunADotOut EXPORTS SunADotOut ~ BEGIN Module: TYPE ~ SunADotOut.Module; ModuleObject: PUBLIC TYPE ~ SunADotOutPrivate.ModuleObject; Segment: TYPE ~ SunADotOutPrivate.Segment; ROPE: TYPE ~ Rope.ROPE; <> PresetSparcVM: PROC [segType: SparcSoftcardVM.SegmentType, n: CARD16, dummyAddress: CARD32] ~ { <> value: SparcSoftcardVM.SparcPageValue; value.realPage _ dummyAddress / SparcSoftcardVM.pageSiz; FOR i: NAT IN [0..n) DO SparcSoftcardVM.SetPageValue[segType, i, value]; ENDLOOP; }; <<>> SetSparcVM: PROC [segType: SparcSoftcardVM.SegmentType, n: CARD16, startAddress: CARD32] ~ { <> value: SparcSoftcardVM.SparcPageValue; FOR i: NAT IN [0..n) DO value.realPage _ startAddress / SparcSoftcardVM.pageSiz + i; SparcSoftcardVM.SetPageValue[segType, i, value]; ENDLOOP; }; <<>> backdoorStart: CARD32 ~ 03C0000H; --Backdoor starts at 3.75 meg cpStart: CARD32 ~ 01000000H; --CP has a 16 meg offset in specialIO VM space SetBackdoorVM: PROC [n: CARD16, startAddress: CARD32] ~ { <> value: SparcSoftcardVM.SparcPageValue; virtualPage: CARD16; FOR i: NAT IN [0..n) DO virtualPage _ (backdoorStart + cpStart) / SparcSoftcardVM.pageSiz + i; value.realPage _ startAddress / SparcSoftcardVM.pageSiz + i; SparcSoftcardVM.SetPageValue[specialIO, virtualPage, value]; ENDLOOP; }; <<>> <> LoadSegment: PROC [seg: Segment, startAddress: CARD32] ~ { <> word: CARD16; p: LONG POINTER _ seg.block.base; address: CARD32 _ (startAddress + backdoorStart)/2; FOR i: INT IN [0..seg.block.count/2) DO TRUSTED {word _ p^; p _ p + 1}; DoveInputOutput.Poke[address, word]; address _ address + 1; ENDLOOP; }; <<>> ZeroSegment: PUBLIC PROC [startAddress, length: CARD32] ~ { address: CARD32 _ (startAddress + backdoorStart)/2; FOR i: CARD32 IN [0..length/2) DO DoveInputOutput.Poke[address, 0]; address _ address + 1; ENDLOOP; }; <<>> 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[backdoorStart/2, Basics.HighHalf[instruction]]; DoveInputOutput.Poke[backdoorStart/2 + 1, Basics.LowHalf[instruction]]; instruction _ 01000000H; -- nop DoveInputOutput.Poke[backdoorStart/2 + 2, Basics.HighHalf[instruction]]; DoveInputOutput.Poke[backdoorStart/2 + 3, Basics.LowHalf[instruction]]; }; <<>> IndicateVMSize: PUBLIC PROC [sparcVMSize: CARD32] ~ { <> DoveInputOutput.Poke[backdoorStart/2 + 4, Basics.HighHalf[sparcVMSize]]; DoveInputOutput.Poke[backdoorStart/2 + 5, Basics.LowHalf[sparcVMSize]]; }; <<>> <
> 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; }; BasicLoaderProc: Commander.CommandProc ~ { in: IO.STREAM _ IO.RIS[cmd.commandLine]; inputFile: ROPE _ GetCmdToken[in]; m: Module _ SunADotOut.ModuleFromFile[inputFile]; sparcVMSize: CARD32 ~ 600000H - SparcSoftcardVM.pageSiz; -- 6 Meg minus one page.. the first 256 K are covered by backdoor backdoorSize: CARD32 ~ 040000H; -- 256 K... numberOfSparcPages: CARD16 ~ sparcVMSize / SparcSoftcardVM.pageSiz; numberOfBackdoorPages: CARD16 ~ backdoorSize / SparcSoftcardVM.pageSiz; numberOfUserPages: CARD16 ~ 02000H; numberOfSuperPages: CARD16 ~ 02000H; startAddress: CARD32 ~ 0200000H; --Uses real mem starting at 2 meg loadText, loadData, loadBss: CARD32; symbol: SunADotOutPrivate.Symbol; firstModuleLoaded: ROPE ~ "initializesparc.o"; -- Name of the init module <> SparcSoftcardOps.SparcReset[]; SparcSoftcardOps.SparcCacheDisable[]; <> <<=== For christian tests ===>> <> <> <> <> <> PresetSparcVM[superData, numberOfSuperPages, sparcVMSize]; PresetSparcVM[superText, numberOfSuperPages, sparcVMSize]; <> <> <> SetSparcVM[superData, numberOfSparcPages, startAddress]; SetSparcVM[superText, numberOfSparcPages, startAddress]; SetBackdoorVM[numberOfBackdoorPages, startAddress]; <> IF RedBlackTree.LookupNode[m.symbolTable, firstModuleLoaded] = NIL THEN ERROR; <> symbol _ NARROW[RedBlackTree.LookupNode[m.symbolTable, firstModuleLoaded].data]; <> loadText _ symbol.value; <> LoadSegment[m.programText, loadText]; <<>> <> <<>> loadData _ Basics.BITAND[(loadText + m.programText.block.count + SparcSoftcardVM.pageSiz - 1), Basics.BITNOT[SparcSoftcardVM.pageSiz - 1]]; <> <> LoadSegment[m.programData, loadData]; <<>> <<>> <> <<>> loadBss _ loadData + m.programData.block.count; <> <> ZeroSegment[loadBss, m.header.bss]; <> InsertResetPointer[m.header.entryPoint]; IndicateVMSize[sparcVMSize]; <> <<>> <<>> <> SparcSoftcardOps.SparcResetAndStart[]; }; <<>> <<>> <> Commander.Register[ key: "BasicLoader", proc: BasicLoaderProc, doc: "Loads a a.out file into the SparcSoftcard memory"]; <<>> <<>> END.