/* codez80.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator Zilog Z80/180/380                                           */
/*                                                                           */
/* Historie: 26. 8.1996 Grundsteinlegung                                     */
/*            1. 2.1998 ChkPC ersetzt                                        */
/*                                                                           */
/*****************************************************************************/

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

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

/*-------------------------------------------------------------------------*/
/* Instruktionsgruppendefinitionen */

typedef struct
         {
          char *Name;
          CPUVar MinCPU;
          Byte Len;
          Word Code;
         } BaseOrder;

typedef struct
         {
          char *Name;
          Byte Code;
         } Condition; 

typedef struct
         {
          char *Name;
          Byte Code;
         } ALUOrder; 

/*-------------------------------------------------------------------------*/
/* Praefixtyp */

typedef enum {Pref_IN_N,Pref_IN_W ,Pref_IB_W ,Pref_IW_W ,Pref_IB_N ,
	 	        Pref_IN_LW,Pref_IB_LW,Pref_IW_LW,Pref_IW_N} PrefType;


#define ExtFlagName    "INEXTMODE"       /* Flag-Symbolnamen */
#define LWordFlagName  "INLWORDMODE"

#define ModNone (-1)
#define ModReg8 1
#define ModReg16 2
#define ModIndReg16 3
#define ModImm 4
#define ModAbs 5
#define ModRef 6
#define ModInt 7
#define ModSPRel 8

#define FixedOrderCnt 53
#define AccOrderCnt 3
#define HLOrderCnt 3
#define ALUOrderCnt 5
#define ShiftOrderCnt 8
#define BitOrderCnt 3
#define ConditionCnt 12

#define IXPrefix 0xdd
#define IYPrefix 0xfd

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

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

static BaseOrder *FixedOrders;
static BaseOrder *AccOrders;
static BaseOrder *HLOrders;
static ALUOrder *ALUOrders;
static char **ShiftOrders;
static char **BitOrders;
static Condition *Conditions;

static SimpProc SaveInitProc;

static CPUVar CPUZ80,CPUZ80U,CPUZ180,CPUZ380;

static Boolean MayLW,		  /* Instruktion erlaubt 32 Bit */
               ExtFlag,           /* Prozessor im 4GByte-Modus ? */
               LWordFlag;         /* 32-Bit-Verarbeitung ? */

static PrefType CurrPrefix,       /* mom. explizit erzeugter Praefix */
                LastPrefix;       /* von der letzten Anweisung generierter Praefix */

/*==========================================================================*/
/* Codetabellenerzeugung */

	static void AddFixed(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
BEGIN
   if (InstrZ>=FixedOrderCnt) exit(255);
   FixedOrders[InstrZ].Name=NewName;
   FixedOrders[InstrZ].MinCPU=NewMin;
   FixedOrders[InstrZ].Len=NewLen;
   FixedOrders[InstrZ++].Code=NewCode;
END

	static void AddAcc(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
BEGIN
   if (InstrZ>=AccOrderCnt) exit(255);
   AccOrders[InstrZ].Name=NewName;
   AccOrders[InstrZ].MinCPU=NewMin;
   AccOrders[InstrZ].Len=NewLen;
   AccOrders[InstrZ++].Code=NewCode;
END

        static void AddHL(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
BEGIN
   if (InstrZ>=HLOrderCnt) exit(255);
   HLOrders[InstrZ].Name=NewName;
   HLOrders[InstrZ].MinCPU=NewMin;
   HLOrders[InstrZ].Len=NewLen;
   HLOrders[InstrZ++].Code=NewCode;
END

	static void AddALU(char *NewName, Byte NCode)
BEGIN
   if (InstrZ>=ALUOrderCnt) exit(255);
   ALUOrders[InstrZ].Name=NewName;
   ALUOrders[InstrZ++].Code=NCode;
END

	static void AddShift(char *NName)
BEGIN
   if (InstrZ>=ShiftOrderCnt) exit(255);
   ShiftOrders[InstrZ++]=NName;
END

        static void AddBit(char *NName)
BEGIN
   if (InstrZ>=BitOrderCnt) exit(255);
   BitOrders[InstrZ++]=NName;
END

	static void AddCondition(char *NewName, Byte NewCode)
BEGIN
   if (InstrZ>=ConditionCnt) exit(255);
   Conditions[InstrZ].Name=NewName;
   Conditions[InstrZ++].Code=NewCode;
END

	static void InitFields(void)
BEGIN
   InstrZ=0; Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt);
   AddCondition("NZ",0); AddCondition("Z" ,1);
   AddCondition("NC",2); AddCondition("C" ,3);
   AddCondition("PO",4); AddCondition("NV",4);
   AddCondition("PE",5); AddCondition("V" ,5);
   AddCondition("P" ,6); AddCondition("NS",6);
   AddCondition("M" ,7); AddCondition("S" ,7);

   InstrZ=0; FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt);
   AddFixed("EXX"  ,CPUZ80 ,1,0x00d9); AddFixed("LDI"  ,CPUZ80 ,2,0xeda0);
   AddFixed("LDIR" ,CPUZ80 ,2,0xedb0); AddFixed("LDD"  ,CPUZ80 ,2,0xeda8);
   AddFixed("LDDR" ,CPUZ80 ,2,0xedb8); AddFixed("CPI"  ,CPUZ80 ,2,0xeda1);
   AddFixed("CPIR" ,CPUZ80 ,2,0xedb1); AddFixed("CPD"  ,CPUZ80 ,2,0xeda9);
   AddFixed("CPDR" ,CPUZ80 ,2,0xedb9); AddFixed("RLCA" ,CPUZ80 ,1,0x0007);
   AddFixed("RRCA" ,CPUZ80 ,1,0x000f); AddFixed("RLA"  ,CPUZ80 ,1,0x0017);
   AddFixed("RRA"  ,CPUZ80 ,1,0x001f); AddFixed("RLD"  ,CPUZ80 ,2,0xed6f);
   AddFixed("RRD"  ,CPUZ80 ,2,0xed67); AddFixed("DAA"  ,CPUZ80 ,1,0x0027);
   AddFixed("CCF"  ,CPUZ80 ,1,0x003f); AddFixed("SCF"  ,CPUZ80 ,1,0x0037);
   AddFixed("NOP"  ,CPUZ80 ,1,0x0000); AddFixed("HALT" ,CPUZ80 ,1,0x0076);
   AddFixed("RETI" ,CPUZ80 ,2,0xed4d); AddFixed("RETN" ,CPUZ80 ,2,0xed45);
   AddFixed("INI"  ,CPUZ80 ,2,0xeda2); AddFixed("INIR" ,CPUZ80 ,2,0xedb2);
   AddFixed("IND"  ,CPUZ80 ,2,0xedaa); AddFixed("INDR" ,CPUZ80 ,2,0xedba);
   AddFixed("OUTI" ,CPUZ80 ,2,0xeda3); AddFixed("OTIR" ,CPUZ80 ,2,0xedb3);
   AddFixed("OUTD" ,CPUZ80 ,2,0xedab); AddFixed("OTDR" ,CPUZ80 ,2,0xedbb);
   AddFixed("SLP"  ,CPUZ180,2,0xed76); AddFixed("OTIM" ,CPUZ180,2,0xed83);
   AddFixed("OTIMR",CPUZ180,2,0xed93); AddFixed("OTDM" ,CPUZ180,2,0xed8b);
   AddFixed("OTDMR",CPUZ180,2,0xed9b); AddFixed("BTEST",CPUZ380,2,0xedcf);
   AddFixed("EXALL",CPUZ380,2,0xedd9); AddFixed("EXXX" ,CPUZ380,2,0xddd9);
   AddFixed("EXXY" ,CPUZ380,2,0xfdd9); AddFixed("INDW" ,CPUZ380,2,0xedea);
   AddFixed("INDRW",CPUZ380,2,0xedfa); AddFixed("INIW" ,CPUZ380,2,0xede2);
   AddFixed("INIRW",CPUZ380,2,0xedf2); AddFixed("LDDW" ,CPUZ380,2,0xede8);
   AddFixed("LDDRW",CPUZ380,2,0xedf8); AddFixed("LDIW" ,CPUZ380,2,0xede0);
   AddFixed("LDIRW",CPUZ380,2,0xedf0); AddFixed("MTEST",CPUZ380,2,0xddcf);
   AddFixed("OTDRW",CPUZ380,2,0xedfb); AddFixed("OTIRW",CPUZ380,2,0xedf3);
   AddFixed("OUTDW",CPUZ380,2,0xedeb); AddFixed("OUTIW",CPUZ380,2,0xede3);
   AddFixed("RETB" ,CPUZ380,2,0xed55);

   InstrZ=0; AccOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*AccOrderCnt);
   AddAcc("CPL"  ,CPUZ80 ,1,0x002f); AddAcc("NEG"  ,CPUZ80 ,2,0xed44);
   AddAcc("EXTS" ,CPUZ380,2,0xed65);

   InstrZ=0; HLOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*HLOrderCnt);
   AddHL("CPLW" ,CPUZ380,2,0xdd2f);  AddHL("NEGW" ,CPUZ380,2,0xed54);
   AddHL("EXTSW",CPUZ380,2,0xed75);

   InstrZ=0; ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt);
   AddALU("SUB", 2); AddALU("AND", 4);
   AddALU("OR" , 6); AddALU("XOR", 5);
   AddALU("CP" , 7);

   InstrZ=0; ShiftOrders=(char **) malloc(sizeof(char *)*ShiftOrderCnt);
   AddShift("RLC"); AddShift("RRC"); AddShift("RL"); AddShift("RR"); 
   AddShift("SLA"); AddShift("SRA"); AddShift("SLIA"); AddShift("SRL");

   InstrZ=0; BitOrders=(char **) malloc(sizeof(char *)*BitOrderCnt);
   AddBit("BIT"); AddBit("RES"); AddBit("SET");
END

	static void DeinitFields(void)
BEGIN
   free(Conditions);
   free(FixedOrders);
   free(AccOrders);
   free(HLOrders);
   free(ALUOrders);
   free(ShiftOrders);
   free(BitOrders);
END

/*==========================================================================*/
/* Adressbereiche */

	static LargeWord CodeEnd(void)
BEGIN
#ifdef __STDC__
   if (ExtFlag) return 0xfffffffflu;
#else
   if (ExtFlag) return 0xffffffffl;
#endif
   else if (MomCPU==CPUZ180) return 0x7ffffl;
   else return 0xffff;
END

	static LargeWord PortEnd(void)
BEGIN
#ifdef __STDC__
   if (ExtFlag) return 0xfffffffflu;
#else
   if (ExtFlag) return 0xffffffffl;
#endif
   else return 0xff;
END

/*==========================================================================*/
/* Praefix dazuaddieren */

	static Boolean ExtendPrefix(PrefType *Dest, char *AddArg)
BEGIN
   Byte SPart,IPart;

   switch (*Dest)
    BEGIN
     case Pref_IB_N:
     case Pref_IB_W:
     case Pref_IB_LW: IPart=1; break;
     case Pref_IW_N:
     case Pref_IW_W:
     case Pref_IW_LW: IPart=2; break;
     default: IPart=0;
    END

   switch (*Dest)
    BEGIN
     case Pref_IN_W:
     case Pref_IB_W:
     case Pref_IW_W:  SPart=1; break;
     case Pref_IN_LW:
     case Pref_IB_LW: 
     case Pref_IW_LW: SPart=2; break;
     default: SPart=0;
    END

   if (strcmp(AddArg,"W")==0)         /* Wortverarbeitung */
    SPart=1;
   else if (strcmp(AddArg,"LW")==0)   /* Langwortverarbeitung */
    SPart=2;
   else if (strcmp(AddArg,"IB")==0)   /* ein Byte im Argument mehr */
    IPart=1;
   else if (strcmp(AddArg,"IW")==0)   /* ein Wort im Argument mehr */
    IPart=2;
   else return False;

   switch ((IPart << 4)+SPart)
    BEGIN
     case 0x00:*Dest=Pref_IN_N; break;
     case 0x01:*Dest=Pref_IN_W; break;
     case 0x02:*Dest=Pref_IN_LW; break;
     case 0x10:*Dest=Pref_IB_N; break;
     case 0x11:*Dest=Pref_IB_W; break;
     case 0x12:*Dest=Pref_IB_LW; break;
     case 0x20:*Dest=Pref_IW_N; break;
     case 0x21:*Dest=Pref_IW_W; break;
     case 0x22:*Dest=Pref_IW_LW; break;
    END

   return True;
END

/*--------------------------------------------------------------------------*/
/* Code fuer Praefix bilden */

	static void GetPrefixCode(PrefType inp, Byte *b1 ,Byte *b2)
BEGIN
   int z;

   z=((int)inp)-1;
   *b1=0xdd+((z & 4) << 3);
   *b2=0xc0+(z & 3);
END

/*--------------------------------------------------------------------------*/
/* DD-Praefix addieren, nur EINMAL pro Instruktion benutzen! */

	static void ChangeDDPrefix(char *Add)
BEGIN
   PrefType ActPrefix;
   int z;

   ActPrefix=LastPrefix;
   if (ExtendPrefix(&ActPrefix,Add))
    if (LastPrefix!=ActPrefix)
     BEGIN
      if (LastPrefix!=Pref_IN_N) RetractWords(2);
      for (z=PrefixCnt-1; z>=0; z--) BAsmCode[2+z]=BAsmCode[z];
      PrefixCnt+=2;
      GetPrefixCode(ActPrefix,BAsmCode+0,BAsmCode+1);
     END
END

/*--------------------------------------------------------------------------*/
/* Wortgroesse ? */

	static Boolean InLongMode(void)
BEGIN
   switch (LastPrefix)
    BEGIN
     case Pref_IN_W:
     case Pref_IB_W:
     case Pref_IW_W: return False;
     case Pref_IN_LW:
     case Pref_IB_LW:
     case Pref_IW_LW: return MayLW;
     default: return LWordFlag AND MayLW;
    END
END

/*--------------------------------------------------------------------------*/
/* absolute Adresse */

	static LongWord EvalAbsAdrExpression(char *inp, Boolean *OK)
BEGIN
   return EvalIntExpression(inp,ExtFlag?Int32:UInt16,OK);
END

/*==========================================================================*/
/* Adressparser */

        static Boolean DecodeReg8(char *Asc, Byte *Erg)
BEGIN
#define Reg8Cnt 7
   static char *Reg8Names[Reg8Cnt]={"B","C","D","E","H","L","A"};
   int z;

   for (z=0; z<Reg8Cnt; z++)
    if (strcasecmp(Asc,Reg8Names[z])==0)
     BEGIN
      *Erg=z; if (z==6) (*Erg)++;
      return True;
     END

   return False;
END

	static Boolean IsSym(char ch)
BEGIN
   return ((ch=='_') OR ((ch>='0') AND (ch<='9')) OR ((ch>='A') AND (ch<='Z')) OR ((ch>='a') AND (ch<='z')));
END

	static void DecodeAdr(char *Asc_O)
BEGIN
#define Reg8XCnt 4
   static char *Reg8XNames[Reg8XCnt]={"IXU","IXL","IYU","IYL"};
#define Reg16Cnt 6
   static char *Reg16Names[Reg16Cnt]={"BC","DE","HL","SP","IX","IY"};

   int z;
   Integer AdrInt;
   LongInt AdrLong;
   Boolean OK;
   String Asc;

   AdrMode=ModNone; AdrCnt=0; AdrPart=0;

   /* 0. Sonderregister */

   if (strcasecmp(Asc_O,"R")==0)
    BEGIN
     AdrMode=ModRef; return;
    END

   if (strcasecmp(Asc_O,"I")==0)
    BEGIN
     AdrMode=ModInt; return;
    END

   /* 1. 8-Bit-Register ? */

   if (DecodeReg8(Asc_O,&AdrPart))
    BEGIN
     AdrMode=ModReg8;
     return;
    END

   /* 1a. 8-Bit-Haelften von IX/IY ? (nur Z380, sonst als Symbole zulassen) */

   if ((MomCPU>=CPUZ380) OR (MomCPU==CPUZ80U))
    for (z=0; z<Reg8XCnt; z++)
     if (strcasecmp(Asc_O,Reg8XNames[z])==0)
      BEGIN
       AdrMode=ModReg8;
       BAsmCode[PrefixCnt++]=(z<=1)?IXPrefix:IYPrefix;
       AdrPart=4+(z & 1); /* = H /L */
       return;
      END

   /* 2. 16-Bit-Register ? */

   for (z=0; z<Reg16Cnt; z++)
    if (strcasecmp(Asc_O,Reg16Names[z])==0)
     BEGIN
      AdrMode=ModReg16;
      if (z<=3) AdrPart=z;
      else
       BEGIN
	BAsmCode[PrefixCnt++]=(z==4)?IXPrefix:IYPrefix;
	AdrPart=2; /* = HL */
       END
      return;
     END

   /* 3. 16-Bit-Register indirekt ? */

   if ((strlen(Asc_O)>=4) AND (*Asc_O=='(') AND (Asc_O[strlen(Asc_O)-1]==')')) 
    for (z=0; z<Reg16Cnt; z++)
     if ((strncasecmp(Asc_O+1,Reg16Names[z],2)==0)
     AND (NOT IsSym(Asc_O[3])))
      BEGIN
       if (z<3)
        BEGIN
	 if (strlen(Asc_O)!=4)
	  BEGIN
	   WrError(1350); return;
	  END
	 switch (z)
          BEGIN
	   case 0:
           case 1:   /* BC,DE */
	    AdrMode=ModIndReg16; AdrPart=z;
	    break;
	   case 2:   /* HL=M-Register */
	    AdrMode=ModReg8; AdrPart=6;
	    break;
	  END
        END
       else
        BEGIN        /* SP,IX,IY */
         strmaxcpy(Asc,Asc_O+3,255); Asc[strlen(Asc)-1]='\0';
	 if (*Asc=='+') strcpy(Asc,Asc+1);
         AdrLong=EvalIntExpression(Asc,(MomCPU>=CPUZ380)?SInt24:SInt8,&OK);
	 if (OK)
	  BEGIN
           if (z==3) AdrMode=ModSPRel;
           else
            BEGIN
	     AdrMode=ModReg8; AdrPart=6;
             BAsmCode[PrefixCnt++]=(z==4)?IXPrefix:IYPrefix;
	    END
	   AdrVals[AdrCnt++]=AdrLong & 0xff;
           if ((AdrLong>=-0x80l) AND (AdrLong<=0x7fl));
	   else
	    BEGIN
	     AdrVals[AdrCnt++]=(AdrLong >> 8) & 0xff;
             if ((AdrLong>=-0x8000l) AND (AdrLong<=0x7fffl)) ChangeDDPrefix("IB");
	     else
	      BEGIN
	       AdrVals[AdrCnt++]=(AdrLong >> 16) & 0xff;
	       ChangeDDPrefix("IW");
	      END
	    END
	  END
        END
       return;
      END

   /* absolut ? */

   if (IsIndirect(Asc_O))
    BEGIN
     AdrLong=EvalAbsAdrExpression(Asc_O,&OK);
     if (OK)
      BEGIN
       ChkSpace(SegCode);
       AdrMode=ModAbs;
       AdrVals[0]=AdrLong & 0xff;
       AdrVals[1]=(AdrLong >> 8) & 0xff;
       AdrCnt=2;
#ifdef __STDC__
       if ((AdrLong & 0xffff0000u)==0);
#else
       if ((AdrLong & 0xffff0000)==0);
#endif
       else
        BEGIN
         AdrVals[AdrCnt++]=((AdrLong >> 16) & 0xff);
#ifdef __STDC__
         if ((AdrLong & 0xff000000u)==0) ChangeDDPrefix("IB");
#else
         if ((AdrLong & 0xff000000)==0) ChangeDDPrefix("IB");
#endif
         else
          BEGIN
           AdrVals[AdrCnt++]=((AdrLong >> 24) & 0xff);
           ChangeDDPrefix("IW");
          END
        END
      END
     return;
    END

   /* ...immediate */

   switch (OpSize)
    BEGIN
     case 0xff:
      WrError(1132);
      break;
     case 0:
      AdrVals[0]=EvalIntExpression(Asc_O,Int8,&OK);
      if (OK)
       BEGIN
        AdrMode=ModImm; AdrCnt=1;
       END;
      break;
     case 1:
      if (InLongMode())
       BEGIN
        AdrLong=EvalIntExpression(Asc_O,Int32,&OK);
        if (OK)
         BEGIN
          AdrVals[0]=Lo(AdrLong); AdrVals[1]=Hi(AdrLong);
          AdrMode=ModImm; AdrCnt=2;
#ifdef __STDC__
          if ((AdrLong & 0xffff0000u)==0);
#else
          if ((AdrLong & 0xffff0000)==0);
#endif
          else
           BEGIN
            AdrVals[AdrCnt++]=(AdrLong >> 16) & 0xff;
#ifdef __STDC__
            if ((AdrLong & 0xff000000u)==0) ChangeDDPrefix("IB");
#else
            if ((AdrLong & 0xff000000)==0) ChangeDDPrefix("IB");
#endif
            else
             BEGIN
              AdrVals[AdrCnt++]=(AdrLong >> 24) & 0xff;
              ChangeDDPrefix("IW");
             END
           END
         END
       END
      else
       BEGIN
        AdrInt=EvalIntExpression(Asc_O,Int16,&OK);
        if (OK)
         BEGIN
          AdrVals[0]=Lo(AdrInt); AdrVals[1]=Hi(AdrInt);
          AdrMode=ModImm; AdrCnt=2;
         END
       END
      break;
    END
END

/*-------------------------------------------------------------------------*/
/* Bedingung entschluesseln */

	static Boolean DecodeCondition(char *Name, int *Erg)
BEGIN
   int z;
   String Name_N;

   strmaxcpy(Name_N,Name,255); NLS_UpString(Name_N);

   z=0;
   while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,Name_N)!=0)) z++;
   if (z>ConditionCnt) return False;
   else
    BEGIN
     *Erg=Conditions[z].Code; return True;
    END
END

/*-------------------------------------------------------------------------*/
/* Sonderregister dekodieren */

	static Boolean DecodeSFR(char *Inp, Byte *Erg)
BEGIN
   if (strcasecmp(Inp,"SR")==0) *Erg=1;
   else if (strcasecmp(Inp,"XSR")==0) *Erg=5;
   else if (strcasecmp(Inp,"DSR")==0) *Erg=6;
   else if (strcasecmp(Inp,"YSR")==0) *Erg=7;
   else return False;
   return True;
END

/*=========================================================================*/

	static Boolean DecodePseudo(void)
BEGIN
   if (Memo("PORT"))
    BEGIN
     CodeEquate(SegIO,0,PortEnd());
     return True;
    END

   /* Kompatibilitaet zum M80 */

   if (Memo("DEFB")) strmaxcpy(OpPart,"DB",255);
   if (Memo("DEFW")) strmaxcpy(OpPart,"DW",255);

   return False;
END

	static void DecodeLD(void)
BEGIN
   Byte AdrByte,HLen;
   int z;
   Byte HVals[5];

   if (ArgCnt!=2) WrError(1110);
   else
    BEGIN
     DecodeAdr(ArgStr[1]);
     switch (AdrMode)
      BEGIN
       case ModReg8:
        if (AdrPart==7) /* LD A,... */
         BEGIN
	  OpSize=0; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg8: /* LD A,R8/RX8/(HL)/(XY+D) */
	     BAsmCode[PrefixCnt]=0x78+AdrPart;
	     memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+1+AdrCnt;
	     break;
	    case ModIndReg16: /* LD A,(BC)/(DE) */
	     BAsmCode[0]=0x0a+(AdrPart << 4); CodeLen=1;
	     break;
	    case ModImm: /* LD A,imm8 */
	     BAsmCode[0]=0x3e; BAsmCode[1]=AdrVals[0]; CodeLen=2;
	     break;
	    case ModAbs: /* LD a,(adr) */
	     BAsmCode[PrefixCnt]=0x3a;
	     memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+1+AdrCnt;
	     break;
	    case ModRef: /* LD A,R */
	     BAsmCode[0]=0xed; BAsmCode[1]=0x5f;
	     CodeLen=2;
	     break;
	    case ModInt: /* LD A,I */
	     BAsmCode[0]=0xed; BAsmCode[1]=0x57;
	     CodeLen=2;
	     break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        else if ((AdrPart!=6) AND (PrefixCnt==0)) /* LD R8,... */
         BEGIN
	  AdrByte=AdrPart; OpSize=0; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg8: /* LD R8,R8/RX8/(HL)/(XY+D) */
	     if (((AdrByte==4) OR (AdrByte==5)) AND (PrefixCnt==1) AND (AdrCnt==0)) WrError(1350);
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0x40+(AdrByte << 3)+AdrPart;
	       memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	       CodeLen=PrefixCnt+1+AdrCnt;
	      END
             break;
	    case ModImm: /* LD R8,imm8 */
	     BAsmCode[0]=0x06+(AdrByte << 3); BAsmCode[1]=AdrVals[0];
	     CodeLen=2;
	     break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        else if ((AdrPart==4) OR (AdrPart==5)) /* LD RX8,... */
         BEGIN
	  AdrByte=AdrPart; OpSize=0; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg8: /* LD RX8,R8/RX8 */
	     if (AdrPart==6) WrError(1350);
	     else if ((AdrPart>=4) AND (AdrPart<=5) AND (PrefixCnt!=2)) WrError(1350);
	     else if ((AdrPart>=4) AND (AdrPart<=5) AND (BAsmCode[0]!=BAsmCode[1])) WrError(1350);
	     else
	      BEGIN
	       if (PrefixCnt==2) PrefixCnt--;
	       BAsmCode[PrefixCnt]=0x40+(AdrByte << 3)+AdrPart;
	       CodeLen=PrefixCnt+1;
	      END
             break;
	    case ModImm: /* LD RX8,imm8 */
	     BAsmCode[PrefixCnt]=0x06+(AdrByte << 3);
	     BAsmCode[PrefixCnt+1]=AdrVals[0];
	     CodeLen=PrefixCnt+2;
	     break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        else /* LD (HL)/(XY+d),... */
         BEGIN
	  HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt); z=PrefixCnt;
	  if ((z==0) AND (Memo("LDW")))
	   BEGIN
	    OpSize=1; MayLW=True;
	   END
	  else OpSize=0;
	  DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg8: /* LD (HL)/(XY+D),R8 */
	     if ((PrefixCnt!=z) OR (AdrPart==6)) WrError(1350);
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0x70+AdrPart;
	       memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
	       CodeLen=PrefixCnt+1+HLen;
	      END
             break;
	    case ModImm: /* LD (HL)/(XY+D),imm8:16:32 */
	     if ((z==0) AND (Memo("LDW")))
	      if (MomCPU<CPUZ380) WrError(1500);
	      else
	       BEGIN
	        BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0x36;
	        memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	        CodeLen=PrefixCnt+2+AdrCnt;
	       END
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0x36;
	       memcpy(BAsmCode+1+PrefixCnt,HVals,HLen);
	       BAsmCode[PrefixCnt+1+HLen]=AdrVals[0];
	       CodeLen=PrefixCnt+1+HLen+AdrCnt;
	      END
             break;
	    case ModReg16: /* LD (HL)/(XY+D),R16/XY */
	     if (MomCPU<CPUZ380) WrError(1500);
	     else if (AdrPart==3) WrError(1350);
	     else if (HLen==0)
	      if (PrefixCnt==z) /* LD (HL),R16 */
	       BEGIN
	        if (AdrPart==2) AdrPart=3;
	        BAsmCode[0]=0xfd; BAsmCode[1]=0x0f+(AdrPart << 4);
	        CodeLen=2;
	       END
	      else /* LD (HL),XY */
	       BEGIN
	        CodeLen=PrefixCnt+1; BAsmCode[PrefixCnt]=0x31;
	        CodeLen=1+PrefixCnt;
	       END
	     else
	      if (PrefixCnt==z) /* LD (XY+D),R16 */
	       BEGIN
	        if (AdrPart==2) AdrPart=3;
	        BAsmCode[PrefixCnt]=0xcb;
	        memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
	        BAsmCode[PrefixCnt+1+HLen]=0x0b+(AdrPart << 4);
	        CodeLen=PrefixCnt+1+HLen+1;
	       END
	      else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
	      else
	       BEGIN
	        PrefixCnt--;
	        BAsmCode[PrefixCnt]=0xcb;
	        memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
	        BAsmCode[PrefixCnt+1+HLen]=0x2b;
	        CodeLen=PrefixCnt+1+HLen+1;
	       END
             break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        break;
       case ModReg16:
        if (AdrPart==3) /* LD SP,... */
         BEGIN
	  OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg16: /* LD SP,HL/XY */
	     if (AdrPart!=2) WrError(1350);
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0xf9; CodeLen=PrefixCnt+1;
	      END
             break;
	    case ModImm: /* LD SP,imm16:32 */
	     BAsmCode[PrefixCnt]=0x31;
	     memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+1+AdrCnt;
	     break;
	    case ModAbs: /* LD SP,(adr) */
	     BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0x7b;
	     memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+2+AdrCnt;
             break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        else if (PrefixCnt==0) /* LD R16,... */
         BEGIN
          AdrByte=(AdrPart==2) ? 3 : AdrPart;
	  OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModInt: /* LD HL,I */
	     if (MomCPU<CPUZ380) WrError(1500);
	     else if (AdrByte!=3) WrError(1350);
	     else
	      BEGIN
	       BAsmCode[0]=0xdd; BAsmCode[1]=0x57; CodeLen=2;
	      END
             break;
	    case ModReg8:
	     if (AdrPart!=6) WrError(1350);
	     else if (MomCPU<CPUZ380) WrError(1500);
	     else if (PrefixCnt==0) /* LD R16,(HL) */
	      BEGIN
	       BAsmCode[0]=0xdd; BAsmCode[1]=0x0f+(AdrByte << 4);
	       CodeLen=2;
	      END
	     else /* LD R16,(XY+d) */
	      BEGIN
	       BAsmCode[PrefixCnt]=0xcb;
	       memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	       BAsmCode[PrefixCnt+1+AdrCnt]=0x03+(AdrByte << 4);
	       CodeLen=PrefixCnt+1+AdrCnt+1;
	      END
             break;
	    case ModReg16:
	     if (AdrPart==3) WrError(1350);
	     else if (MomCPU<CPUZ380) WrError(1500);
	     else if (PrefixCnt==0) /* LD R16,R16 */
	      BEGIN
	       if (AdrPart==2) AdrPart=3;
	       else if (AdrPart==0) AdrPart=2;
	       BAsmCode[0]=0xcd+(AdrPart << 4);
	       BAsmCode[1]=0x02+(AdrByte << 4);
	       CodeLen=2;
	      END
	     else /* LD R16,XY */
	      BEGIN
	       BAsmCode[PrefixCnt]=0x0b+(AdrByte << 4);
	       CodeLen=PrefixCnt+1;
	      END
             break;
	    case ModIndReg16: /* LD R16,(R16) */
	     if (MomCPU<CPUZ380) WrError(1500);
	     else
	      BEGIN
	       CodeLen=2; BAsmCode[0]=0xdd;
	       BAsmCode[1]=0x0c+(AdrByte << 4)+AdrPart;
	      END
             break;
	    case ModImm: /* LD R16,imm */
	     if (AdrByte==3) AdrByte=2;
	     CodeLen=PrefixCnt+1+AdrCnt;
	     BAsmCode[PrefixCnt]=0x01+(AdrByte << 4);
	     memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	     break;
	    case ModAbs: /* LD R16,(adr) */
	     if (AdrByte==3)
	      BEGIN
	       BAsmCode[PrefixCnt]=0x2a;
	       memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	       CodeLen=1+PrefixCnt+AdrCnt;
	      END
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0xed;
	       BAsmCode[PrefixCnt+1]=0x4b+(AdrByte << 4);
	       memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	       CodeLen=PrefixCnt+2+AdrCnt;
	      END
             break;
	    case ModSPRel: /* LD R16,(SP+D) */
	     if (MomCPU<CPUZ380) WrError(1500);
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0xdd;
	       BAsmCode[PrefixCnt+1]=0xcb;
	       memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	       BAsmCode[PrefixCnt+2+AdrCnt]=0x01+(AdrByte << 4);
	       CodeLen=PrefixCnt+3+AdrCnt;
	      END
             break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        else /* LD XY,... */
         BEGIN
	  OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg8:
	     if (AdrPart!=6) WrError(1350);
 	     else if (MomCPU<CPUZ380) WrError(1500);
	     else if (AdrCnt==0) /* LD XY,(HL) */
	      BEGIN
	       BAsmCode[PrefixCnt]=0x33; CodeLen=PrefixCnt+1;
	      END
	     else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
	     else /* LD XY,(XY+D) */
	      BEGIN
	       BAsmCode[0]=BAsmCode[1]; PrefixCnt--;
	       BAsmCode[PrefixCnt]=0xcb;
	       memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	       BAsmCode[PrefixCnt+1+AdrCnt]=0x23;
	       CodeLen=PrefixCnt+1+AdrCnt+1;
	      END
             break;
	    case ModReg16:
	     if (MomCPU<CPUZ380) WrError(1500);
	     else if (AdrPart==3) WrError(1350);
	     else if (PrefixCnt==1) /* LD XY,R16 */
	      BEGIN
	       if (AdrPart==2) AdrPart=3;
	       CodeLen=1+PrefixCnt;
	       BAsmCode[PrefixCnt]=0x07+(AdrPart << 4);
	      END
	     else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
	     else /* LD XY,XY */
	      BEGIN
	       BAsmCode[--PrefixCnt]=0x27;
	       CodeLen=1+PrefixCnt;
	      END
             break;
	    case ModIndReg16:
	     if (MomCPU<CPUZ380) WrError(1500);
	     else /* LD XY,(R16) */
	      BEGIN
	       BAsmCode[PrefixCnt]=0x03+(AdrPart << 4);
	       CodeLen=PrefixCnt+1;
	      END
             break;
	    case ModImm: /* LD XY,imm16:32 */
	     BAsmCode[PrefixCnt]=0x21;
	     memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+1+AdrCnt;
	     break;
	    case ModAbs: /* LD XY,(adr) */
	     BAsmCode[PrefixCnt]=0x2a;
	     memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+1+AdrCnt;
	     break;
	    case ModSPRel: /* LD XY,(SP+D) */
	     if (MomCPU<CPUZ380) WrError(1500);
	     else
	      BEGIN
	       BAsmCode[PrefixCnt]=0xcb;
	       memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	       BAsmCode[PrefixCnt+1+AdrCnt]=0x21;
	       CodeLen=PrefixCnt+1+AdrCnt+1;
	      END
             break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        break;
       case ModIndReg16:
        AdrByte=AdrPart;
        if (Memo("LDW"))
 	 BEGIN
	  OpSize=1; MayLW=True;
	 END
        else OpSize=0;
        DecodeAdr(ArgStr[2]);
        switch (AdrMode)
         BEGIN
          case ModReg8: /* LD (R16),A */
	   if (AdrPart!=7) WrError(1350);
	   else
	    BEGIN
	     CodeLen=1; BAsmCode[0]=0x02+(AdrByte << 4);
	    END
           break;
          case ModReg16:
	   if (AdrPart==3) WrError(1350);
	   else if (MomCPU<CPUZ380) WrError(1500);
	   else if (PrefixCnt==0) /* LD (R16),R16 */
	    BEGIN
	     if (AdrPart==2) AdrPart=3;
	     BAsmCode[0]=0xfd; BAsmCode[1]=0x0c+AdrByte+(AdrPart << 4);
	     CodeLen=2;
	    END
	   else /* LD (R16),XY */
	    BEGIN
	     BAsmCode[PrefixCnt]=0x01+(AdrByte << 4);
	     CodeLen=PrefixCnt+1;
	    END
           break;
          case ModImm:
	   if (NOT Memo("LDW")) WrError(1350);
	   else if (MomCPU<CPUZ380) WrError(1500);
	   else
	    BEGIN
	     BAsmCode[PrefixCnt]=0xed;
	     BAsmCode[PrefixCnt+1]=0x06+(AdrByte << 4);
	     memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+2+AdrCnt;
	    END
           break;
          default: if (AdrMode!=ModNone) WrError(1350);
         END
        break;
       case ModAbs:
        HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt);
        OpSize=0; DecodeAdr(ArgStr[2]);
        switch (AdrMode)
         BEGIN
          case ModReg8: /* LD (adr),A */
           if (AdrPart!=7) WrError(1350);
           else
	    BEGIN
	     BAsmCode[PrefixCnt]=0x32;
	     memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
	     CodeLen=PrefixCnt+1+HLen;
	    END
           break;
          case ModReg16:
	   if (AdrPart==2) /* LD (adr),HL/XY */
	    BEGIN
	     BAsmCode[PrefixCnt]=0x22;
	     memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
	     CodeLen=PrefixCnt+1+HLen;
	    END
	   else /* LD (adr),R16 */
	    BEGIN
	     BAsmCode[PrefixCnt]=0xed;
	     BAsmCode[PrefixCnt+1]=0x43+(AdrPart << 4);
	     memcpy(BAsmCode+PrefixCnt+2,HVals,HLen);
	     CodeLen=PrefixCnt+2+HLen;
	    END
           break;
          default: if (AdrMode!=ModNone) WrError(1350);
         END
        break;
       case ModInt:
        if (strcasecmp(ArgStr[2],"A")==0) /* LD I,A */
         BEGIN
	  CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x47;
         END
        else if (strcasecmp(ArgStr[2],"HL")==0) /* LD I,HL */
         if (MomCPU<CPUZ380) WrError(1500);
         else
	  BEGIN
	   CodeLen=2; BAsmCode[0]=0xdd; BAsmCode[1]=0x47;
	  END
         else WrError(1350);
        break;
       case ModRef:
        if (strcasecmp(ArgStr[2],"A")==0) /* LD R,A */
         BEGIN
	  CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x4f;
         END
        else WrError(1350);
        break;
       case ModSPRel:
        if (MomCPU<CPUZ380) WrError(1500);
        else
         BEGIN
	  HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt);
	  OpSize=0; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModReg16:
	     if (AdrPart==3) WrError(1350);
	     else if (PrefixCnt==0) /* LD (SP+D),R16 */
	      BEGIN
	       if (AdrPart==2) AdrPart=3;
	       BAsmCode[PrefixCnt]=0xdd;
	       BAsmCode[PrefixCnt+1]=0xcb;
	       memcpy(BAsmCode+PrefixCnt+2,HVals,HLen);
	       BAsmCode[PrefixCnt+2+HLen]=0x09+(AdrPart << 4);
	       CodeLen=PrefixCnt+2+HLen+1;
	      END
	     else /* LD (SP+D),XY */
	      BEGIN
	       BAsmCode[PrefixCnt]=0xcb;
	       memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
	       BAsmCode[PrefixCnt+1+HLen]=0x29;
	       CodeLen=PrefixCnt+1+HLen+1;
	      END
             break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
         END
        break;
       default: if (AdrMode!=ModNone) WrError(1350);
      END /* outer switch */
    END
END

	static Boolean ParPair(char *Name1, char *Name2)
BEGIN
   return (((strcasecmp(ArgStr[1],Name1)==0) AND (strcasecmp(ArgStr[2],Name2)==0)) OR
	   ((strcasecmp(ArgStr[1],Name2)==0) AND (strcasecmp(ArgStr[2],Name1)==0)));
END

	static Boolean ImmIs8(void)
BEGIN
   Word tmp;

   if (AdrCnt<2) return True;

   tmp=(Word) AdrVals[AdrCnt-2];

   return ((tmp<=255) OR (tmp>=0xff80));
END

	static Boolean CodeAri(void)
BEGIN
   int z;
   Byte AdrByte;
   Boolean OK;

   for (z=0; z<ALUOrderCnt; z++)
    if (Memo(ALUOrders[z].Name))
     BEGIN
      if (ArgCnt==1)
       BEGIN
	strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255); ArgCnt=2;
       END
      if (ArgCnt!=2) WrError(1110);
      else if (strcasecmp(ArgStr[1],"HL")==0)
       BEGIN
        if (NOT Memo("SUB")) WrError(1350);
        else
 	 BEGIN
	  OpSize=1; DecodeAdr(ArgStr[2]);
	  switch (AdrMode)
           BEGIN
	    case ModAbs:
	     BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0xd6;
	     memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	     CodeLen=PrefixCnt+2+AdrCnt;
	     break;
	    default: if (AdrMode!=ModNone) WrError(1350);
	   END
	 END
       END
      else if (strcasecmp(ArgStr[1],"SP")==0)
       BEGIN
        if (NOT Memo("SUB")) WrError(1350);
        else
         BEGIN
          OpSize=1; DecodeAdr(ArgStr[2]);
          switch (AdrMode)
           BEGIN
	    case ModImm:
             BAsmCode[0]=0xed; BAsmCode[1]=0x92;
	     memcpy(BAsmCode+2,AdrVals,AdrCnt);
             CodeLen=2+AdrCnt;
	     break;
            default: if (AdrMode!=ModNone) WrError(1350);
           END
         END
       END
      else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
      else
       BEGIN
        OpSize=0; DecodeAdr(ArgStr[2]);
        switch (AdrMode)
         BEGIN
          case ModReg8:
           CodeLen=PrefixCnt+1+AdrCnt;
           BAsmCode[PrefixCnt]=0x80+(ALUOrders[z].Code << 3)+AdrPart;
           memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
           break;
          case ModImm:
           if (NOT ImmIs8()) WrError(1320);
           else
            BEGIN
             CodeLen=2;
             BAsmCode[0]=0xc6+(ALUOrders[z].Code << 3);
             BAsmCode[1]=AdrVals[0];
            END
           break;
          default: if (AdrMode!=ModNone) WrError(1350);
         END
       END
      return True;
     END
    else if ((strncmp(ALUOrders[z].Name,OpPart,strlen(ALUOrders[z].Name))==0) AND (OpPart[strlen(OpPart)-1]=='W'))
     BEGIN
      if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
      else if (MomCPU<CPUZ380) WrError(1500);
      else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
      else
       BEGIN
        OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
        switch (AdrMode)
         BEGIN
          case ModReg16:
	   if (PrefixCnt>0)      /* wenn Register, dann nie DDIR! */
            BEGIN
             BAsmCode[PrefixCnt]=0x87+(ALUOrders[z].Code << 3);
	     CodeLen=1+PrefixCnt;
            END
           else if (AdrPart==3) WrError(1350);
           else
            BEGIN
             if (AdrPart==2) AdrPart=3;
             BAsmCode[0]=0xed; BAsmCode[1]=0x84+(ALUOrders[z].Code << 3)+AdrPart;
	     CodeLen=2;
            END
           break;
          case ModReg8:
           if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
           else
            BEGIN
             BAsmCode[PrefixCnt]=0xc6+(ALUOrders[z].Code << 3);
             memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
             CodeLen=PrefixCnt+1+AdrCnt;
            END
           break;
          case ModImm:
           BAsmCode[0]=0xed; BAsmCode[1]=0x86+(ALUOrders[z].Code << 3);
           memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
           break;
	  default: if (AdrMode!=ModNone) WrError(1350);
         END
       END
      return True;
     END

   if (Memo("ADD"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
          if (AdrPart!=7) WrError(1350);
          else
           BEGIN
            OpSize=0; DecodeAdr(ArgStr[2]);
            switch (AdrMode)
             BEGIN
              case ModReg8:
               CodeLen=PrefixCnt+1+AdrCnt;
               BAsmCode[PrefixCnt]=0x80+AdrPart;
               memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
               break;
              case ModImm:
               CodeLen=PrefixCnt+1+AdrCnt;
               BAsmCode[PrefixCnt]=0xc6;
               memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
               break;
	      default: if (AdrMode!=ModNone) WrError(1350);
             END
           END
          break;
         case ModReg16:
	  if (AdrPart==3) /* SP */
	   BEGIN
	    OpSize=1; DecodeAdr(ArgStr[2]);
	    switch (AdrMode)
             BEGIN
	      case ModImm:
	       if (MomCPU<CPUZ380) WrError(1500);
	       else
	        BEGIN
	         BAsmCode[0]=0xed; BAsmCode[1]=0x82;
	         memcpy(BAsmCode+2,AdrVals,AdrCnt);
	         CodeLen=2+AdrCnt;
	        END
               break;
              default: if (AdrMode!=ModNone) WrError(1350);
	     END
	   END
	  else if (AdrPart!=2) WrError(1350);
	  else
	   BEGIN
	    z=PrefixCnt; /* merkt, ob Indexregister */
	    OpSize=1; DecodeAdr(ArgStr[2]);
	    switch (AdrMode)
             BEGIN
	      case ModReg16:
	       if ((AdrPart==2) AND (PrefixCnt!=0) AND ((PrefixCnt!=2) OR (BAsmCode[0]!=BAsmCode[1]))) WrError(1350);
	       else
	        BEGIN
	         if (PrefixCnt==2) PrefixCnt--; CodeLen=1+PrefixCnt;
	         BAsmCode[PrefixCnt]=0x09+(AdrPart << 4);
	        END
               break;
	      case ModAbs:
	       if (z!=0) WrError(1350);
	       else if (MomCPU<CPUZ380) WrError(1500);
	       else
	        BEGIN
	         BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0xc2;
	         memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	         CodeLen=PrefixCnt+2+AdrCnt;
	        END
               break;
              default: if (AdrMode!=ModNone) WrError(1350);
	     END
	   END
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   if (Memo("ADDW"))
    BEGIN
     if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
     else
      BEGIN
       OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
       switch (AdrMode)
        BEGIN
         case ModReg16:
	  if (PrefixCnt>0)      /* wenn Register, dann nie DDIR! */
	   BEGIN
	    BAsmCode[PrefixCnt]=0x87;
	    CodeLen=1+PrefixCnt;
	   END
	  else if (AdrPart==3) WrError(1350);
	  else
	   BEGIN
	    if (AdrPart==2) AdrPart=3;
	    BAsmCode[0]=0xed; BAsmCode[1]=0x84+AdrPart;
	    CodeLen=2;
	   END
          break;
         case ModReg8:
	  if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
	  else
	   BEGIN
	    BAsmCode[PrefixCnt]=0xc6;
	    memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	    CodeLen=PrefixCnt+1+AdrCnt;
	   END
          break;
         case ModImm:
	  BAsmCode[0]=0xed; BAsmCode[1]=0x86;
	  memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
	  break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   if ((Memo("ADC")) OR (Memo("SBC")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
	  if (AdrPart!=7) WrError(1350);
	  else
	   BEGIN
	    OpSize=0; DecodeAdr(ArgStr[2]);
	    switch (AdrMode)
             BEGIN
              case ModReg8:
	       CodeLen=PrefixCnt+1+AdrCnt;
	       BAsmCode[PrefixCnt]=0x88+AdrPart;
	       memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
	       break;
	      case ModImm:
	       CodeLen=PrefixCnt+1+AdrCnt;
	       BAsmCode[PrefixCnt]=0xce;
	       memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
	       break;
	      default: if (AdrMode!=ModNone) WrError(1350);
	     END
	    if ((Memo("SBC")) AND (CodeLen!=0)) BAsmCode[PrefixCnt]+=0x10;
	   END
          break; 
         case ModReg16:
	  if ((AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
	  else
	   BEGIN
	    OpSize=1; DecodeAdr(ArgStr[2]);
	    switch (AdrMode)
             BEGIN
	      case ModReg16:
	       if (PrefixCnt!=0) WrError(1350);
	       else
	        BEGIN
	         CodeLen=2; BAsmCode[0]=0xed;
	         BAsmCode[1]=0x42+(AdrPart << 4);
	         if (Memo("ADC")) BAsmCode[1]+=8;
	        END
               break;
	      default: if (AdrMode!=ModNone) WrError(1350);
	     END
	   END
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   if ((Memo("ADCW")) OR (Memo("SBCW")))
    BEGIN
     if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
     else
      BEGIN
       z=Ord(Memo("SBCW")) << 4;
       OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
       switch (AdrMode)
        BEGIN
         case ModReg16:
	  if (PrefixCnt>0)      /* wenn Register, dann nie DDIR! */
	   BEGIN
	    BAsmCode[PrefixCnt]=0x8f+z;
	    CodeLen=1+PrefixCnt;
	   END
	  else if (AdrPart==3) WrError(1350);
	  else
	   BEGIN
	    if (AdrPart==2) AdrPart=3;
	    BAsmCode[0]=0xed; BAsmCode[1]=0x8c+z+AdrPart;
	    CodeLen=2;
	   END
          break;
         case ModReg8:
	  if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
	  else
	   BEGIN
	    BAsmCode[PrefixCnt]=0xce + z; /* ANSI :-0 */
	    memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	    CodeLen=PrefixCnt+1+AdrCnt;
	   END
          break;
         case ModImm:
	  BAsmCode[0]=0xed; BAsmCode[1]=0x8e + z;
	  memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
	  break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   if ((Memo("INC")) OR (Memo("DEC")) OR (Memo("INCW")) OR (Memo("DECW")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       z=Ord((Memo("DEC")) OR (Memo("DECW")));
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
	  if (OpPart[strlen(OpPart)-1]=='W') WrError(1350);
	  else
	   BEGIN
	    CodeLen=PrefixCnt+1+AdrCnt;
	    BAsmCode[PrefixCnt]=0x04+(AdrPart << 3)+z;
	    memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	   END
          break;
         case ModReg16:
	  CodeLen=1+PrefixCnt;
	  BAsmCode[PrefixCnt]=0x03+(AdrPart << 4)+(z << 3);
	  break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   for (z=0; z<ShiftOrderCnt; z++)
    if (Memo(ShiftOrders[z]))
     BEGIN
      if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
      else if ((z==6) AND (MomCPU!=CPUZ80U)) WrError(1500); /* SLIA undok. Z80 */
      else
       BEGIN
        OpSize=0;
        DecodeAdr(ArgStr[ArgCnt]);
        switch (AdrMode)
         BEGIN
          case ModReg8:
           if ((PrefixCnt>0) AND (AdrPart!=6)) WrError(1350); /* IXL..IYU verbieten */
           else
            BEGIN
             if (ArgCnt==1) OK=True;
             else if (MomCPU!=CPUZ80U)
              BEGIN
               WrError(1500); OK=False;
              END
             else if ((AdrPart!=6) OR (PrefixCnt!=1) OR (NOT DecodeReg8(ArgStr[1],&AdrPart)))
              BEGIN
               WrError(1350); OK=False;
              END
             else OK=True;
             if (OK)
              BEGIN
               CodeLen=PrefixCnt+1+AdrCnt+1;
               BAsmCode[PrefixCnt]=0xcb;
               memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
               BAsmCode[PrefixCnt+1+AdrCnt]=AdrPart+(z << 3);
               if ((AdrPart==7) AND (z<4)) WrError(10);
              END
            END
           break;
          default: if (AdrMode!=ModNone) WrError(1350);
         END
       END
      return True;
     END
    else if ((strncmp(OpPart,ShiftOrders[z],strlen(ShiftOrders[z]))==0) AND (OpPart[strlen(OpPart)-1]=='W'))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else if ((MomCPU<CPUZ380) OR (z==6)) WrError(1500);
      else
       BEGIN
        OpSize=1; DecodeAdr(ArgStr[1]);
        switch (AdrMode)
         BEGIN
          case ModReg16:
           if (PrefixCnt>0)
            BEGIN
             BAsmCode[2]=0x04+(z << 3)+((BAsmCode[0] >> 5) & 1);
             BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
             CodeLen=3;
            END
           else if (AdrPart==3) WrError(1350);
           else
            BEGIN
             if (AdrPart==2) AdrPart=3;
             BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
             BAsmCode[2]=(z << 3)+AdrPart;
             CodeLen=3;
            END
           break;
          case ModReg8:
           if (AdrPart!=6) WrError(1350);
           else
            BEGIN
             if (AdrCnt==0)
              BEGIN
               BAsmCode[0]=0xed; PrefixCnt=1;
              END
             BAsmCode[PrefixCnt]=0xcb;
             memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
             BAsmCode[PrefixCnt+1+AdrCnt]=0x02+(z << 3);
             CodeLen=PrefixCnt+1+AdrCnt+1;
            END
           break;
          default: if (AdrMode!=ModNone) WrError(1350);
         END
       END
      return True;
     END

   for (z=0; z<BitOrderCnt; z++)
    if (Memo(BitOrders[z]))
     BEGIN
      if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
      else
       BEGIN
        DecodeAdr(ArgStr[ArgCnt]);
	switch (AdrMode)
         BEGIN
	  case ModReg8:
	   if ((AdrPart!=6) AND (PrefixCnt!=0)) WrError(1350);
	   else
	    BEGIN
             AdrByte=EvalIntExpression(ArgStr[ArgCnt-1],UInt3,&OK);
	     if (OK)
	      BEGIN
               if (ArgCnt==2) OK=True;
               else if (MomCPU!=CPUZ80U)
                BEGIN
                 WrError(1500); OK=False;
                END
               else if ((AdrPart!=6) OR (PrefixCnt!=1) OR (z==0) OR (NOT DecodeReg8(ArgStr[1],&AdrPart)))
                BEGIN
                 WrError(1350); OK=False;
                END
               else OK=True;
               if (OK)
                BEGIN
                 CodeLen=PrefixCnt+2+AdrCnt;
                 BAsmCode[PrefixCnt]=0xcb;
                 memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
                 BAsmCode[PrefixCnt+1+AdrCnt]=AdrPart+(AdrByte << 3)+((z+1) << 6);
                END
              END
	    END
           break;
          default: if (AdrMode!=ModNone) WrError(1350); 
	 END
       END
      return True;
     END

   if (Memo("MLT"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPUZ180) WrError(1500);
     else
      BEGIN
       DecodeAdr(ArgStr[1]);
       if ((AdrMode!=ModReg16) OR (PrefixCnt!=0)) WrError(1350);
       else
	BEGIN
	 BAsmCode[CodeLen]=0xed; BAsmCode[CodeLen+1]=0x4c+(AdrPart << 4);
	 CodeLen=2;
	END
      END
     return True;
    END

   if ((Memo("DIVUW")) OR (Memo("MULTW")) OR (Memo("MULTUW")))
    BEGIN
     if (ArgCnt==1)
      BEGIN
       strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"HL",255); ArgCnt=2;
      END
     if (MomCPU<CPUZ380) WrError(1500);
     else if (ArgCnt!=2) WrError(1110);
     else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
     else
      BEGIN
       AdrByte=Ord(*OpPart=='D');
       z=Ord(OpPart[strlen(OpPart)-2]=='U');
       OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
	  if ((AdrPart!=6) OR (PrefixCnt==0)) WrError(1350);
	  else
	   BEGIN
	    BAsmCode[PrefixCnt]=0xcb;
	    memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
	    BAsmCode[PrefixCnt+1+AdrCnt]=0x92+(z << 3)+(AdrByte << 5);
	    CodeLen=PrefixCnt+1+AdrCnt+1;
	   END
          break;
         case ModReg16:
	  if (AdrPart==3) WrError(1350);
	  else if (PrefixCnt==0)
	   BEGIN
	    if (AdrPart==2) AdrPart=3;
	    BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
	    BAsmCode[2]=0x90+AdrPart+(z << 3)+(AdrByte << 5);
	    CodeLen=3;
	   END
	  else
	   BEGIN
	    BAsmCode[2]=0x94+((BAsmCode[0] >> 5) & 1)+(z << 3)+(AdrByte << 5);
	    BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
	    CodeLen=3;
	   END
          break;
         case ModImm:
	  BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
	  BAsmCode[2]=0x97+(z << 3)+(AdrByte << 5);
	  memcpy(BAsmCode+3,AdrVals,AdrCnt);
	  CodeLen=3+AdrCnt;
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   if (Memo("TST"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPUZ180) WrError(1500);
     else
      BEGIN
       OpSize=0; DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
	  if (PrefixCnt!=0) WrError(1350);
	  else
	   BEGIN
	    BAsmCode[0]=0xed; BAsmCode[1]=4+(AdrPart << 3);
	    CodeLen=2;
	   END
          break;
         case ModImm:
	  BAsmCode[0]=0xed; BAsmCode[1]=0x64; BAsmCode[2]=AdrVals[0];
	  CodeLen=3;
	  break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   if (Memo("SWAP"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else
      BEGIN
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg16:
          if (AdrPart==3) WrError(1350);
	  else if (PrefixCnt==0)
	   BEGIN
	    if (AdrPart==2) AdrPart=3;
	    BAsmCode[0]=0xed; BAsmCode[1]=0x0e + (AdrPart << 4); /*?*/
	    CodeLen=2;
	   END
	  else
	   BEGIN
	    BAsmCode[PrefixCnt]=0x3e; CodeLen=PrefixCnt+1;
	   END
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return True;
    END

   return False;
END

	static void MakeCode_Z80(void)
BEGIN
   Boolean OK;
   LongWord AdrLong;
   LongInt AdrLInt;
   Byte AdrByte;
   int z;

   CodeLen=0; DontPrint=False; PrefixCnt=0; OpSize=0xff; MayLW=False;

   /* zu ignorierendes */

   if (Memo("")) return;

   /* Pseudoanweisungen */

   if (DecodePseudo()) return;

   /* letzten Praefix umkopieren */

   LastPrefix=CurrPrefix; CurrPrefix=Pref_IN_N;

   /* evtl. Datenablage */

   if (DecodeIntelPseudo(False)) return;

/*--------------------------------------------------------------------------*/
/* Instruktionspraefix */

   if (Memo("DDIR"))
    BEGIN
     if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else
      BEGIN
       OK=True;
       for (z=1; z<=ArgCnt; z++)
	if (OK)
	 BEGIN
          NLS_UpString(ArgStr[z]);
	  OK=ExtendPrefix(&CurrPrefix,ArgStr[z]);
	  if (NOT OK) WrError(1135);
	 END
       if (OK)
	BEGIN
         GetPrefixCode(CurrPrefix,BAsmCode+0,BAsmCode+1);
	 CodeLen=2;
	END
      END
     return;
    END

/*--------------------------------------------------------------------------*/
/* mit Sicherheit am haeufigsten... */

   if ((Memo("LD")) OR (Memo("LDW")))
    BEGIN
     DecodeLD();
     return;
    END

/*--------------------------------------------------------------------------*/
/* ohne Operanden */

   for (z=0; z<FixedOrderCnt; z++)
    if (Memo(FixedOrders[z].Name))
     BEGIN
      if (ArgCnt!=0) WrError(1110);
      else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
	if ((CodeLen=FixedOrders[z].Len)==2)
	 BEGIN
	  BAsmCode[0]=Hi(FixedOrders[z].Code);
	  BAsmCode[1]=Lo(FixedOrders[z].Code);
	 END
	else BAsmCode[0]=Lo(FixedOrders[z].Code);
       END;
      return;
     END

   /* nur Akku zugelassen */

   for (z=0; z<AccOrderCnt; z++)
    if (Memo(AccOrders[z].Name))
     BEGIN
      if (ArgCnt==0)
       BEGIN
	ArgCnt=1; strmaxcpy(ArgStr[1],"A",255);
       END
      if (ArgCnt!=1) WrError(1110);
      else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
      else if (MomCPU<AccOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
	if ((CodeLen=AccOrders[z].Len)==2)
	 BEGIN
	  BAsmCode[0]=Hi(AccOrders[z].Code);
	  BAsmCode[1]=Lo(AccOrders[z].Code);
	 END
	else BAsmCode[0]=Lo(AccOrders[z].Code);
       END
      return;
     END

   for (z=0; z<HLOrderCnt; z++)
    if (Memo(HLOrders[z].Name))
     BEGIN
      if (ArgCnt==0)
       BEGIN
	ArgCnt=1; strmaxcpy(ArgStr[1],"HL",255);
       END;
      if (ArgCnt!=1) WrError(1110);
      else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
      else if (MomCPU<HLOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
	if ((CodeLen=HLOrders[z].Len)==2)
	 BEGIN
	  BAsmCode[0]=Hi(HLOrders[z].Code);
	  BAsmCode[1]=Lo(HLOrders[z].Code);
	 END
	else BAsmCode[0]=Lo(HLOrders[z].Code);
       END
      return;
     END

/*-------------------------------------------------------------------------*/
/* Datentransfer */

   if ((Memo("PUSH")) OR (Memo("POP")))
    BEGIN
     z=Ord(Memo("PUSH")) << 2;
     if (ArgCnt!=1) WrError(1110);
     else if (strcasecmp(ArgStr[1],"SR")==0)
      if (MomCPU<CPUZ380) WrError(1500);
      else
       BEGIN
	CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0xc1+z;
       END
     else
      BEGIN
       if (strcasecmp(ArgStr[1],"SP")==0) strmaxcpy(ArgStr[1],"A",255);
       if (strcasecmp(ArgStr[1],"AF")==0) strmaxcpy(ArgStr[1],"SP",255);
       OpSize=1; MayLW=True;
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg16:
	  CodeLen=1+PrefixCnt;
	  BAsmCode[PrefixCnt]=0xc1+(AdrPart << 4)+z;
	  break;
         case ModImm:
	  if (MomCPU<CPUZ380) WrError(1500);
	  else
	   BEGIN
	    BAsmCode[PrefixCnt]=0xfd; BAsmCode[PrefixCnt+1]=0xf5;
	    memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
	    CodeLen=PrefixCnt+2+AdrCnt;
	   END
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return;
    END

   if (Memo("EX"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (ParPair("DE","HL"))
      BEGIN
       CodeLen=1; BAsmCode[0]=0xeb;
      END
     else if (ParPair("AF","AF\'"))
      BEGIN
       CodeLen=1; BAsmCode[0]=0x08;
      END
     else if (ParPair("AF","AF`"))
      BEGIN
       CodeLen=1; BAsmCode[0]=0x08;
      END
     else if (ParPair("(SP)","HL"))
      BEGIN
       CodeLen=1; BAsmCode[0]=0xe3;
      END
     else if (ParPair("(SP)","IX"))
      BEGIN
       CodeLen=2; BAsmCode[0]=IXPrefix; BAsmCode[1]=0xe3;
      END
     else if (ParPair("(SP)","IY"))
      BEGIN
       CodeLen=2; BAsmCode[0]=IYPrefix; BAsmCode[1]=0xe3;
      END
     else if (ParPair("(HL)","A"))
      BEGIN
       if (MomCPU<CPUZ380) WrError(1500);
       else
	BEGIN
	 CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x37;
	END
      END
     else
      BEGIN
       if (ArgStr[2][strlen(ArgStr[2])-1]=='\'')
	BEGIN
	 OK=True; ArgStr[2][strlen(ArgStr[2])-1]='\0';
	END
       else OK=False;
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
	  if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
	  else
	   BEGIN
	    AdrByte=AdrPart;
	     DecodeAdr(ArgStr[2]);
	     switch (AdrMode)
              BEGIN
	       case ModReg8:
	        if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
	        else if (MomCPU<CPUZ380) WrError(1500);
	        else if ((AdrByte==7) AND (NOT OK))
	         BEGIN
	          BAsmCode[0]=0xed; BAsmCode[1]=0x07+(AdrPart << 3);
	          CodeLen=2;
	         END
	        else if ((AdrPart==7) AND (NOT OK))
	         BEGIN
	          BAsmCode[0]=0xed; BAsmCode[1]=0x07+(AdrByte << 3);
	          CodeLen=2;
	         END
	        else if ((OK) AND (AdrPart==AdrByte))
	         BEGIN
	          BAsmCode[0]=0xcb; BAsmCode[1]=0x30+AdrPart;
	          CodeLen=2;
	         END
	        else WrError(1350);
                break;
	       default: if (AdrMode!=ModNone) WrError(1350);
	      END
	   END
          break;
         case ModReg16:
	  if (AdrPart==3) WrError(1350);
	  else if (PrefixCnt==0) /* EX R16,... */
	   BEGIN
	    if (AdrPart==2) AdrByte=3; else AdrByte=AdrPart;
	    DecodeAdr(ArgStr[2]);
	    switch (AdrMode)
             BEGIN
	      case ModReg16:
	       if (AdrPart==3) WrError(1350);
	       else if (MomCPU<CPUZ380) WrError(1500);
	       else if (OK)
	        BEGIN
	         if (AdrPart==2) AdrPart=3;
	         if ((PrefixCnt!=0) OR (AdrPart!=AdrByte)) WrError(1350);
	         else
	          BEGIN
	           CodeLen=3; BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
	           BAsmCode[2]=0x30+AdrByte;
	          END
	        END
	       else if (PrefixCnt==0)
	        BEGIN
	         if (AdrByte==0)
	          BEGIN
	           if (AdrPart==2) AdrPart=3;
	           BAsmCode[0]=0xed; BAsmCode[1]=0x01+(AdrPart << 2);
	           CodeLen=2;
	          END
	         else if (AdrPart==0)
	          BEGIN
	           BAsmCode[0]=0xed; BAsmCode[1]=0x01+(AdrByte << 2);
	           CodeLen=2;
	          END
	        END
	       else
	        BEGIN
	         if (AdrPart==2) AdrPart=3;
	         BAsmCode[1]=0x03+((BAsmCode[0] >> 2) & 8)+(AdrByte << 4);
	         BAsmCode[0]=0xed;
	         CodeLen=2;
	        END
               break;
	      default: if (AdrMode!=ModNone) WrError(1350);
	     END
	   END
	  else /* EX XY,... */
	   BEGIN
	    DecodeAdr(ArgStr[2]);
	    switch (AdrMode)
             BEGIN
 	      case ModReg16:
	       if (AdrPart==3) WrError(1350);
	       else if (MomCPU<CPUZ380) WrError(1500);
	       else if (OK)
  	        if ((PrefixCnt!=2) OR (BAsmCode[0]!=BAsmCode[1])) WrError(1350);
	        else
	         BEGIN
	          CodeLen=3; BAsmCode[2]=((BAsmCode[0] >> 5) & 1)+0x34;
	          BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
	         END
	       else if (PrefixCnt==1)
	        BEGIN
	         if (AdrPart==2) AdrPart=3; 
	         BAsmCode[1]=((BAsmCode[0] >> 2) & 8)+3+(AdrPart << 4);
	         BAsmCode[0]=0xed;
	         CodeLen=2;
	        END
	       else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
	       else
	        BEGIN
	         BAsmCode[0]=0xed; BAsmCode[1]=0x2b; CodeLen=2;
	        END
               break;
	      default: if (AdrMode!=ModNone) WrError(1350);
	     END
	   END
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     return;
    END

/*-------------------------------------------------------------------------*/
/* Arithmetik */

   if (CodeAri()) return;

/*-------------------------------------------------------------------------*/
/* Ein/Ausgabe */

   if (Memo("TSTI"))
    BEGIN
     if (MomCPU!=CPUZ80U) WrError(1500);
     else if (ArgCnt!=0) WrError(1110);
     else
      BEGIN
       BAsmCode[0]=0xed; BAsmCode[1]=0x70; CodeLen=2;
      END
     return;
    END

   if ((Memo("IN")) OR (Memo("OUT")))
    BEGIN
     if ((ArgCnt==1) AND (Memo("IN")))
      BEGIN
       if (MomCPU!=CPUZ80U) WrError(1500);
       else if (strcasecmp(ArgStr[1],"(C)")!=0) WrError(1350);
       else
        BEGIN
         BAsmCode[0]=0xed; BAsmCode[1]=0x70; CodeLen=2;
        END
      END
     else if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (Memo("OUT"))
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
	END
       if (strcasecmp(ArgStr[2],"(C)")==0)
	BEGIN
	 OpSize=0; DecodeAdr(ArgStr[1]);
	 switch (AdrMode)
          BEGIN
	   case ModReg8:
	    if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
	    else
	     BEGIN
	      CodeLen=2;
	      BAsmCode[0]=0xed; BAsmCode[1]=0x40+(AdrPart << 3);
	      if (Memo("OUT")) BAsmCode[1]++;
	     END
            break;
	   case ModImm:
	    if (Memo("IN")) WrError(1350);
            else if ((MomCPU==CPUZ80U) AND (AdrVals[0]==0))
             BEGIN
              BAsmCode[0]=0xed; BAsmCode[1]=0x71; CodeLen=2;
             END
	    else if (MomCPU<CPUZ380) WrError(1500);
	    else
	     BEGIN
	      BAsmCode[0]=0xed; BAsmCode[1]=0x71; BAsmCode[2]=AdrVals[0];
	      CodeLen=3;
	     END
            break;
	   default: if (AdrMode!=ModNone) WrError(1350);
	  END
	END
       else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
       else
	BEGIN
	 BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt8,&OK);
	 if (OK)
	  BEGIN
	   ChkSpace(SegIO);
	   CodeLen=2;
	   BAsmCode[0]=(Memo("OUT")) ? 0xd3 : 0xdb;
	  END
	END
      END
     return;
    END

   if ((Memo("INW")) OR (Memo("OUTW")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else
      BEGIN
       if (Memo("OUTW"))
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
	END;
       if (strcasecmp(ArgStr[2],"(C)")!=0) WrError(1350);
       else
	BEGIN
	 OpSize=1; DecodeAdr(ArgStr[1]);
	 switch (AdrMode)
          BEGIN
	   case ModReg16:
	    if ((AdrPart==3) OR (PrefixCnt>0)) WrError(1350);
	    else
	     BEGIN
	      switch (AdrPart)
               BEGIN
	        case 1: AdrPart=2; break;
	        case 2: AdrPart=7; break;
	       END
	      BAsmCode[0]=0xdd; BAsmCode[1]=0x40+(AdrPart << 3);
	      if (Memo("OUTW")) BAsmCode[1]++;
	      CodeLen=2;
	     END
            break;
	   case ModImm:
	    if (Memo("INW")) WrError(1350);
	    else
	     BEGIN
	      BAsmCode[0]=0xfd; BAsmCode[1]=0x79;
	      memcpy(BAsmCode+2,AdrVals,AdrCnt);
	      CodeLen=2+AdrCnt;
	     END
            break;
	   default: if (AdrMode!=ModNone) WrError(1350);
	  END
	END
      END
     return;
    END

   if ((Memo("IN0")) OR (Memo("OUT0")))
    BEGIN
     if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
     else if ((ArgCnt==1) AND (Memo("OUT0"))) WrError(1110);
     else if (MomCPU<CPUZ180) WrError(1500);
     else
      BEGIN
       if (Memo("OUT0"))
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
	END
       OpSize=0;
       if (ArgCnt==1)
	BEGIN
	 AdrPart=6; OK=True;
	END
       else
	BEGIN
	 DecodeAdr(ArgStr[1]);
	 if ((AdrMode==ModReg8) AND (AdrPart!=6) AND (PrefixCnt==0)) OK=True;
	 else
	  BEGIN
	   OK=False; if (AdrMode!=ModNone) WrError(1350);
	  END
	END
       if (OK)
	BEGIN
	 BAsmCode[2]=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
	 if (OK)
	  BEGIN
	   BAsmCode[0]=0xed; BAsmCode[1]=AdrPart << 3;
	   if (Memo("OUT0")) BAsmCode[1]++;
	   CodeLen=3;
	  END
	END
      END
     return;
    END

   if ((Memo("INA")) OR (Memo("INAW")) OR (Memo("OUTA")) OR (Memo("OUTAW")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else
      BEGIN
       if (*OpPart=='O')
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
	END
       OpSize=Ord(OpPart[strlen(OpPart)-1]=='W');
       if (((OpSize==0) AND (strcasecmp(ArgStr[1],"A")!=0))
       OR  ((OpSize==1) AND (strcasecmp(ArgStr[1],"HL")!=0))) WrError(1350);
       else
	BEGIN
         AdrLong=EvalIntExpression(ArgStr[2],ExtFlag?Int32:UInt8,&OK);
	 if (OK)
	  BEGIN
	   ChkSpace(SegIO);
	   if (AdrLong>0xffffff) ChangeDDPrefix("IW");
	   else if (AdrLong>0xffff) ChangeDDPrefix("IB");
	   BAsmCode[PrefixCnt]=0xed+(OpSize << 4);
	   BAsmCode[PrefixCnt+1]=0xd3+(Ord(*OpPart=='I') << 3);
	   BAsmCode[PrefixCnt+2]=AdrLong & 0xff;
	   BAsmCode[PrefixCnt+3]=(AdrLong >> 8) & 0xff;
	   CodeLen=PrefixCnt+4;
	   if (AdrLong>0xffff)
	    BAsmCode[CodeLen++]=(AdrLong >> 16) & 0xff;
	   if (AdrLong>0xffffff)
	    BAsmCode[CodeLen++]=(AdrLong >> 24) & 0xff;
	  END
	END
      END
     return;
    END

   if (Memo("TSTIO"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPUZ180) WrError(1500);
     else
      BEGIN
       BAsmCode[2]=EvalIntExpression(ArgStr[1],Int8,&OK);
       if (OK)
	BEGIN
	 BAsmCode[0]=0xed; BAsmCode[1]=0x74;
	 CodeLen=3;
	END
      END
     return;
    END

/*-------------------------------------------------------------------------*/
/* Spruenge */

   if (Memo("RET"))
    BEGIN
     if (ArgCnt==0)
      BEGIN
       CodeLen=1; BAsmCode[0]=0xc9;
      END
     else if (ArgCnt!=1) WrError(1110);
     else if (NOT DecodeCondition(ArgStr[1],&z)) WrError(1360);
     else
      BEGIN
       CodeLen=1; BAsmCode[0]=0xc0+(z << 3);
      END
     return;
    END

   if (Memo("JP"))
    BEGIN
     if (ArgCnt==1)
      BEGIN
       if (strcasecmp(ArgStr[1],"(HL)")==0)
        BEGIN
         CodeLen=1; BAsmCode[0]=0xe9; OK=False;
        END
       else if (strcasecmp(ArgStr[1],"(IX)")==0)
        BEGIN
         CodeLen=2; BAsmCode[0]=IXPrefix; BAsmCode[1]=0xe9; OK=False;
	END
       else if (strcasecmp(ArgStr[1],"(IY)")==0)
        BEGIN
         CodeLen=2; BAsmCode[0]=IYPrefix; BAsmCode[1]=0xe9; OK=False;
        END
       else
        BEGIN
	 z=1; OK=True;
        END
      END
     else if (ArgCnt==2)
      BEGIN
       OK=DecodeCondition(ArgStr[1],&z);
       if (OK) z<<=3; else WrError(1360);
      END
     else
      BEGIN
       WrError(1110); OK=False;
      END
     if (OK)
      BEGIN
       AdrLong=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
       if (OK)
#ifdef __STDC__
        if ((AdrLong & 0xffff0000u)==0)
#else
        if ((AdrLong & 0xffff0000)==0)
#endif
         BEGIN
          CodeLen=3; BAsmCode[0]=0xc2+z;
	  BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
         END
#ifdef __STDC__
        else if ((AdrLong & 0xff000000u)==0)
#else
        else if ((AdrLong & 0xff000000)==0)
#endif
         BEGIN
          ChangeDDPrefix("IB");
          CodeLen=4+PrefixCnt; BAsmCode[PrefixCnt]=0xc2+z;
          BAsmCode[PrefixCnt+1]=Lo(AdrLong);
          BAsmCode[PrefixCnt+2]=Hi(AdrLong);
          BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
         END
        else
         BEGIN
          ChangeDDPrefix("IW");
          CodeLen=5+PrefixCnt; BAsmCode[PrefixCnt]=0xc2+z;
          BAsmCode[PrefixCnt+1]=Lo(AdrLong);
          BAsmCode[PrefixCnt+2]=Hi(AdrLong);
	  BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
          BAsmCode[PrefixCnt+4]=Hi(AdrLong >> 16);
         END
      END
     return;
    END

   if (Memo("CALL"))
    BEGIN
     if (ArgCnt==1)
      BEGIN
       z=9; OK=True;
      END
     else if (ArgCnt==2)
      BEGIN
       OK=DecodeCondition(ArgStr[1],&z);
       if (OK) z<<=3; else WrError(1360);
      END
     else
      BEGIN
       WrError(1110); OK=False;
      END
     if (OK)
      BEGIN
       AdrLong=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
       if (OK)
#ifdef __STDC__
        if ((AdrLong & 0xffff0000u)==0)
#else
        if ((AdrLong & 0xffff0000)==0)
#endif
         BEGIN
          CodeLen=3; BAsmCode[0]=0xc4+z;
	  BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
         END
#ifdef __STDC__
        else if ((AdrLong & 0xff000000u)==0)
#else
        else if ((AdrLong & 0xff000000)==0)
#endif
         BEGIN
          ChangeDDPrefix("IB");
          CodeLen=4+PrefixCnt; BAsmCode[PrefixCnt]=0xc4+z;
	  BAsmCode[PrefixCnt+1]=Lo(AdrLong);
          BAsmCode[PrefixCnt+2]=Hi(AdrLong);
          BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
         END
        else
         BEGIN
          ChangeDDPrefix("IW");
          CodeLen=5+PrefixCnt; BAsmCode[PrefixCnt]=0xc4+z;
          BAsmCode[PrefixCnt+1]=Lo(AdrLong);
          BAsmCode[PrefixCnt+2]=Hi(AdrLong);
          BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
          BAsmCode[PrefixCnt+4]=Hi(AdrLong >> 16);
         END
      END
     return;
    END

   if (Memo("JR"))
    BEGIN
     if (ArgCnt==1)
      BEGIN
       z=3; OK=True;
      END
     else if (ArgCnt==2)
      BEGIN
       OK=DecodeCondition(ArgStr[1],&z);
       if ((OK) AND (z>3)) OK=False;
       if (OK) z+=4; else WrError(1360);
      END
     else
      BEGIN
       WrError(1110); OK=False;
      END
     if (OK)
      BEGIN
       AdrLInt=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
       if (OK)
        BEGIN
         AdrLInt-=EProgCounter()+2;
         if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
          BEGIN
           CodeLen=2; BAsmCode[0]=z << 3;
           BAsmCode[1]=AdrLInt & 0xff;
          END
         else
          if (MomCPU<CPUZ380) WrError(1370);
          else
           BEGIN
	    AdrLInt-=2;
            if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
             BEGIN
              CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=z << 3;
              BAsmCode[2]=AdrLInt & 0xff;
              BAsmCode[3]=(AdrLInt >> 8) & 0xff;
             END
            else
             BEGIN
              AdrLInt--;
              if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
               BEGIN
                CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=z << 3;
                BAsmCode[2]=AdrLInt & 0xff;
                BAsmCode[3]=(AdrLInt >> 8) & 0xff;
                BAsmCode[4]=(AdrLInt >> 16) & 0xff;
               END
              else WrError(1370);
             END
           END
        END
      END
     return;
    END

   if (Memo("CALR"))
    BEGIN
     if (ArgCnt==1)
      BEGIN
       z=9; OK=True;
      END
     else if (ArgCnt==2)
      BEGIN
       OK=DecodeCondition(ArgStr[1],&z);
       if (OK) z<<=3; else WrError(1360);
      END
     else
      BEGIN
       WrError(1110); OK=False;
      END
     if (OK)
      if (MomCPU<CPUZ380) WrError(1500);
      else
       BEGIN
        AdrLInt=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
        if (OK)
         BEGIN
          AdrLInt-=EProgCounter()+3;
          if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
           BEGIN
            CodeLen=3; BAsmCode[0]=0xed; BAsmCode[1]=0xc4+z;
            BAsmCode[2]=AdrLInt & 0xff;
           END
          else
           BEGIN
            AdrLInt--;
            if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
	     BEGIN
              CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=0xc4+z;
              BAsmCode[2]=AdrLInt & 0xff;
              BAsmCode[3]=(AdrLInt >> 8) & 0xff;
             END
            else
             BEGIN
              AdrLInt--;
              if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
               BEGIN
                CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=0xc4+z;
                BAsmCode[2]=AdrLInt & 0xff;
                BAsmCode[3]=(AdrLInt >> 8) & 0xff;
		BAsmCode[4]=(AdrLInt >> 16) & 0xff;
               END
              else WrError(1370);
             END
           END
         END
       END
     return;
    END

   if (Memo("DJNZ"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       AdrLInt=EvalAbsAdrExpression(ArgStr[1],&OK);
       if (OK)
        BEGIN
         AdrLInt-=EProgCounter()+2;
         if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
          BEGIN
           CodeLen=2; BAsmCode[0]=0x10; BAsmCode[1]=Lo(AdrLInt);
	  END
         else if (MomCPU<CPUZ380) WrError(1370);
         else
          BEGIN
           AdrLInt-=2;
           if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
            BEGIN
             CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=0x10;
             BAsmCode[2]=AdrLInt & 0xff;
             BAsmCode[3]=(AdrLInt >> 8) & 0xff;
            END
           else
            BEGIN
	     AdrLInt--;
             if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
              BEGIN
               CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=0x10;
               BAsmCode[2]=AdrLInt & 0xff;
               BAsmCode[3]=(AdrLInt >> 8) & 0xff;
               BAsmCode[4]=(AdrLInt >> 16) & 0xff;
              END
             else WrError(1370);
            END
          END
        END
      END
     return;
    END

   if (Memo("RST"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       FirstPassUnknown=False;
       AdrByte=EvalIntExpression(ArgStr[1],Int8,&OK);
       if (FirstPassUnknown) AdrByte=AdrByte & 0x38;  
       if (OK)
        if ((AdrByte>0x38) OR ((AdrByte & 7)!=0)) WrError(1320);
        else
         BEGIN
	  CodeLen=1; BAsmCode[0]=0xc7+AdrByte;
         END
      END
     return;
    END

/*-------------------------------------------------------------------------*/
/* Sonderbefehle */

   if ((Memo("EI")) OR (Memo("DI")))
    BEGIN
     if (ArgCnt==0)
      BEGIN
       BAsmCode[0]=0xf3+(Ord(Memo("EI")) << 3);
       CodeLen=1;
      END
     else if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else
      BEGIN
       BAsmCode[2]=EvalIntExpression(ArgStr[1],UInt8,&OK);
       if (OK)
	BEGIN
	 BAsmCode[0]=0xdd; BAsmCode[1]=0xf3+(Ord(Memo("EI")) << 3);
	 CodeLen=3;
	END
      END
     return;
    END

   if (Memo("IM"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       AdrByte=EvalIntExpression(ArgStr[1],UInt2,&OK);
       if (OK)
	if (AdrByte>3) WrError(1320);
	else if ((AdrByte==3) AND (MomCPU<CPUZ380)) WrError(1500);
	else
	 BEGIN
	  if (AdrByte==3) AdrByte=1;
	  else if (AdrByte>=1) AdrByte++;
	  CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x46+(AdrByte << 3);
	 END
      END
     return;
    END

   if (Memo("LDCTL"))
    BEGIN
     OpSize=0;
     if (ArgCnt!=2) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else if (DecodeSFR(ArgStr[1],&AdrByte))
      BEGIN
       DecodeAdr(ArgStr[2]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
          if (AdrPart!=7) WrError(1350);
          else
           BEGIN
            BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
            BAsmCode[1]=0xc8+((AdrByte & 4) << 2);
            CodeLen=2;
           END
          break;
         case ModReg16:
          if ((AdrByte!=1) OR (AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
          else
           BEGIN
            BAsmCode[0]=0xed; BAsmCode[1]=0xc8; CodeLen=2;
           END
          break;
         case ModImm:
          BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
          BAsmCode[1]=0xca+((AdrByte & 4) << 2);
          BAsmCode[2]=AdrVals[0];
          CodeLen=3;
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     else if (DecodeSFR(ArgStr[2],&AdrByte))
      BEGIN
       DecodeAdr(ArgStr[1]);
       switch (AdrMode)
        BEGIN
         case ModReg8:
          if ((AdrPart!=7) OR (AdrByte==1)) WrError(1350);
          else
           BEGIN
            BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
            BAsmCode[1]=0xd0;
            CodeLen=2;
           END
          break;
         case ModReg16:
          if ((AdrByte!=1) OR (AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
          else
           BEGIN
            BAsmCode[0]=0xed; BAsmCode[1]=0xc0; CodeLen=2;
           END
          break;
         default: if (AdrMode!=ModNone) WrError(1350);
        END
      END
     else WrError(1350);
     return;
    END

   if ((Memo("RESC")) OR (Memo("SETC")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPUZ380) WrError(1500);
     else
      BEGIN
       AdrByte=0xff; NLS_UpString(ArgStr[1]);
       if (strcmp(ArgStr[1],"LW")==0) AdrByte=1;
       else if (strcmp(ArgStr[1],"LCK")==0) AdrByte=2;
       else if (strcmp(ArgStr[1],"XM")==0) AdrByte=3;
       else WrError(1440);
       if (AdrByte!=0xff)
        BEGIN
         CodeLen=2; BAsmCode[0]=0xcd+(AdrByte << 4);
	 BAsmCode[1]=0xf7+(Ord(Memo("RESC")) << 3);
        END
      END
     return;
    END

   WrXError(1200,OpPart);
END

	static void InitCode_Z80(void)
BEGIN
   SaveInitProc();
   SetFlag(&ExtFlag,ExtFlagName,False);
   SetFlag(&LWordFlag,LWordFlagName,False);
END

	static Boolean IsDef_Z80(void)
BEGIN
   return Memo("PORT");
END

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

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

   PCSymbol="$"; HeaderID=0x51; NOPCode=0x00;
   DivideChars=","; HasAttrs=False;

   ValidSegs=(1<<SegCode)+(1<<SegIO);
   Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
   SegLimits[SegCode] = CodeEnd();
   Grans[SegIO  ]=1; ListGrans[SegIO  ]=1; SegInits[SegIO  ]=0;
   SegLimits[SegIO  ] = PortEnd();

   MakeCode=MakeCode_Z80; IsDef=IsDef_Z80;
   SwitchFrom=SwitchFrom_Z80; InitFields();

   /* erweiterte Modi nur bei Z380 */

   if (MomCPU>=CPUZ380)
    BEGIN
     AddONOFF("EXTMODE",   &ExtFlag   , ExtFlagName   ,False);
     AddONOFF("LWORDMODE", &LWordFlag , LWordFlagName ,False);
    END
   SetFlag(&ExtFlag,ExtFlagName,False);
   SetFlag(&LWordFlag,LWordFlagName,False);
END

	void codez80_init(void)
BEGIN
   CPUZ80 =AddCPU("Z80" ,SwitchTo_Z80);
   CPUZ80U=AddCPU("Z80UNDOC",SwitchTo_Z80);
   CPUZ180=AddCPU("Z180",SwitchTo_Z80);
   CPUZ380=AddCPU("Z380",SwitchTo_Z80);

   SaveInitProc=InitPassProc; InitPassProc=InitCode_Z80;
END
