SparcLoaderImpl.Mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bill Jackson (bj) July 5, 1988 3:32:36 pm PDT
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;
Resolver & Loader
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: BOOLFALSE; -- 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 };
/* (take off text reloc later if pc-relative) */
( 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];
};
}.