SimpleLoader
Card16ArrayPtr: TYPE ~ LONG POINTER TO
RECORD [SEQUENCE COMPUTED CARD16 OF CARD16];
ODD: PROC [ i: INT32 ] RETURNS [ b: BOOL ← FALSE ] ~ INLINE
{ b ← ( i MOD 1 ) # 0 };
SimpleLoader:
PUBLIC
PROC [ fname:
ROPE ←
NIL, putCard16: PutCard16Proc ] ~ {
vmTarget: TargetAddress ← [bufSiz];
SimpleAllocate: AllocateProc ~ {
nextAddress: TargetAddress ~ [vmTarget + segment.block.count];
nextPageBoundary: TargetAddress ~ [RoundUpBytes[vmTarget]];
nextWithRoundup: TargetAddress ~ [nextPageBoundary + segment.block.count];
SELECT flavor
FROM
$text => { address ← vmTarget; vmTarget ← nextAddress };
$data => { address ← nextPageBoundary; vmTarget ← nextWithRoundup };
$bss => { address ← vmTarget; vmTarget ← nextAddress };
ENDCASE => { ERROR };
};
ZeroFill:
PROC [ oldPos:
CARD32, newPos:
CARD32 ] ~ {
diff: CARD32 ~ newPos - oldPos; -- can't/shouldn't ever be negative!
};
pos: CARD32 ← 0;
SimplePoke: PokeProc ~ {
wordAddrBase: INT32 ~ address / 2;
firstWord: INT32 ~ block.startIndex / 2;
lastWord: INT32 ~ ( block.startIndex + block.count ) / 2;
SELECT
TRUE
FROM
( ODD[address] ) => { ERROR };
( ODD[block.startIndex] ) => { ERROR };
( ODD[block.startIndex + block.count] ) => { ERROR };
( pos = address ) => { NULL };
( pos < address ) => { ZeroFill[pos, address] };
ENDCASE => { ERROR };
FOR i:
INT32
IN [firstWord .. lastWord)
DO
TRUSTED { putCard16[wordAddrBase + i, LOOPHOLE[block.base, Card16ArrayPtr][i]] };
pos ← ( wordAddrBase + i ) * 2;
ENDLOOP;
};
out: IO.STREAM ~ FS.StreamOpen["SparcLoader.log", $create];
test: Module ~ SunADotOut.ModuleFromFile[fname];
SparcLoader.Load[test, SimpleAllocate, SimplePoke, bufSiz ! UndefinedSymbol =>
{ out.PutF[" undefined symbol: \"%g\"\n", IO.rope[info.symbol.text]]; RESUME[NIL] } ];
out.Close[];
};
Debugging and Test routines
rawHdrSiz: NAT ~ 32; -- BYTES[HdrObj];
test: Module;
code: IO.STREAM;
lowcore: TargetAddress ← [rawHdrSiz]; -- magic for a.out header!
zeroBuf: REF TEXT ~ NEW[TEXT[bufSiz]];
ZeroFill:
PROC [ code:
IO.
STREAM, oldPos:
CARD32, newPos:
CARD32 ] ~ {
code.SetLength[newPos]; code.SetIndex[newPos] - should this be enough?
diff: CARD32 ~ newPos - oldPos; -- can't/shouldn't ever be negative!
code.PutBlock[zeroBuf, 0, diff];
IF ( CARD32[code.GetIndex[]] # newPos ) THEN ERROR; -- huh?
};
ChunksForBytes: PROC [ bytes: CARD32 ] RETURNS [ chunks: CARD32 ] ~
INLINE { chunks ← ( bytes + bufSiz.PRED ) / bufSiz };
BytesForChunks: PROC [ chunks: CARD32 ] RETURNS [ bytes: CARD32 ] ~
INLINE { bytes ← chunks * bufSiz };
RoundUpBytes:
PROC [ rough:
CARD32 ]
RETURNS [ even:
CARD32 ] ~
INLINE { even ← BytesForChunks[ChunksForBytes[rough]] };
DummyAllocate: AllocateProc ~ {
nextAddress: TargetAddress ~ [lowcore + segment.block.count];
nextPageBoundary: TargetAddress ~ [RoundUpBytes[lowcore]];
nextWithRoundup: TargetAddress ~ [nextPageBoundary + segment.block.count];
SELECT flavor
FROM
$text => { address ← lowcore; lowcore ← nextAddress };
$data => { address ← nextPageBoundary; lowcore ← nextWithRoundup };
$bss => { address ← lowcore; lowcore ← nextAddress };
ENDCASE => { ERROR };
};
DummyPoke: PokeProc ~ {
pos: CARD32 ~ code.GetIndex[];
SELECT
TRUE
FROM
( pos = address ) => { NULL };
( pos < address ) => { ZeroFill[code, pos, address] };
ENDCASE => { ERROR };
code.UnsafePutBlock[block];
};
Module: TYPE ~ REF ModuleObject;
ModuleObject: PUBLIC TYPE ~ SunADotOutPrivate.ModuleObject;
FixUpHdr:
PROC [ code:
IO.
STREAM, m: Module ] ~ {
pos: INT ~ code.GetIndex[];
m.header.dynamic ← TRUE; -- just for now!
m.header.magic ← ZMAGIC;
m.header.text ← RoundUpBytes[m.header.text + rawHdrSiz];
m.header.data ← RoundUpBytes[m.header.data + m.header.bss];
m.header.bss ← 0;
m.header.symbolTableSize ← 0;
m.header.entryPoint ← rawHdrSiz; -- just for now!
m.header.textRelocationSize ← 0;
m.header.dataRelocationSize ← 0;
m.header.stringTableSize ← 0;
code.SetIndex[0];
SunADotOut.WriteModule[code, m];
code.SetIndex[pos];
ZeroFill[code, pos, RoundUpBytes[pos]];
code.SetLength[RoundUpBytes[pos]];
};
bufSiz: NAT ~ 8192;
TestLoader:
PROC [ fname:
ROPE ←
NIL ] ~ {
out: IO.STREAM ~ FS.StreamOpen["SparcLoader.log", $create];
code ← FS.StreamOpen["CodeImage.bin", $create];
test ← SunADotOut.ModuleFromFile[fname];
lowcore ← [rawHdrSiz]; -- magic for a.out header!
SparcLoader.Load[test, DummyAllocate, DummyPoke, bufSiz ! UndefinedSymbol =>
{ out.PutF[" undefined symbol: \"%g\"\n", IO.rope[info.symbol.text]]; RESUME[NIL] } ];
FixUpHdr[code, test];
code.Close[];
out.Close[];
};
}.