/* codexa.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* AS-Codegenerator Philips XA                                               */
/*                                                                           */
/* Historie: 25.10.1996 Grundsteinlegung                                     */
/*           19. 8.1998 autom. Verlaengerung Spruenge                        */
/*           23. 8.1998 Umbau auf Hash-Tabelle                               */
/*                      lange Spruenge fuer JBC                              */
/*           24. 8.1998 lange Spruenge fuer DJNZ CJNE                        */
/*           25. 8.1998 nach Hashing ueberfluessige Namensfelder entfernt    */
/*           14.10.1998 BRANCHEXT auch fuer BR-Befehle                       */
/*                      Padding-Byte auch fuer Sprung auf sich selber        */
/*                      Das $ zu verschieben ist aber noch etwas tricky...   */
/*            9. 1.1999 ChkPC jetzt mit Adresse als Parameter                */
/*           20. 1.1999 Formate maschinenunabhaengig gemacht                 */
/*                                                                           */
/*****************************************************************************/

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

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

/*-------------------------------------------------------------------------*/
/* Definitionen */

#define ModNone (-1)
#define ModReg 0
#define MModReg (1 << ModReg)
#define ModMem 1
#define MModMem (1 << ModMem)
#define ModImm 2
#define MModImm (1 << ModImm)
#define ModAbs 3
#define MModAbs (1 << ModAbs)

#define FixedOrderCnt 5
#define JBitOrderCnt 3
#define RegOrderCnt 4
#define RotateOrderCount 4
#define RelOrderCount 17
#define StackOrderCount 4

typedef struct
         {   
          Word Code;
         } FixedOrder;

typedef struct
         {   
          Byte SizeMask;
          Byte Code;
         } RegOrder;

typedef struct
         {
          char *Name;
          Byte SizeMask;
          Byte Code;
          Byte Inversion;
         } InvOrder;

static CPUVar CPUXAG1,CPUXAG2,CPUXAG3;

static FixedOrder *FixedOrders;
static InvOrder *JBitOrders;
static FixedOrder *StackOrders;
static RegOrder *RegOrders;
static FixedOrder *RotateOrders;
static InvOrder *RelOrders;

static PInstTable InstTable;

static LongInt Reg_DS;
static SimpProc SaveInitProc;

static ShortInt AdrMode;
static Byte AdrPart,MemPart;
static Byte AdrVals[4];
static ShortInt OpSize;

/*-------------------------------------------------------------------------*/
/* Hilfsroutinen */

	static void SetOpSize(ShortInt NSize)
BEGIN
   if (OpSize==-1) OpSize=NSize;
   else if (OpSize!=NSize)
    BEGIN
     AdrMode=ModNone; AdrCnt=0; WrError(1131);
    END
END

	static Boolean DecodeReg(char *Asc, ShortInt *NSize, Byte *Erg)
BEGIN
   if (strcasecmp(Asc,"SP")==0)
    BEGIN
     *Erg=7; *NSize=1; return True;
    END
   else if ((strlen(Asc)>=2) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='7'))
    if (strlen(Asc)==2)
     BEGIN
      *Erg=Asc[1]-'0';
      if (OpSize==2)
       BEGIN
        if ((*Erg&1)==1)
         BEGIN
          WrError(1760); (*Erg)--;
         END
        *NSize=2;
        return True;
       END
      else
       BEGIN
        *NSize=1;
        return True;
       END
     END
    else if ((strlen(Asc)==3) AND (toupper(Asc[2])=='L'))
     BEGIN
      *Erg=(Asc[1]-'0') << 1; *NSize=0; return True;
     END
    else if ((strlen(Asc)==3) AND (toupper(Asc[2])=='H'))
     BEGIN
      *Erg=((Asc[1]-'0') << 1)+1; *NSize=0; return True;
     END
    else return False;
   return False;
END

	static void ChkAdr(Word Mask)
BEGIN
   if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0))
    BEGIN
     WrError(1350); AdrMode=ModNone; AdrCnt=0;
    END
END

	static void DecodeAdr(char *Asc, Word Mask)
BEGIN
   ShortInt NSize;
   LongInt DispAcc,DispPart,AdrLong;
   Boolean FirstFlag,NegFlag,NextFlag,ErrFlag,OK;
   char *PPos,*MPos;
   Word AdrInt;
   Byte Reg;
   String Part;

   AdrMode=ModNone; AdrCnt=0; KillBlanks(Asc);

   if (DecodeReg(Asc,&NSize,&AdrPart))
    BEGIN
     if ((Mask & MModReg)!=0)
      BEGIN
       AdrMode=ModReg; SetOpSize(NSize);
      END
     else
      BEGIN
       AdrMode=ModMem; MemPart=1; SetOpSize(NSize);
      END
     ChkAdr(Mask); return;
    END

   if (*Asc=='#')
    BEGIN
     switch (OpSize)
      BEGIN
       case -4:
        AdrVals[0]=EvalIntExpression(Asc+1,UInt5,&OK);
        if (OK)
         BEGIN
          AdrCnt=1; AdrMode=ModImm;
         END
        break;
       case -3:
        AdrVals[0]=EvalIntExpression(Asc+1,SInt4,&OK);
        if (OK)
         BEGIN
          AdrCnt=1; AdrMode=ModImm;
         END
        break;
       case -2:
        AdrVals[0]=EvalIntExpression(Asc+1,UInt4,&OK);
        if (OK)
         BEGIN
          AdrCnt=1; AdrMode=ModImm;
         END
        break;
       case -1:
        WrError(1132);
        break;
       case 0:
        AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
        if (OK)
         BEGIN
          AdrCnt=1; AdrMode=ModImm;
         END
        break;
       case 1:
        AdrInt=EvalIntExpression(Asc+1,Int16,&OK);
        if (OK)
         BEGIN
          AdrVals[0]=Hi(AdrInt); AdrVals[1]=Lo(AdrInt);
          AdrCnt=2; AdrMode=ModImm;
         END
        break;
       case 2:
        AdrLong=EvalIntExpression(Asc+1,Int32,&OK);
        if (OK)
         BEGIN
          AdrVals[0]=(AdrLong >> 24) & 0xff;
          AdrVals[1]=(AdrLong >> 16) & 0xff;
          AdrVals[2]=(AdrLong >> 8) & 0xff;
          AdrVals[3]=AdrLong & 0xff;
          AdrCnt=4; AdrMode=ModImm;
         END
        break;
      END
     ChkAdr(Mask); return;
    END

   if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']'))
    BEGIN
     strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
     if (Asc[strlen(Asc)-1]=='+')
      BEGIN
       Asc[strlen(Asc)-1]='\0';
       if (NOT DecodeReg(Asc,&NSize,&AdrPart)) WrXError(1445,Asc);
       else if (NSize!=1) WrError(1350);
       else
        BEGIN
         AdrMode=ModMem; MemPart=3;
        END
      END
     else
      BEGIN
       FirstFlag=False; ErrFlag=False;
       DispAcc=0; AdrPart=0xff; NegFlag=False;
       while ((*Asc!='\0') AND (NOT ErrFlag))
        BEGIN
         PPos=QuotPos(Asc,'+'); MPos=QuotPos(Asc,'-');
         if (PPos==Nil) PPos=MPos;
         else if ((MPos!=Nil) AND (PPos>MPos)) PPos=MPos;
         NextFlag=((PPos!=Nil) AND (*PPos=='-'));
         if (PPos==Nil)
          BEGIN
           strmaxcpy(Part,Asc,255); *Asc='\0';
          END
         else
          BEGIN
           *PPos='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,PPos+1);
          END
         if (DecodeReg(Part,&NSize,&Reg))
          if ((NSize!=1) OR (AdrPart!=0xff) OR (NegFlag))
           BEGIN
            WrError(1350); ErrFlag=True;
           END
          else AdrPart=Reg;
         else
          BEGIN
           FirstPassUnknown=False;
           DispPart=EvalIntExpression(Part,Int32,&ErrFlag);
           ErrFlag=NOT ErrFlag;
           if (NOT ErrFlag)
            BEGIN
             FirstFlag=FirstFlag OR FirstPassUnknown;
             if (NegFlag) DispAcc-=DispPart;
             else DispAcc+=DispPart;
            END
          END
         NegFlag=NextFlag;
        END
       if (FirstFlag) DispAcc&=0x7fff;
       if (AdrPart==0xff) WrError(1350);
       else if (DispAcc==0)
        BEGIN
         AdrMode=ModMem; MemPart=2;
        END
       else if ((DispAcc>=-128) AND (DispAcc<127))
        BEGIN
         AdrMode=ModMem; MemPart=4;
         AdrVals[0]=DispAcc & 0xff; AdrCnt=1;
        END
       else if (ChkRange(DispAcc,-0x8000l,0x7fffl))
        BEGIN
         AdrMode=ModMem; MemPart=5;
         AdrVals[0]=(DispAcc >> 8) & 0xff;
         AdrVals[1]=DispAcc & 0xff;
         AdrCnt=2;
        END
      END
     ChkAdr(Mask); return;
    END

   FirstPassUnknown=False;
   AdrLong=EvalIntExpression(Asc,UInt24,&OK);
   if (OK)
    BEGIN
     if (FirstPassUnknown)
      BEGIN
       if ((Mask & MModAbs)==0) AdrLong&=0x3ff;
      END
     if ((AdrLong & 0xffff)>0x7ff) WrError(1925);
     else if ((AdrLong & 0xffff)<=0x3ff)
      BEGIN
       if ((AdrLong >> 16)!=Reg_DS) WrError(110);
       ChkSpace(SegData);
       AdrMode=ModMem; MemPart=6;
       AdrPart=Hi(AdrLong); AdrVals[0]=Lo(AdrLong);
       AdrCnt=1;
      END
     else if (AdrLong>0x7ff) WrError(1925);
     else
      BEGIN
       ChkSpace(SegIO);
       AdrMode=ModMem; MemPart=6;
       AdrPart=Hi(AdrLong); AdrVals[0]=Lo(AdrLong);
       AdrCnt=1;
      END
    END

   ChkAdr(Mask);
END

	static Boolean DecodeBitAddr(char *Asc, LongInt *Erg)
BEGIN
   char *p;
   Byte BPos,Reg;
   ShortInt Size,Res;
   LongInt AdrLong;
   Boolean OK;

   p=RQuotPos(Asc,'.'); Res=0;
   if (p==Nil)
    BEGIN
     FirstPassUnknown=False;
     AdrLong=EvalIntExpression(Asc,UInt24,&OK);
     if (FirstPassUnknown) AdrLong&=0x3ff;
     *Erg=AdrLong; Res=1;
    END
   else
    BEGIN
     FirstPassUnknown=False; *p='\0';
     BPos=EvalIntExpression(p+1,UInt4,&OK);
     if (FirstPassUnknown) BPos&=7;
     if (OK)
      BEGIN
       if (DecodeReg(Asc,&Size,&Reg))
        if ((Size==0) AND (BPos>7)) WrError(1320);
        else
         BEGIN
          if (Size==0) *Erg=(Reg << 3)+BPos;
          else *Erg=(Reg << 4)+BPos;
          Res=1;
         END
       else if (BPos>7) WrError(1320);
       else
        BEGIN
         FirstPassUnknown=False;
         AdrLong=EvalIntExpression(Asc,UInt24,&OK);
         if ((TypeFlag & (1 << SegIO))!=0)
          BEGIN
           ChkSpace(SegIO);
           if (FirstPassUnknown) AdrLong=(AdrLong & 0x3f) | 0x400;
           if (ChkRange(AdrLong,0x400,0x43f))
            BEGIN
             *Erg=0x200+((AdrLong & 0x3f) << 3)+BPos;
             Res=1;
            END
           else Res=(-1);
          END
         else
	  BEGIN
           ChkSpace(SegData);
	   if (FirstPassUnknown) AdrLong=(AdrLong & 0x00ff003f) | 0x20;
	   if (ChkRange(AdrLong & 0xff,0x20,0x3f))
            BEGIN
             *Erg=0x100+((AdrLong & 0x1f) << 3)+BPos+(AdrLong & 0xff0000);
             Res=1;
            END
           else Res=(-1);
          END
        END
      END
     *p='.';
    END
   if (Res==0) WrError(1350);
   return (Res==1);
END

	static void ChkBitPage(LongInt Adr)
BEGIN
   if ((Adr >> 16)!=Reg_DS) WrError(110);
END

/*-------------------------------------------------------------------------*/
/* Befehlsdekoder */

	static Boolean DecodePseudo(void)
BEGIN
#define ASSUMEXACount 1
static ASSUMERec ASSUMEXAs[ASSUMEXACount]=
             {{"DS", &Reg_DS, 0, 0xff, 0x100}};
   LongInt BAdr;

   if (Memo("PORT"))
    BEGIN
     CodeEquate(SegIO,0x400,0x7ff);
     return True;
    END

   if (Memo("BIT"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*AttrPart!='\0') WrError(1100);
     else if (DecodeBitAddr(ArgStr[1],&BAdr))
      BEGIN
       EnterIntSymbol(LabPart,BAdr,SegNone,False);
       switch ((BAdr & 0x3ff) >> 8)
        BEGIN
         case 0:
          sprintf(ListLine,"=R%d.%d", (int)((BAdr >> 4) & 15),
                  (int) (BAdr & 15));
          break;
         case 1:
          sprintf(ListLine,"=%x:%x.%d",(int)((BAdr >> 16) & 255),
                  (int)((BAdr & 0x1f8) >> 3), (int)(BAdr & 7));
          break;
         default:
          sprintf(ListLine, "=S:%x.%d", (int)(((BAdr >> 3) & 0x3f)+0x400),
                  (int)(BAdr & 7));
          break;
        END
      END
     return True;
    END

   if (Memo("ASSUME"))
    BEGIN
     CodeASSUME(ASSUMEXAs,ASSUMEXACount);
     return True;
    END

   return False;
END

	static void DecodeFixed(Word Index)
BEGIN
   FixedOrder *Op=FixedOrders+Index;

   if (ArgCnt!=0) WrError(1110);
   else
    BEGIN
     if (Hi(Op->Code)!=0) BAsmCode[CodeLen++]=Hi(Op->Code);
     BAsmCode[CodeLen++]=Lo(Op->Code);
     if ((Memo("RETI")) AND (NOT SupAllowed)) WrError(50);
    END
END

	static void DecodeStack(Word Index)
BEGIN
   FixedOrder *Op=StackOrders+Index;
   Byte HReg;
   Boolean OK;
   Word Mask;
   int i;

   if (ArgCnt<1) WrError(1110);
   else
    BEGIN
     HReg=0xff; OK=True; Mask=0;
     for (i=1; i<=ArgCnt; i++)
      if (OK)
       BEGIN
        DecodeAdr(ArgStr[i],MModMem);
        if (AdrMode==ModNone) OK=False;
        else switch (MemPart)
         BEGIN
          case 1:
           if (HReg==0)
            BEGIN
             WrError(1350); OK=False;
            END
           else
            BEGIN
             HReg=1; Mask|=(1 << AdrPart);
            END
           break;
          case 6:
           if (HReg!=0xff)
            BEGIN
             WrError(1350); OK=False;
            END
           else HReg=0;
           break;
          default:
           WrError(1350); OK=False;
         END
       END
     if (OK)
      if (OpSize==-1) WrError(1132);
      else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
      else if (HReg==0)
       BEGIN
        BAsmCode[CodeLen++]=0x87+(OpSize << 3);
        BAsmCode[CodeLen++]=Hi(Op->Code)+AdrPart;
        BAsmCode[CodeLen++]=AdrVals[0];
       END
      else if (Index<2)  /* POP: obere Register zuerst */
       BEGIN
        if (Hi(Mask)!=0)
         BEGIN
          BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3)+0x40;
          BAsmCode[CodeLen++]=Hi(Mask);
         END
        if (Lo(Mask)!=0)
         BEGIN
          BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3);
          BAsmCode[CodeLen++]=Lo(Mask);
         END
        if ((OpSize==1) AND (Memo("POP")) AND ((Mask & 0x80)!=0)) WrError(140);
       END
      else              /* PUSH: untere Register zuerst */
       BEGIN
        if (Lo(Mask)!=0)
         BEGIN
          BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3);
          BAsmCode[CodeLen++]=Lo(Mask);
         END
        if (Hi(Mask)!=0)
         BEGIN
          BAsmCode[CodeLen++]=Lo(Op->Code)+(OpSize << 3)+0x40;
          BAsmCode[CodeLen++]=Hi(Mask);
         END
       END
    END
END

	static void DecodeALU(Word Index)
BEGIN
    Byte HReg,HCnt,HVals[3],HMem;

    if (ArgCnt!=2) WrError(1110);
    else
     BEGIN
      DecodeAdr(ArgStr[1],MModReg+MModMem);
      switch (AdrMode)
       BEGIN
        case ModReg:
         if (OpSize>=2) WrError(1130);
         else if (OpSize==-1) WrError(1132);
         else
          BEGIN
           HReg=AdrPart;
           DecodeAdr(ArgStr[2],MModMem+MModImm);
           switch (AdrMode)
            BEGIN
             case ModMem:
              BAsmCode[CodeLen++]=(Index << 4)+(OpSize << 3)+MemPart;
              BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
              memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
              CodeLen+=AdrCnt;
              if ((MemPart==3) AND ((HReg >> (1-OpSize))==AdrPart)) WrError(140);
              break;
             case ModImm:
              BAsmCode[CodeLen++]=0x91+(OpSize << 3);
              BAsmCode[CodeLen++]=(HReg << 4)+Index;
              memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
              CodeLen+=AdrCnt;
              break;
            END
          END
         break;
        case ModMem:
         HReg=AdrPart; HMem=MemPart; HCnt=AdrCnt;
         memcpy(HVals,AdrVals,AdrCnt);
         DecodeAdr(ArgStr[2],MModReg+MModImm);
         switch (AdrMode)
          BEGIN
           case ModReg:
            if (OpSize==2) WrError(1130);
            else if (OpSize==-1) WrError(1132);
            else
             BEGIN
              BAsmCode[CodeLen++]=(Index << 4)+(OpSize << 3)+HMem;
              BAsmCode[CodeLen++]=(AdrPart << 4)+8+HReg;
              memcpy(BAsmCode+CodeLen,HVals,HCnt);
              CodeLen+=HCnt;
              if ((HMem==3) AND ((AdrPart >> (1-OpSize))==HReg)) WrError(140);
             END
            break;
           case ModImm:
            if (OpSize==2) WrError(1130);
            else if (OpSize==-1) WrError(1132);
            else
             BEGIN
              BAsmCode[CodeLen++]=0x90+HMem+(OpSize << 3);
              BAsmCode[CodeLen++]=(HReg << 4)+Index;
              memcpy(BAsmCode+CodeLen,HVals,HCnt);
              memcpy(BAsmCode+CodeLen+HCnt,AdrVals,AdrCnt);
              CodeLen+=AdrCnt+HCnt;
             END
            break;
          END
         break;
       END
     END
END

	static void DecodeRegO(Word Index)
BEGIN
   RegOrder *Op=RegOrders+Index;

   if (ArgCnt!=1) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     switch (AdrMode)
      BEGIN
       case ModReg:
        if ((Op->SizeMask & (1 << OpSize))==0) WrError(1130);
        else
         BEGIN
          BAsmCode[CodeLen++]=0x90+(OpSize << 3);
          BAsmCode[CodeLen++]=(AdrPart << 4)+Op->Code;
         END
        break;
      END
    END
END

	static void DecodeShift(Word Index)
BEGIN
   Byte HReg,HMem;

   if (ArgCnt!=2) WrError(1110);
   else if (OpSize>2) WrError(1130);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     switch (AdrMode)
      BEGIN
       case ModReg:
        HReg=AdrPart; HMem=OpSize;
        if (*ArgStr[2]=='#') OpSize=(HMem==2)?-4:-2;
        else OpSize=0;
        DecodeAdr(ArgStr[2],MModReg+((Index==3)?0:MModImm));
        switch (AdrMode)
         BEGIN
          case ModReg:
           BAsmCode[CodeLen++]=0xc0+((HMem & 1) << 3)+Index;
           if (HMem==2) BAsmCode[CodeLen-1]+=12;
           BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
           if (Memo("NORM"))
            if (HMem==2)
             BEGIN
              if ((AdrPart >> 2)==(HReg >> 1)) WrError(140);
             END
            else if ((AdrPart >> HMem)==HReg) WrError(140);
           break;
          case ModImm:
           BAsmCode[CodeLen++]=0xd0+((HMem & 1) << 3)+Index;
           if (HMem==2)
            BEGIN
             BAsmCode[CodeLen-1]+=12;
             BAsmCode[CodeLen++]=((HReg & 14) << 4)+AdrVals[0];
            END
           else BAsmCode[CodeLen++]=(HReg << 4)+AdrVals[0];
           break;
         END
        break;
      END
    END
END

	static void DecodeRotate(Word Index)
BEGIN
   FixedOrder *Op=RotateOrders+Index;
   Byte HReg,HMem;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     switch (AdrMode)
      BEGIN
       case ModReg:
        if (OpSize==2) WrError(1130);
        else
         BEGIN
          HReg=AdrPart; HMem=OpSize; OpSize=(-2);
          DecodeAdr(ArgStr[2],MModImm);
          switch (AdrMode)
           BEGIN
            case ModImm:
             BAsmCode[CodeLen++]=Op->Code+(HMem << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrVals[0];
             break;
           END
         END
        break;
      END
    END
END

	static void DecodeRel(Word Index)
BEGIN
   InvOrder *Op=RelOrders+Index;
   Boolean OK;
   LongInt SaveLong,AdrLong;

   if (ArgCnt!=1) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else
    BEGIN
     FirstPassUnknown=True;
     AdrLong=SaveLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
     if (OK)
      BEGIN
       ChkSpace(SegCode);
#ifdef __STDC__
       if (FirstPassUnknown) AdrLong&=0xfffffffeu;
#else
       if (FirstPassUnknown) AdrLong&=0xfffffffe;
#endif
       AdrLong-=(EProgCounter()+CodeLen+2) & 0xfffffe;
       if ((AdrLong&1)==1) WrError(1325);
       else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
        BEGIN
         BAsmCode[CodeLen++]=Op->Code;
         BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
        END
       else if (NOT DoBranchExt) WrError(1370);
       else if (Op->Inversion==255)  /* BR */
        BEGIN
         AdrLong=SaveLong-((EProgCounter()+CodeLen+3) & 0xfffffe);
         if ((NOT SymbolQuestionable) AND ((AdrLong>65534) OR (AdrLong<-65536))) WrError(1370);
         else if ((AdrLong&1)==1) WrError(1325);
         else
          BEGIN
           AdrLong>>=1;
           BAsmCode[CodeLen++]=0xd5;
           BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
           BAsmCode[CodeLen++]=AdrLong & 0xff;
          END
        END
       else
        BEGIN
         AdrLong=SaveLong-((EProgCounter()+CodeLen+5) & 0xfffffe);
         if ((AdrLong>65534) OR (AdrLong<-65536)) WrError(1370);
         else
          BEGIN
           BAsmCode[CodeLen++]=RelOrders[Op->Inversion].Code;
           BAsmCode[CodeLen++]=2;
           BAsmCode[CodeLen++]=0xd5;
           BAsmCode[CodeLen++]=(AdrLong>>9)&0xff;
           BAsmCode[CodeLen++]=(AdrLong>>1)&0xff;
           if (Odd(EProgCounter()+CodeLen)) BAsmCode[CodeLen++]=0;
          END
        END
      END
    END
END

	static void DecodeJBit(Word Index)
BEGIN
   LongInt BitAdr,AdrLong,SaveLong,odd;
   Boolean OK;
   InvOrder *Op=JBitOrders+Index;

   if (ArgCnt!=2) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else if (DecodeBitAddr(ArgStr[1],&BitAdr))
    BEGIN
     FirstPassUnknown=False;
     AdrLong=SaveLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
     if (OK)
      BEGIN
#ifdef __STDC__
       if (FirstPassUnknown) AdrLong&=0xfffffffeu;
#else
       if (FirstPassUnknown) AdrLong&=0xfffffffe;
#endif
       AdrLong-=(EProgCounter()+CodeLen+4) & 0xfffffe;
       if ((AdrLong&1)==1) WrError(1325);
       else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
        BEGIN
         BAsmCode[CodeLen++]=0x97;
         BAsmCode[CodeLen++]=Op->Code+Hi(BitAdr);
         BAsmCode[CodeLen++]=Lo(BitAdr);
         BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
        END
       else if (NOT DoBranchExt) WrError(1370);
       else if (Op->Inversion==255)
        BEGIN
         odd=EProgCounter()&1;
         AdrLong=SaveLong-((EProgCounter()+CodeLen+9+odd)  & 0xfffffe);
         if ((AdrLong>65534) OR (AdrLong<-65536)) WrError(1370);
         else                 
          BEGIN
           BAsmCode[CodeLen++]=0x97;
           BAsmCode[CodeLen++]=Op->Code+Hi(BitAdr);
           BAsmCode[CodeLen++]=Lo(BitAdr);
           BAsmCode[CodeLen++]=1+odd;
           BAsmCode[CodeLen++]=0xfe;
           BAsmCode[CodeLen++]=2+odd;
           if (odd) BAsmCode[CodeLen++]=0;
           BAsmCode[CodeLen++]=0xd5;
           BAsmCode[CodeLen++]=(AdrLong>>9)&0xff;
           BAsmCode[CodeLen++]=(AdrLong>>1)&0xff;
           BAsmCode[CodeLen++]=0;
          END
        END
       else
        BEGIN
         AdrLong=SaveLong-((EProgCounter()+CodeLen+7)  & 0xfffffe);
         if ((AdrLong>65534) OR (AdrLong<-65536)) WrError(1370);  
         else
          BEGIN
           BAsmCode[CodeLen++]=0x97;
           BAsmCode[CodeLen++]=JBitOrders[Op->Inversion].Code+Hi(BitAdr);
           BAsmCode[CodeLen++]=Lo(BitAdr);
           BAsmCode[CodeLen++]=2;
           BAsmCode[CodeLen++]=0xd5;
           BAsmCode[CodeLen++]=(AdrLong>>9)&0xff;
           BAsmCode[CodeLen++]=(AdrLong>>1)&0xff;
           if (Odd(EProgCounter()+CodeLen)) BAsmCode[CodeLen++]=0;
          END
        END
      END
    END
END


	static void DecodeMOV(Word Index)
BEGIN
   LongInt AdrLong;
   Byte HVals[3],HReg,HPart,HCnt;

   if (ArgCnt!=2) WrError(1110);
   else if (strcasecmp(ArgStr[1],"C")==0)
    BEGIN
     if (DecodeBitAddr(ArgStr[2],&AdrLong))
      if (*AttrPart!='\0') WrError(1100);
      else
       BEGIN
        ChkBitPage(AdrLong);
        BAsmCode[CodeLen++]=0x08;
        BAsmCode[CodeLen++]=0x20+Hi(AdrLong);
        BAsmCode[CodeLen++]=Lo(AdrLong);
       END
    END
   else if (strcasecmp(ArgStr[2],"C")==0)
    BEGIN
     if (DecodeBitAddr(ArgStr[1],&AdrLong))
      if (*AttrPart!='\0') WrError(1100);
      else
       BEGIN
        ChkBitPage(AdrLong);
        BAsmCode[CodeLen++]=0x08;
        BAsmCode[CodeLen++]=0x30+Hi(AdrLong);
        BAsmCode[CodeLen++]=Lo(AdrLong);
       END
    END
   else if (strcasecmp(ArgStr[1],"USP")==0)
    BEGIN
     SetOpSize(1);
     DecodeAdr(ArgStr[2],MModReg);
     if (AdrMode==ModReg)
      BEGIN
       BAsmCode[CodeLen++]=0x98;
       BAsmCode[CodeLen++]=(AdrPart << 4)+0x0f;
      END
    END
   else if (strcasecmp(ArgStr[2],"USP")==0)
    BEGIN
     SetOpSize(1);
     DecodeAdr(ArgStr[1],MModReg);
     if (AdrMode==ModReg)
      BEGIN
       BAsmCode[CodeLen++]=0x90;
       BAsmCode[CodeLen++]=(AdrPart << 4)+0x0f;
      END
    END
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg+MModMem);
     switch (AdrMode)
      BEGIN
       case ModReg:
        if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
        else
         BEGIN
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],MModMem+MModImm);
          switch (AdrMode)
           BEGIN
            case ModMem:
             BAsmCode[CodeLen++]=0x80+(OpSize << 3)+MemPart;
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
             CodeLen+=AdrCnt;
             if ((MemPart==3) AND ((HReg >> (1-OpSize))==AdrPart)) WrError(140);
             break;
            case ModImm:
             BAsmCode[CodeLen++]=0x91+(OpSize << 3);
             BAsmCode[CodeLen++]=0x08+(HReg << 4);
             memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
             CodeLen+=AdrCnt;
             break;
           END
         END
        break;
       case ModMem:
        memcpy(HVals,AdrVals,AdrCnt); HCnt=AdrCnt; HPart=MemPart; HReg=AdrPart;
        DecodeAdr(ArgStr[2],MModReg+MModMem+MModImm);
        switch (AdrMode)
         BEGIN
          case ModReg:
           if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else
            BEGIN
             BAsmCode[CodeLen++]=0x80+(OpSize << 3)+HPart;
             BAsmCode[CodeLen++]=(AdrPart << 4)+0x08+HReg;
             memcpy(BAsmCode+CodeLen,HVals,HCnt);
             CodeLen+=HCnt;
             if ((HPart==3) AND ((AdrPart >> (1-OpSize))==HReg)) WrError(140);
            END
           break;
          case ModMem:
           if (OpSize==-1) WrError(1132);
           else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else if ((HPart==6) AND (MemPart==6))
            BEGIN
             BAsmCode[CodeLen++]=0x97+(OpSize << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             BAsmCode[CodeLen++]=HVals[0];
             BAsmCode[CodeLen++]=AdrVals[0];
            END
           else if ((HPart==6) AND (MemPart==2))
            BEGIN
             BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
             BAsmCode[CodeLen++]=0x80+(AdrPart << 4)+HReg;
             BAsmCode[CodeLen++]=HVals[0];
            END
           else if ((HPart==2) AND (MemPart==6))
            BEGIN
             BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             BAsmCode[CodeLen++]=AdrVals[0];
            END
           else if ((HPart==3) AND (MemPart==3))
            BEGIN
             BAsmCode[CodeLen++]=0x90+(OpSize << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             if (HReg==AdrPart) WrError(140);
            END
           else WrError(1350);
           break;
          case ModImm:
           if (OpSize==-1) WrError(1132);
           else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else
            BEGIN
             BAsmCode[CodeLen++]=0x90+(OpSize << 3)+HPart;
             BAsmCode[CodeLen++]=0x08+(HReg << 4);
             memcpy(BAsmCode+CodeLen,HVals,HCnt);
             memcpy(BAsmCode+CodeLen+HCnt,AdrVals,AdrCnt);
             CodeLen+=HCnt+AdrCnt;
            END
           break;
         END
        break;
      END
    END
END

	static void DecodeMOVC(Word Index)
BEGIN
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     if ((*AttrPart=='\0') AND (strcasecmp(ArgStr[1],"A")==0)) OpSize=0;
     if (strcasecmp(ArgStr[2],"[A+DPTR]")==0)
      if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
      else if (OpSize!=0) WrError(1130);
      else
       BEGIN
        BAsmCode[CodeLen++]=0x90;
        BAsmCode[CodeLen++]=0x4e;
       END
     else if (strcasecmp(ArgStr[2],"[A+PC]")==0)
      if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
      else if (OpSize!=0) WrError(1130);
      else
       BEGIN
        BAsmCode[CodeLen++]=0x90;
        BAsmCode[CodeLen++]=0x4c;
       END
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModReg);
       if (AdrMode!=ModNone)
        if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
        else
         BEGIN
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],MModMem);
          if (AdrMode!=ModNone)
           if (MemPart!=3) WrError(1350);
           else
            BEGIN
             BAsmCode[CodeLen++]=0x80+(OpSize << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             if ((MemPart==3) AND ((HReg >> (1-OpSize))==AdrPart)) WrError(140);
            END
         END
      END
    END
END

	static void DecodeMOVX(Word Index)
BEGIN
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModMem);
     if (AdrMode==ModMem)
      switch (MemPart)
       BEGIN
        case 1:
         if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
         else
          BEGIN
           HReg=AdrPart; DecodeAdr(ArgStr[2],MModMem);
           if (AdrMode==ModMem)
            if (MemPart!=2) WrError(1350);
            else
             BEGIN
              BAsmCode[CodeLen++]=0xa7+(OpSize << 3);
              BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             END
          END
         break;
        case 2:
         HReg=AdrPart; DecodeAdr(ArgStr[2],MModReg);
         if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
         else
          BEGIN
           BAsmCode[CodeLen++]=0xa7+(OpSize << 3);
           BAsmCode[CodeLen++]=0x08+(AdrPart << 4)+HReg;
          END
         break;
        default:
         WrError(1350);
       END
    END
END

	static void DecodeXCH(Word Index)
BEGIN
   Byte HReg,HPart,HVals[3];

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModMem);
     if (AdrMode==ModMem)
      switch (MemPart)
       BEGIN
        case 1:
         HReg=AdrPart; DecodeAdr(ArgStr[2],MModMem);
         if (AdrMode==ModMem)
          if ((OpSize!=1) AND (OpSize!=0)) WrError(1130);
          else switch (MemPart)
           BEGIN
            case 1:
             BAsmCode[CodeLen++]=0x60+(OpSize << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             if (HReg==AdrPart) WrError(140);
             break;
            case 2:
             BAsmCode[CodeLen++]=0x50+(OpSize << 3);
             BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
             break;
            case 6:
             BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
             BAsmCode[CodeLen++]=0x08+(HReg << 4)+AdrPart;
             BAsmCode[CodeLen++]=AdrVals[0];
             break;
            default:
             WrError(1350);
           END
         break;
        case 2:
         HReg=AdrPart;
         DecodeAdr(ArgStr[2],MModReg);
         if (AdrMode==ModReg)
          if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
          else
           BEGIN
            BAsmCode[CodeLen++]=0x50+(OpSize << 3);
            BAsmCode[CodeLen++]=(AdrPart << 4)+HReg;
           END
         break;
        case 6:
         HPart=AdrPart; HVals[0]=AdrVals[0];
         DecodeAdr(ArgStr[2],MModReg);
         if (AdrMode==ModReg)
          if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
          else
           BEGIN
            BAsmCode[CodeLen++]=0xa0+(OpSize << 3);
            BAsmCode[CodeLen++]=0x08+(AdrPart << 4)+HPart;
            BAsmCode[CodeLen++]=HVals[0];
           END
         break;
        default:
         WrError(1350);
       END
    END
END

	static void DecodeADDSMOVS(Word Index)
BEGIN
   Byte HReg,HMem;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     HMem=OpSize; OpSize=(-3);
     DecodeAdr(ArgStr[2],MModImm);
     switch (AdrMode)
      BEGIN
       case ModImm:
        HReg=AdrVals[0]; OpSize=HMem;
        DecodeAdr(ArgStr[1],MModMem);
        switch (AdrMode)
         BEGIN
          case ModMem:
           if (OpSize==2) WrError(1130);
           else if (OpSize==-1) WrError(1132);
           else
            BEGIN
             BAsmCode[CodeLen++]=0xa0+(Index << 4)+(OpSize << 3)+MemPart;
             BAsmCode[CodeLen++]=(AdrPart << 4)+(HReg & 0x0f);
             memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
             CodeLen+=AdrCnt;
            END
           break;
         END
        break;
      END 
    END
END

	static void DecodeDIV(Word Index)
BEGIN
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     if (AdrMode==ModReg)
      if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
      else
       BEGIN
        HReg=AdrPart; OpSize--; DecodeAdr(ArgStr[2],MModReg+MModImm);
        switch (AdrMode)
         BEGIN
          case ModReg:
           BAsmCode[CodeLen++]=0xe7+(OpSize << 3);
           BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
           break;
          case ModImm:
           BAsmCode[CodeLen++]=0xe8+OpSize;
           BAsmCode[CodeLen++]=(HReg << 4)+0x0b-(OpSize << 1);
           memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
           CodeLen+=AdrCnt;
           break;
         END
       END
    END
END

	static void DecodeDIVU(Word Index)
BEGIN
   Byte HReg;
   int z;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     if (AdrMode==ModReg)
      if ((OpSize==0) AND ((AdrPart&1)==1)) WrError(1445);
      else
       BEGIN
        HReg=AdrPart; z=OpSize; if (OpSize!=0) OpSize--;
        DecodeAdr(ArgStr[2],MModReg+MModImm);
        switch (AdrMode)
         BEGIN
          case ModReg:
           BAsmCode[CodeLen++]=0xe1+(z << 2);
           if (z==2) BAsmCode[CodeLen-1]+=4;
           BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
           break;
          case ModImm:
           BAsmCode[CodeLen++]=0xe8+Ord(z==2);
           BAsmCode[CodeLen++]=(HReg << 4)+0x01+(Ord(z==1) << 1);
           memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
           CodeLen+=AdrCnt;
           break;
         END
       END
    END
END

	static void DecodeMUL(Word Index)
BEGIN
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     if (AdrMode==ModReg)
      if (OpSize!=1) WrError(1130);
      else if ((AdrPart&1)==1) WrError(1445);
      else
       BEGIN
        HReg=AdrPart; DecodeAdr(ArgStr[2],MModReg+MModImm);
        switch (AdrMode)
         BEGIN
          case ModReg:
           BAsmCode[CodeLen++]=0xe6;
           BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
           break;
          case ModImm:
           BAsmCode[CodeLen++]=0xe9;
           BAsmCode[CodeLen++]=(HReg << 4)+0x08;
           memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
           CodeLen+=AdrCnt;
           break;
         END
       END
    END
END

	static void DecodeMULU(Word Index)
BEGIN
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     if (AdrMode==ModReg)
      if ((AdrPart&1)==1) WrError(1445);
      else
       BEGIN
        HReg=AdrPart;
        DecodeAdr(ArgStr[2],MModReg+MModImm);
        switch (AdrMode)
         BEGIN
          case ModReg:
           BAsmCode[CodeLen++]=0xe0+(OpSize << 2);
           BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
           break;
          case ModImm:
           BAsmCode[CodeLen++]=0xe8+OpSize;
           BAsmCode[CodeLen++]=(HReg << 4);
           memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
           CodeLen+=AdrCnt;
           break;
         END
       END
    END
END

	static void DecodeLEA(Word Index)
BEGIN
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1],MModReg);
     if (AdrMode==ModReg)
      if (OpSize!=1) WrError(1130);
      else
       BEGIN
        HReg=AdrPart;
        strmaxprep(ArgStr[2],"[",255); strmaxcat(ArgStr[2],"]",255);
        DecodeAdr(ArgStr[2],MModMem);
        if (AdrMode==ModMem)
         switch (MemPart)
          BEGIN
           case 4:
           case 5:
            BAsmCode[CodeLen++]=0x20+(MemPart << 3);
            BAsmCode[CodeLen++]=(HReg << 4)+AdrPart;
            memcpy(BAsmCode+CodeLen,AdrVals,AdrCnt);
            CodeLen+=AdrCnt;
            break;
           default:
            WrError(1350);
          END
       END
    END
END

	static void DecodeANLORL(Word Index)
BEGIN
   LongInt AdrLong;
   Boolean OK;

   if (ArgCnt!=2) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else if (strcasecmp(ArgStr[1],"C")!=0) WrError(1350);
   else
    BEGIN
     if (*ArgStr[2]=='/')
      BEGIN
       OK=True; strcpy(ArgStr[2],ArgStr[2]+1);
      END
     else OK=False;
     if (DecodeBitAddr(ArgStr[2],&AdrLong))
      BEGIN
       ChkBitPage(AdrLong);
       BAsmCode[CodeLen++]=0x08;
       BAsmCode[CodeLen++]=0x40+(Index << 5)+(Ord(OK) << 4)+(Hi(AdrLong) & 3);
       BAsmCode[CodeLen++]=Lo(AdrLong);
      END
    END
END

	static void DecodeCLRSETB(Word Index)
BEGIN
   LongInt AdrLong;

   if (ArgCnt!=1) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else if (DecodeBitAddr(ArgStr[1],&AdrLong))
    BEGIN
     ChkBitPage(AdrLong);
     BAsmCode[CodeLen++]=0x08;
     BAsmCode[CodeLen++]=(Index << 4)+(Hi(AdrLong) & 3);
     BAsmCode[CodeLen++]=Lo(AdrLong);
    END
END

	static void DecodeTRAP(Word Index)
BEGIN
   if (ArgCnt!=1) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else
    BEGIN
     OpSize=(-2);
     DecodeAdr(ArgStr[1],MModImm);
     switch (AdrMode)
      BEGIN
       case ModImm:
        BAsmCode[CodeLen++]=0xd6;
        BAsmCode[CodeLen++]=0x30+AdrVals[0];
        break;
      END
    END
END

	static void DecodeCALL(Word Index)
BEGIN
   LongInt AdrLong;
   Boolean OK;

   if (ArgCnt!=1) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else if (*ArgStr[1]=='[')
    BEGIN
     DecodeAdr(ArgStr[1],MModMem);
     if (AdrMode!=ModNone)
      if (MemPart!=2) WrError(1350);
      else
       BEGIN
        BAsmCode[CodeLen++]=0xc6;
        BAsmCode[CodeLen++]=AdrPart;
       END
    END
   else
    BEGIN
     FirstPassUnknown=False;
     AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
     if (OK)
      BEGIN
       ChkSpace(SegCode);
#ifdef __STDC__
       if (FirstPassUnknown) AdrLong&=0xfffffffeu;
#else
       if (FirstPassUnknown) AdrLong&=0xfffffffe;
#endif
       AdrLong-=(EProgCounter()+CodeLen+3) & 0xfffffe;
       if ((NOT SymbolQuestionable) AND ((AdrLong>65534) OR (AdrLong<-65536))) WrError(1370);
       else if ((AdrLong&1)==1) WrError(1325);
       else
        BEGIN
         AdrLong>>=1;
         BAsmCode[CodeLen++]=0xc5;
         BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
         BAsmCode[CodeLen++]=AdrLong & 0xff;
        END
      END
    END
END

	static void DecodeJMP(Word Index)
BEGIN
   LongInt AdrLong;
   Boolean OK;

   if (ArgCnt!=1) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else if (strcasecmp(ArgStr[1],"[A+DPTR]")==0)
    BEGIN
     BAsmCode[CodeLen++]=0xd6;
     BAsmCode[CodeLen++]=0x46;
    END
   else if (strncmp(ArgStr[1],"[[",2)==0)
    BEGIN
     ArgStr[1][strlen(ArgStr[1])-1]='\0';
     DecodeAdr(ArgStr[1]+1,MModMem);
     if (AdrMode==ModMem)
      switch (MemPart)
       BEGIN
        case 3:
         BAsmCode[CodeLen++]=0xd6;
         BAsmCode[CodeLen++]=0x60+AdrPart;
         break;
        default:
         WrError(1350);
       END
    END
   else if (*ArgStr[1]=='[')
    BEGIN
     DecodeAdr(ArgStr[1],MModMem);
     if (AdrMode==ModMem)
      switch (MemPart)
       BEGIN
        case 2:
         BAsmCode[CodeLen++]=0xd6;
         BAsmCode[CodeLen++]=0x70+AdrPart;
         break;
        default:
         WrError(1350);
       END
    END
   else
    BEGIN
     FirstPassUnknown=False;
     AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
     if (OK)
      BEGIN
       ChkSpace(SegCode);
#ifdef __STDC__
       if (FirstPassUnknown) AdrLong&=0xfffffffeu;
#else
       if (FirstPassUnknown) AdrLong&=0xfffffffe;
#endif
       AdrLong-=((EProgCounter()+CodeLen+3) & 0xfffffe);
       if ((NOT SymbolQuestionable) AND ((AdrLong>65534) OR (AdrLong<-65536))) WrError(1370);
       else if ((AdrLong&1)==1) WrError(1325);
       else
        BEGIN
         AdrLong>>=1;
         BAsmCode[CodeLen++]=0xd5;
         BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
         BAsmCode[CodeLen++]=AdrLong & 0xff;
        END
      END
    END
END

	static void DecodeCJNE(Word Index)
BEGIN
   LongInt AdrLong,SaveLong,odd;
   Boolean OK;
   Byte HReg;

   if (ArgCnt!=3) WrError(1110);
   else
    BEGIN
     FirstPassUnknown=False;
     AdrLong=SaveLong=EvalIntExpression(ArgStr[3],UInt24,&OK);
     if (FirstPassUnknown) AdrLong&=0xfffffe;
     if (OK)
      BEGIN
       ChkSpace(SegCode); OK=False; HReg=0;
       DecodeAdr(ArgStr[1],MModMem);
       if (AdrMode==ModMem)
        switch (MemPart)
         BEGIN
          case 1:
           if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else
            BEGIN
             HReg=AdrPart; DecodeAdr(ArgStr[2],MModMem+MModImm);
             switch (AdrMode)
              BEGIN
               case ModMem:
                if (MemPart!=6) WrError(1350);
                else
                 BEGIN
                  BAsmCode[CodeLen]=0xe2+(OpSize << 3);
                  BAsmCode[CodeLen+1]=(HReg << 4)+AdrPart;
                  BAsmCode[CodeLen+2]=AdrVals[0];
                  HReg=CodeLen+3;
                  CodeLen+=4; OK=True;
                 END
                break;
               case ModImm:
                BAsmCode[CodeLen]=0xe3+(OpSize << 3);
                BAsmCode[CodeLen+1]=HReg << 4;
                HReg=CodeLen+2;
                memcpy(BAsmCode+CodeLen+3,AdrVals,AdrCnt);
                CodeLen+=3+AdrCnt; OK=True;
                break;
              END
            END
           break;
          case 2:
           if ((OpSize!=-1) AND (OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else
            BEGIN
             HReg=AdrPart; DecodeAdr(ArgStr[2],MModImm);
             if (AdrMode==ModImm)
              BEGIN
               BAsmCode[CodeLen]=0xe3+(OpSize << 3);
               BAsmCode[CodeLen+1]=(HReg << 4)+8;
               HReg=CodeLen+2;
               memcpy(BAsmCode+CodeLen+3,AdrVals,AdrCnt);
               CodeLen+=3+AdrCnt; OK=True;
              END
            END
           break;
          default:
           WrError(1350);
         END
       if (OK)
        BEGIN
         AdrLong-=(EProgCounter()+CodeLen) & 0xfffffe; OK=False;
         if ((AdrLong&1)==1) WrError(1325);
         else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
          BEGIN
           BAsmCode[HReg]=(AdrLong >> 1) & 0xff; OK=True;
          END
         else if (NOT DoBranchExt) WrError(1370);
         else
          BEGIN
           odd=(EProgCounter()+CodeLen) & 1;
           AdrLong=SaveLong-((EProgCounter()+CodeLen+5+odd)&0xfffffe);
           if ((AdrLong<-65536) OR (AdrLong>65534)) WrError(1370);
           else
            BEGIN
             BAsmCode[HReg]=1+odd;
             BAsmCode[CodeLen++]=0xfe;
             BAsmCode[CodeLen++]=2+odd;
             if (odd) BAsmCode[CodeLen++]=0;
             BAsmCode[CodeLen++]=0xd5;
             BAsmCode[CodeLen++]=(AdrLong >> 9) & 0xff;
             BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
             BAsmCode[CodeLen++]=0;
             OK=True;
            END
          END
        END
       if (NOT OK) CodeLen=0;
      END
    END
END

	static void DecodeDJNZ(Word Index)
BEGIN
   LongInt AdrLong,SaveLong,odd;
   Boolean OK;
   Byte HReg;

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     FirstPassUnknown=False;
     SaveLong=AdrLong=EvalIntExpression(ArgStr[2],UInt24,&OK);
     if (FirstPassUnknown) AdrLong&=0xfffffe;
     if (OK)
      BEGIN
       ChkSpace(SegCode); HReg=0;
       DecodeAdr(ArgStr[1],MModMem);
       OK=False; DecodeAdr(ArgStr[1],MModMem);
       if (AdrMode==ModMem)
        switch (MemPart)
         BEGIN
          case 1:
           if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else
            BEGIN
             BAsmCode[CodeLen]=0x87+(OpSize << 3);
             BAsmCode[CodeLen+1]=(AdrPart << 4)+0x08;
             HReg=CodeLen+2;
             CodeLen+=3; OK=True;
            END
           break;
          case 6:
           if (OpSize==-1) WrError(1132);
           else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
           else
            BEGIN
             BAsmCode[CodeLen]=0xe2+(OpSize << 3);
             BAsmCode[CodeLen+1]=0x08+AdrPart;
             BAsmCode[CodeLen+2]=AdrVals[0];
             HReg=CodeLen+3;
             CodeLen+=4; OK=True;
            END
           break;
          default:
           WrError(1350);
         END
       if (OK)
        BEGIN
         AdrLong-=(EProgCounter()+CodeLen) & 0xfffffe; OK=False;
         if ((AdrLong&1)==1) WrError(1325);
         else if ((SymbolQuestionable) OR ((AdrLong<=254) AND (AdrLong>=-256)))
          BEGIN
           BAsmCode[HReg]=(AdrLong >> 1) & 0xff; OK=True;
          END
         else if (NOT DoBranchExt) WrError(1370);
         else
          BEGIN
           odd=(EProgCounter()+CodeLen) & 1;
           AdrLong=SaveLong-((EProgCounter()+CodeLen+5+odd)&0xfffffe);
           if ((AdrLong<-65536) OR (AdrLong>65534)) WrError(1370);
           else
            BEGIN
             BAsmCode[HReg]=1+odd;
             BAsmCode[CodeLen++]=0xfe;
             BAsmCode[CodeLen++]=2+odd;
             if (odd) BAsmCode[CodeLen++]=0;
             BAsmCode[CodeLen++]=0xd5;
             BAsmCode[CodeLen++]=(AdrLong >> 9) & 0xff;
             BAsmCode[CodeLen++]=(AdrLong >> 1) & 0xff;
             BAsmCode[CodeLen++]=0;
             OK=True;
            END
          END
        END
       if (NOT OK) CodeLen=0;
      END
    END
END

	static void DecodeFCALLJMP(Word Index)
BEGIN
   LongInt AdrLong;
   Boolean OK;

   if (ArgCnt!=1) WrError(1110);
   else if (*AttrPart!='\0') WrError(1100);
   else
    BEGIN
     FirstPassUnknown=False;
     AdrLong=EvalIntExpression(ArgStr[1],UInt24,&OK);
     if (FirstPassUnknown) AdrLong&=0xfffffe;
     if (OK)
      if ((AdrLong&1)==1) WrError(1325);
      else
       BEGIN
        BAsmCode[CodeLen++]=0xc4+(Index << 4);
        BAsmCode[CodeLen++]=(AdrLong >> 8) & 0xff;
        BAsmCode[CodeLen++]=AdrLong & 0xff;
        BAsmCode[CodeLen++]=(AdrLong >> 16) & 0xff;
       END
    END
END

	static Boolean IsRealDef(void)
BEGIN
   return ((Memo("PORT")) OR (Memo("BIT")));
END

	static void ForceAlign(void)
BEGIN
   if ((EProgCounter()&1)==1)
    BEGIN
     BAsmCode[0]=NOPCode; CodeLen=1;
    END
END

	static void MakeCode_XA(void)
BEGIN
   CodeLen=0; DontPrint=False; OpSize=(-1);

   /* Operandengroesse */

   if (*AttrPart!='\0')
    switch (toupper(*AttrPart))
     BEGIN
      case 'B': SetOpSize(0); break;
      case 'W': SetOpSize(1); break;
      case 'D': SetOpSize(2); break;
      default : WrError(1107); return;
     END

   /* Pseudoanweisungen */

   if (DecodePseudo()) return;

   /* Labels muessen auf geraden Adressen liegen */

   if ( (ActPC==SegCode) AND (NOT IsRealDef()) AND 
        ((*LabPart!='\0') OR ((ArgCnt == 1) AND (strcmp(ArgStr[1],"$")==0))) )
    BEGIN
     ForceAlign();
     if (*LabPart!='\0') 
      EnterIntSymbol(LabPart,EProgCounter()+CodeLen,ActPC,False);
    END

   if (DecodeMoto16Pseudo(OpSize,False)) return;
   if (DecodeIntelPseudo(False)) return;

   /* zu ignorierendes */

   if (Memo("")) return;

   /* via Tabelle suchen */

   if (NOT LookupInstTable(InstTable,OpPart)) WrXError(1200,OpPart);
END

/*-------------------------------------------------------------------------*/
/* Codetabellenverwaltung */

        static void AddFixed(char *NName, Word NCode)
BEGIN
   if (InstrZ>=FixedOrderCnt) exit(255);
   FixedOrders[InstrZ].Code=NCode;
   AddInstTable(InstTable,NName,InstrZ++,DecodeFixed);
END

        static void AddJBit(char *NName, Word NCode)
BEGIN
   if (InstrZ>=JBitOrderCnt) exit(255);
   JBitOrders[InstrZ].Name=NName;
   JBitOrders[InstrZ].Inversion=255;
   JBitOrders[InstrZ].Code=NCode;
   AddInstTable(InstTable,NName,InstrZ++,DecodeJBit);
END

        static void AddStack(char *NName, Word NCode)
BEGIN
   if (InstrZ>=StackOrderCount) exit(255);
   StackOrders[InstrZ].Code=NCode;
   AddInstTable(InstTable,NName,InstrZ++,DecodeStack);
END

        static void AddReg(char *NName, Byte NMask, Byte NCode)
BEGIN
   if (InstrZ>=RegOrderCnt) exit(255);
   RegOrders[InstrZ].Code=NCode;
   RegOrders[InstrZ].SizeMask=NMask;
   AddInstTable(InstTable,NName,InstrZ++,DecodeRegO);
END

        static void AddRotate(char *NName, Word NCode)
BEGIN
   if (InstrZ>=RotateOrderCount) exit(255);
   RotateOrders[InstrZ].Code=NCode;
   AddInstTable(InstTable,NName,InstrZ++,DecodeRotate);
END

        static void AddRel(char *NName, Word NCode)
BEGIN
   if (InstrZ>=RelOrderCount) exit(255);
   RelOrders[InstrZ].Name=NName;
   RelOrders[InstrZ].Inversion=255;
   RelOrders[InstrZ].Code=NCode;
   AddInstTable(InstTable,NName,InstrZ++,DecodeRel);
END

	static void SetInv(char *Name1, char *Name2, InvOrder *Orders)
BEGIN
   InvOrder *Order1,*Order2;

   for (Order1=Orders; strcmp(Order1->Name,Name1)!=0; Order1++);
   for (Order2=Orders; strcmp(Order2->Name,Name2)!=0; Order2++);
   Order1->Inversion=Order2-Orders;
   Order2->Inversion=Order1-Orders;
END

	static void InitFields(void)
BEGIN
   InstTable=CreateInstTable(201); 
   AddInstTable(InstTable,"MOV" ,0,DecodeMOV);
   AddInstTable(InstTable,"MOVC",0,DecodeMOVC);
   AddInstTable(InstTable,"MOVX",0,DecodeMOVX);
   AddInstTable(InstTable,"XCH" ,0,DecodeXCH);
   AddInstTable(InstTable,"ADDS",0,DecodeADDSMOVS);
   AddInstTable(InstTable,"MOVS",1,DecodeADDSMOVS);
   AddInstTable(InstTable,"DIV" ,0,DecodeDIV);
   AddInstTable(InstTable,"DIVU",0,DecodeDIVU);
   AddInstTable(InstTable,"MUL" ,0,DecodeMUL);
   AddInstTable(InstTable,"DIVU",0,DecodeDIVU);
   AddInstTable(InstTable,"MULU",0,DecodeMULU);
   AddInstTable(InstTable,"LEA" ,0,DecodeLEA);
   AddInstTable(InstTable,"ANL" ,0,DecodeANLORL);
   AddInstTable(InstTable,"ORL" ,1,DecodeANLORL);
   AddInstTable(InstTable,"CLR" ,0,DecodeCLRSETB);
   AddInstTable(InstTable,"SETB",1,DecodeCLRSETB);
   AddInstTable(InstTable,"TRAP",0,DecodeTRAP);
   AddInstTable(InstTable,"CALL",0,DecodeCALL);
   AddInstTable(InstTable,"JMP" ,0,DecodeJMP);
   AddInstTable(InstTable,"CJNE",0,DecodeCJNE);
   AddInstTable(InstTable,"DJNZ",0,DecodeDJNZ);
   AddInstTable(InstTable,"FCALL",0,DecodeFCALLJMP);
   AddInstTable(InstTable,"FJMP",1,DecodeFCALLJMP);

   FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
   AddFixed("NOP"  ,0x0000);
   AddFixed("RET"  ,0xd680);
   AddFixed("RETI" ,0xd690);
   AddFixed("BKPT" ,0x00ff);
   AddFixed("RESET",0xd610);

   JBitOrders=(InvOrder *) malloc(sizeof(InvOrder)*JBitOrderCnt); InstrZ=0;
   AddJBit("JB"  ,0x80);
   AddJBit("JBC" ,0xc0);
   AddJBit("JNB" ,0xa0);
   SetInv("JB","JNB",JBitOrders);

   StackOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*StackOrderCount); InstrZ=0;
   AddStack("POP"  ,0x1027);
   AddStack("POPU" ,0x0037);
   AddStack("PUSH" ,0x3007);
   AddStack("PUSHU",0x2017);

   InstrZ=0;
   AddInstTable(InstTable,"ADD" ,InstrZ++,DecodeALU);
   AddInstTable(InstTable,"ADDC",InstrZ++,DecodeALU);
   AddInstTable(InstTable,"SUB" ,InstrZ++,DecodeALU);
   AddInstTable(InstTable,"SUBB",InstrZ++,DecodeALU);
   AddInstTable(InstTable,"CMP" ,InstrZ++,DecodeALU);
   AddInstTable(InstTable,"AND" ,InstrZ++,DecodeALU);
   AddInstTable(InstTable,"OR"  ,InstrZ++,DecodeALU);
   AddInstTable(InstTable,"XOR" ,InstrZ++,DecodeALU);

   RegOrders=(RegOrder *) malloc(sizeof(RegOrder)*RegOrderCnt); InstrZ=0;
   AddReg("NEG" ,3,0x0b);
   AddReg("CPL" ,3,0x0a);
   AddReg("SEXT",3,0x09);
   AddReg("DA"  ,1,0x08);

   InstrZ=0;
   AddInstTable(InstTable,"LSR" ,InstrZ++,DecodeShift);
   AddInstTable(InstTable,"ASL" ,InstrZ++,DecodeShift);
   AddInstTable(InstTable,"ASR" ,InstrZ++,DecodeShift);
   AddInstTable(InstTable,"NORM",InstrZ++,DecodeShift);

   RotateOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RotateOrderCount); InstrZ=0;
   AddRotate("RR" ,0xb0); AddRotate("RL" ,0xd3);
   AddRotate("RRC",0xb7); AddRotate("RLC",0xd7);

   RelOrders=(InvOrder *) malloc(sizeof(InvOrder)*RelOrderCount); InstrZ=0;
   AddRel("BCC",0xf0); AddRel("BCS",0xf1); AddRel("BNE",0xf2);
   AddRel("BEQ",0xf3); AddRel("BNV",0xf4); AddRel("BOV",0xf5);
   AddRel("BPL",0xf6); AddRel("BMI",0xf7); AddRel("BG" ,0xf8);
   AddRel("BL" ,0xf9); AddRel("BGE",0xfa); AddRel("BLT",0xfb);
   AddRel("BGT",0xfc); AddRel("BLE",0xfd); AddRel("BR" ,0xfe);
   AddRel("JZ" ,0xec); AddRel("JNZ",0xee);
   SetInv("BCC","BCS",RelOrders);
   SetInv("BNE","BEQ",RelOrders);
   SetInv("BNV","BOV",RelOrders);
   SetInv("BPL","BMI",RelOrders);
   SetInv("BG" ,"BL" ,RelOrders);
   SetInv("BGE","BLT",RelOrders);
   SetInv("BGT","BLE",RelOrders);
   SetInv("JZ" ,"JNZ",RelOrders);
END

        static void DeinitFields(void)
BEGIN
   free(FixedOrders);
   free(JBitOrders);
   free(StackOrders);
   free(RegOrders);
   free(RotateOrders);
   free(RelOrders);

   DestroyInstTable(InstTable);
END

/*-------------------------------------------------------------------------*/
/* Callbacks */

	static void InitCode_XA(void)
BEGIN
   SaveInitProc();
   Reg_DS=0;
END

	static Boolean ChkPC_XA(LargeWord Addr)
BEGIN
   switch (ActPC)
    BEGIN
     case SegCode:
     case SegData:
      return (Addr<0x1000000);
     case SegIO:
      return ((Addr>0x3ff) AND (Addr<0x800));
     default:
      return False;
    END
END

	static Boolean IsDef_XA(void)
BEGIN
   return (ActPC==SegCode);
END

        static void SwitchFrom_XA(void)
BEGIN
   DeinitFields(); ClearONOFF();
END

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

   PCSymbol="$"; HeaderID=0x3c; NOPCode=0x00;
   DivideChars=","; HasAttrs=True; AttrChars=".";

   ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
   Grans[SegCode ]=1; ListGrans[SegCode ]=1; SegInits[SegCode ]=0;
   Grans[SegData ]=1; ListGrans[SegData ]=1; SegInits[SegData ]=0;
   Grans[SegIO   ]=1; ListGrans[SegIO   ]=1; SegInits[SegIO   ]=0x400;

   MakeCode=MakeCode_XA; ChkPC=ChkPC_XA; IsDef=IsDef_XA;
   SwitchFrom=SwitchFrom_XA; InitFields();
   AddONOFF("SUPMODE",  &SupAllowed, SupAllowedName,False);
   AddONOFF("BRANCHEXT",&DoBranchExt,BranchExtName ,False);
   AddMoto16PseudoONOFF();

   SetFlag(&DoPadding,DoPaddingName,False);
END

	void codexa_init(void)
BEGIN
   CPUXAG1=AddCPU("XAG1",SwitchTo_XA);
   CPUXAG2=AddCPU("XAG2",SwitchTo_XA);
   CPUXAG3=AddCPU("XAG3",SwitchTo_XA);

   SaveInitProc=InitPassProc; InitPassProc=InitCode_XA;
END
