<> <> <> <<>> DIRECTORY Basics USING [ Card32FromF, DoubleAnd, DoubleNot, DoubleOr, DoubleShiftRight, FFromCard32, FWORD, HFromCard16, LongNumber, LowByte, LowHalf, UnsafeBlock ], Rope USING [ ROPE ], SparcLoader USING [ AllocateProc, PokeProc ], SunADotOut USING [ ], SunADotOutPrivate USING [ ModuleObject, RelocationInfo, Segment, Symbol ], VM USING [ AddressForPageNumber ]; SparcLoaderImpl: CEDAR MONITOR IMPORTS Basics, VM EXPORTS SparcLoader, SunADotOut ~ { OPEN SparcLoader, SunADotOutPrivate; ROPE: TYPE ~ Rope.ROPE; <> PrivateError: SIGNAL [ msg: ROPE ] ~ CODE; UndefinedSymbol: PUBLIC SIGNAL [ info: RelocationInfo ] RETURNS [ s: Symbol _ NIL ] ~ CODE; ResolveFixUps: PROC [ m: Module, segment: Segment, list: LIST OF RelocationInfo ] ~ { FOR item: LIST OF RelocationInfo _ list, item.rest WHILE ( item # NIL ) DO newSymbol: Symbol _ NIL; SELECT TRUE FROM ( NOT item.first.extern ) => { NULL }; ( item.first.symbol.type # undefined ) => { NULL }; ( ( newSymbol _ UndefinedSymbol[item.first] ) = NIL ) => { LOOP }; ( newSymbol.type = undefined ) => { ERROR }; -- client provided! ENDCASE => { NULL }; OneFixUp[m, segment, item.first]; ENDLOOP; }; BytePointer: TYPE ~ MACHINE DEPENDENT RECORD [ SELECT OVERLAID * FROM charStar => [ lh: BYTE, ll: [0..3FH), bytePart: [0..4), hh, hl: BYTE ], card32 => [ card32: CARD32 ], long32 => [ long32: Basics.LongNumber ] ENDCASE ]; Pieces: PROC [ pos: CARD32 ] RETURNS [ word30: CARD32, bytePart: NAT ] ~ { addr: BytePointer; addr.card32 _ pos; bytePart _ addr.bytePart; addr.bytePart _ 0; word30 _ Basics.DoubleShiftRight[addr.long32, 2].lc; }; sillyPatch: BOOL _ FALSE; -- bias from "text" rather than "data/bss" OneFixUp: PROC [ m: Module, segment: Segment, reloc: RelocationInfo ] ~ { block: Basics.UnsafeBlock ~ segment.block; StuffByte: PROC [ pos: CARD32, byte: BYTE ] ~ TRUSTED { word: CARD32; bytePart: NAT; [word, bytePart] _ Pieces[pos]; { p: LONG POINTER TO Basics.FWORD ~ block.base + ( word * 2 ); SELECT bytePart FROM 0 => { p.hi.hi _ byte }; 1 => { p.hi.lo _ byte }; 2 => { p.lo.hi _ byte }; 3 => { p.lo.lo _ byte }; ENDCASE => { ERROR }; }; }; StuffCard16: PROC [ pos: CARD32, card16: CARD16 ] ~ TRUSTED { word: CARD32; bytePart: NAT; [word, bytePart] _ Pieces[pos]; { p: LONG POINTER TO Basics.FWORD ~ block.base + ( word * 2 ); SELECT bytePart FROM 0 => { p.hi _ Basics.HFromCard16[card16] }; 2 => { p.lo _ Basics.HFromCard16[card16] }; ENDCASE => { ERROR }; }; }; StuffCard32: PROC [ pos: CARD32, card32: CARD32 ] ~ TRUSTED { word: CARD32; bytePart: NAT; [word, bytePart] _ Pieces[pos]; { p: LONG POINTER TO Basics.FWORD ~ block.base + ( word * 2 ); SELECT bytePart FROM 0 => { p^ _ Basics.FFromCard32[card32] }; ENDCASE => { ERROR }; }; }; FetchCard32: PROC [ pos: CARD32 ] RETURNS [ c: CARD32 ] ~ TRUSTED { word: CARD32; bytePart: NAT; [word, bytePart] _ Pieces[pos]; { p: LONG POINTER TO Basics.FWORD ~ block.base + ( word * 2 ); SELECT bytePart FROM 0 => { c _ Basics.Card32FromF[p^] }; ENDCASE => { PrivateError["huh?"] }; }; }; FieldOp: PROC [ value: CARD32, addend: INT32, shift: NAT, mask: Basics.LongNumber ] RETURNS [ card32: CARD32 ] ~ { <<((*(long *)word & (mask)) | ((reloc_item) >> (shift)) & (~ (mask)))>> <<( ( value BITAND mask ) BITOR ( ( addend >> shift ) BITAND ( BITNOT mask ) ) )>> e1: Basics.LongNumber ~ Basics.DoubleAnd[LOOPHOLE[value], mask]; e2: Basics.LongNumber ~ Basics.DoubleShiftRight[LOOPHOLE[addend], shift]; e3: Basics.LongNumber ~ Basics.DoubleNot[mask]; e4: Basics.LongNumber ~ Basics.DoubleAnd[e2, e3]; e5: Basics.LongNumber ~ Basics.DoubleOr[e1, e4]; card32 _ e5.lc; }; addend: INT32 _ 0; SELECT TRUE FROM ( reloc.extern ) => { addend _ reloc.addend + reloc.symbol.value }; <> ( reloc.basedUpon = text ) => { addend _ reloc.addend + m.programText.target }; ( ( sillyPatch ) AND ( ( reloc.basedUpon = data ) OR ( reloc.basedUpon = bss ) ) ) => { addend _ reloc.addend + m.programText.target }; ( reloc.basedUpon = data ) => { addend _ reloc.addend + m.programData.target }; ( reloc.basedUpon = bss ) => { addend _ reloc.addend + m.programBss.target }; ENDCASE => { PrivateError["Unexpected FixUp\n" ] }; { sillyTarget: CARD32 ~ IF ( NOT sillyPatch ) THEN segment.target ELSE m.programText.target; offset: INT32 ~ addend - sillyTarget; address: CARD32 ~ reloc.address; -- or segment.target + reloc.address; mask30: Basics.LongNumber ~ LOOPHOLE[0C0000000H]; mask22: Basics.LongNumber ~ LOOPHOLE[0FFC00000H]; mask13: Basics.LongNumber ~ LOOPHOLE[0FFFFE000H]; mask10: Basics.LongNumber ~ LOOPHOLE[0FFFFFC00H]; reloc.rawWord _ FetchCard32[address]; SELECT reloc.type FROM simple8 => { StuffByte[address, Basics.LowByte[Basics.LowHalf[offset]]] }; simple16 => { StuffCard16[address, Basics.LowHalf[offset]] }; simple32 => { StuffCard32[address, addend] }; disp8 => { StuffByte[address, Basics.LowByte[Basics.LowHalf[offset]]] }; disp16 => { StuffCard16[address, Basics.LowHalf[offset]] }; disp32 => { StuffCard32[address, offset] }; worddisp30 => { StuffCard32[address, FieldOp[reloc.rawWord, offset, 2, mask30]] }; worddisp22 => { StuffCard32[address, FieldOp[reloc.rawWord, offset, 2, mask22]] }; srHi22 => { StuffCard32[address, FieldOp[reloc.rawWord, addend, 10, mask22]] }; sr22 => { StuffCard32[address, FieldOp[reloc.rawWord, addend, 0, mask22]] }; sr13 => { StuffCard32[address, FieldOp[reloc.rawWord, addend, 0, mask13]] }; srLo10 => { StuffCard32[address, FieldOp[reloc.rawWord, addend, 0, mask10]] }; sfaBase => { PrivateError["sfaBase: what's that? (Tell Weiser).\n"] }; sfaOff13 => { PrivateError["sfaOff13: what's that? (Tell Weiser).\n"] }; base10 => { ERROR }; base13 => { ERROR }; pc10 => { ERROR }; pc22 => { ERROR }; jumpTable => { ERROR }; segmentOffset16 => { PrivateError["segmentOffset16: Shared Libraries Unsupported.\n"] }; globalData => { ERROR }; jumpSlot => { ERROR }; relative => { ERROR }; ENDCASE => { ERROR }; { newContents: CARD32 _ FetchCard32[address]; }; }; }; LoadSegment: PROC [ segment: Segment, poke: PokeProc, chunk: CARD32 ] ~ { bytes: CARD32 _ segment.block.count; FOR p: CARD32 _ 0, p + chunk WHILE ( p < CARD32[segment.block.count] ) DO stuff: CARD32 ~ MIN[bytes, chunk]; finger: LONG POINTER ~ VM.AddressForPageNumber[segment.interval.page] + p; block: Basics.UnsafeBlock ~ [finger, 0, stuff]; TRUSTED { poke[[segment.target + p], block] }; bytes _ bytes - stuff; ENDLOOP; }; Module: TYPE ~ REF ModuleObject; ModuleObject: PUBLIC TYPE ~ SunADotOutPrivate.ModuleObject; Load: PUBLIC PROC [ m: Module, allocate: AllocateProc, poke: PokeProc, chunk: CARD32 ] ~ { m.programText.target _ allocate[$text, m.programText]; m.programData.target _ allocate[$data, m.programData]; m.programBss.target _ allocate[$bss, m.programBss]; ResolveFixUps[m, m.programText, m.textRelocation]; ResolveFixUps[m, m.programData, m.dataRelocation]; LoadSegment[m.programText, poke, chunk]; LoadSegment[m.programData, poke, chunk]; }; }.