SECTION "CG4"

GET "CGHDR"

// MAKE ANY LVALUES ADDRESSABLE - IE GET THEM
// INTO A REGISTER
LET GETVALUE(A) BE
       IF H1!A=K.LVLOC | H1!A=K.LVGLOB | H1!A=K.LVLAB DO
          MOVETOINDEXR(A)


// MOVE A SS ITEM INTO AN INDEX REGISTER AND SHIFT
// IT LEFT FOR USE WITH CGRV
AND MOVETOINDEXRSH(A) = VALOF
    $( LET K,N,R = H1!A,H2!A,?
       LET KM = K=K.LOC -> K.MLOC,
                K=K.LAB -> K.MLAB,
                K=K.GLOB -> K.MGLOB, K.NONE
       UNLESS KM=K.NONE DO
       $( R := LOOKINREGS(KM,N)
          IF R>=0 DO UNLESS (SETR(R) & V.RI)=0 RESULTIS R $)
      R := MOVETOINDEXR(A)
       GENSHIFT(F.SHL, 1, K.REG, R)
       SETINFO(R,KM,N)
       RESULTIS R
    $)


// MOVE A SS ITEM INTO ANY REGISTER
// PREFERABLY IN SET S
AND MOVETOANYR(A,S) = VALOF
    $( LET K,N,R = H1!A,H2!A,?
       IF K=K.REG RESULTIS N
       R := LOOKINFREEREGS(K,N)
       IF R>=0 DO
       $( H1!A,H2!A := K.REG,R
          RESULTIS R $)
       RESULTIS MOVETOR(A,NEXTRSET(-1,S))
    $)


// CHANGE R TO BIT STRING SET FORMAT
AND SETR(R) =  1<<R

// MOVE ARGUMENT TO AN INDEX REGISTER (BX OR SI)
AND MOVETOINDEXR(A) = VALOF
 $(M LET K,N = H1!A, H2!A
     LET T1, T2 = -1, -1

     IF K=K.REG & (N=R.SI | N=R.BX) RESULTIS N

     IF REG.K!R.SI=K & REG.N!R.SI=N & ISFREE(R.SI) DO T1 := R.SI

     IF REG.K!R.BX=K & REG.N!R.BX=N & ISFREE(R.BX) DO T2 := R.BX

     UNLESS T1=-1 & T2=-1 DO $( LET T= T2=-1 -> T1, T2
                                 H1!A, H2!A := K.REG, T
                                 RESULTIS T
                              $)

     RESULTIS MOVETOR(A, (ISFREE(R.BX)->R.BX,
               ISFREE(R.SI)->R.SI, R.BX))
 $)M


// MOVE A SS ITEM INTO A GIVEN  REGISTER
AND MOVETOR(A,R) = VALOF
    $( FREEREG(R,A)
       GENMOV(H1!A,H2!A,K.REG,R)
       H1!A,H2!A := K.REG,R
       RESULTIS R
    $)


// LOOK FOR THE VALUE OF AN ITEM (K,N) IN THE
// REGISTERS; THE REGISTER WILL NOT BE MODIFIED
AND LOOKINREGS(K,N) = VALOF
    $( FOR R=R0 TO R4 DO
          IF REG.K!R=K & REG.N!R=N RESULTIS R
       RESULTIS -1
    $)


// LOOK FOR THE VALUE OF AN ITEM (K,N) IN THE
// FREE REGISTERS; THE REGISTER MAY BE MODIFIED
AND LOOKINFREEREGS(K,N) = VALOF
    $( FOR R=R0 TO R4 DO
          IF REG.K!R=K & REG.N!R=N & ISFREE(R) RESULTIS R
       RESULTIS -1
    $)


// ALLOCATE THE NEXT REGISTER (EXCEPT X);
// FREE IT IF REQUIRED
AND NEXTR(X) = VALOF
    $( FOR R=R0 TO R4 DO
          UNLESS R=X DO
             IF REG.K!R=K.NONE & ISFREE(R) RESULTIS R
       FOR R=R0 TO R4 DO
          UNLESS R=X DO
             IF ISFREE(R) RESULTIS R
       FOR T=TEMPV TO ARG1 BY 3 DO
       $( LET R=REGUSEDBY(T)
          UNLESS R=X IF R>=0 DO
          $( FREEREG(R,0)
             RESULTIS R $)
       $)
    $)


//TRY AND ALLOCATE THE NEXT REGISTER FROM THE GIVEN SET
AND NEXTRSET(X, E) = VALOF
  $( FOR R = R0 TO R4 DO
      UNLESS R=X DO
       IF REG.K!R=K.NONE & ISFREE(R) & INSET(E, R) RESULTIS R
      FOR R = R0 TO R4 DO
      UNLESS R=X DO
       IF ISFREE(R) & INSET(E, R) RESULTIS R
     RESULTIS NEXTR(X)
  $)



AND NEXTRFORCESET(X, E) = VALOF
   $( FOR R = R0 TO R4 DO
      UNLESS R=X DO
       IF REG.K!R=K.NONE & ISFREE(R) & INSET(E, R) RESULTIS R
      FOR R = R0 TO R4 DO
      UNLESS R=X DO
       IF ISFREE(R) & INSET(E, R) RESULTIS R

      IF (SETR(X) NEQV E)=0 DO CGERROR("SET MEMBER %N EXCLUDED", TRUE, X)
      IF E=0 DO CGERROR("EMPTY SET", TRUE)

      FOR T=TEMPV TO ARG1 BY 3 DO
      $( LET R = REGUSEDBY(T)
         UNLESS R=X IF R>=0 & INSET(E, R) DO
         $( FREEREG(R, 0)
            RESULTIS R
         $)
      $)
      FOR R = R0 TO R4 DO
       UNLESS R=X DO
          IF INSET(E,R) DO
            $( FREEREG(R, 0)
               RESULTIS R
            $)
      CGERROR("FALL OUT NEXTRFSET %N", TRUE, E)
   $)


AND INSET(SET, R) = ((SET>>R)&1)=1


// FIND WHICH REGISTER, IF ANY, IS USED BY
// AN SS ITEM
AND REGUSEDBY(A) = VALOF
    $( LET K=H1!A
       IF K=K.REG RESULTIS H2!A
       IF K=K.XBX | K=K.XSI RESULTIS K-K.ROFF
       RESULTIS -1  $)


AND ISFREE(R) = VALOF
    $( FOR T=TEMPV TO ARG1 BY 3 DO
          IF REGUSEDBY(T)=R RESULTIS FALSE
       RESULTIS TRUE
    $)


// FREE REGISTER R BY STORING THE VALUES OF
// ALL SS ITEMS (EXCEPT X) THAT DEPEND UPON IT
AND FREEREG(R,X) BE
       FOR T=TEMPV TO ARG1 BY 3 DO
          UNLESS T=X DO IF REGUSEDBY(T)=R DO
             STORET(T)


// STORE THE VALUE OF AN SS ITEM IN ITS TRUE
// STACK LOCATION
AND STORET(A) BE UNLESS H1!A=K.LOC & H2!A=H3!A DO // CHECK REDUNDANT
    $( GETVALUE(A)
       UNLESS H1!A=K.REG | H1!A=K.NUMB DO
         MOVETOANYR(A, V.XX)
       GENMOV(H1!A,H2!A,K.LOC,H3!A)
       H1!A := K.LOC
       H2!A := H3!A  $)


// LOAD AN ITEM (K,N) ONTO THE SS
AND LOADT(K, N) BE
    $( CGPENDINGOP(V.XX)
       ARG2 := ARG1
       ARG1 := ARG1 + 3
       IF H3+ARG1-TEMPT>=0 DO
          CGERROR("SIM STACK OVF", TRUE)
       H1!ARG1,H2!ARG1,H3!ARG1 := K,N,SSP
       SSP := SSP + 1
       IF MAXSSP<SSP DO MAXSSP := SSP
    $)


// REPLACE THE TOP TWO SS ITEMS BY (K,N)
AND LOSE1(K, N) BE
    $( SSP := SSP - 1
       TEST ARG2=TEMPV
       THEN $( H1!ARG2,H2!ARG2 := K.LOC,SSP-2
               H3!ARG2 := SSP-2 $)
       ELSE $( ARG1 := ARG2
               ARG2 := ARG2-3 $)
       H1!ARG1, H2!ARG1, H3!ARG1 := K,N,SSP-1
    $)


AND CGBYTEAP(OP) BE
$(1 CGPENDINGOP(V.XX)
 $( LET S = MOVETOINDEXRSH(ARG2)
    LET I = H2!ARG1
    LET BYT.M, BYT.V = ?, ?
    LET RST = ?
    UNLESS H1!ARG1=K.NUMB DO
    $( FREEREG(S,ARG2)
       GETVALUE(ARG1)
       CGPLUS(ARG1,K.REG,S)
       I := 0
    $)
    FORMADDR(S+K.ROFF, I)
    BYT.M, BYT.V := ADDR.M, ADDR.V
    RST := S=R.BX->"BX","SI"
    TEST OP=S.GETBYTE
    THEN $( LET R = NEXTRFORCESET(S,V.R80)
            LET TN = TRANR(R)
            GENRS(F.XOR, R, K.REG, R)
            CHECKBREFS(5)
 //*<3032
            LISTL("MOV %S,%N(%S)", STRINGRB(TN), I, RST)
 /*3032>*/
            CODEB((F.MOVRTRM & #376) | 2)
            CODEB(CONSB2(TN, BYT.M, BYT.V))
            CODEDISP(BYT.M, BYT.V)
            LOSE1(K.REG,R)
         $)
   OR $( LET R, TN = ?, ?

         TEST ARG2=TEMPV DO
         $( R := NEXTRFORCESET(S, V.R80)
            TN := TRANR(R)
            GENMOV(K.LOC, SSP-3, K.REG, R)
         $)
         OR
         $( LET ARG3 = ARG2-3
            TEST H1!ARG3=K.REG & INSET(V.R80, H2!ARG3) DO
              R := H2!ARG3
            OR
              R := NEXTRFORCESET(S, V.R80)
            TN := TRANR(R)
            MOVETOR(ARG3, R)
         $)

          CHECKBREFS(5)
 //*<3032
          LISTL("MOV %N(%S),%S", I, RST, STRINGRB(TN))
 /*3032>*/
          CODEB(F.MOVRTRM & #376)
          CODEB(CONSB2(TN, BYT.M, BYT.V))
          CODEDISP(BYT.M, BYT.V)
          FORGETVARS()
          STACK(SSP-3)
       $)
   $)
 $)1


AND CGSTIND() BE
    $( CGRV()
       UNLESS H1!ARG2=K.REG | H1!ARG2=K.NUMB DO
       $( LET R = NEXTR((H2!ARG1)-K.ROFF)
          MOVETOR(ARG2, R)
       $)
       GENMOV(H1!ARG2,H2!ARG2,H1!ARG1,H2!ARG1)
       FORGETVARS()
       STACK(SSP-2)
    $)


// STORE THE TOP ITEM OF THE SS IN (K,N)
AND STOREIN(K, N) BE

$(1 LET B = (H1!ARG1=K & H2!ARG1=N) -> 1,
            (H1!ARG2=K & H2!ARG2=N) -> 2, 0
    LET ARG = B=2 -> ARG1,ARG2
    LET NUM = B=2 & H1!ARG=K.NUMB
    LET KK = H2!ARG
    LET SW = FALSE
    LET PENDOP = PENDINGOP

    IF B=0 GOTO GENCASE

    PENDINGOP := S.NONE
    SWITCHON PENDOP INTO

    $(2 DEFAULT:
        GENCASE: PENDINGOP := PENDOP
                 CGPENDINGOP(V.XX)

        CASE S.NONE:
                 GETVALUE(ARG1)
                 UNLESS H1!ARG1=K.REG | (H1!ARG1=K.NUMB & H2!ARG1~=0) DO
                   MOVETOANYR(ARG1, V.XX)
                 GENMOV(H1!ARG1,H2!ARG1,K,N)
                 STACK(SSP-1)
                 RETURN

        CASE S.NEG:
                 SW := TRUE
        CASE S.NOT:
                 UNLESS B=1 GOTO GENCASE
                 GEND(SW -> F.NEG, F.NOT, K, N)
                 STACK(SSP-1)
                 RETURN

        CASE S.PLUS:
                 GETVALUE(ARG)
                 CGPLUS(ARG, K, N)
                 ENDCASE

        CASE S.MINUS:
                 GETVALUE(ARG)
                 CGMINUS(ARG, K, N)
                 IF B=1 DO GEND(F.NEG,K, N)
                 ENDCASE

        CASE S.LOGOR:
                 SW := TRUE
        CASE S.LOGAND:
                 GETVALUE(ARG)
                 CGLOGORANDNEQV(SW->F.OR,F.AND, ARG, K, N)
                 ENDCASE

        CASE S.EQV:
                 SW := TRUE
        CASE S.NEQV:
                 GETVALUE(ARG)
                 CGLOGORANDNEQV(F.XOR,ARG, K, N)
                 IF SW DO GEND(F.NOT, K, N)
                 ENDCASE

        CASE S.MULT:
                 IF H1!ARG=K.NUMB DO
                    IF KK=2 | KK=4 DO
                    $( FOR I = 1 TO KK/2 DO
                        GENSHIFT(F.SHL,1,K,N)
                       ENDCASE
                    $)
                 GOTO GENCASE

        CASE S.LSHIFT:
                 SW := TRUE
        CASE S.RSHIFT:
                 UNLESS B=2 GOTO GENCASE
                 IF NUM DO
                    IF 0<=KK<=3 DO
                    $( FOR I = 1 TO KK DO
                        GENSHIFT(SW->F.SHL,F.SHR,1,K,N)
                       ENDCASE
                    $)

                 MOVETOR(ARG1, R.CX)
                 GENSHIFT(SW->F.SHL,F.SHR,0,K,N)
                 ENDCASE
    $)2
    STACK(SSP-2)
$)1

.