-- Checksum.mesa (last edited on:  October 4, 1980  2:03 PM by: Forrest)

DIRECTORY
  MiscAlpha USING [aCHKSUM],
  Mopcodes USING [zADD, zDADD, zDUP, zEXCH, zINC, zLI0, zMISC];

Checksum: DEFINITIONS =
  BEGIN

  -- Produce checksum for nWords starting at p.  Start with initial value cs (useful if forming a single checksum for discontinuous areas of memory).

  ComputeChecksum: PROC [cs: CARDINAL ← 0, nWords: CARDINAL, p: LONG POINTER]
    RETURNS [checksum: CARDINAL] = MACHINE CODE
    BEGIN Mopcodes.zMISC, MiscAlpha.aCHKSUM; END;

  -- ComputeChecksumSoftware is provided as documentation.

  ComputeChecksumSoftware: PRIVATE PROC [
    cs: CARDINAL ← 0, nWords: CARDINAL, p: LONG POINTER]
    RETURNS [checksum: CARDINAL] = INLINE
    BEGIN
    THROUGH [0..nWords) DO
      t: CARDINAL;
      -- cs ← ((cs ONESADD p↑) LEFTROTATE 1)
      IF cs > (t ← cs + p↑) THEN cs ← t + 1 ELSE cs ← t;
      IF cs >= 100000B THEN cs ← cs*2 + 1 ELSE cs ← cs*2;
      p ← p + 1;
      ENDLOOP;
    IF cs = 177777B THEN cs ← 0;
    RETURN[cs];
    END;

  -- ComputeChecksumProc is provided as an aid to processors required to compute checksum as part of their unimplemented instruction trap.

  ComputeChecksumProc: PRIVATE PROC [
    cs: CARDINAL ← 0, nWords: CARDINAL, p: LONG POINTER]
    RETURNS [checksum: CARDINAL] = INLINE
    BEGIN
    Push: PROC [CARDINAL] = MACHINE CODE BEGIN END;
    Pop: PROC RETURNS [CARDINAL] = MACHINE CODE BEGIN END;
    TOS: PROC RETURNS [CARDINAL] = MACHINE CODE BEGIN Mopcodes.zDUP; END;
    IncTOS: PROC = MACHINE CODE BEGIN Mopcodes.zINC; END;
    OnesAddAndLeftRotate: PROC [
      --cs: CARDINAL,--zero: CARDINAL ← 0, wd: CARDINAL, zero1: CARDINAL ← 0]
      --RETURNS [cs: CARDINAL]-- = MACHINE CODE
      BEGIN
      Mopcodes.zDADD;
      Mopcodes.zADD; -- cs ← (cs ONESADD wd)
      Mopcodes.zDUP;
      Mopcodes.zLI0;
      Mopcodes.zEXCH;
      Mopcodes.zLI0; -- Long[cs], Long[cs]
      Mopcodes.zDADD;
      Mopcodes.zADD; -- Rotate via long add to self, merging carry
      END;

    --TOS←-- Push[cs]; -- leave cs on the stack throughout the procedure
    THROUGH [0..nWords) DO
      --TOS←-- OnesAddAndLeftRotate[--cs: TOS,-- wd: p↑]; p ← p + 1 ENDLOOP;
    IF TOS[] = 177777B THEN IncTOS[];
    RETURN[Pop[--TOS--]];
    END;


  END....