--functions for Alto and D0 Microcode
DIRECTORY
AltoMicrocodeDefs: FROM "AltoMicrocodeDefs",
D0MicrocodeDefs: FROM "D0MicrocodeDefs",
MiscDefs: FROM "MiscDefs" USING [DestroyFakeModule],
MemoryOps: FROM "MemoryOps" USING [GetMemoryConfig,MachineType],
Mopcodes: FROM "Mopcodes" USING [zMISC],
RamDefs: FROM "RamDefs",
SegmentDefs: FROM "SegmentDefs" USING
[FileSegmentAddress,FileSegmentHandle,SwapIn,SwapOut,Unlock];

Microcode: PROGRAM IMPORTS AltoMicrocodeDefs, D0MicrocodeDefs, MemoryOps, MiscDefs, RamDefs, SegmentDefs EXPORTS AltoMicrocodeDefs, D0MicrocodeDefs =
BEGIN

LRJBlock
: TYPE = RECORD
[
VersionID: CARDINAL,--current version is 0
AllOnes: CARDINAL,--high order 12 bits must be all ones
CheckSum: CARDINAL, --unused
StartAddr: CARDINAL
];

EndBlock: LRJBlock ← [0,177777B,0,0];

LoadRamAndJump: PROCEDURE [LONG POINTER, BOOLEAN] =
MACHINE CODE BEGIN
Mopcodes.zMISC,3;
END;

LoadRamAndJumpArg: PROCEDURE [UNSPECIFIED, LONG POINTER, BOOLEAN] =
MACHINE CODE BEGIN
Mopcodes.zMISC,3;
END;

LoadRamAndJumpRslt: PROCEDURE [LONG POINTER, BOOLEAN] RETURNS [UNSPECIFIED] =
MACHINE CODE BEGIN
Mopcodes.zMISC,3;
END;

LoadRamAndJumpArgRslt: PROCEDURE [UNSPECIFIED, LONG POINTER, BOOLEAN] RETURNS [UNSPECIFIED] =
MACHINE CODE BEGIN
Mopcodes.zMISC,3;
END;

JumpRam: PUBLIC PROCEDURE [RAMAddress: [0..7777B]] =
BEGIN
EndBlock.StartAddr ← RAMAddress;
LoadRamAndJump[@EndBlock,TRUE];
END;

JumpRamArg
: PUBLIC PROCEDURE [RAMAddress: [0..7777B],Argument: UNSPECIFIED] =
BEGIN
EndBlock.StartAddr ← RAMAddress;
LoadRamAndJumpArg[Argument,@EndBlock,TRUE];
END;

JumpRamRslt
: PUBLIC PROCEDURE [RAMAddress: [0..7777B]] RETURNS [UNSPECIFIED] =
BEGIN
EndBlock.StartAddr ← RAMAddress;
RETURN[LoadRamAndJumpRslt[@EndBlock,TRUE]];
END;

JumpRamArgRslt
: PUBLIC PROCEDURE [RAMAddress: [0..7777B],Argument: UNSPECIFIED]
RETURNS [UNSPECIFIED] =
BEGIN
EndBlock.StartAddr ← RAMAddress;
RETURN[LoadRamAndJumpArgRslt[Argument,@EndBlock,TRUE]];
END;
--Kludge to make sure module is started from alto
LoadRam
: PUBLIC PROCEDURE =
BEGIN
END;

uImageFile: SegmentDefs.FileSegmentHandle;
uCode: POINTER;
offset: CARDINAL;
machine: MemoryOps.MachineType ← MemoryOps.GetMemoryConfig[].AltoType;

IF machine IN [AltoIIXM..D0] THEN
BEGIN
[uImageFile,offset] ←
MiscDefs.DestroyFakeModule[LOOPHOLE[
(IF machine = D0 THEN D0MicrocodeDefs.MicrocodeImage
ELSE AltoMicrocodeDefs.MicrocodeImage)]];
SegmentDefs.SwapIn[uImageFile];
uCode ← SegmentDefs.FileSegmentAddress[uImageFile]+offset;
IF machine = D0 THEN LoadRamAndJump[uCode,FALSE]
ELSE [] ← RamDefs.LoadRamAndBoot[LOOPHOLE[uCode-20B],FALSE];
SegmentDefs.Unlock[uImageFile];
SegmentDefs.SwapOut[uImageFile];
END;

END.