-- file: PeepholeQ.mesa
-- last edited by Sweet on  5-Oct-82 11:26:03
-- last edited by Satterthwaite on December 16, 1982 9:48 am

DIRECTORY
  Alloc: TYPE USING [Notifier],
  Code: TYPE USING [CodePassInconsistency, codeptr],
  CodeDefs: TYPE USING [
    Base, CCIndex, CCNull, CodeCCIndex, codeType, JumpCCIndex, JumpType],
  FOpCodes: TYPE USING [
    qACD, qADC, qADD, qADDSB, qAL0IB, qAMUL, qAND, qDADD, qDBL,
    qDBS, qDDBL, qDDUP, qDEC, qDI, qDINC, qDIS, qDIS2, qDMUL, qDSHIFT,
    qDSK, qDSUB, qDUDIV, qDUP, qEFC, qEI, qEXCH, qEXDIS, qGA, qINC,
    qIOR, qKFCB, qLA, qLFC, qLG, qLGD, qLI, qLID, qLL, qLLD, qLLK, qLP,
    qLSTE, qLSTF, qMUL, qNEG, qNULL, qPI, qPL, qPLD, qPO, qPS, 
    qPSCDL, qPSCIDL, qPSD, qPSDL, qPSF, qPSL, qPSLF, qR, qRD, qRDL,
    qREC, qREC2, qRET, qRF, qRGDI, qRGDIL, qRGI, qRGIL, qRGILF,
    qRKDI, qRKI, qRL, qRLDI, qRLDIL, qRLF, qRLI, qRLIF, qRLIL, qRLILF,
    qRSTR, qRSTRL, qSDIV, qSFC, qSG, qSGD, qSHIFT, qSHIFTSB, qSL, qSLD,
    qSUB, qTRPL, qUDIV, qWDL, qWF, qWGDI, qWGDIL, qWGI, qWGIL, qWGILF,
    qWL, qWLDI, qWLDIL, qWLF, qWLI, qWLIL, qWLILF, qWS, qWSCDL,
    qWSCIDL, qWSD, qWSDL, qWSF,  qWSL, qWSLF, qWSTR, qWSTRL, qXOR],
  Inline: TYPE USING [BITAND, BITSHIFT],
  OpCodeParams: TYPE USING [BYTE, GlobalHB, HB, LocalBase, LocalHB],
  P5: TYPE USING [PopEffect, PushEffect, C0, C1, C2, C3, LoadConstant],
  P5U: TYPE USING [DeleteCell],
  PeepholeDefs: TYPE USING [
    ConsPeepState, DblLoadInst, Delete2, Delete3, InitConsState, InitJParametersBC,
    InitParameters, JumpPeepState, LoadInst, NextInteresting, NextIsPush, PeepholeANotify,
    PeepholeUNotify, PeepholeZNotify, Peep1, Peep2, Peep10, PeepState, PeepZ,
    SetRealInst, SlideConsState, SlidePeepState2, UnpackFD],
  PrincOps: TYPE USING [FieldDescriptor];

PeepholeQ: PROGRAM
    IMPORTS CPtr: Code, Inline, P5, P5U, PeepholeDefs
    EXPORTS CodeDefs, P5, PeepholeDefs =
  BEGIN OPEN PeepholeDefs, OpCodeParams, CodeDefs;

  -- imported definitions

  BYTE: TYPE = OpCodeParams.BYTE;
  qNULL: BYTE = FOpCodes.qNULL;

  cb: CodeDefs.Base;		-- code base (local copy)

  DummyProc: PROC =
    BEGIN -- every 2 minutes of compile time helps
    s: PeepState;
    js: JumpPeepState;
    IF FALSE THEN [] ← s;
    IF FALSE THEN [] ← js;
    END;

  PeepholeNotify: PUBLIC Alloc.Notifier =
    BEGIN  -- called by allocator whenever table area is repacked
    cb ← base[codeType];
    PeepholeANotify[base];  PeepholeZNotify[base];  PeepholeUNotify[base];
    END;

  
  start: PUBLIC CodeCCIndex;

  PeepHole: PUBLIC PROC [s: CCIndex] =
    BEGIN
    start ← LOOPHOLE[s];
    SetRealInst[FALSE];
    Peep0[]; -- remove POPs by modifying previous instruction
    Peep1[]; -- expand families
    Peep2[]; -- discover short magic
    Peep5[]; -- discover long magic
    Peep3[]; -- discover doubles (shouldn't uncover any long magic)
    Peep4[]; -- long arithmetic: INC and DEC, MUL to SHIFT etc
    Peep5a[]; -- constructor stuff
    Peep3[]; -- discover doubles again (5a may have uncovered some)
    Peep6[]; -- sprinkle single DUPs
    Peep7[]; -- sprinkle double DUPs
    Peep8[]; -- PUTs and PUSHs, RF and WF to RSTR and WSTR
    Peep9[]; -- long PUTs and PUSHs
    Peep10[]; -- expand unimplemented magic
    Peep11[]; -- short arithmetic: INC and DEC, MUL to SHIFT etc
    Peep13[]; -- find special jumps
    SetRealInst[TRUE];
    PeepZ[start];
    END;

  BackupCP: PROC [n: INTEGER] RETURNS [INTEGER] =
    BEGIN OPEN FOpCodes; -- back up codeptr n stack positions
    cc: CCIndex ← CPtr.codeptr;
    netEffect: INTEGER;
    WHILE (cc ← cb[cc].blink) # CCNull AND n # 0 DO
      WITH cb[cc] SELECT FROM
	code =>
	  BEGIN
	  IF realinst THEN EXIT;
	  SELECT inst FROM
	    qEFC, qLFC, qSFC, qKFCB, qRET, qPO, qPI, qLSTE, qLSTF, qDSK => EXIT;
	    ENDCASE;
	  netEffect ← P5.PushEffect[inst] - P5.PopEffect[inst];
	  IF n < netEffect THEN EXIT;
	  n ← n - netEffect;
	  END;
	other => IF otag = table THEN EXIT;
	ENDCASE => EXIT;
      ENDLOOP;
    CPtr.codeptr ← cc;
    RETURN [n]
    END;

  InsertPOP: PROC [n: INTEGER] =
    BEGIN OPEN FOpCodes; -- insert (or simulate) a POP of the word at tos-n
    saveCodePtr: CCIndex ← CPtr.codeptr;
    n ← BackupCP[n];
    SELECT n FROM
      0 => P5.C0[qDIS];
      1 => {P5.C0[qEXCH]; P5.C0[qDIS]};
      2 => {P5.C0[qDIS]; P5.C0[qEXCH]; P5.C0[qREC]; P5.C0[qEXCH]; P5.C0[qDIS]};
      3 =>
	BEGIN
	P5.C0[qDIS]; P5.C0[qDIS]; P5.C0[qEXCH]; P5.C0[qREC]; P5.C0[qEXCH];
	P5.C0[qREC]; P5.C0[qEXCH]; P5.C0[qDIS];
	END;
      ENDCASE => SIGNAL CPtr.CodePassInconsistency;
    CPtr.codeptr ← saveCodePtr;
    END;

  Peep0: PUBLIC PROC =
    BEGIN -- remove POPs by modifying previous instruction
    OPEN FOpCodes;
    next, ci: CCIndex;
    changed: BOOL ← TRUE;
    WHILE changed DO
      next ← start;
      changed ← FALSE;
      UNTIL (ci ← next) = CCNull DO
        next ← NextInteresting[ci];
        WITH cb[ci] SELECT FROM
	  code => IF ~realinst THEN SELECT inst FROM
	    qDIS => changed ← changed OR RemoveThisPop[ci];
	    qDIS2 => {
	      inst ← qDIS;
	      CPtr.codeptr ← ci; P5.C0[qDIS];
	      next ← CPtr.codeptr;
	      changed ← changed OR RemoveThisPop[ci]};
	    ENDCASE;
	  ENDCASE;
        ENDLOOP;
      ENDLOOP;
    END;

  RemoveThisPop: PUBLIC PROC [ci: CCIndex] RETURNS [didThisTime: BOOL] =
    BEGIN -- remove POP by modifying previous instruction, if possible
    OPEN FOpCodes;
    state: PeepState;
    didThisTime ← FALSE;
    WITH cb[ci] SELECT FROM
      code =>
        BEGIN OPEN state;
        InitParameters[@state, LOOPHOLE[ci], abc];
        SELECT cInst FROM
          qDIS =>
            IF Popable[bInst] THEN
              {P5U.DeleteCell[b]; P5U.DeleteCell[c]; didThisTime ← TRUE}
            ELSE
              SELECT bInst FROM
                qR, qRF, qNEG, qDBS, qINC, qDEC =>
                  BEGIN
                  P5U.DeleteCell[b];
		 [] ← RemoveThisPop[c]; -- the blink may be popable now
		      -- above is unnecessary if called from Peep1
		      -- but useful if called from jump elimination
                  didThisTime ← TRUE;
                  END;
	        qRSTR, qADD, qSUB, qMUL, qAMUL, qUDIV, qSDIV, qAND, qIOR, qXOR,
		qSHIFT, qRL, qRLF =>
		  BEGIN
		  np: CCIndex;
		  P5U.DeleteCell[b];
		  CPtr.codeptr ← cb[c].blink;
		  P5.C0[qDIS];
		  np ← CPtr.codeptr;
		  [] ← RemoveThisPop[np];  [] ← RemoveThisPop[c];
		  END;
		-- should add arm for RLFS
                qDADD =>
                  IF Popable[aInst] THEN
                    BEGIN
                    Delete2[a,b];
                    InsertPOP[1];
                    P5.C0[qADD];
                    P5U.DeleteCell[c];
                    didThisTime ← TRUE;
                    END;
 	        qLGD => {cb[b].inst ← qLG; P5U.DeleteCell[c]; didThisTime ← TRUE};
	        qLLD => {cb[b].inst ← qLL; P5U.DeleteCell[c]; didThisTime ← TRUE};
	        qLID => {cb[b].inst ← qLI; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRD => {cb[b].inst ← qR; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRDL => {cb[b].inst ← qRL; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRGDI => {
		  cb[b].inst ← qRGI; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRGDIL => {
		  cb[b].inst ← qRGIL; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRKDI => {
		  cb[b].inst ← qRKI; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRLDI => {
		  cb[b].inst ← qRLI; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qRLDIL => {
		  cb[b].inst ← qRLIL; P5U.DeleteCell[c]; didThisTime ← TRUE};
                qDI, qEI => {CommuteCells[b,c]; didThisTime ← TRUE};
		-- could handle qACD and qADC when have more time to think thru
	        qEXCH => 
		  IF IsLoad[aInst] THEN
		    BEGIN
		    Delete2[b, c];
		    CPtr.codeptr ← cb[a].blink;
		    P5.C0[qDIS];
		    [] ← RemoveThisPop[CPtr.codeptr];
		    didThisTime ← TRUE;
		    END
		  ELSE {cb[c].inst ← qEXDIS; P5U.DeleteCell[b]; didThisTime ← TRUE};
                ENDCASE;
          ENDCASE;
        END;
      ENDCASE; -- of WITH
    END;

  Popable: PROC [inst: BYTE] RETURNS [BOOL] =
    BEGIN
    RETURN [inst#qNULL AND
      (P5.PopEffect[inst]=0 AND P5.PushEffect[inst]=1 OR inst = FOpCodes.qDUP)]
    END;

  IsLoad: PROC [inst: BYTE] RETURNS [BOOL] =
    BEGIN
    RETURN [inst#qNULL AND inst # FOpCodes.qREC AND
      (P5.PopEffect[inst]=0 AND P5.PushEffect[inst]=1)]
    END;

  Peep5: PUBLIC PROC =
    BEGIN -- discover long magic
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    state: PeepState;
    canSlide: BOOL ← FALSE;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    -- discover family members from sequences
	    qRL =>
	      IF cP[1] IN HB THEN
		SELECT bInst FROM
		  qLLD =>
		    IF -- RiImplemented[read][local][long][single] AND
		    bP[1] IN LocalHB THEN 
		      {P5.C2[qRLIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  qLGD =>
		    IF -- RiImplemented[read][global][long][single] AND
		    bP[1] IN GlobalHB THEN 
		      {P5.C2[qRGIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  ENDCASE => canSlide ← TRUE;
	    qWL =>
	      IF cP[1] IN HB THEN
		SELECT bInst FROM
		  qLLD =>
		    IF -- RiImplemented[write][local][long][single] AND
		     bP[1] IN LocalHB THEN 
		      {P5.C2[qWLIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  qLGD =>
		    IF -- RiImplemented[write][global][long][single] AND
		     bP[1] IN GlobalHB THEN 
		      {P5.C2[qWGIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  ENDCASE => canSlide ← TRUE;
	    qRDL =>
	      IF cP[1] IN HB THEN
		SELECT bInst FROM
		  qLLD =>
		    IF -- RiImplemented[read][local][long][double] AND
		     bP[1] IN LocalHB THEN 
		      {P5.C2[qRLDIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  qLGD =>
		    IF -- RiImplemented[read][global][long][double] AND
		     bP[1] IN GlobalHB THEN 
		      {P5.C2[qRGDIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  ENDCASE => canSlide ← TRUE;
	    qWDL =>
	      IF cP[1] IN HB THEN
		SELECT bInst FROM
		  qLLD =>
		    IF -- RiImplemented[write][local][long][double] AND
		     bP[1] IN LocalHB THEN 
		      {P5.C2[qWLDIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  qLGD =>
		    IF -- RiImplemented[write][global][long][double] AND
		     bP[1] IN GlobalHB THEN 
		      {P5.C2[qWGDIL, bP[1], cP[1]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  ENDCASE => canSlide ← TRUE;
	    qRLF =>
	      IF cP[1] IN HB THEN
		SELECT bInst FROM
		  qLLD =>
		    IF -- RiImplemented[read][local][long][field] AND
		     bP[1] IN LocalHB THEN 
		      {P5.C3[qRLILF, bP[1], cP[1], cP[2]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  qLGD =>
		    IF -- RiImplemented[read][global][long][field] AND
		     bP[1] IN GlobalHB THEN 
		      {P5.C3[qRGILF, bP[1], cP[1], cP[2]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  ENDCASE => canSlide ← TRUE;
	    qWLF =>
	      IF cP[1] IN HB THEN
		SELECT bInst FROM
		  qLLD =>
		    IF -- RiImplemented[write][local][long][field] AND
		     bP[1] IN LocalHB THEN 
		      {P5.C3[qWLILF, bP[1], cP[1], cP[2]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  qLGD =>
		    IF -- RiImplemented[write][global][long][field] AND
		     bP[1] IN GlobalHB THEN 
		      {P5.C3[qWGILF, bP[1], cP[1], cP[2]]; Delete2[b,c]}
		    ELSE canSlide ← TRUE;
		  ENDCASE => canSlide ← TRUE;
	    ENDCASE => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Peep5a: PUBLIC PROC =
    BEGIN -- constructor stuff
    OPEN FOpCodes;
    di: CCIndex;
    next: CCIndex;
    state: ConsPeepState;
    didSomething: BOOL ← TRUE;
    canSlide: BOOL ← FALSE;
    WHILE didSomething DO
      next ← start;
      didSomething ← FALSE;
    UNTIL (di ← next) = CCNull DO
      next ← NextInteresting[di];
      WITH dd: cb[di] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlideConsState[@state, LOOPHOLE[di]]
	  ELSE InitConsState[@state, LOOPHOLE[di]];
	  SELECT d.inst FROM
	    qPSF, qWSF => 
	      IF c.inst = qLI AND b.inst = qPSF AND a.inst = qLI THEN
	      BEGIN
	      newOp: BYTE = IF d.inst = qPSF THEN qPS ELSE qWS;
	      mask: ARRAY [0..16] OF CARDINAL = [
	        0, 1, 3, 7, 17B, 37B, 77B, 177B, 377B,
		777B, 1777B, 3777B, 7777B, 17777B, 37777B,
		77777B, 177777B];
	      p1, s1, p2, s2, v: CARDINAL;
	      fd: PrincOps.FieldDescriptor;
	      FullWord: PrincOps.FieldDescriptor = [offset: 0, posn: 0, size: 16];
	      IF b.params[1] # d.params[1] THEN GO TO slide;
	      [p: p1, s: s1] ← UnpackFD[LOOPHOLE[b.params[2]]];
	      [p: p2, s: s2] ← UnpackFD[LOOPHOLE[d.params[2]]];
	      IF p1+s1 # p2 THEN GO TO slide;
	      v ← Inline.BITSHIFT[a.params[1], s2] + Inline.BITAND[c.params[1], mask[s2]];
	      fd ← [offset: 0, posn: p1, size: s1+s2];
	      IF fd = FullWord THEN {
	        P5.C1[newOp, d.params[1]];
		Delete3[a.index, b.index, d.index]}
	      ELSE {
	        cb[d.index].parameters[2] ← LOOPHOLE[fd];
	        Delete2[a.index, b.index]};
	      cb[c.index].parameters[1] ← v;
	      didSomething ← TRUE;
	      canSlide ← FALSE;
	      END; 
	    qPSLF, qWSLF => 
	      IF c.inst = qLI AND b.inst = qPSLF AND a.inst = qLI THEN
	      BEGIN
	      newOp: BYTE = IF d.inst = qPSLF THEN qPSL ELSE qWSL;
	      mask: ARRAY [0..16] OF CARDINAL = [
	        0, 1, 3, 7, 17B, 37B, 77B, 177B, 377B,
		777B, 1777B, 3777B, 7777B, 17777B, 37777B,
		77777B, 177777B];
	      p1, s1, p2, s2, v: CARDINAL;
	      fd: PrincOps.FieldDescriptor;
	      FullWord: PrincOps.FieldDescriptor = [offset: 0, posn: 0, size: 16];
	      IF b.params[1] # d.params[1] THEN GO TO slide;
	      [p: p1, s: s1] ← UnpackFD[LOOPHOLE[b.params[2]]];
	      [p: p2, s: s2] ← UnpackFD[LOOPHOLE[d.params[2]]];
	      IF p1+s1 # p2 THEN GO TO slide;
	      v ← Inline.BITSHIFT[a.params[1], s2] + Inline.BITAND[c.params[1], mask[s2]];
	      fd ← [offset: 0, posn: p1, size: s1+s2];
	      IF fd = FullWord THEN {
	        P5.C1[newOp, d.params[1]];
		Delete3[a.index, b.index, d.index]}
	      ELSE {
	        cb[d.index].parameters[2] ← LOOPHOLE[fd];
	        Delete2[a.index, b.index]};
	      cb[c.index].parameters[1] ← v;
	      didSomething ← TRUE;
	      canSlide ← FALSE;
	      END; 
	    qPS, qWS => 
	      BEGIN
	      newOp: BYTE = IF d.inst = qPS THEN qPSD ELSE qWSD;
	      IF LoadInst[c.index] AND b.inst = qPS AND LoadInst[a.index] 
	        AND b.params[1] + 1 = d.params[1] THEN
	        BEGIN
		cb[d.index].inst ← newOp;
		cb[d.index].parameters[1] ← b.params[1];
		P5U.DeleteCell[b.index];
	        didSomething ← TRUE;
	        canSlide ← FALSE;
	        END
	      ELSE canSlide ← TRUE; 
	      END;
	    qPSL, qWSL => 
	      BEGIN
	      newOp: BYTE = IF d.inst = qPSL THEN qPSDL ELSE qWSDL;
	      IF LoadInst[c.index] AND b.inst = qPSL AND LoadInst[a.index] 
	        AND b.params[1] + 1 = d.params[1] THEN
	        BEGIN
		cb[d.index].inst ← newOp;
		cb[d.index].parameters[1] ← b.params[1];
		P5U.DeleteCell[b.index];
	        didSomething ← TRUE;
	        canSlide ← FALSE;
	        END
	      ELSE canSlide ← TRUE; 
	      END;
	    qSL, qSG => 
	      BEGIN
	      newOp: BYTE = IF d.inst = qSL THEN qSLD ELSE qSGD;
	      IF LoadInst[c.index] AND b.inst = d.inst AND LoadInst[a.index] 
	        AND b.params[1] + 1 = d.params[1] AND ~NextIsPush[d.index] THEN
	        BEGIN
		cb[d.index].inst ← newOp;
		cb[d.index].parameters[1] ← b.params[1];
		P5U.DeleteCell[b.index];
	        didSomething ← TRUE;
	        canSlide ← FALSE;
	        END
	      ELSE canSlide ← TRUE; 
	      END;
	    ENDCASE => canSlide ← TRUE;
	  EXITS
	    slide => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
      ENDLOOP; -- of WHILE didSomething
    END;


  Peep6: PUBLIC PROC =
    BEGIN -- sprinkle single DUPs
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    state: PeepState;
    canSlide: BOOL ← FALSE;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    -- replace load,load with load,DUP
	    qLI =>
	      IF bInst = cInst AND cP[1] = bP[1] THEN 
	        IF cP[1] = 0 THEN {P5.C1[qLID, 0]; Delete2[b, c]}
		ELSE {P5.C0[qDUP]; P5U.DeleteCell[c]}
	      ELSE canSlide ← TRUE;
	    qLP =>
	      IF bInst = qLI AND bP[1] = 0 THEN {
	        P5.C1[qLID, 0]; Delete2[b, c]}
	      ELSE canSlide ← TRUE;
	    qLL, qLG, qLLK, qLA, qGA =>
	      IF bInst = cInst AND cP[1] = bP[1] THEN {
	        P5.C0[qDUP]; P5U.DeleteCell[c]}
	      ELSE canSlide ← TRUE;
	    qRLI, qRGI, qRLIL, qRGIL, qRKI =>
	      IF bInst = cInst AND cP[1] = bP[1] AND 
	        cP[2] = bP[2] THEN
		{P5.C0[qDUP]; P5U.DeleteCell[c]}
	      ELSE canSlide ← TRUE;
	    qRLIF, qRLILF =>
	      IF bInst = cInst AND cP[1] = bP[1] AND 
	        cP[2] = bP[2] AND cP[3] = bP[3] THEN
		{P5.C0[qDUP]; P5U.DeleteCell[c]}
	      ELSE canSlide ← TRUE;
	    ENDCASE => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Peep7: PUBLIC PROC =
    BEGIN -- sprinkle double DUPs
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    state: PeepState;
    canSlide: BOOL ← FALSE;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    -- replace load,load with load,DDUP
	    qLLD, qLGD =>
	      IF bInst = cInst AND cP[1] = bP[1] THEN {P5.C0[qDDUP]; P5U.DeleteCell[c]};
	    qRLDI, qRLDIL, qRKDI =>
	      IF bInst = cInst AND cP[1] = bP[1] AND cP[2] = bP[2] THEN
		{P5.C0[qDDUP]; P5U.DeleteCell[c]};
	    ENDCASE => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Peep8: PUBLIC PROC =
    BEGIN -- PUTs and PUSHs, RF and WF to RSTR and WSTR
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    state: PeepState;
    canSlide: BOOL ← FALSE;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    qLL =>
	      IF bInst = qSL AND cP[1] IN BYTE AND cP[1] = bP[1] THEN
		{cb[b].inst ← qPL; P5U.DeleteCell[c]}
	      ELSE IF bInst = qSLD AND cP[1] = bP[1] THEN
	        {CPtr.codeptr ← b; P5.C0[qREC]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qREC => SELECT bInst FROM 
	      qSL => IF bP[1] IN BYTE THEN {cb[b].inst ← qPL; P5U.DeleteCell[c]};
	      qREC => {cb[b].inst ← qREC2; P5U.DeleteCell[c]};
	      ENDCASE =>  GO TO Slide;
	    qLG =>
	      IF (bInst = qSG OR bInst = qSGD) AND cP[1] = bP[1] THEN
		{CPtr.codeptr ← b; P5.C0[qREC]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRLI =>
	      IF (bInst = qWLI OR bInst = qWLDI) AND 
	        cP[1] = bP[1] AND cP[2] = bP[2] THEN
		{CPtr.codeptr ← b; P5.C0[qREC]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRLIL =>
	      IF (bInst = qWLIL OR bInst = qWLDIL)
	        AND cP[1] = bP[1] AND cP[2] = bP[2] THEN
		{CPtr.codeptr ← b; P5.C0[qREC]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRF, qWF, qRLF, qWLF =>
	      BEGIN
	      position, size: [0..16);
	      [position, size] ← UnpackFD[LOOPHOLE[cP[2]]];
	      IF size = 8 AND cP[1] <= BYTE.LAST/2 THEN
		SELECT position FROM
		  0, 8 => 
		    BEGIN 
		    P5.LoadConstant[0];
		    P5.C1[(SELECT cInst FROM
		      qRF => qRSTR,
		      qWF => qWSTR,
		      qRLF => qRSTRL,
		      ENDCASE => qWSTRL), cP[1]*2+position/8];
		    P5U.DeleteCell[c];
		    END;
		  ENDCASE => GO TO Slide
	      ELSE GO TO Slide; 
	      END;
	    ENDCASE => GO TO Slide;
	  EXITS
	    Slide => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Peep9: PUBLIC PROC =
    BEGIN -- long PUTs and PUSHs
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    state: PeepState;
    canSlide: BOOL ← FALSE;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    qLL =>
	      IF bInst = qPL AND cP[1] = bP[1]+1 AND aInst = qSL AND aP[1] = cP[1] THEN
		{cb[b].inst ← qPLD; Delete2[a, c]}
	      ELSE GO TO Slide;
	    qLLD =>
	      IF bInst = qSLD AND cP[1] IN BYTE AND cP[1] = bP[1] THEN
		{cb[b].inst ← qPLD; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qREC2 => SELECT bInst FROM 
	      qSLD => IF bP[1] IN BYTE THEN {cb[b].inst ← qPLD; P5U.DeleteCell[c]};
	      qWSL => {cb[b].inst ← qPSL; P5U.DeleteCell[c]};
	      qWSDL => {cb[b].inst ← qPSDL; P5U.DeleteCell[c]};
	      qWSLF => {cb[b].inst ← qPSLF; P5U.DeleteCell[c]};
	      qWSCIDL => {cb[b].inst ← qPSCIDL; P5U.DeleteCell[c]};
	      qWSCDL => {cb[b].inst ← qPSCDL; P5U.DeleteCell[c]};
	      ENDCASE =>  GO TO Slide;
	    qLGD =>
	      IF bInst = qSGD AND cP[1] = bP[1] THEN
		{CPtr.codeptr ← b; P5.C0[qREC2]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRLDI =>
	      IF bInst = qWLDI AND cP[1] = bP[1] AND cP[2] = bP[2] THEN
		{CPtr.codeptr ← b; P5.C0[qREC2]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRLDIL =>
	      IF bInst = qWLDIL AND cP[1] = bP[1] AND cP[2] = bP[2] THEN
		{CPtr.codeptr ← b; P5.C0[qREC2]; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    ENDCASE => GO TO Slide;
	  EXITS
	    Slide => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Peep3: PUBLIC PROC =
    BEGIN -- discover doubles
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    state: PeepState;
    canSlide: BOOL ← FALSE;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cc:cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    qLL =>
	      IF bInst = qLL AND cP[1] = bP[1]+1 THEN
		{cb[b].inst ← qLLD; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qSL =>
	      IF bInst = qSL AND cP[1] = bP[1]-1 THEN
		{cb[c].inst ← qSLD; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qLG =>
	      IF bInst = qLG AND cP[1] = bP[1]+1 THEN
		{cb[b].inst ← qLGD; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qSG =>
	      IF bInst = qSG AND cP[1] = bP[1]-1 THEN
		{cb[c].inst ← qSGD; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qRLI =>
	      IF bInst = qRLI AND cP[1] = bP[1] AND cP[2] = bP[2]+1 THEN
		{cb[b].inst ← qRLDI; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRGI =>
	      IF bInst = qRGI AND cP[1] = bP[1] AND cP[2] = bP[2]+1 THEN
		{cb[b].inst ← qRGDI; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRLIL =>
	      IF bInst = qRLIL AND cP[1] = bP[1] AND cP[2] = bP[2]+1 THEN
		{cb[b].inst ← qRLDIL; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qRGIL =>
	      IF bInst = qRGIL AND cP[1] = bP[1] AND cP[2] = bP[2]+1 THEN
		{cb[b].inst ← qRGDIL; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qWLI =>
	      IF bInst = qWLI AND cP[1] = bP[1] AND cP[2]+1 = bP[2] THEN
		{cb[c].inst ← qWLDI; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qWGI =>
	      IF bInst = qWGI AND cP[1] = bP[1] AND cP[2]+1 = bP[2] THEN
		{cb[c].inst ← qWGDI; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qWLIL =>
	      IF bInst = qWLIL AND cP[1] = bP[1] AND cP[2]+1 = bP[2] THEN
		{cb[c].inst ← qWLDIL; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qWGIL =>
	      IF bInst = qWGIL AND cP[1] = bP[1] AND cP[2]+1 = bP[2] THEN
		{cb[c].inst ← qWGDIL; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qRKI =>
	      IF bInst = qRKI AND cP[1] = bP[1] AND cP[2] = bP[2]+1 THEN
		{cb[b].inst ← qRKDI; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    qDIS =>
	      IF bInst = qDIS THEN
		{cb[b].inst ← qDIS2; P5U.DeleteCell[c]}
	      ELSE GO TO Slide;
	    ENDCASE => GO TO Slide;
	  EXITS
	    Slide => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  CommuteCells: PUBLIC PROC [a, b: CCIndex] =
    BEGIN -- could be a "source other CCItem" between,
    --  in any case, move a to after b
    --  see 3/5/80 notes for rationale
    aPrev: CCIndex = cb[a].blink; -- never Null
    aNext: CCIndex = cb[a].flink; -- probably b
    bPrev: CCIndex = cb[b].blink; -- probably a
    bNext: CCIndex = cb[b].flink;
    cb[aPrev].flink ← aNext;
    cb[aNext].blink ← aPrev;
    cb[b].flink ← a;
    cb[a].blink ← b;  cb[a].flink ← bNext;
    IF bNext # CCNull THEN cb[bNext].blink ← a;
    END;
    
  Peep11: PUBLIC PROC =
    BEGIN -- short arithmetic: INC and DEC, MUL to SHIFT etc
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    canSlide: BOOL ← FALSE;
    state: PeepState;
    negate: BOOL ← FALSE;

    D2: PROC = {Delete2[state.b, state.c]; IF negate THEN P5.C0[qNEG]};

    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    qADD =>
	      IF bInst = qLI THEN
		BEGIN
		SELECT aInst FROM
		  qLL => IF aP[1] = LocalBase AND bP[1] IN BYTE THEN {
		    P5.C1[qAL0IB, bP[1]]; Delete3[a, b, c]; GO TO done};
		  qGA, qLA, qLI => {
		    cb[a].parameters[1] ← cb[a].parameters[1] + bP[1];
		    Delete2[b, c];
		    GO TO done};
		  qADD => {
		    z: CCIndex = cb[a].blink;
		    WITH zz: cb[z] SELECT FROM
		      code => IF ~zz.realinst AND zz.inst = qLI THEN {
		        cb[b].parameters[1] ← bP[1] ← bP[1] + zz.parameters[1];
			Delete2[z, a]};
		      ENDCASE};
		  qADDSB => {
		    cb[b].parameters[1] ← bP[1] ← bP[1] + aP[1];
		    P5U.DeleteCell[a]};
		  qINC => {
		    cb[b].parameters[1] ← bP[1] ← bP[1] + 1;
		    P5U.DeleteCell[a]};
		  qDEC => {
		    cb[b].parameters[1] ← bP[1] ← bP[1] - 1;
		    P5U.DeleteCell[a]};
		  ENDCASE;
		SELECT LOOPHOLE[bP[1], INTEGER] FROM
		  0 => Delete2[b,c];
		  1 => {cb[c].inst ← qINC; P5U.DeleteCell[b]};
		  -1 => {cb[c].inst ← qDEC; P5U.DeleteCell[b]};
		  IN [-200B..200B) => {P5.C1[qADDSB, bP[1]]; Delete2[b, c]};
		  ENDCASE => GO TO Slide;
		EXITS
		  done => NULL;
		END 
	      ELSE IF bInst = qNEG THEN
		{cb[c].inst ← qSUB; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qSUB =>
	      IF bInst = qLI THEN
		BEGIN
		SELECT LOOPHOLE[bP[1], INTEGER] FROM
		  0 => Delete2[b,c];
		  1 => {cb[c].inst ← qDEC; P5U.DeleteCell[b]};
		  -1 => {cb[c].inst ← qINC; P5U.DeleteCell[b]};
		  IN (-200B..200B] => {P5.C1[qADDSB, -INTEGER[bP[1]]]; Delete2[b, c]};
		  ENDCASE => GO TO Slide;
		END 
	      ELSE IF bInst = qNEG THEN
		{cb[c].inst ← qADD; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qSHIFT =>
	      IF bInst = qLI THEN
		SELECT INTEGER[bP[1]] FROM
		  1 => 
		    IF aInst = qSHIFTSB AND aP[1] > 0 THEN {
		      cb[a].parameters[1] ← aP[1] + bP[1];
		      Delete2[b,c]}
		    ELSE {cb[c].inst ← qDBL; P5U.DeleteCell[b]};
		  0 => Delete2[b,c];
		  IN [-200B..200B) =>
		    IF aInst = qSHIFTSB
		     AND INTEGER[aP[1]]*INTEGER[bP[1]] > 0 THEN {
		      cb[a].parameters[1] ← aP[1] + bP[1]; 
		      Delete2[b,c]}
		    ELSE {
		      P5.C1[qSHIFTSB, bP[1]];
		      Delete2[b, c]};
		  ENDCASE => GO TO Slide
	      ELSE GO TO Slide;
	    qSHIFTSB =>
	      IF bInst = qSHIFTSB AND INTEGER[bP[1]]*INTEGER[cP[1]] > 0 THEN {
		cb[c].parameters[1] ← bP[1] + cP[1];
		P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    qMUL =>
	      IF bInst = qLI THEN
		BEGIN
		negate ← FALSE;
		IF LOOPHOLE[bP[1], INTEGER] < 0 THEN
		  {negate ← TRUE; bP[1] ← -LOOPHOLE[bP[1], INTEGER]};
		SELECT bP[1] FROM
		  1 => D2[];
		  2 => {P5.C0[qDBL]; D2[]};
		  3 => {P5.C0[qTRPL]; D2[]};
		  4 => {P5.C0[qDBL]; P5.C0[qDBL]; D2[]};
		  5 => {P5.C0[qDUP]; P5.C0[qDBL]; P5.C0[qDBL]; P5.C0[qADD]; D2[]};
		  6 => {P5.C0[qDBL]; P5.C0[qTRPL]; D2[]};
		  7 => {P5.C0[qDUP]; P5.C0[qDBL]; P5.C0[qTRPL]; P5.C0[qADD]; D2[]};
		  9 => {P5.C0[qTRPL]; P5.C0[qTRPL]; D2[]};
		  10 => {P5.C0[qDUP]; P5.C0[qTRPL]; P5.C0[qTRPL]; P5.C0[qADD]; D2[]};
		  ENDCASE =>
		    BEGIN
		    powerOf2: BOOL;
		    log: CARDINAL;
		    [powerOf2, log] ← Log2[LOOPHOLE[bP[1]]];
		    IF powerOf2 THEN {P5.C1[qSHIFTSB, log]; D2[]}
		    ELSE GO TO Slide;
		    END;
		END;
	    qUDIV =>
	      IF bInst = qLI THEN
		BEGIN
		powerOf2: BOOL;
		log: CARDINAL;
		negate ← FALSE;
		[powerOf2, log] ← Log2[LOOPHOLE[bP[1]]];
		IF powerOf2 THEN {P5.C1[qSHIFTSB, -log]; D2[]}
		ELSE GO TO Slide;
	        END;
	    qDIS =>
	      IF bInst = qEXCH THEN {cb[c].inst ← qEXDIS; P5U.DeleteCell[b]}
	      ELSE GO TO Slide;
	    ENDCASE => GO TO Slide;
	  EXITS
	    Slide => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Peep4: PUBLIC PROC =
    BEGIN -- long arithmetic: INC and DEC, MUL to SHIFT etc
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    canSlide: BOOL ← FALSE;
    state: PeepState;

    D3: PROC = {Delete3[state.a, state.b, state.c]};

    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH cb[ci] SELECT FROM
	code =>
	  BEGIN OPEN state;
	  IF canSlide THEN SlidePeepState2[@state, LOOPHOLE[ci]]
	  ELSE InitParameters[@state, LOOPHOLE[ci], abc];
	  canSlide ← FALSE;
	  SELECT cInst FROM
	    qDADD =>
	      IF bInst = qLI AND bP[1] = 0 THEN
		BEGIN
		IF aInst = qLI THEN SELECT aP[1] FROM
		  0 => {Delete3[a,b,c]; GO TO done};
		  1 => {cb[c].inst ← qDINC; Delete2[a,b]; GO TO done};
		  ENDCASE;
		cb[c].inst ← qADC; P5U.DeleteCell[b];
		EXITS
		  done => NULL;
		END 
	      ELSE IF DblLoadInst[b] AND aInst = qLI AND aP[1] = 0 THEN {
	        cb[c].inst ← qACD; P5U.DeleteCell[a]}
	      ELSE IF bInst = qLID AND bP[1] = 0 THEN Delete3[a,b,c]
	      ELSE GO TO Slide;
	    qDSUB =>
	      IF bInst = qLI AND bP[1] = 0 AND aInst = qLI AND aP[1] = 0 THEN
	        Delete3[a,b,c]
	      ELSE IF bInst = qLID AND bP[1] = 0 THEN Delete3[a,b,c]
	      ELSE GO TO Slide;
	    qADC =>
	      IF bInst = qLI THEN SELECT bP[1] FROM
	        1 => {cb[c].inst ← qDINC; P5U.DeleteCell[b]};
	        0 => Delete3[a,b,c];
		ENDCASE => GO TO Slide
	      ELSE GO TO Slide;
	    qREC =>
	      IF bInst = qAMUL AND aInst = qLI THEN
		BEGIN
		SELECT aP[1] FROM
		  1 => D3[];
		  2 => {P5.C1[qLI, 0]; P5.C0[qDDBL]; D3[]};
		  3 => {P5.C1[qLI, 0]; P5.C0[qDDUP]; P5.C0[qDDBL]; P5.C0[qDADD]; D3[]};
		  4 => {P5.C1[qLI, 0]; P5.C0[qDDBL]; P5.C0[qDDBL]; D3[]};
		  8 => {P5.C1[qLI, 0]; P5.C0[qDDBL]; P5.C0[qDDBL]; P5.C0[qDDBL]; D3[]};
		  ENDCASE => GO TO Slide;
		END;
	    qDUDIV =>
	      IF bInst = qLI AND bP[1] = 0 AND aInst = qLI THEN
		BEGIN
		powerOf2: BOOL;
		log: CARDINAL;
		[powerOf2, log] ← Log2[LOOPHOLE[aP[1]]];
		IF powerOf2 THEN {
		      P5.C1[qLI, -log];
		      P5.C0[qDSHIFT]; D3[]}
		ELSE GO TO Slide;
	        END;
	    qDMUL =>
	      IF bInst = qLI AND bP[1] = 0 AND aInst = qLI THEN
		BEGIN
		SELECT aP[1] FROM
		  1 => D3[];
		  2 => {P5.C0[qDDBL]; D3[]};
		  3 => {P5.C0[qDDUP]; P5.C0[qDDBL]; P5.C0[qDADD]; D3[]};
		  4 => {P5.C0[qDDBL]; P5.C0[qDDBL]; D3[]};
		  5 => {P5.C0[qDDUP]; P5.C0[qDDBL]; P5.C0[qDDBL]; P5.C0[qDADD]; D3[]};
		  6 => {P5.C0[qDDBL]; P5.C0[qDDUP]; P5.C0[qDDBL]; P5.C0[qDADD]; D3[]};
		  8 => {P5.C0[qDDBL]; P5.C0[qDDBL]; P5.C0[qDDBL]; D3[]};
		  ENDCASE =>
		    BEGIN
		    powerOf2: BOOL;
		    log: CARDINAL;
		    [powerOf2, log] ← Log2[LOOPHOLE[aP[1]]];
		    IF powerOf2 THEN {
		      P5.C1[qLI, log];
		      P5.C0[qDSHIFT]; D3[]}
		    ELSE GO TO Slide;
		    END;
		END;
	    ENDCASE => GO TO Slide;
	  EXITS
	    Slide => canSlide ← TRUE;
	  END; -- of OPEN state
	ENDCASE => canSlide ← FALSE; -- of WITH
      ENDLOOP;
    END;

  Log2: PROC [i: INTEGER] RETURNS [BOOL, CARDINAL] =
    BEGIN OPEN Inline;
    IF i = 0 THEN RETURN [FALSE, 0];
    i ← ABS[i];
    IF BITAND[i, i-1] # 0 THEN RETURN [FALSE, 0];
    FOR shift: CARDINAL IN [0..16) DO
      IF BITAND[i,1] = 1 THEN RETURN [TRUE, shift];
      i ← BITSHIFT[i, -1];
      ENDLOOP;
    ERROR; -- can't be reached
    END;


  Peep13: PUBLIC PROC =
    BEGIN -- find special jumps
    OPEN FOpCodes;
    ci: CCIndex;
    next: CCIndex ← start;
    jstate: JumpPeepState;
    UNTIL (ci ← next) = CCNull DO
      next ← NextInteresting[ci];
      WITH jj: cb[ci] SELECT FROM
	jump =>
	  BEGIN OPEN jstate;
	  InitJParametersBC[@jstate, LOOPHOLE[ci]];
	  SELECT jj.jtype FROM
	    JumpE => IF bInst = qLI THEN SELECT bP[1] FROM
	      0 => {jj.jtype ← ZJumpE; P5U.DeleteCell[b]};
	      IN [0..256) => {
	        jj.jtype ← BYTEJumpE; jj.jparam ← bP[1]; P5U.DeleteCell[b]};
	      ENDCASE;
	    JumpN => IF bInst = qLI THEN SELECT bP[1] FROM
	      0 => {jj.jtype ← ZJumpN; P5U.DeleteCell[b]};
	      IN [0..256) => {
	        jj.jtype ← BYTEJumpN; jj.jparam ← bP[1]; P5U.DeleteCell[b]};
	      ENDCASE;
	    UJumpGE => IF bInst = qLI AND bP[1] = 0 THEN
	      {jj.jtype ← ZJumpN; P5U.DeleteCell[b]};
	    ENDCASE;
	  END; -- of OPEN jstate
	ENDCASE; -- of WITH
      ENDLOOP;
    END;

  END.