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[]; 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. BasicLoader.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. First created by Christophe Cuenod, August 30, 1988 1:06:13 pm PDT Loads a simple a.out file into the SparcSoftcard Sparc VM setting Preset the n first VM pages of segType to map a dummy page. Set the n first VM pages of segType to map the Softcard Physical memory Starting at address startAddress. Set the n first VM backdoor pages to map the Softcard Physical memory Starting at address startAddress. Loading Sparc VM Load seg at address startAddress in the Sparc VM Insert by hand the instruction ba resetVector followed by nop Insert by hand the size of the VM at address 8 (byte address) Main proc and misc Reset the Sparc and the cache SparcSoftcardOps.SparcCacheFlushAndEnable[]; === For christian tests === Set all the Sparc map entries to point outside any used area (the last page of the memory) PresetSparcVM[userData, numberOfUserPages, sparcVMSize]; PresetSparcVM[userDataAlt, numberOfUserPages, sparcVMSize]; PresetSparcVM[userText, numberOfUserPages, sparcVMSize]; PresetSparcVM[userTextAlt, numberOfUserPages, sparcVMSize]; Set the map entries SetSparcVM[userData, numberOfSparcPages, startAddress]; SetSparcVM[userText, numberOfSparcPages, startAddress]; Computes load address for text The first module to be linked has to be called "firstModuleLoaded" The loading address is the address of the first module Loads text Computes load address for data Round to the beginning of the page following the end of the text Loads data Computes address for bss Bss will be zeroed after the end of the data segment Zero bss Clean up: Insert the reset pointer and the vmSize pointer Put in a wellknown address the VM Size so the init program can load the Stack with it Start the sparc Registration Κ1˜code•Mark outsideHeaderšœ™Kšœ<™Kšœ œ˜(Kšœœ ˜Kšœœ)œœ˜>Kšœ œ˜ Kšœœœ˜KšœœO˜eKšœœ6˜KKšœ œ˜*Kšœœ#˜:—K˜KšΟn œœ˜Kšœ%œ=˜kKšœ ˜šœ˜K˜Kšœœ˜!Kšœœœ"˜;Kšœ œ˜*Kšœœœ˜—headšœœ™šž œœ+œœ˜_Kšœ;™;Jšœ&˜&Jšœ8˜8šœœœ˜Jšœ0˜0Jšœ˜—K˜K™—šž œœ+œœ˜\KšœœW™iJšœ&˜&šœœœ˜Jšœ<˜K– "cedar" stylešœœ˜ K– "cedar" stylešœ+œœ˜MKšœ˜—K˜šžœ˜*Kš œœœœœ˜(Kšœ œ˜"Kšœ1˜1Kšœ œ&ŸB˜{Kšœœ Ÿ ˜+Kšœœ)˜CKšœœ*˜GKšœœ ˜#Kšœœ ˜$Kšœœ Ÿ!˜BKšœœ˜$Kšœ!˜!KšœœŸ˜IK˜™K˜Kšœ˜Kšœ%˜%šœ,™,K™—K˜—™ZK˜Kšœ8™8Kšœ;™;Kšœ8™8Kšœ;™;Kšœ:˜:Kšœ:˜:K˜—™K˜Kšœ7™7Kšœ7™7Kšœ8˜8Kšœ8˜8Kšœ3˜3K˜—™K˜šœ=œœœ˜NKšœC™C—šœ œA˜PK™6—Kšœ˜K˜—™ K˜Kšœ%˜%K™—šœ™K™šœœNœ˜‹K™@K˜—K˜—šœ ™ K˜Kšœ%˜%K™K™—šœ™K™šœ/˜/K™4—K˜—™K˜Kšœ#˜#K˜—™9K˜Kšœ(˜(šœ˜Kšœœ5™V—K™K™—™K˜Jšœ&˜&—šœ˜K™K™———™ šœ˜Jšœd˜dK™K™——K˜Kšœ˜J˜—…— #O