SECTION "CG2"

GET "CGHDR"

// INITIALISE THE SIMULATED STACK (SS)
LET INITSTACK(N) BE
    $( ARG2, ARG1 := TEMPV, TEMPV+3
       SSP := N
       PENDINGOP := S.NONE
       H1!ARG2, H2!ARG2, H3!ARG2 := K.LOC, SSP-2, SSP-2
       H1!ARG1, H2!ARG1, H3!ARG1 := K.LOC, SSP-1, SSP-1
       IF MAXSSP<SSP DO MAXSSP := SSP  $)


// MOVE SIMULATED STACK (SS) POINTER TO N
AND STACK(N) BE
$(1 IF MAXSSP<N DO MAXSSP := N
    IF N>SSP+SAVESPACESIZE DO // I wonder how this works
        $( STORE(0,SSP-1)
           INITSTACK(N)
           RETURN   $)

    WHILE N>SSP DO LOADT(K.LOC, SSP)

    UNTIL N=SSP DO
    $( IF ARG2=TEMPV DO
       $( TEST N=SSP-1
            THEN $( SSP := N
                    H1!ARG1,H2!ARG1 := H1!ARG2,H2!ARG2
                    H3!ARG1 := SSP-1
                    H1!ARG2,H2!ARG2 := K.LOC,SSP-2
                    H3!ARG2 := SSP-2  $)
            ELSE INITSTACK(N)
          RETURN  $)

       ARG1, ARG2 := ARG1-3, ARG2-3
       SSP := SSP-1  $)
$)1



// STORE ALL SS ITEMS FROM A TO B IN THEIR TRUE
// LOCATIONS ON THE STACK
AND STORE(A,B) BE FOR P = TEMPV TO ARG1 BY 3 DO
    $( LET S = H3!P
       IF S>B RETURN
       IF S>=A DO STORET(P)  $)


 //*<3032
 // THE LINE BELOW WILL BE REMOVED FOR THE TRIPOS VERSION
 AND TESTFLAGS(N) = FALSE
 /*3032>*/


AND SCAN() BE

$(1 IF TESTFLAGS(1) DO CGERROR("BREAK", TRUE)

    SWITCHON OP INTO

 $(SW DEFAULT:     CGERROR("BAD OP %N", FALSE, OP)
                   ENDCASE

      CASE 0:      RETURN

 //*<3032
      CASE S.DEBUG:DEBUGGING := NOT DEBUGGING
                   ENDCASE
 /*3032>*/

      CASE S.LP:   LOADT(K.LOC, RDN()); ENDCASE
      CASE S.LG:   LOADT(K.GLOB, RDGN()); ENDCASE
      CASE S.LL:   LOADT(K.LAB, RDL()); ENDCASE
      CASE S.LN:   LOADT(K.NUMB, RDN()); ENDCASE

      CASE S.LSTR: CGSTRING(RDN()); ENDCASE

      CASE S.TRUE: LOADT(K.NUMB, -1); ENDCASE
      CASE S.FALSE:LOADT(K.NUMB, 0); ENDCASE

      CASE S.LLP:  LOADT(K.LVLOC, RDN()); ENDCASE
      CASE S.LLG:  LOADT(K.LVGLOB, RDGN()); ENDCASE
      CASE S.LLL:  LOADT(K.LVLAB, RDL()); ENDCASE

      CASE S.SP:   STOREIN(K.LOC, RDN()); ENDCASE
      CASE S.SG:   STOREIN(K.GLOB, RDGN()); ENDCASE
      CASE S.SL:   STOREIN(K.LAB, RDL()); ENDCASE

      CASE S.STIND:CGSTIND(); ENDCASE

      CASE S.RV:   CGRV(); ENDCASE

      CASE S.MULT:CASE S.DIV:CASE S.REM:
      CASE S.PLUS:CASE S.MINUS:
      CASE S.EQ: CASE S.NE:
      CASE S.LS:CASE S.GR:CASE S.LE:CASE S.GE:
      CASE S.LSHIFT:CASE S.RSHIFT:
      CASE S.LOGAND:CASE S.LOGOR:CASE S.EQV:CASE S.NEQV:
      CASE S.NOT:CASE S.NEG:CASE S.ABS:
                   CGPENDINGOP(REGSET(OP))
                   PENDINGOP := OP
                   ENDCASE

      CASE S.JUMP: CGPENDINGOP(V.XX)
                   STORE(0, SSP-1)
                   GENBRANCH(F.JMP, RDL())
                   ENDCASE

      CASE S.ENDFOR:
                   CGPENDINGOP(V.XX)
                   PENDINGOP := S.LE
      CASE S.JT:   CGJUMP(TRUE, RDL())
                   ENDCASE

      CASE S.JF:   CGJUMP(FALSE, RDL())
                   ENDCASE

      CASE S.GOTO: CGPENDINGOP(V.XX)
                   STORE(0, SSP-2)
                   GETVALUE(ARG1)
                   IF H1!ARG1=K.NUMB THEN
                      H2!ARG1 := H2!ARG1 * 2
                   MOVETOINDEXR(ARG1)
                      // CS same as now so can do JI (instead of JIS)
                   GENJ(F.JI,H2!ARG1=R.BX->K.XBX, K.XSI, 0)
                   STACK(SSP-1)
                   ENDCASE

      CASE S.LAB:  CGPENDINGOP(V.XX)
                   STORE(0, SSP-1)
                   CGLAB(RDL())
                   ENDCASE

      CASE S.QUERY:CGPENDINGOP(V.XX)
                   STACK(SSP+1)
                   ENDCASE

      CASE S.STACK:CGPENDINGOP(V.XX)
                   STACK(RDN())
                   ENDCASE

      CASE S.STORE:CGPENDINGOP(V.XX)
                   STORE(0, SSP-1)
                   ENDCASE

      CASE S.ENTRY:
                CGENTRY(RDN(), RDL())
                ENDCASE

      CASE S.SAVE: CGSAVE(RDN())
                   IF STKCHKING DO
                   $( IF PROCSTKP>=20 DO
                         CGERROR("PROC STACK OVF", TRUE)
                      PROCSTK!PROCSTKP := MAXSSP
                      GENINT(I.STKCHECK)
                      PROCSTK!(PROCSTKP+1) := STVP
 //*<3032
                      LISTAT(S.ITEMN, 0)
 /*3032>*/
                      CODE(0,0) // MAXSSP OF CALLED ROUTINE IS PLACED HERE
                      MAXSSP := SSP $)
                   PROCSTKP := PROCSTKP+2
                   ENDCASE

      CASE S.FNAP:
      CASE S.RTAP: CGAPPLY(OP, RDN())
                   ENDCASE

      CASE S.RTRN:
      CASE S.FNRN: CGRETURN(OP)
                   ENDCASE

      CASE S.ENDPROC:
                   RDN()
                   PROCSTKP := PROCSTKP-2
                   IF STKCHKING  DO
                   $( PWABO(STV, PROCSTK!(PROCSTKP+1), MAXSSP)
                      MAXSSP := PROCSTK!PROCSTKP $)
                   ENDCASE

      CASE S.RES:  CGPENDINGOP(V.R0)
                   STORE(0, SSP-2)
                   MOVETOR(ARG1,R0)
                   GENBRANCH(F.JMP, RDL())
                   STACK(SSP-1)
                   ENDCASE

      CASE S.RSTACK:
                   INITSTACK(RDN())
                   LOADT(K.REG, R0)
                   ENDCASE

      CASE S.FINISH:
                   LOADT(K.NUMB, 0)
                   LOADT(K.NUMB, 0)
                   CGGLOBCALL(GN.STOP)
                   ENDCASE

      CASE S.SWITCHON:
                   CGSWITCH(RDN())
                   ENDCASE

      CASE S.GETBYTE:
      CASE S.PUTBYTE:
                   CGBYTEAP(OP)
                   ENDCASE

      CASE S.GLOBAL:
                   CGGLOBAL(RDN())
                   RETURN

      CASE S.DATALAB:
      CASE S.ITEML:CGDATA(OP, RDL()); ENDCASE
      CASE S.ITEMN:CGDATA(OP, RDN()); ENDCASE
 $)SW

 //*<3032
    IF DEBUGGING DO DBOUTPUT()
 /*3032>*/
    OP := RDN()

$)1 REPEAT

.