/* code3206x.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator TMS320C6x                                                   */
/*                                                                           */
/* Historie: 24. 2.1997 Grundsteinlegung                                     */
/*           22. 5.1998 Schoenheitsoperatioenen fuer K&R-Compiler            */
/*            3. 1.1999 ChkPC-Anpassung                                      */
/*           23. 1.1999 DecodeCtrlReg jetzt mit unsigned-Ergebnis            */
/*           30. 1.1999 Formate maschinenunabhaengig gemacht                 */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"
#include <string.h>
#include <ctype.h>

#include "strutil.h"
#include "bpemu.h"
#include "nls.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmcode.h"
#include "codepseudo.h"
#include "asmitree.h"

/*---------------------------------------------------------------------------*/

typedef enum {NoUnit,L1,L2,S1,S2,M1,M2,D1,D2,LastUnit,UnitCnt} TUnit;

typedef struct
         {
          LongInt OpCode;
          LongInt SrcMask,SrcMask2,DestMask;
          Byte CrossUsed; /* Bit 0 -->X1 benutzt, Bit 1 -->X2 benutzt */
          Byte AddrUsed;  /* Bit 0 -->Addr1 benutzt, Bit 1 -->Addr2 benutzt
                             Bit 2 -->LdSt1 benutzt, Bit 3 -->LdSt2 benutzt */
          Byte LongUsed;  /* Bit 0 -->lange Quelle, Bit 1-->langes Ziel */
          Boolean StoreUsed,LongSrc,LongDest;
          TUnit U;
         } InstrRec;

typedef struct
         {
          char *Name;
          LongInt Code;
         } FixedOrder;

typedef struct
         {
          char *Name;
          LongInt Code;
          LongInt Scale;
         } MemOrder;

typedef struct
         {
          char *Name;
          LongInt Code;
          Boolean DSign,SSign1,SSign2;
          Boolean MayImm;
         } MulOrder;

typedef struct
         {
          char *Name;
          LongInt Code;
          Boolean Rd,Wr;
         } CtrlReg;

static char *UnitNames[UnitCnt]={"  ","L1","L2","S1","S2","M1","M2","D1","D2","  "};
#define MaxParCnt 8
#define FirstUnit L1

#define LinAddCnt 6
#define CmpCnt 5
#define MemCnt 8
#define MulCnt 20
#define CtrlCnt 13

#define ModNone (-1)
#define ModReg 0
#define MModReg (1 << ModReg)
#define ModLReg 1
#define MModLReg (1 << ModLReg)
#define ModImm 2
#define MModImm (1 << ModImm)

static ShortInt AdrMode;

static CPUVar CPU32060;

static Boolean ThisPar,ThisCross,ThisStore;
static Byte ThisAddr,ThisLong;
static LongInt ThisSrc,ThisSrc2,ThisDest;
static LongInt Condition;
static TUnit ThisUnit;
static LongWord UnitFlag,ThisInst;
static Integer ParCnt;
static LongWord PacketAddr;

static InstrRec ParRecs[MaxParCnt];

FixedOrder *LinAddOrders;
FixedOrder *CmpOrders;
MemOrder *MemOrders;
MulOrder *MulOrders;
CtrlReg *CtrlRegs;
PInstTable InstTable;

/*-------------------------------------------------------------------------*/

	static Boolean CheckOpt(char *Asc)
BEGIN
   Boolean Flag,erg=True;
   int l=strlen(Asc);

   if (strcmp(Asc,"||")==0) ThisPar=True;
   else if ((*Asc=='[') AND (Asc[l-1]==']'))
    BEGIN
     Asc++; Asc[l-2]='\0'; l-=2;
     if (*Asc=='!')
      BEGIN
       Asc++; l--; Condition=1;
      END
     else Condition=0;
     Flag=True;
     if (l!=2) Flag=False;
     else if (toupper(*Asc)=='A')
      if ((Asc[1]>='1') AND (Asc[1]<='2')) Condition+=(Asc[1]-'0'+3) << 1;
      else Flag=False;
     else if (toupper(*Asc)=='B')
      if ((Asc[1]>='0') AND (Asc[1]<='2')) Condition+=(Asc[1]-'0'+1) << 1;
      else Flag=False;
     if (NOT Flag) WrXError(1445,Asc); erg=Flag;
    END
   else erg=False;

   return erg;
END

	static Boolean ReiterateOpPart(void)
BEGIN
   char *p;
   int z;

   if (NOT CheckOpt(OpPart)) return False;

   if (ArgCnt<1)
    BEGIN
     WrError(1210); return False;
    END
   p=FirstBlank(ArgStr[1]);
   if (p==Nil)
    BEGIN
     strcpy(OpPart,ArgStr[1]);
     for (z=2; z<=ArgCnt; z++) strcpy(ArgStr[z-1],ArgStr[z]);
     ArgCnt--;
    END
   else
    BEGIN
     *p='\0'; strcpy(OpPart,ArgStr[1]); strcpy(ArgStr[1],p+1);
     KillPrefBlanks(ArgStr[1]);
    END
   NLS_UpString(OpPart);
   p=strchr(OpPart,'.');
   if (p==Nil) *AttrPart='\0';
   else
    BEGIN
     strcpy(AttrPart,p+1);
     *p='\0';
    END;
   return True;
END

/*-------------------------------------------------------------------------*/

	static void AddSrc(LongWord Reg)
BEGIN
   LongWord Mask=1 << Reg;

   if ((ThisSrc & Mask)==0) ThisSrc|=Mask;
   else ThisSrc2|=Mask;
END

	static void AddLSrc(LongWord Reg)
BEGIN
   AddSrc(Reg); AddSrc(Reg+1);
   ThisLong|=1;
END

	static void AddDest(LongWord Reg)
BEGIN
   ThisDest|=(1 << Reg);
END

	static void AddLDest(LongWord Reg)
BEGIN
   ThisDest|=(3 << Reg);
   ThisLong|=2;
END

        static LongInt FindReg(LongInt Mask)
BEGIN
   int z;

   for (z=0; z<32; z++)
    BEGIN
     if ((Mask&1)!=0) break;
     Mask=Mask >> 1;
    END
   return z;
END

	static char *RegName(LongInt Num)
BEGIN
   static char s[5];

   Num&=31;
   sprintf(s, "%c%ld", 'A' + (Num >> 4), (long) (Num & 15));
   return s;
END

	static Boolean DecodeSReg(char *Asc, LongWord *Reg, Boolean Quarrel)
BEGIN
   char *end;
   Byte RVal;
   Boolean TFlag;

   TFlag=True;
   if (toupper(*Asc)=='A') *Reg=0;
   else if (toupper(*Asc)=='B') *Reg=16;
   else TFlag=False;
   if (TFlag)
    BEGIN
     RVal=strtol(Asc+1,&end,10);
     if (*end!='\0') TFlag=False;
     else if (RVal>15) TFlag=False;
     else *Reg+=RVal;
    END
   if ((NOT TFlag) AND (Quarrel)) WrXError(1445,Asc);
   return TFlag;
END

	static Boolean DecodeReg(char *Asc, LongWord *Reg, Boolean *PFlag, Boolean Quarrel)
BEGIN
   char *p;
   LongWord NextReg;

   p=strchr(Asc,':');
   if (p==0)
    BEGIN
     *PFlag=False; return DecodeSReg(Asc,Reg,Quarrel);
    END
   else
    BEGIN
     *PFlag=True; *p='\0';
     if (NOT DecodeSReg(Asc,&NextReg,Quarrel)) return False;
     else if (NOT DecodeSReg(p+1,Reg,Quarrel)) return False;
     else if ((Odd(*Reg)) OR (NextReg!=(*Reg)+1) OR ((((*Reg) ^ NextReg) & 0x10)!=0))
      BEGIN
       if (Quarrel) WrXError(1760,Asc); return False;
      END
     else return True;
    END
END

	static Boolean DecodeCtrlReg(char *Asc, LongWord *Erg, Boolean Write)
BEGIN
   int z;

   for (z=0; z<CtrlCnt; z++)
    if (strcasecmp(Asc,CtrlRegs[z].Name)==0)
     BEGIN
      *Erg=CtrlRegs[z].Code;
      return (Write AND CtrlRegs[z].Wr) OR ((NOT Write) AND CtrlRegs[z].Rd);
     END
   return False;
END

/* Was bedeutet das r-Feld im Adressoperanden mit kurzem Offset ???
   und wie ist das genau mit der Skalierung gemeint ??? */

	static Boolean DecodeMem(char *Asc, LongWord *Erg, LongWord Scale)
BEGIN
   String RegPart,DispPart;
   LongInt DispAcc,Mode;
   LongWord BaseReg,IndReg;
   int l;
   char Counter;
   char *p;
   Boolean OK;

   /* das muss da sein */

   if (*Asc!='*')
    BEGIN
     WrError(1350); return False;
    END;
   Asc++;

   /* teilen */

   p=strchr(Asc,'['); Counter=']';
   if (p==Nil)
    BEGIN
     p=strchr(Asc,'('); Counter=')';
    END
   if (p!=Nil)
    BEGIN
     if (Asc[strlen(Asc)-1]!=Counter)
      BEGIN
       WrError(1350); return False;
      END
     Asc[strlen(Asc)-1]='\0'; *p='\0';
     strmaxcpy(RegPart,Asc,255); strmaxcpy(DispPart,p+1,255);
    END
   else
    BEGIN
     strcpy(RegPart,Asc); *DispPart='\0';
    END

   /* Registerfeld entschluesseln */

   l=strlen(RegPart);
   Mode=1; /* Default ist *+R */
   if (*RegPart=='+')
    BEGIN
     strcpy(RegPart,RegPart+1); Mode=1;
     if (*RegPart=='+')
      BEGIN
       strcpy(RegPart,RegPart+1); Mode=9;
      END
    END
   else if (*RegPart=='-')
    BEGIN
     strcpy(RegPart,RegPart+1); Mode=0;
     if (*RegPart=='-')
      BEGIN
       strcpy(RegPart,RegPart+1); Mode=8;
      END
    END
   else if (RegPart[l-1]=='+')
    BEGIN
     if (RegPart[l-2]!='+')
      BEGIN
       WrError(1350); return False;
      END
     RegPart[l-2]='\0'; Mode=11;
    END
   else if (RegPart[l-1]=='-')
    BEGIN
     if (RegPart[l-2]!='-')
      BEGIN
       WrError(1350); return False;
      END
     RegPart[l-2]='\0'; Mode=10;
    END
   if (NOT DecodeSReg(RegPart,&BaseReg,False))
    BEGIN
     WrXError(1445,RegPart); return False;
    END
   AddSrc(BaseReg);

   /* kein Offsetfeld ? --> Skalierungsgroesse bei Autoinkrement/De-
      krement, sonst 0 */

   if (*DispPart=='\0')
    DispAcc=(Mode<2) ? 0 : Scale;

   /* Register als Offsetfeld? Dann Bit 2 in Modus setzen */

   else if (DecodeSReg(DispPart,&IndReg,False))
    BEGIN
     if ((IndReg ^ BaseReg)>15)
      BEGIN
       WrError(1350); return False;
      END
     Mode+=4; AddSrc(DispAcc=IndReg);
    END

   /* ansonsten normaler Offset */

   else
    BEGIN
     FirstPassUnknown=False;
     DispAcc=EvalIntExpression(DispPart,UInt15,&OK);
     if (NOT OK) return False;
     if (FirstPassUnknown) DispAcc&=7;
     if (Counter==']') DispAcc*=Scale;
    END

   /* Benutzung des Adressierers markieren */

   ThisAddr|=(BaseReg>15) ? 2 : 1;

   /* Wenn Offset>31, muessen wir Variante 2 benutzen */

   if (((Mode & 4)==0) AND (DispAcc>31))
    if ((BaseReg<0x1e) OR (Mode!=1)) WrError(1350);
    else
     BEGIN
      *Erg=((DispAcc & 0x7fff) << 8)+((BaseReg & 1) << 7)+12;
      return True;
     END

   else
    BEGIN
     *Erg=(BaseReg << 18)+((DispAcc & 0x1f) << 13)+(Mode << 9)
         +((BaseReg & 0x10) << 3)+4;
     return True;
    END

   return False;
END

	static Boolean DecodeAdr(char *Asc, Byte Mask, Boolean Signed, LongWord *AdrVal)
BEGIN
   Boolean OK;

   AdrMode=ModNone;

   if (DecodeReg(Asc,AdrVal,&OK,False))
    BEGIN
     AdrMode=(OK) ? ModLReg : ModReg;
    END
   else
    BEGIN
     if (Signed) *AdrVal=EvalIntExpression(Asc,SInt5,&OK) & 0x1f;
     else *AdrVal=EvalIntExpression(Asc,UInt5,&OK);
     if (OK) AdrMode=ModImm;
    END

   if ((AdrMode!=ModNone) AND (((1 << AdrMode) AND Mask)==0))
    BEGIN
     WrError(1350); AdrMode=ModNone; return False;
    END
   else return True;
END

	static Boolean ChkUnit(LongWord Reg, TUnit U1, TUnit U2)
BEGIN
   UnitFlag=Ord(Reg>15);
   if (ThisUnit==NoUnit)
    BEGIN
     ThisUnit=(Reg>15) ? U2 : U1;
     return True;
    END
   else if (((ThisUnit==U1) AND (Reg<16)) OR ((ThisUnit==U2) AND (Reg>15))) return True;
   else
    BEGIN
     WrError(1107); return False;
    END
END

	static TUnit UnitCode(char c)
BEGIN
   switch (c)
    BEGIN
     case 'L': return L1;
     case 'S': return S1;
     case 'D': return D1;
     case 'M': return M1;
     default: return NoUnit;
   END
END

	static Boolean UnitUsed(TUnit TestUnit)
BEGIN
   Integer z;

   for (z=0; z<ParCnt; z++)
    if (ParRecs[z].U==TestUnit) return True;

   return False;
END

	static Boolean IsCross(LongWord Reg)
BEGIN
   return (Reg >> 4)!=UnitFlag;
END

        static void SetCross(LongWord Reg)
BEGIN
   ThisCross=((Reg >> 4)!=UnitFlag);
END

	static Boolean DecideUnit(LongWord Reg, char *Units)
BEGIN
   Integer z;
   TUnit TestUnit;

   if (ThisUnit==NoUnit)
    BEGIN
     z=0;
     while ((Units[z]!='\0') AND (ThisUnit==NoUnit))
      BEGIN
       TestUnit=UnitCode(Units[z]);
       if (Reg>=16) TestUnit++;
       if (NOT UnitUsed(TestUnit)) ThisUnit=TestUnit;
       z++;
      END
     if (ThisUnit==NoUnit)
      BEGIN
       ThisUnit=UnitCode(*Units);
       if (Reg>16) TestUnit++;
      END
    END
   UnitFlag=(ThisUnit-FirstUnit) & 1;
   if (IsCross(Reg))
    BEGIN
     WrError(1107); return False;
    END
   else return True;
END

	static void SwapReg(LongWord *r1, LongWord *r2)
BEGIN
   LongWord tmp;

   tmp=(*r1); *r1=(*r2); *r2=tmp;
END

	static Boolean DecodePseudo(void)
BEGIN
   return False;
END


	static Boolean CodeL(LongWord OpCode,LongWord Dest,LongWord Src1,LongWord Src2)
BEGIN
   ThisInst=0x18+(OpCode << 5)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
                +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
   return True;
END

	static Boolean CodeM(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
BEGIN
   ThisInst=0x00+(OpCode << 7)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
                +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
   return True;
END

	static Boolean CodeS(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
BEGIN
   ThisInst=0x20+(OpCode << 6)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
                +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
   return True;
END

	static Boolean CodeD(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
BEGIN
   ThisInst=0x40+(OpCode << 7)+(UnitFlag << 1)
                +(Dest << 23)+(Src2 << 18)+(Src1 << 13);
   return True;
END

/*-------------------------------------------------------------------------*/

static Boolean __erg;

	static void DecodeIDLE(Word Index)
BEGIN
   if (ArgCnt!=0) WrError(1110);
   else if ((ThisCross) OR (ThisUnit!=NoUnit)) WrError(1107);
   else
    BEGIN
     ThisInst=0x0001e000; __erg=True;
    END
END

	static void DecodeNOP(Word Index)
BEGIN
   LongInt Count;
   Boolean OK;

   if ((ArgCnt!=0) AND (ArgCnt!=1)) WrError(1110);
   else if ((ThisCross) OR (ThisUnit!=NoUnit)) WrError(1107);
   else
    BEGIN
     if (ArgCnt==0)
      BEGIN
       OK=True; Count=0;
      END
     else
      BEGIN
       FirstPassUnknown=False;
       Count=EvalIntExpression(ArgStr[1],UInt4,&OK);
       if (FirstPassUnknown) Count=0; else Count--;
       OK=ChkRange(Count,0,8);
      END
     if (OK)
      BEGIN
       ThisInst=Count << 13; __erg=True;
      END
    END
END

	static void DecodeMul(Word Index)
BEGIN
   LongWord DReg,S1Reg,S2Reg;
   MulOrder *POrder=MulOrders+Index;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     if (DecodeAdr(ArgStr[3],MModReg,POrder->DSign,&DReg))
      if (ChkUnit(DReg,M1,M2))
       BEGIN
        if (DecodeAdr(ArgStr[2],MModReg,POrder->SSign2,&S2Reg))
         BEGIN
          AddSrc(S2Reg);
          DecodeAdr(ArgStr[1],(POrder->MayImm?MModImm:0)+MModReg,
                    POrder->SSign1,&S1Reg);
          switch (AdrMode)
           BEGIN
            case ModReg:
             if ((ThisCross) AND (NOT IsCross(S2Reg)) AND (NOT IsCross(S1Reg))) WrError(1350);
             else if ((IsCross(S2Reg)) AND (IsCross(S1Reg))) WrError(1350);
             else
              BEGIN
               if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
               SetCross(S2Reg);
               AddSrc(S1Reg);
               __erg=CodeM(POrder->Code,DReg,S1Reg,S2Reg);
              END
             break;
            case ModImm:
             if (Memo("MPY")) __erg=CodeM(POrder->Code-1,DReg,S1Reg,S2Reg);
             else __erg=CodeM(POrder->Code+3,DReg,S1Reg,S2Reg);
             break;
           END
         END
       END
    END
END

	static void DecodeMemO(Word Index)
BEGIN
   LongWord DReg,S1Reg;
   MemOrder *POrder=MemOrders+Index;
   Boolean OK,IsStore;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     IsStore=(*OpPart)=='S';
     if (IsStore)
      BEGIN
       strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]);
       strcpy(ArgStr[2],ArgStr[3]);
       ThisStore=True;
      END
     if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
      BEGIN
       if (IsStore) AddSrc(DReg);
       ThisAddr|=(DReg>15) ? 8 : 4;
       /* Zielregister 4 Takte verzoegert, nicht als Dest eintragen */
       OK=DecodeMem(ArgStr[1],&S1Reg,POrder->Scale);
       if (OK)
        if ((S1Reg & 8)==0) OK=ChkUnit((S1Reg >> 18) & 31,D1,D2);
        else OK=ChkUnit(0x1e,D1,D2);
       if (OK)
        BEGIN
         ThisInst=S1Reg+(DReg << 23)+(POrder->Code << 4)
                 +((DReg & 16) >> 3);
         __erg=True;
        END
      END;
    END
END

	static void DecodeSTP(Word Index)
BEGIN
   LongWord S2Reg;

   if (ArgCnt!=1) WrError(1110);
   else if (ChkUnit(0x10,S1,S2))
    BEGIN
     if (DecodeAdr(ArgStr[1],MModReg,False,&S2Reg))
      if ((ThisCross) OR (S2Reg<16)) WrError(1110);
      else
       BEGIN
        AddSrc(S2Reg);
        __erg=CodeS(0x0c,0,0,S2Reg);
       END
    END
END

	static void DecodeABS(Word Index)
BEGIN
   Boolean DPFlag,S1Flag;
   LongWord DReg,S1Reg;

   if (ArgCnt!=2) WrError(1110);
   else if (DecodeReg(ArgStr[2],&DReg,&DPFlag,True))
    if (ChkUnit(DReg,L1,L2))
     if (DecodeReg(ArgStr[1],&S1Reg,&S1Flag,True))
      if (DPFlag!=S1Flag) WrError(1350);
      else if ((ThisCross) AND ((S1Reg >> 4)==UnitFlag)) WrError(1350);
      else
       BEGIN
        SetCross(S1Reg);
        if (DPFlag) __erg=CodeL(0x38,DReg,0,S1Reg);
        else __erg=CodeL(0x1a,DReg,0,S1Reg);
        if (DPFlag) AddLSrc(S1Reg); else AddSrc(S1Reg);
        if (DPFlag) AddLDest(DReg); else AddDest(DReg);
       END
END

	static void DecodeADD(Word Index)
BEGIN
   LongWord S1Reg,S2Reg,DReg;
   Boolean OK;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
     UnitFlag=DReg >> 4;
     switch (AdrMode)
      BEGIN
       case ModLReg:      /* ADD ?,?,long */
        AddLDest(DReg);
        DecodeAdr(ArgStr[1],MModReg+MModLReg+MModImm,True,&S1Reg);
        switch (AdrMode)
         BEGIN
          case ModReg:    /* ADD int,?,long */
           AddSrc(S1Reg);
           DecodeAdr(ArgStr[2],MModReg+MModLReg,True,&S2Reg);
           switch (AdrMode)
            BEGIN
             case ModReg: /* ADD int,int,long */
              if (ChkUnit(DReg,L1,L2))
               if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
               else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
               else
                BEGIN
                 AddSrc(S2Reg);
                 if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
                 SetCross(S2Reg);
                 __erg=CodeL(0x23,DReg,S1Reg,S2Reg);
                END
              break;
             case ModLReg:/* ADD int,long,long */
              if (ChkUnit(DReg,L1,L2))
               if (IsCross(S2Reg)) WrError(1350);
               else if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
               else
                BEGIN
                 AddLSrc(S2Reg);
                 SetCross(S1Reg);
                 __erg=CodeL(0x21,DReg,S1Reg,S2Reg);
                END
              break;
            END
           break;
          case ModLReg:   /* ADD long,?,long */
           AddLSrc(S1Reg);
           DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
           switch (AdrMode)
            BEGIN
             case ModReg: /* ADD long,int,long */
              if (ChkUnit(DReg,L1,L2))
               if (IsCross(S1Reg)) WrError(1350);
               else if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
               else
                BEGIN
                 AddSrc(S2Reg);
                 SetCross(S2Reg);
                 __erg=CodeL(0x21,DReg,S2Reg,S1Reg);
                END
              break;
             case ModImm: /* ADD long,imm,long */
              if (ChkUnit(DReg,L1,L2))
               if (IsCross(S1Reg)) WrError(1350);
               else if (ThisCross) WrError(1350);
               else __erg=CodeL(0x20,DReg,S2Reg,S1Reg);
              break;
            END
           break;
          case ModImm:    /* ADD imm,?,long */
           if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
            BEGIN         /* ADD imm,long,long */
             if (ChkUnit(DReg,L1,L2))
              if (IsCross(S2Reg)) WrError(1350);
              else if (ThisCross) WrError(1350);
              else
               BEGIN
                AddLSrc(S2Reg);
                __erg=CodeL(0x20,DReg,S1Reg,S2Reg);
               END
            END
           break;
         END
        break;
       case ModReg:       /* ADD ?,?,int */
        AddDest(DReg);
        DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
        switch (AdrMode)
         BEGIN
          case ModReg:    /* ADD int,?,int */
           AddSrc(S1Reg);
           DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
           switch (AdrMode)
            BEGIN
             case ModReg: /* ADD int,int,int */
              AddSrc(S2Reg);
              if (((DReg^S1Reg)>15) AND ((DReg^S2Reg)>15)) WrError(1350);
              else if ((ThisCross) AND ((DReg^S1Reg)<16) AND ((DReg^S2Reg)<15)) WrError(1350);
              else
               BEGIN
                if ((S1Reg^DReg)>15) SwapReg(&S1Reg,&S2Reg);
                OK=DecideUnit(DReg,((S2Reg^DReg)>15) ? "LS" : "LSD");
                if (OK)
                 BEGIN
                  switch (ThisUnit)
                   BEGIN
                    case L1: case L2: __erg=CodeL(0x03,DReg,S1Reg,S2Reg); break; /* ADD.Lx int,int,int */
                    case S1: case S2: __erg=CodeS(0x07,DReg,S1Reg,S2Reg); break; /* ADD.Sx int,int,int */
                    case D1: case D2: __erg=CodeD(0x10,DReg,S1Reg,S2Reg); break; /* ADD.Dx int,int,int */
                    default: WrError(20000);
                   END
                 END
               END
              break;
             case ModImm: /* ADD int,imm,int */
              if ((ThisCross) AND ((S1Reg^DReg)<16)) WrError(1350);
              else
               BEGIN
                SetCross(S1Reg);
                if (DecideUnit(DReg,"LS"))
                 switch (ThisUnit)
                  BEGIN
                   case L1: case L2: __erg=CodeL(0x02,DReg,S2Reg,S1Reg); break;
                   case S1: case S2: __erg=CodeS(0x06,DReg,S2Reg,S1Reg); break;
                   default: WrError(20000);
                  END
               END
              break;
            END
           break;
          case ModImm:   /* ADD imm,?,int */
           if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
            BEGIN
             AddSrc(S2Reg);
             if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
             else
              BEGIN
               SetCross(S2Reg);
               if (DecideUnit(DReg,"LS"))
                switch (ThisUnit)
                 BEGIN
                  case L1: case L2: __erg=CodeL(0x02,DReg,S1Reg,S2Reg); break;
                  case S1: case S2: __erg=CodeS(0x06,DReg,S1Reg,S2Reg); break;
                  default: WrError(20000);
                 END
              END
            END
           break;
         END
        break;
      END
    END
END

	static void DecodeADDU(Word Index)
BEGIN
   LongWord DReg,S1Reg,S2Reg;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[3],MModReg+MModLReg,False,&DReg);
     switch (AdrMode)
      BEGIN
       case ModReg:      /* ADDU ?,?,int */
        if (ChkUnit(DReg,D1,D2))
         BEGIN
          AddDest(DReg);
          DecodeAdr(ArgStr[1],MModReg+MModImm,False,&S1Reg);
          switch (AdrMode)
           BEGIN
            case ModReg: /* ADDU int,?,int */
             if (IsCross(S1Reg)) WrError(1350);
             else
              BEGIN
               AddSrc(S1Reg);
               if (DecodeAdr(ArgStr[2],MModImm,False,&S2Reg))
                __erg=CodeD(0x12,DReg,S2Reg,S1Reg);
              END
             break;
            case ModImm: /* ADDU imm,?,int */
             if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
              if (IsCross(S2Reg)) WrError(1350);
              else
               BEGIN
                AddSrc(S2Reg);
                __erg=CodeD(0x12,DReg,S1Reg,S2Reg);
               END
             break;
           END
         END
        break;
       case ModLReg:     /* ADDU ?,?,long */
        if (ChkUnit(DReg,L1,L2))
         BEGIN
          AddLDest(DReg);
          DecodeAdr(ArgStr[1],MModReg+MModLReg,False,&S1Reg);
          switch (AdrMode)
           BEGIN
            case ModReg: /* ADDU int,?,long */
             AddSrc(S1Reg);
             DecodeAdr(ArgStr[2],MModReg+MModLReg,False,&S2Reg);
             switch (AdrMode)
              BEGIN
               case ModReg: /* ADDU int,int,long */
                if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
                else if ((ThisCross) AND (((S1Reg^DReg)<16) AND ((S2Reg^DReg)<16))) WrError(1350);
                else
                 BEGIN
                  if ((S1Reg^DReg)>15) SwapReg(&S1Reg,&S2Reg);
                  SetCross(S2Reg);
                  __erg=CodeL(0x2b,DReg,S1Reg,S2Reg);
                 END
                break;
               case ModLReg: /* ADDU int,long,long */
                if (IsCross(S2Reg)) WrError(1350);
                else if ((ThisCross) AND ((S1Reg^DReg)<16)) WrError(1350);
                else
                 BEGIN
                  AddLSrc(S2Reg);
                  SetCross(S1Reg);
                  __erg=CodeL(0x29,DReg,S1Reg,S2Reg);
                 END
                break;
              END
             break;
            case ModLReg:
             if (IsCross(S1Reg)) WrError(1350);
             else
              BEGIN
               AddLSrc(S1Reg);
               if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
                if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
                else
                 BEGIN
                  AddSrc(S2Reg); SetCross(S2Reg);
                  __erg=CodeL(0x29,DReg,S2Reg,S1Reg);
                 END
              END
             break;
           END
         END
        break;
      END
    END
END

	static void DecodeSUB(Word Index)
BEGIN
   LongWord DReg,S1Reg,S2Reg;
   Boolean OK;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
     switch (AdrMode)
      BEGIN
       case ModReg:
        AddDest(DReg);
        DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
        switch (AdrMode)
         BEGIN
          case ModReg:
           AddSrc(S1Reg);
           DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              if ((ThisCross) AND ((S1Reg^DReg)<16) AND ((S2Reg^DReg)<16)) WrError(1350);
              else if (((S1Reg^DReg)>15) AND ((S2Reg^DReg)>15)) WrError(1350);
              else
               BEGIN
                AddSrc(S2Reg);
                ThisCross=((S1Reg^DReg)>15) OR ((S2Reg^DReg)>15);
                if ((S1Reg^DReg)>15) OK=DecideUnit(DReg,"L");
                else if ((S2Reg^DReg)>15) OK=DecideUnit(DReg,"LS");
                else OK=DecideUnit(DReg,"LSD");
                if (OK)
                 switch (ThisUnit)
                  BEGIN
                   case L1: case L2:
                    if ((S1Reg^DReg)>15) __erg=CodeL(0x17,DReg,S1Reg,S2Reg);
                    else __erg=CodeL(0x07,DReg,S1Reg,S2Reg);
                    break;
                   case S1: case S2:
                    __erg=CodeS(0x17,DReg,S1Reg,S2Reg);
                    break;
                   case D1: case D2:
                    __erg=CodeD(0x11,DReg,S2Reg,S1Reg);
                    break;
                   default:
                    WrError(20000);
                  END
               END
              break;
             case ModImm:
              if (ChkUnit(DReg,D1,D2))
               if ((ThisCross) OR ((S1Reg^DReg)>15)) WrError(1350);
               else __erg=CodeD(0x13,DReg,S2Reg,S1Reg);
              break;
            END
           break;
          case ModImm:
           if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
            if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
            else
             BEGIN
              AddSrc(S2Reg);
              if (DecideUnit(DReg,"LS"))
               switch (ThisUnit)
                BEGIN
                 case L1: case L2: __erg=CodeL(0x06,DReg,S1Reg,S2Reg); break;
                 case S1: case S2: __erg=CodeS(0x16,DReg,S1Reg,S2Reg); break;
                 default: WrError(20000);
                END
             END
           break;
         END
        break;
       case ModLReg:
        AddLDest(DReg);
        if (ChkUnit(DReg,L1,L2))
         BEGIN
          DecodeAdr(ArgStr[1],MModImm+MModReg,True,&S1Reg);
          switch (AdrMode)
           BEGIN
            case ModImm:
             if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
              if ((ThisCross) OR (NOT IsCross(S2Reg))) WrError(1350);
              else
               BEGIN
                AddLSrc(S2Reg);
                __erg=CodeL(0x24,DReg,S1Reg,S2Reg);
               END
             break;
            case ModReg:
             AddSrc(S1Reg);
             if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
              if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
              else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
              else
               BEGIN
                AddSrc(S2Reg);
                ThisCross=(IsCross(S1Reg)) OR (IsCross(S2Reg));
                if (IsCross(S1Reg)) __erg=CodeL(0x37,DReg,S1Reg,S2Reg);
                else __erg=CodeL(0x47,DReg,S1Reg,S2Reg);
               END
             break;
           END
         END
        break;
      END
    END
END

	static void DecodeSUBU(Word Index)
BEGIN
   LongWord S1Reg,S2Reg,DReg;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     if ((DecodeAdr(ArgStr[3],MModLReg,False,&DReg)) AND (ChkUnit(DReg,L1,L2)))
      BEGIN
       AddLDest(DReg);
       if (DecodeAdr(ArgStr[1],MModReg,False,&S1Reg))
        BEGIN
         AddSrc(S1Reg);
         if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
          if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
          else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
          else
           BEGIN
            AddSrc(S2Reg);
            ThisCross=IsCross(S1Reg) OR IsCross(S2Reg);
            if (IsCross(S1Reg)) __erg=CodeL(0x3f,DReg,S1Reg,S2Reg);
            else __erg=CodeL(0x2f,DReg,S1Reg,S2Reg);
           END
        END
      END
    END
END

	static void DecodeSUBC(Word Index)
BEGIN
   LongWord DReg,S1Reg,S2Reg;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     if ((DecodeAdr(ArgStr[3],MModReg,False,&DReg)) AND (ChkUnit(DReg,L1,L2)))
      BEGIN
       AddLDest(DReg);
       if (DecodeAdr(ArgStr[1],MModReg,False,&S1Reg))
        BEGIN
         if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
          if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
          else if (IsCross(S1Reg)) WrError(1350);
          else
           BEGIN
            AddSrc(S2Reg); SetCross(S2Reg);
            __erg=CodeL(0x4b,DReg,S1Reg,S2Reg);
           END
        END
      END
    END
END

	static void DecodeLinAdd(Word Index)
BEGIN
   LongWord DReg,S1Reg,S2Reg;
   FixedOrder *POrder=LinAddOrders+Index;

   if (ArgCnt!=3) WrError(1110);
   else if (ThisCross) WrError(1350);
   else
    BEGIN
     if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
      if (ChkUnit(DReg,D1,D2))
       BEGIN
        AddDest(DReg);
        if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
         if (IsCross(S2Reg)) WrError(1350);
         else
          BEGIN
           AddSrc(S2Reg);
           DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              if (IsCross(S1Reg)) WrError(1350);
              else
               BEGIN
                AddSrc(S1Reg);
                __erg=CodeD(POrder->Code,DReg,S1Reg,S2Reg);
               END
              break;
             case ModImm:
              __erg=CodeD(POrder->Code+2,DReg,S1Reg,S2Reg);
              break;
            END
          END
       END
    END
END

	static void DecodeADDK(Word Index)
BEGIN
   LongInt Value;
   LongWord DReg;
   Boolean OK;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
      if (ChkUnit(DReg,S1,S2))
       BEGIN
        AddDest(DReg);
        Value=EvalIntExpression(ArgStr[1],SInt16,&OK);
        if (OK)
         BEGIN
          ThisInst=0x50+(UnitFlag << 1)+((Value & 0xffff) << 7)+(DReg << 23);
          __erg=True;
         END
       END
    END
END

	static void DecodeADD2_SUB2(Word Index)
BEGIN
   LongWord DReg,S1Reg,S2Reg;
   Boolean OK;

   Index=(Index<<5)+1;
   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
      if (ChkUnit(DReg,S1,S2))
       BEGIN
        AddDest(DReg);
        if (DecodeAdr(ArgStr[1],MModReg,True,&S1Reg))
         BEGIN
          AddSrc(S1Reg);
          if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
           if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
           else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
           else
            BEGIN
             OK=True; AddSrc(S2Reg);
             if (IsCross(S1Reg))
              if (Index>1)
               BEGIN
                WrError(1350); OK=False;
               END
              else SwapReg(&S1Reg,&S2Reg);
             if (OK)
              BEGIN
               SetCross(S2Reg);
               __erg=CodeS(Index,DReg,S1Reg,S2Reg);
              END
            END
         END
       END
    END
END

	static void DecodeLogic(Word Index)
BEGIN
   LongWord S1Reg,S2Reg,DReg;
   LongWord Code1,Code2;
   Boolean OK,WithImm;

   Code1=Lo(Index); Code2=Hi(Index);

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
      BEGIN
       AddDest(DReg);
       DecodeAdr(ArgStr[1],MModImm+MModReg,True,&S1Reg); WithImm=False;
       switch (AdrMode)
        BEGIN
         case ModImm:
          OK=DecodeAdr(ArgStr[2],MModReg,True,&S2Reg);
          if (OK) AddSrc(S2Reg);
          WithImm=True;
          break;
         case ModReg:
          AddSrc(S1Reg);
          OK=DecodeAdr(ArgStr[2],MModImm+MModReg,True,&S2Reg);
          switch (AdrMode)
           BEGIN
            case ModImm:
             SwapReg(&S1Reg,&S2Reg); WithImm=True;
             break;
            case ModReg:
             AddSrc(S2Reg); WithImm=False;
             break;
            default:
             OK=False;
           END
          break;
         default:
          OK=False;
        END
       if (OK)
        if (DecideUnit(DReg,"LS"))
         if ((NOT WithImm) AND (IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
         else if ((ThisCross) AND (NOT IsCross(S2Reg)) AND ((WithImm) OR (NOT IsCross(S1Reg)))) WrError(1350);
         else
          BEGIN
           if ((NOT WithImm) AND (IsCross(S1Reg))) SwapReg(&S1Reg,&S2Reg);
           SetCross(S2Reg);
           switch (ThisUnit)
            BEGIN
             case L1: case L2:
              __erg=CodeL(Code1-Ord(WithImm),DReg,S1Reg,S2Reg); break;
             case S1: case S2:
              __erg=CodeS(Code1-Ord(WithImm),DReg,S1Reg,S2Reg); break;
             default:
              WrError(20000);
            END
          END
      END
    END
END

	static Boolean DecodeInst(void)
BEGIN
   Boolean OK,erg;
   LongInt Dist;
   int z;
   LongWord DReg,S1Reg,S2Reg,HReg;
   LongWord Code1;
   Boolean WithImm,HasSign;

   erg=__erg=False;

   /* ueber Tabelle: */

   if (LookupInstTable(InstTable,OpPart)) return __erg;

   /* jetzt geht's los... */

   if ((Memo("CLR") OR (Memo("EXT")) OR (Memo("EXTU")) OR (Memo("SET"))))
    BEGIN
     if ((ArgCnt!=3) AND (ArgCnt!=4)) WrError(1110);
     else
      BEGIN
       if (DecodeAdr(ArgStr[ArgCnt],MModReg,Memo("EXT"),&DReg))
        if (ChkUnit(DReg,S1,S2))
         BEGIN
          AddDest(DReg);
          if (DecodeAdr(ArgStr[1],MModReg,Memo("EXT"),&S2Reg))
           BEGIN
            AddSrc(S2Reg);
            if (ArgCnt==3)
             BEGIN
              if (DecodeAdr(ArgStr[2],MModReg,False,&S1Reg))
               if (IsCross(S1Reg)) WrError(1350);
               else if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
               else
                BEGIN
                 SetCross(S2Reg);
                 if (Memo("CLR")) erg=CodeS(0x3f,DReg,S1Reg,S2Reg);
                 else if (Memo("EXTU")) erg=CodeS(0x2b,DReg,S1Reg,S2Reg);
                 else if (Memo("SET")) erg=CodeS(0x3b,DReg,S1Reg,S2Reg);
                 else erg=CodeS(0x2f,DReg,S1Reg,S2Reg);
                END
             END
            else if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
            else
             BEGIN
              S1Reg=EvalIntExpression(ArgStr[2],UInt5,&OK);
              if (OK)
               BEGIN
                HReg=EvalIntExpression(ArgStr[3],UInt5,&OK);
                if (OK)
                 BEGIN
                  ThisInst=(DReg << 23)+(S2Reg << 18)+(S1Reg << 13)+
                           (HReg << 8)+(UnitFlag << 1);
                  if (Memo("CLR")) ThisInst+=0xc8;
                  else if (Memo("SET")) ThisInst+=0x88;
		  else if (Memo("EXT")) ThisInst+=0x48;
                  else ThisInst+=0x08;
                  erg=True;
                 END
               END
             END
           END
         END
      END
     return erg;
    END

   for (z=0; z<CmpCnt; z++)
    if (Memo(CmpOrders[z].Name))
     BEGIN
      WithImm=OpPart[strlen(OpPart)-1]!='U';
      if (ArgCnt!=3) WrError(1110);
      else
       BEGIN
        if (DecodeAdr(ArgStr[3],MModReg,False,&DReg))
         if (ChkUnit(DReg,L1,L2))
          BEGIN
           AddDest(DReg);
           DecodeAdr(ArgStr[1],MModReg+MModImm,WithImm,&S1Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              AddSrc(S1Reg);
              DecodeAdr(ArgStr[2],MModReg+MModLReg,WithImm,&S2Reg);
              switch (AdrMode)
               BEGIN
                case ModReg:
                 if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
                 else if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
                 else
                  BEGIN
                   AddSrc(S2Reg);
                   if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
                   SetCross(S2Reg);
                   erg=CodeL(CmpOrders[z].Code+3,DReg,S1Reg,S2Reg);
                  END
                 break;
                case ModLReg:
                 if (IsCross(S2Reg)) WrError(1350);
                 else if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
                 else
                  BEGIN
                   AddLSrc(S2Reg); SetCross(S1Reg);
                   erg=CodeL(CmpOrders[z].Code+1,DReg,S1Reg,S2Reg);
                  END
                 break;
               END
              break;
             case ModImm:
              DecodeAdr(ArgStr[2],MModReg+MModLReg,WithImm,&S2Reg);
              switch (AdrMode)
               BEGIN
                case ModReg:
                 if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
                 else
                  BEGIN
                   AddSrc(S2Reg); SetCross(S2Reg);
                   erg=CodeL(CmpOrders[z].Code+2,DReg,S1Reg,S2Reg);
                  END
                 break;
                case ModLReg:
                 if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
                 else
                  BEGIN
                   AddLSrc(S2Reg);
                   erg=CodeL(CmpOrders[z].Code,DReg,S1Reg,S2Reg);
                  END
                 break;
               END
              break;
            END
          END
       END
      return erg;
     END

   if (Memo("LMBD"))
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       if (DecodeAdr(ArgStr[3],MModReg,False,&DReg))
        if (ChkUnit(DReg,L1,L2))
         BEGIN
          AddDest(DReg);
          if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
           if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
           else
            BEGIN
             SetCross(S2Reg);
             if (DecodeAdr(ArgStr[1],MModImm+MModReg,False,&S1Reg))
              BEGIN
               if (AdrMode==ModReg) AddSrc(S1Reg);
               erg=CodeL(0x6a+Ord(AdrMode==ModImm),DReg,S1Reg,S2Reg);
              END
            END
         END
      END
     return erg;
    END

   if (Memo("NORM"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
        if (ChkUnit(DReg,L1,L2))
         BEGIN
          AddDest(DReg);
          DecodeAdr(ArgStr[1],MModReg+MModLReg,True,&S2Reg);
          switch (AdrMode)
           BEGIN
            case ModReg:
             if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
             else
              BEGIN
               SetCross(S2Reg); AddSrc(S2Reg);
               erg=CodeL(0x63,DReg,0,S2Reg);
              END
             break;
            case ModLReg:
             if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
             else
              BEGIN
               AddLSrc(S2Reg);
               erg=CodeL(0x60,DReg,0,S2Reg);
              END
             break;
           END
         END
      END
     return erg;
    END

   if (Memo("SADD"))
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       if ((DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg)) AND (ChkUnit(DReg,L1,L2)))
        switch (AdrMode)
         BEGIN
          case ModReg:
           AddDest(DReg);
           DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              AddSrc(S1Reg);
              DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
              switch (AdrMode)
               BEGIN
                case ModReg:
                 if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
                 else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
                 else
                  BEGIN
                   AddSrc(S2Reg);
                   if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
                   SetCross(S2Reg);
                   erg=CodeL(0x13,DReg,S1Reg,S2Reg);
                  END
                 break;
                case ModImm:
                 if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
                 else
                  BEGIN
                   SetCross(S1Reg);
                   erg=CodeL(0x12,DReg,S2Reg,S1Reg);
                  END
                 break;
               END
              break;
             case ModImm:
              if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
               if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
               else
                BEGIN
                 SetCross(S2Reg);
                 erg=CodeL(0x12,DReg,S1Reg,S2Reg);
                END
              break;
            END
           break;
          case ModLReg:
           AddLDest(DReg);
           DecodeAdr(ArgStr[1],MModReg+MModLReg+MModImm,True,&S1Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              AddSrc(S1Reg);
              if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
               if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
               else
                BEGIN
                 AddLSrc(S2Reg); SetCross(S1Reg);
                 erg=CodeL(0x31,DReg,S1Reg,S2Reg);
                END
              break;
             case ModLReg:
              if (IsCross(S1Reg)) WrError(1350);
              else
               BEGIN
                AddLSrc(S1Reg);
                DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
                switch (AdrMode)
                 BEGIN
                  case ModReg:
                   if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
                   else
                    BEGIN
                     AddSrc(S2Reg); SetCross(S2Reg);
                     erg=CodeL(0x31,DReg,S2Reg,S1Reg);
                    END
                   break;
                  case ModImm:
                   erg=CodeL(0x30,DReg,S2Reg,S1Reg);
                   break;
                 END
               END
              break;
             case ModImm:
              if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
               if (IsCross(S2Reg)) WrError(1350);
               else
                BEGIN
                 AddLSrc(S2Reg);
                 erg=CodeL(0x30,DReg,S1Reg,S2Reg);
                END
              break;
            END
           break;
         END
      END
     return erg;
    END

   if (Memo("SAT"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (DecodeAdr(ArgStr[2],MModReg,True,&DReg))
        if (ChkUnit(DReg,L1,L2))
         BEGIN
          AddDest(DReg);
          if (DecodeAdr(ArgStr[1],MModLReg,True,&S2Reg))
           if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
           else
            BEGIN
             AddLSrc(S2Reg); erg=CodeL(0x40,DReg,0,S2Reg);
            END
         END
      END
     return erg;
    END

   if (Memo("MVC"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if ((ThisUnit!=NoUnit) AND (ThisUnit!=S2)) WrError(1350);
     else
      BEGIN
       z=0; ThisUnit=S2; UnitFlag=1;
       if (DecodeCtrlReg(ArgStr[1],&S2Reg,False)) z=2;
       else if (DecodeCtrlReg(ArgStr[2],&DReg,True)) z=1;
       else WrXError(1440,ArgStr[1]);
       if (z>0)
        BEGIN
         if (DecodeAdr(ArgStr[z],MModReg,False,&S1Reg))
          if ((ThisCross) AND ((z==2) OR (IsCross(S1Reg)))) WrError(1350);
          else
           BEGIN
            if (z==1)
             BEGIN
              S2Reg=S1Reg;
	      AddSrc(S2Reg); SetCross(S2Reg);
             END
            else
             BEGIN
              DReg=S1Reg; AddDest(DReg);
             END
            erg=CodeS(0x0d+z,DReg,0,S2Reg);
           END
        END
      END
     return erg;
    END

   if ((Memo("MVK")) OR (Memo("MVKH")) OR (Memo("MVKLH")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (DecodeAdr(ArgStr[2],MModReg,True,&DReg))
        if (ChkUnit(DReg,S1,S2))
         BEGIN
          S1Reg=EvalIntExpression(ArgStr[1],Memo("MVKLH")?Int16:Int32,&OK);
          if (OK)
           BEGIN
            AddDest(DReg);
            if (Memo("MVKH")) S1Reg=S1Reg >> 16;
            ThisInst=(DReg << 23)+((S1Reg & 0xffff) << 7)+(UnitFlag << 1);
            ThisInst+=Memo("MVK") ? 0x28 : 0x68;
            erg=True;
           END
         END
      END
     return True;
    END

   if (Memo("SHL"))
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
       if ((AdrMode!=ModNone) AND (ChkUnit(DReg,S1,S2)))
        switch (AdrMode)
         BEGIN
          case ModReg:
           AddDest(DReg);
           if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
            if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
            else
             BEGIN
              AddSrc(S2Reg);
              SetCross(S2Reg);
              DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
              switch (AdrMode)
               BEGIN
                case ModReg:
                 if (IsCross(S1Reg)) WrError(1350);
                 else
                  BEGIN
                   AddSrc(S1Reg);
                   erg=CodeS(0x33,DReg,S1Reg,S2Reg);
                  END
                 break;
                case ModImm:
                 erg=CodeS(0x32,DReg,S1Reg,S2Reg);
                 break;
               END
             END
           break;
          case ModLReg:
           AddLDest(DReg);
           DecodeAdr(ArgStr[1],MModReg+MModLReg,True,&S2Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
              else
               BEGIN
                AddSrc(S2Reg); SetCross(S2Reg);
                DecodeAdr(ArgStr[2],MModImm+MModReg,False,&S1Reg);
                switch (AdrMode)
                 BEGIN
                  case ModReg:
                   if (IsCross(S1Reg)) WrError(1350);
                   else
                    BEGIN
                     AddSrc(S1Reg);
                     erg=CodeS(0x13,DReg,S1Reg,S2Reg);
                    END
                   break;
                  case ModImm:
                   erg=CodeS(0x12,DReg,S1Reg,S2Reg);
                   break;
                 END
               END
              break;
             case ModLReg:
              if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
              else
               BEGIN
                AddLSrc(S2Reg);
                DecodeAdr(ArgStr[2],MModImm+MModReg,False,&S1Reg);
                switch (AdrMode)
                 BEGIN
                  case ModReg:
                   if (IsCross(S1Reg)) WrError(1350);
                   else
                    BEGIN
                     AddSrc(S1Reg);
                     erg=CodeS(0x31,DReg,S1Reg,S2Reg);
                    END
                   break;
                  case ModImm:
                   erg=CodeS(0x30,DReg,S1Reg,S2Reg);
                   break;
                 END
               END
              break;
            END
           break;
         END
      END
     return erg;
    END

   if ((Memo("SHR")) OR (Memo("SHRU")))
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       HasSign=Memo("SHR"); z=Ord(HasSign) << 4;
       DecodeAdr(ArgStr[3],MModReg+MModLReg,HasSign,&DReg);
       if ((AdrMode!=ModNone) AND (ChkUnit(DReg,S1,S2)))
        switch (AdrMode)
         BEGIN
          case ModReg:
           AddDest(DReg);
           if (DecodeAdr(ArgStr[1],MModReg,HasSign,&S2Reg))
            if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
            else
             BEGIN
              AddSrc(S2Reg); SetCross(S2Reg);
              DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
              switch (AdrMode)
               BEGIN
                case ModReg:
                 if (IsCross(S1Reg)) WrError(1350);
                 else
                  BEGIN
                   AddSrc(S1Reg);
                   erg=CodeS(0x27+z,DReg,S1Reg,S2Reg);
                  END
                 break;
                case ModImm:
                 erg=CodeS(0x26+z,DReg,S1Reg,S2Reg);
                 break;
               END
             END
           break;
          case ModLReg:
           AddLDest(DReg);
           if (DecodeAdr(ArgStr[1],MModLReg,HasSign,&S2Reg))
            if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
            else
             BEGIN
              AddLSrc(S2Reg);
              DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
              switch (AdrMode)
               BEGIN
                case ModReg:
                 if (IsCross(S1Reg)) WrError(1350);
                 else
                  BEGIN
                   AddSrc(S1Reg);
                   erg=CodeS(0x25+z,DReg,S1Reg,S2Reg);
                  END
                 break;
                case ModImm:
                 erg=CodeS(0x24+z,DReg,S1Reg,S2Reg);
                 break;
               END
             END
           break;
         END
      END
     return erg;
    END

   if (Memo("SSHL"))
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
        if (ChkUnit(DReg,S1,S2))
         BEGIN
          AddDest(DReg);
          if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
           if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
           else
            BEGIN
             AddSrc(S2Reg); SetCross(S2Reg);
             DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
             switch (AdrMode)
              BEGIN
               case ModReg:
                if (IsCross(S1Reg)) WrError(1350);
                else
                 BEGIN
                  AddSrc(S1Reg);
                  erg=CodeS(0x23,DReg,S1Reg,S2Reg);
                 END
                break;
               case ModImm:
                erg=CodeS(0x22,DReg,S1Reg,S2Reg);
                break;
              END
            END
         END
      END
     return erg;
    END

   if (Memo("SSUB"))
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
       if ((AdrMode!=ModNone) AND (ChkUnit(DReg,L1,L2)))
        switch (AdrMode)
         BEGIN
          case ModReg:
           AddDest(DReg);
           DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
           switch (AdrMode)
            BEGIN
             case ModReg:
              AddSrc(S1Reg);
              if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
              if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
              else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
              else if (IsCross(S1Reg))
	       BEGIN
                ThisCross=True;
	        erg=CodeL(0x1f,DReg,S1Reg,S2Reg);
	       END
              else
               BEGIN
                SetCross(S2Reg);
	        erg=CodeL(0x0f,DReg,S1Reg,S2Reg);
               END
              break;
             case ModImm:
              if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
               if ((ThisCross) AND (NOT IsCross(S2Reg)<16)) WrError(1350);
               else
                BEGIN
                 AddSrc(S2Reg); SetCross(S2Reg);
	         erg=CodeL(0x0e,DReg,S1Reg,S2Reg);
                END
              break;
            END
           break;
          case ModLReg:
           AddLDest(DReg);
           if (DecodeAdr(ArgStr[1],MModImm,True,&S1Reg))
            BEGIN
             if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
              if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
              else
               BEGIN
                AddLSrc(S2Reg);
                erg=CodeL(0x2c,DReg,S1Reg,S2Reg);
               END
            END
           break;
         END
      END;
     return erg;
    END

   /* Spruenge */

   /* Wie zum Henker unterscheiden sich B IRP und B NRP ???
      Kann TI keine ordentlichen Handbuecher mehr schreiben ? */

   if (Memo("B"))  
    BEGIN
     if (ArgCnt!=1) WrError(1350);
     else if (ThisCross) WrError(1350);
     else if ((ThisUnit!=NoUnit) AND (ThisUnit!=S1) AND (ThisUnit!=S2)) WrError(1350);
     else
      BEGIN
       OK=True; S2Reg=0; WithImm=False; Code1=0;
       if (strcasecmp(ArgStr[1],"IRP")==0) Code1=0x03;
       else if (strcasecmp(ArgStr[1],"NRP")==0) Code1=0x03; /* !!! */
       else if (DecodeReg(ArgStr[1],&S2Reg,&OK,False))
        BEGIN
         if (OK) WrError(1350); OK=NOT OK;
         Code1=0x0d;
        END
       else WithImm=True;
       if (OK)
        if (WithImm)
         BEGIN
          if (ThisUnit==NoUnit)
           ThisUnit=(UnitUsed(S1)) ? S2 : S1;
          UnitFlag=Ord(ThisUnit==S2);
          Dist=EvalIntExpression(ArgStr[1],Int32,&OK)-PacketAddr;
          if (OK)
           if ((Dist & 3)!=0) WrError(1325);
           else if ((NOT SymbolQuestionable) AND ((Dist>0x3fffff) OR (Dist<-0x400000))) WrError(1370);
           else
            BEGIN
             ThisInst=0x50+((Dist & 0x007ffffc) << 5)+(UnitFlag << 1);
             erg=True;
            END
         END
        else
         BEGIN
          if (ChkUnit(0x10,S1,S2)) erg=CodeS(Code1,0,0,S2Reg);
         END
      END
     return erg;
    END

   WrXError(1200,OpPart);

   return erg;
END

	static void ChkPacket(void)
BEGIN
   LongWord EndAddr,Mask;
   LongInt z,z1,z2;
   Integer RegReads[32];
   char TestUnit[4];

   /* nicht ueber 8er-Grenze */

   EndAddr=PacketAddr+((ParCnt << 2)-1);
   if ((PacketAddr >> 5)!=(EndAddr >> 5)) WrError(2000);

   /* doppelte Units,Crosspaths,Adressierer,Zielregister */

   for (z1=0; z1<ParCnt; z1++)
    for (z2=z1+1; z2<ParCnt; z2++)
     if ((ParRecs[z1].OpCode >> 28)==(ParRecs[z2].OpCode >> 28))
      BEGIN
       /* doppelte Units */
       if ((ParRecs[z1].U!=NoUnit) AND (ParRecs[z1].U==ParRecs[z2].U))
        WrXError(2001,UnitNames[ParRecs[z1].U]);

       /* Crosspaths */
       z=ParRecs[z1].CrossUsed & ParRecs[z2].CrossUsed;
       if (z!=0)
        BEGIN
         *TestUnit=z+'0'; TestUnit[1]='X'; TestUnit[2]='\0';
         WrXError(2001,TestUnit);
        END

       z=ParRecs[z1].AddrUsed & ParRecs[z2].AddrUsed;
       /* Adressgeneratoren */
       if ((z & 1)==1) WrXError(2001,"Addr. A");
       if ((z & 2)==2) WrXError(2001,"Addr. B");
       /* Hauptspeicherpfade */
       if ((z & 4)==4) WrXError(2001,"LdSt. A");
       if ((z & 8)==8) WrXError(2001,"LdSt. B");

       /* ueberlappende Zielregister */
       z=ParRecs[z1].DestMask & ParRecs[z2].DestMask;
       if (z!=0) WrXError(2006,RegName(FindReg(z)));

       if ((ParRecs[z1].U & 1)==(ParRecs[z2].U & 1))
        BEGIN
         TestUnit[0]=ParRecs[z1].U-NoUnit-1+'A';
         TestUnit[1]='\0';

         /* mehrere Long-Reads */
         if ((ParRecs[z1].LongSrc) AND (ParRecs[z2].LongSrc))
          WrXError(2002,TestUnit);

         /* mehrere Long-Writes */
         if ((ParRecs[z1].LongDest) AND (ParRecs[z2].LongDest))
          WrXError(2003,TestUnit);

         /* Long-Read mit Store */
         if ((ParRecs[z1].StoreUsed) AND (ParRecs[z2].LongSrc))
          WrXError(2004,TestUnit);
         if ((ParRecs[z2].StoreUsed) AND (ParRecs[z1].LongSrc))
          WrXError(2004,TestUnit);
        END
      END

   for (z2=0; z2<32; RegReads[z2++]=0);
   for (z1=0; z1<ParCnt; z1++)
    BEGIN
     Mask=1;
     for (z2=0; z2<32; z2++)
      BEGIN
       if ((ParRecs[z1].SrcMask & Mask)!=0) RegReads[z2]++;
       if ((ParRecs[z1].SrcMask2 & Mask)!=0) RegReads[z2]++;
       Mask=Mask << 1;
      END
    END

   /* Register mehr als 4mal gelesen */

   for (z1=0; z1<32; z1++)
    if (RegReads[z1]>4) WrXError(2005,RegName(z1));
END

	static void MakeCode_3206X(void)
BEGIN
   CodeLen=0; DontPrint=False;

   /* zu ignorierendes */

   if ((*OpPart=='\0') AND (*LabPart=='\0')) return;

   /* Pseudoanweisungen */

   if (DecodePseudo()) return;

   /* Flags zuruecksetzen */

   ThisPar=False; Condition=0;

   /* Optionen aus Label holen */

   if (*LabPart!='\0')
    if ((strcmp(LabPart,"||")==0) OR (*LabPart=='['))
     if (NOT CheckOpt(LabPart)) return;

   /* eventuell falsche Mnemonics verwerten */

   if (strcmp(OpPart,"||")==0)
    if (NOT ReiterateOpPart()) return;
   if (*OpPart=='[')
    if (NOT ReiterateOpPart()) return;

   if (Memo("")) return;

   /* Attribut auswerten */

   ThisUnit=NoUnit; ThisCross=False;
   if (*AttrPart!='\0')
    BEGIN
     if (toupper(AttrPart[strlen(AttrPart)-1])=='X')
      BEGIN
       ThisCross=True;
       AttrPart[strlen(AttrPart)-1]='\0';
      END
     if (*AttrPart=='\0') ThisUnit=NoUnit;
     else 
      for (; ThisUnit!=LastUnit; ThisUnit++)
       if (strcasecmp(AttrPart,UnitNames[ThisUnit])==0) break;
     if (ThisUnit==LastUnit)
      BEGIN
       WrError(1107); return;
      END
     if (((ThisUnit==D1) OR (ThisUnit==D2)) AND (ThisCross))
      BEGIN
       WrError(1350); return;
      END
    END

   /* falls nicht parallel, vorherigen Stack durchpruefen und verwerfen */

   if ((NOT ThisPar) AND (ParCnt>0))
    BEGIN
     ChkPacket();
     ParCnt=0; PacketAddr=EProgCounter();
    END

   /* dekodieren */

   ThisSrc=0; ThisSrc2=0; ThisDest=0;
   ThisAddr=0; ThisStore=False; ThisLong=0;
   if (NOT DecodeInst()) return;

   /* einsortieren */

   ParRecs[ParCnt].OpCode=(Condition << 28)+ThisInst;
   ParRecs[ParCnt].U=ThisUnit;
   if (ThisCross)
    switch (ThisUnit)
     BEGIN
      case L1: case S1: case M1: case D1: ParRecs[ParCnt].CrossUsed=1; break;
      default: ParRecs[ParCnt].CrossUsed=2;
     END
   else ParRecs[ParCnt].CrossUsed=0;
   ParRecs[ParCnt].AddrUsed=ThisAddr;
   ParRecs[ParCnt].SrcMask=ThisSrc;
   ParRecs[ParCnt].SrcMask2=ThisSrc2;
   ParRecs[ParCnt].DestMask=ThisDest;
   ParRecs[ParCnt].LongSrc=(ThisLong & 1)==1;
   ParRecs[ParCnt].LongDest=(ThisLong & 2)==2;
   ParRecs[ParCnt].StoreUsed=ThisStore;
   ParCnt++;

   /* wenn mehr als eine Instruktion, Ressourcenkonflikte abklopfen und
     vorherige Instruktion zuruecknehmen */

   if (ParCnt>1)
    BEGIN
     RetractWords(4);
     DAsmCode[CodeLen >> 2]=ParRecs[ParCnt-2].OpCode | 1;
     CodeLen+=4;
    END

   /* aktuelle Instruktion auswerfen: fuer letzte kein Parallelflag setzen */

   DAsmCode[CodeLen >> 2]=ParRecs[ParCnt-1].OpCode;
   CodeLen+=4;
END

/*-------------------------------------------------------------------------*/

static int InstrZ;


   	static void AddLinAdd(char *NName, LongInt NCode)
BEGIN
   if (InstrZ>=LinAddCnt) exit(255);
   LinAddOrders[InstrZ].Name=NName;
   LinAddOrders[InstrZ].Code=NCode;
   AddInstTable(InstTable,NName,InstrZ++,DecodeLinAdd);
END

   	static void AddCmp(char *NName, LongInt NCode)
BEGIN
   if (InstrZ>=CmpCnt) exit(255);
   CmpOrders[InstrZ].Name=NName;
   CmpOrders[InstrZ++].Code=NCode;
END

   	static void AddMem(char *NName, LongInt NCode, LongInt NScale)
BEGIN
   if (InstrZ>=MemCnt) exit(255);
   MemOrders[InstrZ].Name=NName;
   MemOrders[InstrZ].Code=NCode;
   MemOrders[InstrZ].Scale=NScale;
   AddInstTable(InstTable,NName,InstrZ++,DecodeMemO);
END

   	static void AddMul(char *NName, LongInt NCode,
	                   Boolean NDSign,Boolean NSSign1,Boolean NSSign2, Boolean NMay)
BEGIN
   if (InstrZ>=MulCnt) exit(255);
   MulOrders[InstrZ].Name=NName;
   MulOrders[InstrZ].Code=NCode;
   MulOrders[InstrZ].DSign=NDSign;
   MulOrders[InstrZ].SSign1=NSSign1;
   MulOrders[InstrZ].SSign2=NSSign2;
   MulOrders[InstrZ].MayImm=NMay;
   AddInstTable(InstTable,NName,InstrZ++,DecodeMul);
END

   	static void AddCtrl(char *NName, LongInt NCode,
	                    Boolean NWr, Boolean NRd)
BEGIN
   if (InstrZ>=CtrlCnt) exit(255);
   CtrlRegs[InstrZ].Name=NName;
   CtrlRegs[InstrZ].Code=NCode;
   CtrlRegs[InstrZ].Wr=NWr;
   CtrlRegs[InstrZ++].Rd=NRd;
END

	static void InitFields(void)
BEGIN
   InstTable=CreateInstTable(203);

   AddInstTable(InstTable,"IDLE",0,DecodeIDLE);
   AddInstTable(InstTable,"NOP",0,DecodeNOP);
   AddInstTable(InstTable,"STP",0,DecodeSTP);
   AddInstTable(InstTable,"ABS",0,DecodeABS);
   AddInstTable(InstTable,"ADD",0,DecodeADD);
   AddInstTable(InstTable,"ADDU",0,DecodeADDU);
   AddInstTable(InstTable,"SUB",0,DecodeSUB);
   AddInstTable(InstTable,"SUBU",0,DecodeSUBU);
   AddInstTable(InstTable,"SUBC",0,DecodeSUBC);
   AddInstTable(InstTable,"ADDK",0,DecodeADDK);
   AddInstTable(InstTable,"ADD2",0,DecodeADD2_SUB2);
   AddInstTable(InstTable,"SUB2",1,DecodeADD2_SUB2);
   AddInstTable(InstTable,"AND",0x1f79,DecodeLogic);
   AddInstTable(InstTable,"OR",0x1b7f,DecodeLogic);
   AddInstTable(InstTable,"XOR",0x0b6f,DecodeLogic);

   LinAddOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LinAddCnt); InstrZ=0;
   AddLinAdd("ADDAB",0x30); AddLinAdd("ADDAH",0x34); AddLinAdd("ADDAW",0x38);
   AddLinAdd("SUBAB",0x31); AddLinAdd("SUBAH",0x35); AddLinAdd("SUBAW",0x39);

   CmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*CmpCnt); InstrZ=0;
   AddCmp("CMPEQ",0x50); AddCmp("CMPGT",0x44); AddCmp("CMPGTU",0x4c);
   AddCmp("CMPLT",0x54); AddCmp("CMPLTU",0x5c);

   MemOrders=(MemOrder *) malloc(sizeof(MemOrder)*MemCnt); InstrZ=0;
   AddMem("LDB",2,1);  AddMem("LDH",4,2);  AddMem("LDW",6,4);
   AddMem("LDBU",1,1); AddMem("LDHU",0,2); AddMem("STB",3,1);
   AddMem("STH",5,2);  AddMem("STW",7,4);

   MulOrders=(MulOrder *) malloc(sizeof(MulOrder)*MulCnt); InstrZ=0;
   AddMul("MPY"    ,0x19,True ,True ,True ,True );
   AddMul("MPYU"   ,0x1f,False,False,False,False);
   AddMul("MPYUS"  ,0x1d,True ,False,True ,False);
   AddMul("MPYSU"  ,0x1b,True ,True ,False,True );
   AddMul("MPYH"   ,0x01,True ,True ,True ,False);
   AddMul("MPYHU"  ,0x07,False,False,False,False);
   AddMul("MPYHUS" ,0x05,True ,False,True ,False);
   AddMul("MPYHSU" ,0x03,True ,True ,False,False);
   AddMul("MPYHL"  ,0x09,True ,True ,True ,False);
   AddMul("MPYHLU" ,0x0f,False,False,False,False);
   AddMul("MPYHULS",0x0d,True ,False,True ,False);
   AddMul("MPYHSLU",0x0b,True ,True ,False,False);
   AddMul("MPYLH"  ,0x11,True ,True ,True ,False);
   AddMul("MPYLHU" ,0x17,False,False,False,False);
   AddMul("MPYLUHS",0x15,True ,False,True ,False);
   AddMul("MPYLSHU",0x13,True ,True ,False,False);
   AddMul("SMPY"   ,0x1a,True ,True ,True ,False);
   AddMul("SMPYHL" ,0x0a,True ,True ,True ,False);
   AddMul("SMPYLH" ,0x12,True ,True ,True ,False);
   AddMul("SMPYH"  ,0x02,True ,True ,True ,False);

   CtrlRegs=(CtrlReg *) malloc(sizeof(CtrlReg)*CtrlCnt); InstrZ=0;
   AddCtrl("AMR"    , 0,True ,True );
   AddCtrl("CSR"    , 1,True ,True );
   AddCtrl("IFR"    , 2,False,True );
   AddCtrl("ISR"    , 2,True ,False);
   AddCtrl("ICR"    , 3,True ,False);
   AddCtrl("IER"    , 4,True ,True );
   AddCtrl("ISTP"   , 5,True ,True );
   AddCtrl("IRP"    , 6,True ,True );
   AddCtrl("NRP"    , 7,True ,True );
   AddCtrl("IN"     , 8,False,True );
   AddCtrl("OUT"    , 9,True ,True );
   AddCtrl("PCE1"   ,16,False,True );
   AddCtrl("PDATA_O",15,True ,True );
END

	static void DeinitFields(void)
BEGIN
   DestroyInstTable(InstTable);
   free(LinAddOrders);
   free(CmpOrders);
   free(MemOrders);
   free(MulOrders);
   free(CtrlRegs);
END

/*------------------------------------------------------------------------*/

	static Boolean IsDef_3206X(void)
BEGIN
   return (strcmp(LabPart,"||")==0) OR (*LabPart=='[');
END

        static void SwitchFrom_3206X(void)
BEGIN
   if (ParCnt>1) ChkPacket();
   DeinitFields();
END

	static void SwitchTo_3206X(void)
BEGIN
   TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;

   PCSymbol="$"; HeaderID=0x47; NOPCode=0x00000000;
   DivideChars=","; HasAttrs=True; AttrChars=".";
   SetIsOccupied=True;

   ValidSegs=1<<SegCode;
   Grans[SegCode]=1; ListGrans[SegCode]=4; SegInits[SegCode]=0;
#ifdef __STDC__
   SegLimits[SegCode] = 0xfffffffful;
#else
   SegLimits[SegCode] = 0xffffffffl;
#endif

   MakeCode=MakeCode_3206X; IsDef=IsDef_3206X;
   SwitchFrom=SwitchFrom_3206X; InitFields();

   ParCnt=0; PacketAddr=0;
END

	void code3206x_init(void)
BEGIN
   CPU32060=AddCPU("32060",SwitchTo_3206X);
END
