SECTION "CG5"

GET "CGHDR"

LET CGRV() BE

$(1 LET R = 0

    IF PENDINGOP=S.MINUS & H1!ARG1=K.NUMB DO
             PENDINGOP, H2!ARG1 := S.PLUS, -H2!ARG1

    TEST PENDINGOP=S.PLUS &
          (H1!ARG1=K.NUMB | H1!ARG2=K.NUMB)

    THEN $( LET ARG = ARG2
            LET N = H2!ARG1
            IF H1!ARG2=K.NUMB DO ARG,N := ARG1,H2!ARG2
            PENDINGOP := S.NONE
            R := MOVETOINDEXRSH(ARG)
            LOSE1(R+K.ROFF,2*N) $)

    ELSE $( CGPENDINGOP(V.RI)
            R := MOVETOINDEXRSH(ARG1)
            H1!ARG1, H2!ARG1 := R+K.ROFF, 0 $)
$)1


AND CGSHIFTK(SW,KK,K,N) BE
$(1 IF KK=8 DO  // TYPE SHOULD BE K.REG IN THE 8080 SET (V.R80)
    $( TEST SW DO $( GENBYTEXCHG(N); GENCLEARBYTE(N) $)
               OR $( GENCLEARBYTE(N); GENBYTEXCHG(N) $)
       RETURN
    $)
    GENSHIFT(SW -> F.SHL, F.SHR, 1, K, N)
    IF KK=2 DO GENSHIFT(SW -> F.SHL, F.SHR, 1, K, N)
$)1


AND CGADDK(KK, K, N) BE UNLESS KK=0 DO
$(1 IF KK=1  DO $( GENINCDEC(F.INC, K, N); RETURN  $)
    IF KK=-1 DO $( GENINCDEC(F.DEC, K, N); RETURN  $)
    GENKD(F.ADD, KK, K, N)
$)1


AND CGPLUS(A,K,N) BE TEST H1!A=K.NUMB
    THEN CGADDK(H2!A, K, N)
    OR CGDIADWITHR(F.ADD, A, K, N)


AND CGMINUS(A,K,N) BE TEST H1!A=K.NUMB
    THEN CGADDK(-H2!A, K, N)
    OR CGDIADWITHR(F.SUB, A, K, N)


AND CGLOGORANDNEQV(F, A, K, N) BE
   TEST H1!A=K.NUMB THEN GENKD(F, H2!A, K, N)
   OR CGDIADWITHR(F, A, K, N)


AND CGGLOBAL(N) BE
$(1
    EVEN()
 //*<3032
    LISTAT(S.ITEMN, 0)
 /*3032>*/
    CODE(0, 0)
    FOR I = 1 TO N DO
    $( LET G = RDGN()
       LET L = RDL()
       LET DL = NEXTPARAM()
 //*<3032
       LISTAT(S.ITEMN, G)
 /*3032>*/
       CODE(G, 0)
 //*<3032
       LISTAT(S.ITEML,DL)
 /*3032>*/
       CODE(0, -DL)          // GLOBIN DOES RELOCATION
       CGDATA(S.DATALAB, DL) // LABEL OF DESCRIPTOR
       CGDATA(S.GLOBAL, L)   //  THE DESCRIPTOR ITSELF
    $)
 //*<3032
    LISTAT(S.ITEMN, MAXGN)
 /*3032>*/
    CODE(MAXGN, 0)
    CGSTATICS()    // ITEMS IN DATA SEGMENT
$)1


AND CGENTRY(N,L) BE
$(1 GENBREFJUMPS(50,0)
    CGNAME(S.ENTRY,N)
    SETLAB(L)
    INCODE := TRUE
    GENRS(F.ADD, R.BP, K.REG, R.DX)  // ADJUST FRAME
 //*<3032
    LISTL("MOV 4(BP),DX")
 /*3032>*/
    CODEB(#X89); CODEB(#X56); CODEB(4) // MOV 4(BP),DX
            // POP RETURN ADDRESS INTO STACK FRAME
 //*<3032
    LISTL("POP (BP)")
    LISTL("POP 2(BP)")
 /*3032>*/
    CODEB(#X8F); CODEB(#X46); CODEB(0)  // POP (BP)
    CODEB(#X8F); CODEB(#X46); CODEB(2)  // POP 2(BP)
    IF NAMING DO
    $( //*<3032
       LISTL("MOV 6(BP),SI")
       /*3032>*/
       CODEB(#X89); CODEB(#X76); CODEB(6)
    $)
    IF CALLCOUNTING DO INSERTCOUNT()
    FORGETALL()
$)1



AND CGDIADWITHR(F, A, K, N) BE
    $( LET R = K=K.REG -> N,
               H1!A=K.REG -> H2!A, -1
       IF R=-1 DO R := MOVETOANYR(A, V.XX)
       TEST K=K.REG DO GENRS(F, R, H1!A, H2!A)
                    OR GENRD(F, R, K, N)
    $)


AND INDCODE(R) = VALOF
   $( LET IR = TRANR(R)!TABLE -1,-1,-1,7,-1,6,4,5
      IF IR=-1 DO CGERROR("REG %N NOT INDXBLE",FALSE,R)
      RESULTIS IR
   $)



AND TRANR(R) = VALOF
   $( UNLESS 0<=R<=7 DO CGERROR("INVALID REGISTER %N", TRUE, R)
      RESULTIS R!TABLE 3,0,1,2,6,5,4,7
   $)

AND CGSAVE(N) BE
  $(1 LET NRGS = N-SAVESPACESIZE
      FOR I = 0 TO NRGS>=3->2,NRGS-1 DO
      $( GENMOV(K.REG, I, K.LOC, I+SAVESPACESIZE)
         SETINFO(I, K.LOC, I+SAVESPACESIZE)
      $)
      INITSTACK(N)
  $)1


// FUNCTION OR ROUTINE CALL
AND CGAPPLY(OP,K) BE

$(1 LET SR0 = K+SAVESPACESIZE
    LET SR2 = K+SAVESPACESIZE+2
    LET L = ?

    CGPENDINGOP(V.XX)

    // STORE ARGS 4,5,...
    STORE(SR2+1, SSP-2)

    // NOW DEAL WITH NON-ARGS
    FOR T = TEMPV TO ARG2 BY 3 DO
        $( IF H3!T>=K BREAK
           IF REGUSEDBY(T)>=0 DO STORET(T)  $)

    GETVALUE(ARG1)

    // MOVE ARGS 1-3 TO ARG REGISTERS
    FOR T = ARG2 TO TEMPV BY -3 DO
        $( LET S = H3!T
           LET R = S-SR0
           IF S<SR0 BREAK
           IF S<=SR2 & ISFREE(R) DO MOVETOR(T,R)  $)
    FOR T = ARG2 TO TEMPV BY -3 DO
        $( LET S = H3!T
           LET R = S-SR0
           IF S<SR0 BREAK
           IF S<=SR2 DO MOVETOR(T,R)  $)

    // DEAL WITH ARGS NOT IN SS
    FOR S = SR0 TO SR2 DO
    $( LET R = S-SR0
       IF S>=H3!TEMPV BREAK
       FREEREG(R,0)
       GENMOV(K.LOC, S, K.REG, R)  $)

    FREEREG(R.DX, 0)

    GENMOV(K.NUMB, 2*K, K.REG, R.DX)
    IF H1!ARG1=K.NUMB DO H2!ARG1 := H2!ARG1*2

    FREEREG(R.SI, 0)         // SI USED TO HOLD DESCRIPTOR ADDRESS
    GENMOV(H1!ARG1, H2!ARG1, K.REG, R.SI)
    GENJ(F.CIS, K.XSI, 0)

    FORGETALL()
    STACK(K)
    IF OP=S.FNAP DO LOADT(K.REG,R0)
$)1


AND CGRETURN(OP) BE

$(1 CGPENDINGOP(V.R0)
    IF OP=S.FNRN DO
    $( MOVETOR(ARG1,R0)
       STACK(SSP-1)  $)
                 // GENERATE ONLY 1 RETURN SEQUENCE
                 // PER SECTION
   TEST RETURN.SET=0 DO
   $( RETURN.SET := NEXTPARAM()
      INCODE := TRUE     // BE SAFE
      CHECKBREFS(7)
      SETLAB(RETURN.SET)
 //*<3032
       LISTL("MOV SI,4(BP)")
 /*3032>*/
       CODEB(#X8B);CODEB(#X76);CODEB(4) // MOV SI,4(BP)
       GENRS(F.SUB, R.BP, K.REG, R.SI) // OLD FRAME POINTER
 //*<3032
       LISTL("JIS (BP,SI)")
 /*3032>*/
       CODEB(#XFF); CODEB(#X2A)        // JIS (BP,SI)
   $)
   OR
   $( CHECKBREFS(3)
      GENBRANCH(F.JMP, RETURN.SET)
   $)
    INITSTACK(SSP)
$)1


// USED FOR OCODE OPERATORS JT AND JF
AND CGJUMP(B,L) BE
$(1 LET F = CONDBRFN(PENDINGOP)
    IF F=0 DO
    $( CGPENDINGOP(V.XX)
       LOADT(K.NUMB,0)
       F := F.JNE $)
    PENDINGOP := S.NONE
    STORE(0,SSP-3)
    GETVALUE(ARG1)
    GETVALUE(ARG2)
    F := CGCMP(B,F,-1)
    GENBRANCH(F,L)
    STACK(SSP-2)
    IF PROFILING DO INSERTCOUNT()
$)1


AND CGCMPF(F) = VALOF SWITCHON F INTO
    $( CASE F.JL : RESULTIS F.JG
       CASE F.JGE: RESULTIS F.JLE
       CASE F.JLE: RESULTIS F.JGE
       CASE F.JG : RESULTIS F.JL
       DEFAULT   : RESULTIS F
    $)


    // XR IS A REGISTER WHICH MUST NOT BE USED!
AND CGCMP(B,F,XR) = VALOF
$(1 TEST NUMBERIS(0,ARG1) & H1!ARG2=K.REG
    THEN GENRS(F.OR,H2!ARG2, K.REG,H2!ARG2)
    ELSE $( TEST NUMBERIS(0,ARG2) & H1!ARG1=K.REG THEN
              $( GENRS(F.OR,H2!ARG1,K.REG,H2!ARG1)
                 F := CGCMPF(F)
              $)
            OR
            $( TEST H1!ARG1=K.NUMB THEN
                  GENKD(F.CMP, H2!ARG1, H1!ARG2, H2!ARG2)
               OR
               $( TEST H1!ARG2=K.NUMB THEN
                  $( GENKD(F.CMP, H2!ARG2, H1!ARG1, H2!ARG1)
                     F := CGCMPF(F)
                  $)
                OR $( UNLESS H1!ARG1=K.REG | H1!ARG2=K.REG DO
                        MOVETOR(ARG2, NEXTR(XR))
                      CGDIADWITHR(F.CMP, ARG1, H1!ARG2, H2!ARG2)
                   $)
               $)
            $)
         $)
            RESULTIS B -> F, F NEQV 1
$)1

.