  (*$p**************************************************************************)
  (*                                                                           *)
  (*                          File: CODE.3.TEXT                                *)
  (*                                                                           *)
  (*              (C) Copyright 1981 Silicon Valley Software, Inc.             *)
  (*                            1983, 1984 Apple Computer, Inc.                *)
  (*                                                                           *)
  (*                            All rights reserved.               18-Jul-82   *)
  (*                                                                           *)
  (*  5-12-83 Expr2: add TRAPV code                                            *)
  (*  5-15-83 Expression: add param for trapping on overflow                   *)
  (*  8-16-83 Longtrapv: fix up reg. value after overflow chk on neg int value *)
  (*****************************************************************************)
  {[j=0/0/80!,@=6,i=1]}
  {$S SEG1}

  PROCEDURE Expression{(fop: integer; prefReg: integer; trapv: boolean)};

    PROCEDURE Push4Call(FName: Alfa8);

      BEGIN
        Expression(NextByte, - 1, False); PushValue(gCAttr, LongOp);
        GenJSR(FName); gCAttr.cKind := STCK;
      END; {push4call}

    PROCEDURE Push44Call(FName: Alfa8);

      BEGIN
        Expression(NextByte, - 1, False); PushValue(gCAttr, LongOp);
        Expression(NextByte, - 1, False); PushValue(gCAttr, LongOp);
        GenJSR(FName); gCAttr.cKind := STCK;
      END; {push44call}

    PROCEDURE PushAACall(FName: Alfa8);

      BEGIN
        Expression(NextByte, - 1, False); PushAddress(gCAttr);
        Expression(NextByte, - 1, False); PushAddress(gCAttr);
        GenJSR(FName); gCAttr.cKind := STCK;
      END; {pushaacall}

    PROCEDURE LongTRAPV(D: Register);

      BEGIN {detect 16-bit overflow. Use property of divide instruction}
        GenRR($81F8, D, 4); Gen(1); {DIVS #1,d}
        Gen($4E76); {TRAPV}
        GenR($48C0, D); {EXT.L D }                                             {!8-16-83AH}
      END; {longtrapv}

    PROCEDURE GenIndex(ElementSize: Integer);

      VAR
        Lo, lOffset, ShiftCount, lVLev: Integer;
        lCAttr: CAttr;
        AddFlag: Boolean;
        D: Register;
        A: Register;

      BEGIN
        Lo := NextWord; Expression(NextByte, - 1, False);
        lCAttr := gCAttr; Expression(NextByte, - 1, False);
        IF gCAttr.cKind = CNST THEN
          IncOffset(lCAttr, ElementSize * (gCAttr.CValu.IValu[1] - Lo))
        ELSE
          BEGIN
          D := LoadD(gCAttr, WordOp, False); AddFlag := False;
          IF ElementSize <> 1 THEN CheckClobber(D);
          WITH lCAttr DO
            CASE cKind OF
              ADDR: BEGIN
                    A := AdReg; lOffset := AOffset;
                    cKind := INDX; InOffset := lOffset - Lo * ElementSize;
                    InxAReg := A; InxRReg := D; LongIndex := False;
                    END;
              INDX: BEGIN
                    InOffset := InOffset - Lo * ElementSize; AddFlag := True;
                    END;
              VARB: BEGIN
                    lOffset := VOffset; lVLev := VLev; cKind := INDX;
                    InOffset := lOffset - Lo * ElementSize; InxRReg := D;
                    IF lVLev >= 0 THEN
                      InxAReg := GetBase(lVLev)
                    ELSE
                      BEGIN
                      A := GetReg(Alow, Ahigh);
                      GenRR($41ED, A, 0); Gen(InOffset); { LEA A,off(A5) }
                      ComVRef( - lVLev, Ic - 2); InxAReg := A;
                      InOffset := 0;
                      END;
                    LongIndex := False;
                    END;
            END; {case}
          IF ElementSize > 1 THEN
            BEGIN
            IF ShiftMult(ElementSize, ShiftCount) THEN
              GenRR($E140, ShiftCount, D) { ASL.W #xx,D }
            ELSE
              BEGIN { MULS }
              GenRR($C1FC, D, 0); Gen(ElementSize);
              END;
            END;
          IF AddFlag THEN
            BEGIN
            CheckClobber(lCAttr.InxRReg);
            GenRR($D040, lCAttr.InxRReg, D); { ADD.W D,INXRREG }
            FreeReg(D);
            END;
          END;
        gCAttr := lCAttr;
      END; {genindex}

    PROCEDURE PckdIndex;

      VAR
        BitsPerEl, Lo, DataMask, AddrMask, lBitsPerEl, i, AShiftCount: Integer;
        D, D2, D3: Register;
        lCAttr: CAttr;
        Signed: Boolean;

      BEGIN
        BitsPerEl := NextByte; Lo := NextWord; Signed := BitsPerEl > 127;
        IF Signed THEN BitsPerEl := BitsPerEl - 128;
        Expression(NextByte, - 1, False); lCAttr := gCAttr;
        Expression(NextByte, - 1, False);
        { What about constant index? }
        D3 := LoadD(gCAttr, WordOp, False);
        IF BitsPerEl = 8 THEN
          IncOffset(lCAttr, - Lo)
        ELSE
          BEGIN
          IF Lo <> 0 THEN
            BEGIN
            CheckClobber(D3);
            IF Abs(Lo) <= 8 THEN
              IF Lo > 0 THEN
                GenRR($5140, Lo, D3) { SUBQ.W #lo,D3 }
              ELSE
                GenRR($5040, - Lo, D3) { ADDQ.W #-lo,D3 }
            ELSE
              BEGIN
              GenRR($907C, D3, 0); Gen(Lo); { SUBI.W #lo,D3 }
              END;
            END;
          DataMask := 0; AddrMask := 0; lBitsPerEl := BitsPerEl;
          AShiftCount := 0;
          FOR i := 1 TO BitsPerEl DO DataMask := DataMask * 2 + 1;
          WHILE lBitsPerEl < 8 DO
            BEGIN
            AShiftCount := AShiftCount + 1;
            lBitsPerEl := lBitsPerEl * 2; AddrMask := AddrMask * 2 + 1;
            END;
          D2 := GetReg(Dlow, Dhigh);
          IF BitsPerEl = 1 THEN
            BEGIN
            D := D2;
            D2 := D3;
            D3 := D;
            GenRR($3000, D3, D2); { MOVE.W D2,D3 }
            GenRR($E040, AShiftCount, D3); { ASR.W #sc,D3 }
            END
          ELSE
            BEGIN
            GenRR($1000, D2, D3); { MOVE.B D3,D2 }
            GenR($240, D2); Gen(AddrMask); { ANDI.W #am,D2 }
            CheckClobber(D3);
            GenRR($E040, AShiftCount, D3); { ASR.W #sc,D3 }
            IF AShiftCount < 3 THEN GenRR($E108, 3 - AShiftCount, D2); { LSL.B
              #3-sc,D2 }
            END;
          END;
        gCAttr.cKind := INDX; gCAttr.LongIndex := False;
        CASE lCAttr.cKind OF
          ADDR: BEGIN
                gCAttr.InOffset := lCAttr.AOffset;
                gCAttr.InxAReg := lCAttr.AdReg;
                END;
          INDX: BEGIN
                CheckClobber(D3);
                gCAttr := lCAttr; FreeReg(lCAttr.InxRReg);
                GenRR($D040, D3, lCAttr.InxRReg); { ADD.W }
                END;
          VARB: IF lCAttr.VLev > 0 THEN
                  BEGIN
                  gCAttr.InOffset := lCAttr.VOffset;
                  gCAttr.InxAReg := GetBase(lCAttr.VLev);
                  END
                ELSE
                  BEGIN
                  gCAttr.InOffset := 0;
                  gCAttr.InxAReg := LoadAddress(lCAttr);
                  END;
        END; {case}
        gCAttr.InxRReg := D3;

        IF BitsPerEl = 1 THEN { optimize the packed array of boolean }
          BEGIN
          GenEffAddr($0100 + D2 * 512, gCAttr, LongOp, False, 0, 0); {BTST D2,<ea>}
          FreeReg(D2); gCAttr.cKind := COND; gCAttr.CC := NE;
          END
        ELSE IF BitsPerEl = 8 THEN
          BEGIN { optimize those bytes }
          D := GetReg(Dlow, Dhigh);
          LoadAOrd(D, gCAttr, ByteOp);
          IF Signed THEN { EXT.W D }
            GenR($4880, D)
          ELSE
            BEGIN
            GenR($240, D); Gen($00FF); { ANDI.W #00ff,d }
            END;
          END
        ELSE
          BEGIN
          D := LoadD(gCAttr, ByteOp, False);
          CheckClobber(D);
          gCAttr.ExReg := D;
          GenRR($E028, D2, D); { LSR.B D2,D }
          FreeReg(D2);
          IF Signed THEN
            BEGIN
            GenRR($E018, BitsPerEl, D); { ROR.B #bpe,D }
            GenRR($E000, 8 - BitsPerEl, D); { ASR.B #8-bpe,D }
            GenR($4880, D); { EXT.W D }
            END
          ELSE
            BEGIN
            GenR($240, D); Gen(DataMask); { ANDI.W #datamask,d }
            END;
          END;
      END; {pckdindex}

    { [ F E D C B A 9 8 7 6 5 4 3 2 1 0 ] }
    {               x x x x               }
    {   Where:                            }
    {      Numbits = 4, Rightbit = 6.     }

    PROCEDURE ExtUField;

      VAR
        RightBit, NumBits, lSize, Mask, i: Integer;
        D: Register;

      BEGIN
        RightBit := NextByte; NumBits := RightBit DIV 16;
        RightBit := RightBit MOD 16; Expression(NextByte, - 1, False);
        IF NumBits = 1 THEN
          BEGIN
          IF RightBit <= 7 THEN IncOffset(gCAttr, 1);
          GenEffAddr($800 {BTST} , gCAttr, WordOp, True, 0, RightBit MOD 8);
          gCAttr.cKind := COND; gCAttr.CC := NE;
          END
        ELSE
          BEGIN
          IF ((RightBit = 8) OR (RightBit = 0)) AND (NumBits = 8) THEN
            BEGIN
            IF RightBit = 0 THEN IncOffset(gCAttr, 1);
            D := PrefReg;                                                      {!12-1-83}
            IF D < 0 THEN D := GetReg(Dlow, Dhigh);
            LoadAOrd(D, gCAttr, ByteOp);
            GenR($240, D); Gen($00FF); { ANDI.W #datamask,d }
            END
          ELSE
            BEGIN
            lSize := WordOp;
            IF RightBit > 7 THEN
              BEGIN
              lSize := ByteOp; RightBit := RightBit - 8;
              END;
            IF PrefReg < A0 THEN
              D := LoaddWithPrefReg(PrefReg, gCAttr, lSize)                    {!12-1-83}
            ELSE
              BEGIN                                                            {!3-2-83}
              D := LoadD(gCAttr, lSize, False);
              CheckClobber(D);
              gCAttr.ExReg := D;
              END;
            IF RightBit > 0 THEN GenRR($E048, RightBit, D); { RSL.W #x,D }
            Mask := 0;
            FOR i := 1 TO NumBits DO Mask := Mask * 2 + 1;
            GenR($240, D); Gen(Mask); { ANDI.W #mask,D }
            END;
          END;
      END; {extufield}

    PROCEDURE ExtSField;

      VAR
        RightBit, NumBits, LeftBit, Op, ShiftCount: Integer;
        ShortFlag: Boolean;
        D: Register;

      BEGIN
        RightBit := NextByte; NumBits := RightBit DIV 16;
        RightBit := RightBit MOD 16; LeftBit := RightBit + NumBits - 1;
        ShortFlag := LeftBit <= 7; Expression(NextByte, - 1, False);
        IF PrefReg < A0 THEN
          D := LoaddWithPrefReg(PrefReg, gCAttr, WordOp)                       {!12-1-83}
        ELSE
          BEGIN                                                                {!3-2-83}
          D := LoadD(gCAttr, WordOp, False);
          CheckClobber(D);
          gCAttr.ExReg := D;
          END;
        IF ShortFlag THEN
          BEGIN
          Op := $E108; { LSL.B } ShiftCount := 7 - LeftBit;
          END
        ELSE
          BEGIN
          Op := $E148; { LSL.W } ShiftCount := 15 - LeftBit;
          END;
        IF ShiftCount > 0 THEN GenRR(Op, ShiftCount, D);
        RightBit := RightBit + ShiftCount;
        IF ShortFlag THEN
          Op := $E000 { RSA.B }
        ELSE
          Op := $E040; { RSA.W }
        IF RightBit >= 8 THEN
          BEGIN
          GenR(Op, D); RightBit := RightBit - 8;
          END;
        IF RightBit > 0 THEN GenRR(Op, RightBit, D);
        IF ShortFlag THEN GenR($4880, D); { EXT.W }
      END; {extsfield}

    PROCEDURE NumExpr(fOp, fSize: Integer; VAR UsePrefReg: Boolean);

      VAR
        D: Register;

      BEGIN
        Expression(fOp, - 1, False);
        IF gCAttr.cKind IN [BOOL, COND, BITZ] THEN
          IF UsePrefReg THEN
            BEGIN
            D := LoaddWithPrefReg(PrefReg, gCAttr, fSize);
            IF D = PrefReg THEN UsePrefReg := False;
            END
          ELSE
            D := LoadD(gCAttr, fSize, False);
      END; {numexpr}

    PROCEDURE Expr1(fOp: Integer; PrefReg: Integer);

      VAR
        SaveAttr, tCAttr, lCAttr: CAttr;
        RSize, i, Lo, HI, lSize, Count, Junk, lOp: Integer;
        CnstD, D, D2, A, ExReg: Register;
        DoIt, NotOptimized, TriOp, UsePrefReg: Boolean;
        lString: pStrCRec;

      PROCEDURE TryMOVEQ(VAR aCAttr: CAttr);

        BEGIN
          WITH aCAttr DO
            BEGIN
            IF IsQuickCnst(CValu) AND (Odd(fOp) { LongOp } ) THEN
              BEGIN
              CnstD := LoadInt(CValu.IValu[0], CValu.IValu[1], LongOp);
              cKind := EXPR;
              ExReg := CnstD;
              NotOptimized := False;
              GenEffAddr(lOp + D * 512, aCAttr, lSize, False, 0, 0);
              END;
            END;
        END; { tryMOVEQ }

      BEGIN
        WITH gCAttr DO
          BEGIN                                                                {!}{[@=5]}
          CASE fOp OF
            001: { GLOBAL }
                 BEGIN
                 cKind := VARB;
                 VLev := 1;
                 VOffset := NextWord;
                 END;
            002: { LOCAL }
                 BEGIN
                 cKind := VARB;
                 VLev := ProcLvl;
                 VOffset := NextWord;
                 END;
            003: { INTER }
                 BEGIN
                 cKind := VARB;
                 VLev := ProcLvl - NextByte;
                 VOffset := NextWord;
                 END;
            004: { COMMON }
                 BEGIN
                 cKind := VARB;
                 VLev := - NextByte;
                 VOffset := NextWord;
                 END;
            005: { REGISTER }
                 BEGIN
                 cKind := EXPR;
                 ExReg := NextByte;
                 Count := NextByte; {count = # of 'uses' to bump regcount by}  {!12-1-83}
                 RSize := NextByte;
                 IF RSize <> 0 THEN
                   BEGIN { something to load }
                   SaveAttr := gCAttr;
                   Expression(NextByte, ExReg, False);
                   lCAttr := gCAttr;
                   gCAttr := SaveAttr;
                   IF (lCAttr.cKind <> EXPR) OR (ExReg <> lCAttr.ExReg) THEN
                     LoadAOrd(ExReg, lCAttr, RSize);
                   END;
                 IF (ExReg >= Dlow) THEN                                       {!12-1-83}
                   IF (ExReg <= Ahigh) THEN
                     IF (ExReg <= Dhigh) OR (ExReg >= Alow) THEN
                       Reg[ExReg].Count := Reg[ExReg].Count + Count;
                 END;
            012: { UPARROW }
                 BEGIN
                 {writeln('up arrow ');}
                 Expression(NextByte, - 1, False);
                 DoIt := True;
                 IF cKind = EXPR THEN
                   IF ExReg >= A0 THEN
                     BEGIN
                     DoIt := False; A := ExReg;
                     END;
                 IF DoIt THEN
                   BEGIN
                   A := ReuseIfPossible(gCAttr, Alow, Ahigh);
                   {writeln('moving expr into ',a);}
                   GenEffAddr(8256 + (A - 8) * 512, gCAttr, LongOp, False, 0, 0);{
                     MOVE.L ?,A }
                   END;
                 cKind := ADDR; AdReg := A; AOffset := 0;
                 END;
            013, { FILE^ }
            014: { TEXT^ }
                 BEGIN
                 Expression(NextByte, - 1, False); PushAddress(gCAttr);
                 GenJSR('%_UPARR '); A := GetReg(Alow, Ahigh);
                 GenRR($205F, A, 0); { MOVE.L (SP)+,A }
                 cKind := ADDR; AdReg := A; AOffset := 0;
                 END;
            015: { FIELD }
                 BEGIN
                 lSize := NextWord; Expression(NextByte, - 1, False);
                 IncOffset(gCAttr, lSize);
                 END;
            016: { INDX1 }
                 GenIndex(1);
            017: { INDX2 }
                 GenIndex(2);
            018: { INDX4 }
                 GenIndex(4);
            019: { INDX8 }
                 GenIndex(8);
            020: { INDXBIG }
                 GenIndex(NextWord);
            021: { INDXPCK }
                 PckdIndex;
            022: { ADDRESS }
                 BEGIN
                 i := NextByte;
                 IF i = 241 { EXTREF }
                    THEN
                   BEGIN
                   ExtRef; { The front end was fixed so that this }
                   CodError(2006); { only appears at the statement proclvl! }
                   i := NextByte;
                   END;
                 IF (i = 176 {UFUNC} ) OR (i = 177 {UPROC} ) THEN
                   BEGIN
                   i := NextWord;
                   WITH UserProcs[i]^ DO GlobRef(LinkName, UserName, Ic + 2);
                   A := PrefReg;
                   IF A <= D7 THEN A := GetReg(Alow, Ahigh);
                   IF ShortCalls THEN
                     BEGIN
                     GenRR($41FA, A, 0); Gen(0); { LEA $+xxx }
                     END
                   ELSE
                     BEGIN
                     GenRR($41F9, A, 0); Gen(0); Gen(0); { LEA xxx.L }
                     END;
                   END
                 ELSE
                   BEGIN
                   Expression(i, - 1, False);
                   {now we force expr into the proper register! }
                   IF (PrefReg <= D7) THEN
                     A := LoadAddress(gCAttr)
                   ELSE
                     BEGIN
                     A := PrefReg; ALoadAddress(gCAttr, A);
                     END;
                   END;
                 cKind := EXPR; ExReg := A;
                 END;
            023: { NIL }
                 WITH gCAttr DO
                   BEGIN
                   cKind := CNST; CValu.CstKind := SCALCNST;
                   CValu.IValu[0] := 0; CValu.IValu[1] := 0;
                   END;
            024, { CONST1 }
            025, { CONST2 }
            026, { CONST4 }
            027: { CONST8 }
                 WITH gCAttr DO
                   BEGIN
                   cKind := CNST; CValu.CstKind := SCALCNST;
                   CASE fOp - 23 OF                                            {!}{[@=8]}
                     ByteOp: BEGIN
                             i := NextByte;
                             IF i > 127 THEN i := i - 256;
                             CValu.IValu[1] := i;
                             IF i >= 0 THEN
                               CValu.IValu[0] := 0
                             ELSE
                               CValu.IValu[0] := - 1;
                             END;
                     WordOp: BEGIN
                             CValu.IValu[1] := NextWord;
                             CValu.IValu[0] := 0;
                             IF CValu.IValu[1] >= 0 THEN
                               CValu.IValu[0] := 0
                             ELSE
                               CValu.IValu[0] := - 1;
                             END;
                     LongOp: BEGIN
                             CValu.IValu[0] := NextWord;
                             CValu.IValu[1] := NextWord;
                             END;
                     Quad: {CodError} ;
                   END; {case}
                   END;
            028, { STRCNST }
            029: { PAOCNST }
                 BEGIN
                 lSize := NextByte;
                 IF lSize > 0 THEN
                   BEGIN
                   New(lString);
                   WITH lString^ DO
                     BEGIN
                     StrVal := '        '; Next := NIL;
                     END;
                   END
                 ELSE
                   lString := NIL;
                 WITH gCAttr DO
                   BEGIN
                   cKind := CNST;
                   IF fOp = 28 THEN
                     CValu.CstKind := STRCNST
                   ELSE
                     CValu.CstKind := PAOCCNST;
                   CValu.Len := lSize; CValu.StrValu := lString;
                   END;
                 Count := 0;
                 FOR i := 1 TO lSize DO
                   BEGIN
                   Count := Count + 1;
                   IF Count > 8 THEN
                     BEGIN
                     New(lString^.Next); lString := lString^.Next;
                     WITH lString^ DO
                       BEGIN
                       StrVal := '        '; Next := NIL;
                       END;
                     Count := 1;
                     END;
                   lString^.StrVal[Count] := Chr(NextByte);
                   END;
                 END;
            032, {inline ASSIGN 1}
            033, {inline ASSIGN 2}
            034: {inline ASSIGN 4}
                 BEGIN
                 DoIt := False;
                 lSize := Op - 31; TriOp := NextByte <> 2;
                 IF TriOp THEN
                   BEGIN
                   Expression(NextByte, - 1, False);
                   IF gCAttr.cKind = COND THEN LoadCC(gCAttr);
                   SaveAttr := gCAttr;
                   END;
                 Expression(NextByte, - 1, False); lCAttr := gCAttr;
                 IF lCAttr.cKind = EXPR THEN { optimize those moves to register! }
                   BEGIN
                   ExReg := lCAttr.ExReg; Expression(NextByte, ExReg, False);
                   IF (gCAttr.cKind <> EXPR) OR (ExReg <> gCAttr.ExReg) THEN
                     BEGIN
                     lCAttr := gCAttr; LoadAOrd(ExReg, lCAttr, lSize);
                     END;
                   END
                 ELSE
                   BEGIN
                   Expression(NextByte, - 1, False);
                   IF NOT TriOp THEN
                     WITH gCAttr DO
                       CASE cKind OF
                         EXPR:   Reg[ExReg].Count := Reg[ExReg].Count + 1;
                         ADDR:   Reg[AdReg].Count := Reg[AdReg].Count + 1;
                         INDX:   BEGIN
                                 Reg[InxAReg].Count := Reg[InxAReg].Count + 1;
                                 Reg[InxRReg].Count := Reg[InxRReg].Count + 1;
                                 END;
                         OTHERWISE
                                 BEGIN
                                 SaveAttr := gCAttr; DoIt := True;
                                 END;
                       END; {case}
                   Store(gCAttr, lCAttr, lSize);
                   END;
                 IF TriOp OR DoIt THEN gCAttr := SaveAttr;
                 END;
            043: { WITHREC }
                 BEGIN
                 i := NextByte;
                 gCAttr := WithCAttr[i].Cat;
                 IF WithCAttr[i].Indirect THEN
                   BEGIN
                   IF (gCAttr.cKind = EXPR) AND (gCAttr.ExReg >= A0) THEN
                     A := gCAttr.ExReg
                   ELSE
                     BEGIN
                     A := GetReg(Alow, Ahigh);
                     GenEffAddr($2040 + (A - 8) * 512, gCAttr, LongOp, False, 0,
                                0); { MOVE.L g,A }
                     END;
                   gCAttr.cKind := ADDR; AdReg := A; AOffset := 0;
                   END;
                 END;
            046: { RANGE }
                 BEGIN
                 Lo := NextWord; HI := NextWord; Expression(NextByte, - 1, False);
                 D := LoadD(gCAttr, WordOp, False);
                 IF Lo = 0 THEN
                   BEGIN
                   GenRR($41BC, D, 0); Gen(HI); { CHK #hi,D }
                   END
                 ELSE IF HI - Lo > 0 { ie. within 15 bits } THEN
                   BEGIN
                   D2 := GetReg(Dlow, Dhigh);
                   GenRR($3000, D2, D); { MOVE.W D,D2 }
                   IF Abs(Lo) <= 8 THEN
                     IF Lo > 0 THEN
                       GenRR($5140, Lo, D2) { SUBQ.W #lo,D2 }
                     ELSE
                       GenRR($5040, - Lo, D2) { ADDQ.W #-lo,D2 }
                   ELSE
                     BEGIN
                     GenR($440, D2); Gen(Lo); { SUBI.W #lo,D2 }
                     END;
                   GenRR($41BC, D2, 0); Gen(HI - Lo); { CHK #hi-lo,D2 }
                   FreeReg(D2);
                   END
                 ELSE
                   BEGIN
                   GenR($3F00, D); { MOVE.W D,-(SP) }
                   PushInt(Lo, WordOp); PushInt(HI, WordOp);
                   GenJSR('%_RCHCK ');
                   END;
                 END;
            047: { SRANGE }
                 BEGIN
                 HI := NextByte; Expression(NextByte, - 1, False);
                 A := LoadAddress(gCAttr); GenR($1F10, A); { MOVE.B (A),-(SP) }
                 PushInt(HI, WordOp); GenJSR('%_SRCHK ');
                 gCAttr.cKind := ADDR; gCAttr.AdReg := A; gCAttr.AOffset := 0;
                 END;
            048, { INT12 }
            049, { INT24 }
            050: { INT14 }
                 BEGIN
                 IF Odd(fOp) THEN
                   lSize := WordOp
                 ELSE
                   lSize := ByteOp;
                 Expression(NextByte, - 1, False);
                 IF gCAttr.cKind <> CNST THEN
                   BEGIN
                   D := LoadD(gCAttr, lSize, False);
                   gCAttr.ExReg := D;
                   IF NOT Odd(fOp) THEN GenR($4880, D); { EXT.W D }
                   IF fOp >= 49 THEN GenR($48C0, D); { EXT.L D }
                   END;
                 END;
            051, { INT21 }
            052, { INT42 }
            053: { INT41 }
                 BEGIN
                 IF fOp = 51 THEN
                   lSize := WordOp
                 ELSE
                   lSize := LongOp;
                 Expression(NextByte, - 1, False); DoIt := True;
                 IF gCAttr.cKind <> CNST THEN
                   BEGIN
                   WITH gCAttr DO
                     CASE cKind OF                                             {!}{[@=6]}
                       ADDR: DoIt := False;
                       VARB: DoIt := False;
                       INDX: DoIt := False;
                     END; {case}
                   IF DoIt OR TrapV THEN
                     D := LoadD(gCAttr, lSize, False)
                   ELSE
                     IncOffset(gCAttr, fOp - 50);
                   IF TrapV THEN IF lSize = LongOp THEN LongTRAPV(D);
                   END;
                 END;
            054: { REAL48 }
                 BEGIN
                 IF NOT HaveExtTmp THEN
                   BEGIN {allocate an extended real temp for conversions}
                   GetTemp(ExtTmp, 10); HaveExtTmp := True;
                   END; {this is done once per procedure}
                 Expression(NextByte, - 1, False);
                 IF gCAttr.cKind = CNST THEN
                   BEGIN
                   IF NOT HaveRealTmp THEN
                     BEGIN {allocate one real temp for constant conversion}
                     GetTemp(RealTmp, 4); HaveRealTmp := True;
                     END; {need only one per proc}
                   Store(gCAttr, RealTmp, LongOp);
                   gCAttr := RealTmp;
                   END;
                 PushAddress(gCAttr);
                 PushAddress(ExtTmp);
                 Gen($3F3C); Gen($100E); { MOVE.W #FFSGL+FOZ2X,-(SP) ; real to ext}
                 IF MacFlag THEN
                   Gen($A9EB) { _FP68K trap }
                 ELSE
                   GenJSR('FP68K   ');
                 GetTemp(lCAttr, 8);
                 PushAddress(ExtTmp);
                 PushAddress(lCAttr);
                 Gen($3F3C); Gen($0810); { MOVE.W #FFDBL+FOX2Z,-(SP) ; ext to dbl }
                 IF MacFlag THEN
                   Gen($A9EB) { _FP68K trap }
                 ELSE
                   GenJSR('FP68K   ');
                 gCAttr := lCAttr; {leave result in 8-byte temp}
                 END;
            056: { FLOAT4 }
                 Push4Call('%I_FLT  ');
            058: { TRUNC4 }
                 Push4Call('%_TRUNC ');
            060: { ROUND4 }
                 Push4Call('%_ROUND ');
            062: { EXTUFLD }
                 ExtUField;
            063: { EXTSFLD }
                 ExtSField;
            064, { IADD2 }
            065, { IADD4 }
            066, { ISUB2 }
            067: { ISUB4 }
                 BEGIN
                 NotOptimized := True;
                 UsePrefReg := True;
                 IF Odd(fOp) THEN
                   lSize := LongOp
                 ELSE
                   lSize := WordOp;
                 NumExpr(NextByte, lSize, UsePrefReg); lCAttr := gCAttr;
                 NumExpr(NextByte, lSize, UsePrefReg);
                 IF (gCAttr.cKind = CNST) AND (lCAttr.cKind = CNST) THEN
                   BEGIN { fold those suckers }
                   IF fOp <= 65 THEN
                     gCAttr.CValu.lInt := lCAttr.CValu.lInt + gCAttr.CValu.lInt
                   ELSE
                     gCAttr.CValu.lInt := lCAttr.CValu.lInt - gCAttr.CValu.lInt;
                   END
                 ELSE
                   BEGIN
                   IF fOp <= 65 THEN { addition }
                     BEGIN
                     lOp := $D040; { ADD.W }
                     IF Odd(fOp) THEN lOp := lOp + 64; { .W --> .L }
                     IF ((gCAttr.cKind = EXPR) AND (gCAttr.ExReg >= Dhigh) AND
                        (lCAttr.cKind = EXPR)) OR (gCAttr.cKind = CNST) OR (
                        (lCAttr.cKind = EXPR) AND (lCAttr.ExReg = PrefReg)) THEN
                       BEGIN { addition commutes }
                       tCAttr := gCAttr; gCAttr := lCAttr; lCAttr := tCAttr;
                       END;
                     D := LoaddWithPrefReg(PrefReg, gCAttr, lSize);
                     IF PrefReg >= A0 THEN
                       BEGIN
                       D := D - 8;
                       IF Odd(fOp) THEN
                         lOp := lOp + ($1C0 - $80) {-->ADDA.L}
                       ELSE
                         lOp := lOp + $80; {-->ADDA.W}
                       END;
                     IF lCAttr.cKind = CNST THEN
                       BEGIN
                       IF (lCAttr.CValu.IValu[1] <= 8) AND
                          (lCAttr.CValu.IValu[1] >= 0) AND
                          (lCAttr.CValu.IValu[0] = 0) THEN
                         BEGIN
                         NotOptimized := False;
                         IF lCAttr.CValu.IValu[1] <> 0 THEN
                           BEGIN
                           lOp := $5080; { ADDQ.L }
                           IF (fOp = 64 {IADD2} ) THEN lOp := $5040; { ADDQ.W }
                           IF PrefReg >= A0 THEN lOp := lOp + 8;
                           lOp := lOp + (lCAttr.CValu.IValu[1] MOD 8) * 512;
                           GenR(lOp, D);
                           END;
                         END
                       ELSE
                         TryMOVEQ(lCAttr);
                       END;
                     IF NotOptimized THEN
                       GenEffAddr(lOp + D * 512, lCAttr, lSize, False, 0, 0);
                     END
                   ELSE { subtraction }
                     BEGIN
                     lOp := $9040; { SUB.W }
                     IF ((gCAttr.cKind = EXPR) AND (gCAttr.ExReg = PrefReg)) THEN {a-b --> -b+a }
                       BEGIN
                       tCAttr := gCAttr; gCAttr := lCAttr; lCAttr := tCAttr;
                       lOp := $4440; {NEG.W}
                       IF Odd(fOp) THEN lOp := lOp + 64; { .W --> .L }
                       GenEffAddr(lOp, lCAttr, lSize, False, 0, 0);
                       lOp := $D040; { ADD.W }
                       END;
                     IF (gCAttr.cKind = STCK) AND (lCAttr.cKind = STCK) THEN
                       D := LoadD(gCAttr, lSize, False);
                     IF PrefReg >= A0 THEN
                       BEGIN
                       LoadAOrd(PrefReg, lCAttr, lSize);
                       D := PrefReg - 8;
                       IF Odd(fOp) THEN
                         lOp := lOp + $180 {SUBA.L}
                       ELSE
                         lOp := lOp + $80; {SUBA.W}
                       END
                     ELSE
                       BEGIN
                       D := LoaddWithPrefReg(PrefReg, lCAttr, lSize);
                       IF Odd(fOp) THEN lOp := lOp + 64; { .W --> .L }
                       END;
                     IF (gCAttr.cKind = CNST) AND (PrefReg < A0) THEN
                       BEGIN
                       IF (gCAttr.CValu.IValu[1] <= 8) AND
                          (gCAttr.CValu.IValu[1] >= 0) AND
                          (gCAttr.CValu.IValu[0] = 0) THEN
                         BEGIN
                         NotOptimized := False;
                         IF gCAttr.CValu.IValu[1] <> 0 THEN
                           BEGIN
                           lOp := $5180; { SUBQ.L }
                           IF (fOp = 66 {ISUB2} ) THEN lOp := $5140; { SUBQ.W }
                           lOp := lOp + (gCAttr.CValu.IValu[1] MOD 8) * 512;
                           GenR(lOp, D);
                           END;
                         END
                       ELSE
                         TryMOVEQ(gCAttr);
                       END;
                     IF NotOptimized THEN
                       GenEffAddr(lOp + D * 512, gCAttr, lSize, False, 0, 0);
                     END;
                   IF TrapV THEN Gen($4E76); {TRAPV}
                   gCAttr.cKind := EXPR;
                   IF PrefReg >= A0 THEN
                     gCAttr.ExReg := PrefReg
                   ELSE
                     gCAttr.ExReg := D;
                   END;
                 END;
          END; {case}
          END;
      END; {expr1}

    PROCEDURE Expr2(fOp: Integer; PrefReg: Integer);

      VAR
        lCAttr, tCAttr: CAttr;
        ShiftCnt, lOp, mOp, lSize, mSize: Integer;
        D: Register;
        DoIt, Optimized, UsePrefReg: Boolean;
        lCC: GCondition;
        A, A1, A2: Register;

      BEGIN
        CASE fOp OF
          068: { IMULT2 }
               BEGIN
               IF PrefReg >= A0 THEN PrefReg := - 1;
               UsePrefReg := True;
               NumExpr(NextByte, WordOp, UsePrefReg); lCAttr := gCAttr;
               NumExpr(NextByte, WordOp, UsePrefReg);
               Optimized := False;
               IF lCAttr.cKind = CNST THEN
                 BEGIN
                 DoIt := lCAttr.CValu.IValu[1] <> 1;
                 Optimized := ShiftMult(lCAttr.CValu.IValu[1], ShiftCnt);
                 END
               ELSE IF gCAttr.cKind = CNST THEN
                 BEGIN
                 DoIt := gCAttr.CValu.IValu[1] <> 1;
                 Optimized := ShiftMult(gCAttr.CValu.IValu[1], ShiftCnt);
                 IF Optimized THEN gCAttr := lCAttr;
                 END;
               IF Optimized THEN
                 BEGIN
                 IF DoIt THEN
                   BEGIN
                   D := LoaddWithPrefReg(PrefReg, gCAttr, WordOp);
                   GenRR($E140, ShiftCnt, D); { ASL.W #shiftcnt,d }
                   IF TrapV THEN Gen($4E76); {TRAPV}
                   END;
                 END
               ELSE
                 BEGIN
                 IF (gCAttr.cKind = EXPR) AND (gCAttr.ExReg = PrefReg) THEN
                   D := LoaddWithPrefReg(PrefReg, gCAttr, WordOp)
                 ELSE IF lCAttr.cKind = EXPR THEN
                   BEGIN
                   D := LoaddWithPrefReg(PrefReg, lCAttr, WordOp);
                   lCAttr := gCAttr;
                   END
                 ELSE
                   BEGIN
                   D := LoadD(gCAttr, WordOp, False);
                   CheckClobber(D);
                   END;
                 GenEffAddr( - 15936 { C1C0 } + D * 512, lCAttr, WordOp, False, 0,
                            0);
                 IF TrapV THEN LongTRAPV(D);
                 END;
               IF NOT (Optimized AND NOT DoIt) THEN
                 BEGIN
                 gCAttr.cKind := EXPR;
                 gCAttr.ExReg := D;
                 END;
               END;
          069: { IMULT4 }
               BEGIN
               IF PrefReg >= A0 THEN PrefReg := - 1;
               Expression(NextByte, - 1, False);
               lCAttr := gCAttr;
               Expression(NextByte, - 1, False);
               Optimized := False;
               IF lCAttr.cKind = CNST THEN
                 BEGIN
                 DoIt := lCAttr.CValu.IValu[1] <> 1;
                 IF lCAttr.CValu.IValu[0] = 0 THEN
                   Optimized := ShiftMult(lCAttr.CValu.IValu[1], ShiftCnt);
                 END
               ELSE IF gCAttr.cKind = CNST THEN
                 BEGIN
                 DoIt := gCAttr.CValu.IValu[1] <> 1;
                 IF gCAttr.CValu.IValu[0] = 0 THEN
                   Optimized := ShiftMult(gCAttr.CValu.IValu[1], ShiftCnt);
                 IF Optimized THEN gCAttr := lCAttr;
                 END;
               IF Optimized THEN
                 BEGIN
                 IF DoIt THEN
                   BEGIN
                   D := LoaddWithPrefReg(PrefReg, gCAttr, LongOp);
                   GenRR($E180, ShiftCnt, D); { ASL.L #shiftcnt,d }
                   IF TrapV THEN Gen($4E76); {TRAPV}
                   gCAttr.ExReg := D;
                   END;
                 END
               ELSE
                 BEGIN
                 PushValue(lCAttr, LongOp); { JSR %I_MUL4 }
                 PushValue(gCAttr, LongOp);
                 GenJSR('%I_MUL4 ');
                 gCAttr.cKind := STCK;
                 END;
               END;
          070, { IDIV2 }
          072: { IMOD2 }
               BEGIN
               UsePrefReg := False;
               NumExpr(NextByte, WordOp, UsePrefReg); lCAttr := gCAttr;
               NumExpr(NextByte, WordOp, UsePrefReg);
               IF (gCAttr.cKind = STCK) AND (lCAttr.cKind = STCK) THEN
                 D := LoadD(gCAttr, WordOp, False);
               D := LoadD(lCAttr, WordOp, False);
               CheckClobber(D);
               GenR($48C0, D); { EXT.L }
               GenEffAddr( - 32320 { 81C0 } + D * 512, gCAttr, WordOp, False, 0,
                          0);
               IF fOp = 72 THEN
                 BEGIN
                 GenR($4840, D); { SWAP d } GenR($4A40, D); { TST.W d }
                 END
               ELSE IF TrapV THEN Gen($4E76); {TRAPV} ;
               gCAttr.cKind := EXPR; gCAttr.ExReg := D;
               END;
          071: { IDIV4 }
               Push44Call('%I_DIV4 ');
          073: { IMOD4 }
               Push44Call('%I_MOD4 ');
          074, { INEG2 }
          075, { INEG4 }
          076, { IABS2 }
          077: { IABS4 }
               BEGIN
               IF Odd(fOp) THEN
                 BEGIN
                 lOp := $4480; { NEG.L } lSize := LongOp;
                 END
               ELSE
                 BEGIN
                 lOp := $4440; { NEG.W } lSize := WordOp;
                 END;
               Expression(NextByte, - 1, False);
               D := LoadD(gCAttr, lSize, fOp > 75);
               CheckClobber(D); gCAttr.ExReg := D;
               IF fOp > 75 THEN Gen($6A02); { BPL $+4 }
               GenR(lOp, D);
               IF TrapV THEN Gen($4E76); {TRAPV}
               END;
          078: { ISQR2 }
               BEGIN
               Expression(NextByte, - 1, False);
               D := LoadD(gCAttr, WordOp, False);
               CheckClobber(D); GenRR($C1C0, D, D);
               IF TrapV THEN LongTRAPV(D);
               gCAttr.cKind := EXPR; gCAttr.ExReg := D;
               END;
          079: { ISQR4 }
               BEGIN
               Expression(NextByte, - 1, False); PushValue(gCAttr, LongOp);
               Gen($2F17); { MOVE.L (SP),-(SP) }
               GenJSR('%I_MUL4 ');
               gCAttr.cKind := STCK;
               END;
          080, { AND1 }
          081, { AND2 }
          082, { AND4 }
          083, { IOR1 }
          084, { IOR2 }
          085: { IOR4 }
               BEGIN
               IF fOp > 82 THEN
                 lOp := - 32767 - 1 { OR }
               ELSE
                 lOp := $C000; { AND }
               mOp := (fOp - 80) MOD 3;
               IF mOp = 0 THEN
                 lSize := ByteOp
               ELSE IF mOp = 1 THEN
                 BEGIN
                 lSize := WordOp; lOp := lOp + $40;
                 END
               ELSE
                 BEGIN
                 lSize := LongOp; lOp := lOp + $80;
                 END;
               Expression(NextByte, - 1, False);
               IF gCAttr.cKind = COND THEN LoadCC(gCAttr);
               lCAttr := gCAttr; Expression(NextByte, - 1, False);
               IF gCAttr.cKind = COND THEN LoadCC(gCAttr);
               IF (gCAttr.cKind IN [EXPR, BOOL, BITZ]) AND (gCAttr.ExReg = PrefReg) THEN
                 BEGIN
                 tCAttr := gCAttr; gCAttr := lCAttr; lCAttr := tCAttr
                 END;
               IF (lCAttr.cKind = EXPR) OR (lCAttr.cKind = BOOL) OR
                  (lCAttr.cKind = BITZ) THEN
                 BEGIN
                 D := lCAttr.ExReg; tCAttr := gCAttr;
                 END
               ELSE
                 BEGIN
                 IF (gCAttr.cKind = BOOL) OR (gCAttr.cKind = BITZ) THEN
                   D := gCAttr.ExReg
                 ELSE
                   D := LoadD(gCAttr, lSize, False);
                 tCAttr := lCAttr;
                 END;
               IF (tCAttr.cKind = BOOL) OR (tCAttr.cKind = BITZ) THEN
                 tCAttr.cKind := EXPR;
               IF D <> PrefReg THEN CheckClobber(D);
               GenEffAddr(lOp + D * 512, tCAttr, lSize, False, 0, 0);
               IF fOp <= 82 THEN
                 BEGIN
                 { AND  | BOOL  BITZ  else }
                 { -----+----------------- }
                 { BOOL | BOOL  BITZ  EXPR }
                 { BITZ | BITZ  BITZ  EXPR }
                 { else | EXPR  EXPR  EXPR }
                 IF ((gCAttr.cKind = BOOL) OR (gCAttr.cKind = BITZ)) AND (
                    (lCAttr.cKind = BOOL) OR (lCAttr.cKind = BITZ)) THEN
                   IF gCAttr.cKind = BOOL THEN
                     gCAttr.cKind := lCAttr.cKind
                   ELSE
                     gCAttr.cKind := BITZ
                 ELSE
                   gCAttr.cKind := EXPR;
                 END
               ELSE
               { OR   | BOOL  BITZ  else }
               { -----+----------------- }
               { BOOL | BOOL  BITZ  BITZ }
               { BITZ | BITZ  BITZ  BITZ }
               { else | BITZ  BITZ  EXPR }

               IF (gCAttr.cKind = BOOL) AND (lCAttr.cKind = BOOL) THEN
                 gCAttr.cKind := BOOL
               ELSE IF ((gCAttr.cKind <> BOOL) AND (gCAttr.cKind <> BITZ)) AND (
                       (lCAttr.cKind <> BOOL) AND (lCAttr.cKind <> BITZ)) THEN
                 gCAttr.cKind := EXPR
               ELSE
                 gCAttr.cKind := BITZ;
               gCAttr.ExReg := D;
               END;
          089, { NOT1 }
          090, { NOT2 }
          091: { NOT4 }
               BEGIN
               IF PrefReg >= A0 THEN PrefReg := - 1;
               lOp := $4600; { NOT }
               fOp := fOp - 89;
               IF fOp = 0 THEN
                 lSize := ByteOp
               ELSE IF fOp = 1 THEN
                 BEGIN
                 lSize := WordOp; lOp := lOp + 64;
                 END
               ELSE
                 BEGIN
                 lSize := LongOp; lOp := lOp + 128;
                 END;
               Expression(NextByte, - 1, False);
               D := LoaddWithPrefReg(PrefReg, gCAttr, lSize);
               GenR(lOp, D);
               gCAttr.cKind := EXPR; gCAttr.ExReg := D;
               END;
          092, { LT1 }
          093, { LT2 }
          094, { LT4 }
          095, { GT1 }
          096, { GT2 }
          097, { GT4 }
          098, { LE1 }
          099, { LE2 }
          100, { LE4 }
          101, { GE1 }
          102, { GE2 }
          103, { GE4 }
          104, { EQ1 }
          105, { EQ2 }
          106, { EQ4 }
          107, { NE1 }
          108, { NE2 }
          109: { NE4 }
               BEGIN
               fOp := fOp - 92;
               CASE fOp MOD 3 OF
                 0:   lSize := ByteOp;
                 1:   lSize := WordOp;
                 2:   lSize := LongOp;
               END; {case}
               CASE fOp DIV 3 OF
                 0:   lCC := LT;
                 1:   lCC := GT;
                 2:   lCC := LE;
                 3:   lCC := GE;
                 4:   lCC := EQ;
                 5:   lCC := NE;
               END; {case}
               UsePrefReg := False;
               NumExpr(NextByte, lSize, UsePrefReg); lCAttr := gCAttr;
               NumExpr(NextByte, lSize, UsePrefReg);
               IF GenCompare(lCAttr, gCAttr, lSize) THEN
                 CASE lCC OF
                   LT:  lCC := GT;
                   LE:  lCC := GE;
                   GT:  lCC := LT;
                   GE:  lCC := LE;
                 END; {case}
               gCAttr.cKind := COND; gCAttr.CC := lCC;
               END;
          110: { BNOT }
               BEGIN
               IF PrefReg >= A0 THEN PrefReg := - 1;
               Expression(NextByte, - 1, False);
               WITH gCAttr DO
                 IF cKind = COND THEN
                   CASE CC OF
                     LT:  CC := GE;
                     LE:  CC := GT;
                     GT:  CC := LE;
                     GE:  CC := LT;
                     EQ:  CC := NE;
                     NE:  CC := EQ;
                     HI:  CC := LS;
                     LS:  CC := HI;
                   END {case}
                 ELSE IF (cKind = BOOL) OR (cKind = BITZ) THEN
                   BEGIN
                   CheckClobber(ExReg);
                   GenR($5200, ExReg); { ADDQ.B #1,D }
                   IF cKind = BOOL THEN cKind := EXPR;
                   END
                 ELSE
                   BEGIN
                   D := LoaddWithPrefReg(PrefReg, gCAttr, ByteOp);
                   GenR($A00, D); Gen(1); { EORI.B #1,d }
                   ExReg := D;
                   END;
               END;
          111: { ODD }
               BEGIN
               IF PrefReg >= A0 THEN PrefReg := - 1;
               Expression(NextByte, - 1, False);
               D := LoaddWithPrefReg(PrefReg, gCAttr, ByteOp);
               GenR($240, D); Gen(1); { ANDI.W #1,D }
               gCAttr.ExReg := D;
               END;
          112: { FADD4 }
               Push44Call('%F_ADD  ');
          114: { FSUB4 }
               Push44Call('%F_SUB  ');
          116: { FMUL4 }
               Push44Call('%F_MUL  ');
          118: { FDIV4 }
               Push44Call('%F_DIV  ');
          122: { FLT4 }
               Push44Call('%F_LT   ');
          124: { FGT4 }
               Push44Call('%F_GT   ');
          126: { FLE4 }
               Push44Call('%F_LE   ');
          128: { FGE4 }
               Push44Call('%F_GE   ');
          130: { FEQ4 }
               Push44Call('%F_EQ   ');
          132: { FNE4 }
               Push44Call('%F_NE   ');
          134: { FNEG4 }
               Push4Call('%F_NEG  ');
          136: { FABS }
               Push4Call('%F_ABS  ');
          138: { FSQR4 }
               BEGIN
               Expression(NextByte, - 1, False); PushValue(gCAttr, LongOp);
               Gen($2F17); { MOVE.L (SP),-(SP) }
               GenJSR('%F_MUL  ');
               gCAttr.cKind := STCK;
               END;
          140: { TRAPV }
               Expression(NextByte, - 1, True);
          144: { STRLT }
               PushAACall('%S_LT   ');
          145: { STRGT }
               PushAACall('%S_GT   ');
          146: { STRLE }
               PushAACall('%S_LE   ');
          147: { STRGE }
               PushAACall('%S_GE   ');
          148: { STREQ }
               PushAACall('%S_EQ   ');
          149: { STRNE }
               PushAACall('%S_NE   ');
          150, { PAOCLT }
          151, { PAOCGT }
          152, { PAOCLE }
          153, { PAOCGE }
          154, { PAOCEQ }
          155: { PAOCNE }
               BEGIN
               lSize := NextByte; mSize := NextByte;
               IF lSize <> mSize THEN CodError(9000);
               Expression(NextByte, - 1, False); A1 := LoadAddress(gCAttr);
               Expression(NextByte, - 1, False); A2 := LoadAddress(gCAttr);
               D := LoadInt(0, lSize - 1, WordOp);
               CheckClobber(A1); CheckClobber(A2);
               IF (fOp = 150 {LT} ) OR (fOp = 153 {GE} ) THEN
                 BEGIN
                 A := A1; A1 := A2; A2 := A;
                 END;
               GenRR($B108, A1, A2); { CMPM.B (A1)+,(A2)+ }
               GenR($56C8, D); Gen( - 4); { DBNE }
               FreeReg(A1); FreeReg(A2); FreeReg(D);
               WITH gCAttr DO
                 BEGIN
                 cKind := COND;
                 CASE fOp OF
                   150, { PAOCLT }
                   151: { PAOCGT }
                        CC := HI;
                   152, { PAOCLE }
                   153: { PAOCGE }
                        CC := LS;
                   154: { PAOCEQ }
                        CC := EQ;
                   155: { PAOCNE }
                        CC := NE;
                 END; {case}
                 END;
               END;
        END; {case}
      END; {expr2}

    PROCEDURE Expr3(fOp: Integer; PrefReg: Integer);

      VAR
        lCAttr: CAttr;
        lOpSize, lSize, SetSize, lLab1, lLab2: Integer;
        D, D2, t: Register;
        OnStack, LeftStack, RightStack: Boolean;
        A: Register;

      BEGIN
        CASE fOp OF
          163: { IN }
               BEGIN
               SetSize := NextByte; Expression(NextByte, - 1, False);
               D := LoadD(gCAttr, WordOp, True);
               lLab1 := NewLabel;
               lLab2 := NewLabel;
               GenJump(107 * 256, lLab2); { BMI }
               SetExpression(NextByte, OnStack);
               IF OnStack THEN
                 BEGIN
                 D2 := GetReg(Dlow, Dhigh); FreeReg(D2);
                 GenRR($3017, D2, 0); { MOVE.W (SP),D2 }
                 GenR($E748, D2); { LSL.W #3,D2 }
                 GenR($5340, D2); { SUBQ.W #1,D2 }
                 GenRR($B040, D, D2); { CMP.W D2,D }
                 END
               ELSE
                 BEGIN
                 GenRR($B07C, D, 0); Gen(SetSize * 8 - 1); { CMP.W #xx,D }
                 END;
               GenJump(110 * 256, lLab1); { BGT }
               IF OnStack THEN
                 BEGIN
                 CheckClobber(D);
                 D2 := GetReg(Dlow, Dhigh); FreeReg(D2);
                 GenRR($3000, D2, D); { MOVE.W D,D2 }
                 GenR($E648, D2); { LSR.W #3,D2 }
                 GenR($4440, D2); { NEG.W D2 }
                 GenRR($D057, D2, 0); { ADD.W (SP),D2 }
                 GenRR($0130, D, SP); Gen(D2 * 4096 + 1); { BTST D,1(SP,D2.W) }
                 END
               ELSE IF gCAttr.cKind = EXPR THEN
                 BEGIN
                 GenRR(256, D, gCAttr.ExReg); { BTST D,exreg }
                 FreeReg(gCAttr.ExReg);
                 END
               ELSE
                 BEGIN
                 IF gCAttr.cKind <> CNST THEN IncOffset(gCAttr, SetSize);
                 CheckClobber(D);
                 A := LoadAddress(gCAttr); FreeReg(A);
                 D2 := GetReg(Dlow, Dhigh); FreeReg(D2);
                 GenRR($3000, D2, D); { MOVE.W D,D2 }
                 GenR($E648, D2); { LSR.W #3,D2 }
                 GenR($4440, D2); { NEG.W D2 }
                 GenRR($0130, D, A); Gen(D2 * 4096 + 255); { BTST D,-1(A,D2.W) }
                 END;
               Gen($A3C); Gen(4); { EORI.B #4,CCR }
               DefILabel(lLab1); FreeReg(D);
               IF OnStack THEN Gen($DEDF); { ADDA.W (SP)+,SP }
               DefILabel(lLab2); gCAttr.cKind := COND; gCAttr.CC := EQ;
               END;
          164, { SETLE }
          165, { SETGE }
          166, { SETEQ }
          167: { SETNE }
               BEGIN
               SetSize := NextByte; SetExpression(NextByte, LeftStack);
               lCAttr := gCAttr; SetExpression(NextByte, RightStack);
               IF (SetSize > 4) OR LeftStack OR RightStack THEN
                 BEGIN
                 IF NOT LeftStack THEN PushSet(lCAttr, SetSize, True);
                 IF NOT RightStack THEN PushSet(gCAttr, SetSize, True);
                 CASE fOp OF
                   164: IF RightStack AND NOT LeftStack THEN
                          GenJSR('%_SETGE ')
                        ELSE
                          GenJSR('%_SETLE ');
                   165: IF RightStack AND NOT LeftStack THEN
                          GenJSR('%_SETLE ')
                        ELSE
                          GenJSR('%_SETGE ');
                   166: GenJSR('%_SETEQ ');
                   167: GenJSR('%_SETNE ');
                 END; {case}
                 gCAttr.cKind := STCK;
                 END
               ELSE
                 BEGIN
                 IF SetSize = 1 THEN
                   BEGIN
                   lOpSize := 0; lSize := ByteOp;
                   END
                 ELSE IF SetSize = 2 THEN
                   BEGIN
                   lOpSize := 64; lSize := WordOp;
                   END
                 ELSE
                   BEGIN
                   lOpSize := 128; lSize := LongOp;
                   END;
                 D := LoadD(lCAttr, lSize, False);
                 D2 := LoadD(gCAttr, lSize, False);
                 IF fOp = 165 { >= }
                    THEN
                   BEGIN
                   t := D; D := D2; D2 := t;
                   END;
                 IF fOp <= 165 THEN
                   BEGIN
                   CheckClobber(D2);
                   GenR($4600 + lOpSize, D2); { NOT D2 }
                   CheckClobber(D);
                   GenRR( - 16384 { C000 } + lOpSize, D, D2); { AND D2,D }
                   END
                 ELSE { CMP D,D2 }
                   GenRR( - 20480 { B000 } + lOpSize, D, D2);
                 gCAttr.cKind := COND;
                 IF fOp = 167 { <> } THEN
                   gCAttr.CC := NE
                 ELSE
                   gCAttr.CC := EQ;
                 FreeReg(D); FreeReg(D2);
                 END;
               END;
          190: { PARMLST}
               GenCall;
        END; {case}
      END; {expr3}

    BEGIN {expression}
      IF fOp <= 67 THEN
        Expr1(fOp, PrefReg)
      ELSE IF fOp <= 155 THEN
        Expr2(fOp, PrefReg)
      ELSE
        Expr3(fOp, PrefReg);
    END; {expression}

