-- File: PupChecksums.mesa, Last Edit: HGM October 15, 1980 7:37 PM

DIRECTORY
PrincOps USING [aCHKSUM, zMISC, zPOP, zADD, zDADD, zEXCH, zDUP, zLI0],
AltoRam USING [PupChecksum],
PupRouterDefs USING [Checksum],
CommUtilDefs USING [thisIsAnAlto],
BufferDefs USING [PupBuffer];

PupChecksums: PROGRAM IMPORTS AltoRam EXPORTS PupRouterDefs =
BEGIN

checksum: PUBLIC PupRouterDefs.Checksum ←
IF CommUtilDefs.thisIsAnAlto THEN software ELSE princOps;

ShortenData: PROCEDURE [LONG POINTER] RETURNS [POINTER] = MACHINE CODE
BEGIN PrincOps.zPOP; END;

ComputeD0Checksum: PROCEDURE [cs: CARDINAL, nWords: CARDINAL, p: LONG POINTER]
RETURNS [CARDINAL] = MACHINE CODE
BEGIN PrincOps.zMISC, PrincOps.aCHKSUM; END;

OnesComplementAddAndCycle: PROCEDURE [a, b: LONG UNSPECIFIED]
RETURNS [UNSPECIFIED] = MACHINE CODE
BEGIN
PrincOps.zDADD;
PrincOps.zADD; -- Ones add if a+b are in CARDINAL range
PrincOps.zDUP;
PrincOps.zLI0;
PrincOps.zEXCH;
PrincOps.zLI0; -- Make LONG again
PrincOps.zDADD;
PrincOps.zADD;
END;


SetPupChecksum: PUBLIC PROCEDURE [b: BufferDefs.PupBuffer] =
BEGIN
size: CARDINAL ← (b.pupLength - 1)/2;
checksumLoc: LONG POINTER ← @b.pupLength + size;
cs: CARDINAL;
SELECT checksum FROM
princOps =>
 BEGIN checksumLoc^ ← ComputeD0Checksum[0, size, @b.pupLength]; END;
alto =>
 BEGIN
 where: POINTER ← ShortenData[@b.pupLength];
 checksumLoc^ ← AltoRam.PupChecksum[0, where, size];
 END;
none => BEGIN checksumLoc^ ← 177777B; END;
software =>
 BEGIN
 p: LONG POINTER TO ARRAY [0..0) OF WORD = LOOPHOLE[@b.pupLength];
 cs ← 0;
 FOR i: CARDINAL IN [0..size) DO
  cs ← OnesComplementAddAndCycle[p[i], cs]; ENDLOOP;
 IF cs = 177777B THEN cs ← 0;
 checksumLoc^ ← cs;
 END;
ENDCASE => NULL;
END;

TestPupChecksum: PUBLIC PROCEDURE [b: BufferDefs.PupBuffer] RETURNS [BOOLEAN] =
BEGIN
size: CARDINAL ← ((LOOPHOLE[b.pupLength - 1, CARDINAL])/2);
checksumLoc: LONG POINTER ← @b.pupLength + size;
cs: CARDINAL;
IF checksumLoc^ = 177777B THEN RETURN[TRUE];
SELECT checksum FROM
princOps =>
 BEGIN
 -- BEWARE: The stack must be empty. Dont try RETURN[xx^=PupChecksum[xxx]];
 cs ← ComputeD0Checksum[0, size, @b.pupLength];
 END;
alto =>
 BEGIN
 where: POINTER ← ShortenData[@b.pupLength];
 -- BEWARE: The stack must be empty. Dont try RETURN[xx^=PupChecksum[xxx]];
 cs ← AltoRam.PupChecksum[0, where, size];
 END;
none => BEGIN RETURN[TRUE]; END;
software =>
 BEGIN
 p: LONG POINTER TO ARRAY [0..0) OF WORD = LOOPHOLE[@b.pupLength];
 cs ← 0;
 FOR i: CARDINAL IN [0..size) DO
  cs ← OnesComplementAddAndCycle[p[i], cs]; ENDLOOP;
 IF cs = 177777B THEN cs ← 0;
 END;
ENDCASE => NULL;
RETURN[checksumLoc^ = cs];
END;

END.