/* codeavr.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator Atmel AVR                                                   */             
/*                                                                           */
/* Historie: 26.12.1996 Grundsteinlegung                                     */             
/*            7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars     */
/*           18. 8.1998 BookKeeping-Aufruf bei RES                           */
/*           15.10.1998 LDD/STD mit <reg>+<symbol> ging nicht                */
/*            2. 5.1999 JMP/CALL momentan bei keinem Mitglied erlaubt        */
/*                      WRAPMODE eingebaut                                   */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"

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

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

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

typedef struct
         {
          char *Name;
          CPUVar MinCPU;
          Word Code;
         } ArchOrder;


#define FixedOrderCnt 24
#define Reg1OrderCnt 10
#define Reg2OrderCnt 12
#define Reg3OrderCnt 4
#define ImmOrderCnt 7
#define RelOrderCnt 18
#define BitOrderCnt 4
#define PBitOrderCnt 4


static CPUVar CPU90S1200,CPU90S2313,CPU90S4414,CPU90S8515;

static ArchOrder *FixedOrders;
static ArchOrder *Reg1Orders;
static ArchOrder *Reg2Orders;
static FixedOrder *Reg3Orders;
static FixedOrder *ImmOrders;
static FixedOrder *RelOrders;
static FixedOrder *BitOrders;
static FixedOrder *PBitOrders;

static Boolean WrapFlag;
static LongInt ORMask, SignMask;

static char *WrapFlagName = "WRAPMODE";

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

	static LongInt CutAdr(LongInt Adr)
BEGIN
   if ((Adr & SignMask) != 0) return (Adr | ORMask);
   else return (Adr & SegLimits[SegCode]);
END

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

        static void AddFixed(char *NName, CPUVar NMin, Word NCode)
BEGIN
   if (InstrZ>FixedOrderCnt) exit(255);
   FixedOrders[InstrZ].Name=NName;
   FixedOrders[InstrZ].MinCPU=NMin;
   FixedOrders[InstrZ++].Code=NCode;
END

        static void AddReg1(char *NName, CPUVar NMin, Word NCode)
BEGIN
   if (InstrZ>=Reg1OrderCnt) exit(255);
   Reg1Orders[InstrZ].Name=NName;
   Reg1Orders[InstrZ].MinCPU=NMin;
   Reg1Orders[InstrZ++].Code=NCode;
END
   
        static void AddReg2(char *NName, CPUVar NMin, Word NCode)
BEGIN
   if (InstrZ>=Reg2OrderCnt) exit(255);
   Reg2Orders[InstrZ].Name=NName;
   Reg2Orders[InstrZ].MinCPU=NMin;
   Reg2Orders[InstrZ++].Code=NCode;
END

        static void AddReg3(char *NName, Word NCode)
BEGIN
   if (InstrZ>=Reg3OrderCnt) exit(255);
   Reg3Orders[InstrZ].Name=NName;
   Reg3Orders[InstrZ++].Code=NCode;
END

        static void AddImm(char *NName, Word NCode)
BEGIN
   if (InstrZ>=ImmOrderCnt) exit(255);
   ImmOrders[InstrZ].Name=NName;
   ImmOrders[InstrZ++].Code=NCode;
END

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

        static void AddBit(char *NName, Word NCode)
BEGIN
   if (InstrZ>=BitOrderCnt) exit(255);
   BitOrders[InstrZ].Name=NName;
   BitOrders[InstrZ++].Code=NCode;
END

        static void AddPBit(char *NName, Word NCode)
BEGIN
   if (InstrZ>=PBitOrderCnt) exit(255);
   PBitOrders[InstrZ].Name=NName;
   PBitOrders[InstrZ++].Code=NCode;
END

        static void InitFields(void)
BEGIN
   FixedOrders=(ArchOrder *) malloc(sizeof(ArchOrder)*FixedOrderCnt); InstrZ=0;
   AddFixed("IJMP" ,CPU90S2313,0x9409); AddFixed("ICALL",CPU90S2313,0x9509);
   AddFixed("RET"  ,CPU90S1200,0x9508); AddFixed("RETI" ,CPU90S1200,0x9518);
   AddFixed("LPM"  ,CPU90S2313,0x95c8); AddFixed("SEC"  ,CPU90S1200,0x9408);
   AddFixed("CLC"  ,CPU90S1200,0x9488); AddFixed("SEN"  ,CPU90S1200,0x9428);
   AddFixed("CLN"  ,CPU90S1200,0x94a8); AddFixed("SEZ"  ,CPU90S1200,0x9418);
   AddFixed("CLZ"  ,CPU90S1200,0x9498); AddFixed("SEI"  ,CPU90S1200,0x9478);
   AddFixed("CLI"  ,CPU90S1200,0x94f8); AddFixed("SES"  ,CPU90S1200,0x9448);
   AddFixed("CLS"  ,CPU90S1200,0x94c8); AddFixed("SEV"  ,CPU90S1200,0x9438);
   AddFixed("CLV"  ,CPU90S1200,0x94b8); AddFixed("SET"  ,CPU90S1200,0x9468);
   AddFixed("CLT"  ,CPU90S1200,0x94e8); AddFixed("SEH"  ,CPU90S1200,0x9458);
   AddFixed("CLH"  ,CPU90S1200,0x94d8); AddFixed("NOP"  ,CPU90S1200,0x0000);
   AddFixed("SLEEP",CPU90S1200,0x9588); AddFixed("WDR"  ,CPU90S1200,0x95a8);

   Reg1Orders=(ArchOrder *) malloc(sizeof(ArchOrder)*Reg1OrderCnt); InstrZ=0;
   AddReg1("COM"  ,CPU90S1200,0x9400); AddReg1("NEG"  ,CPU90S1200,0x9401);
   AddReg1("INC"  ,CPU90S1200,0x9403); AddReg1("DEC"  ,CPU90S1200,0x940a);
   AddReg1("PUSH" ,CPU90S2313,0x920f); AddReg1("POP"  ,CPU90S2313,0x900f);
   AddReg1("LSR"  ,CPU90S1200,0x9406); AddReg1("ROR"  ,CPU90S1200,0x9407);
   AddReg1("ASR"  ,CPU90S1200,0x9405); AddReg1("SWAP" ,CPU90S1200,0x9402);

   Reg2Orders=(ArchOrder *) malloc(sizeof(ArchOrder)*Reg2OrderCnt); InstrZ=0;
   AddReg2("ADD"  ,CPU90S1200,0x0c00); AddReg2("ADC"  ,CPU90S1200,0x1c00);
   AddReg2("SUB"  ,CPU90S1200,0x1800); AddReg2("SBC"  ,CPU90S1200,0x0800);
   AddReg2("AND"  ,CPU90S1200,0x2000); AddReg2("OR"   ,CPU90S1200,0x2800);
   AddReg2("EOR"  ,CPU90S1200,0x2400); AddReg2("CPSE" ,CPU90S1200,0x1000);
   AddReg2("CP"   ,CPU90S1200,0x1400); AddReg2("CPC"  ,CPU90S1200,0x0400);
   AddReg2("MOV"  ,CPU90S1200,0x2c00); AddReg2("MUL"  ,CPU90S8515+1,0x9c00);

   Reg3Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Reg3OrderCnt); InstrZ=0;
   AddReg3("CLR"  ,0x2400); AddReg3("TST"  ,0x2000); AddReg3("LSL"  ,0x0c00);
   AddReg3("ROL"  ,0x1c00);

   ImmOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*ImmOrderCnt); InstrZ=0;
   AddImm("SUBI" ,0x5000); AddImm("SBCI" ,0x4000); AddImm("ANDI" ,0x7000);
   AddImm("ORI"  ,0x6000); AddImm("SBR"  ,0x6000); AddImm("CPI"  ,0x3000);
   AddImm("LDI"  ,0xe000);

   RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0;
   AddRel("BRCC" ,0xf400); AddRel("BRCS" ,0xf000); AddRel("BREQ" ,0xf001);
   AddRel("BRGE" ,0xf404); AddRel("BRSH" ,0xf400); AddRel("BRID" ,0xf407);
   AddRel("BRIE" ,0xf007); AddRel("BRLO" ,0xf000); AddRel("BRLT" ,0xf004);
   AddRel("BRMI" ,0xf002); AddRel("BRNE" ,0xf401); AddRel("BRHC" ,0xf405);
   AddRel("BRHS" ,0xf005); AddRel("BRPL" ,0xf402); AddRel("BRTC" ,0xf406);
   AddRel("BRTS" ,0xf006); AddRel("BRVC" ,0xf403); AddRel("BRVS" ,0xf003);

   BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); InstrZ=0;
   AddBit("BLD"  ,0xf800); AddBit("BST"  ,0xfa00);
   AddBit("SBRC" ,0xfc00); AddBit("SBRS" ,0xfe00);

   PBitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*PBitOrderCnt); InstrZ=0;
   AddPBit("CBI" ,0x9800); AddPBit("SBI" ,0x9a00);
   AddPBit("SBIC",0x9900); AddPBit("SBIS",0x9b00);
END

        static void DeinitFields(void)
BEGIN
   free(FixedOrders);
   free(Reg1Orders);
   free(Reg2Orders);
   free(Reg3Orders);
   free(ImmOrders);
   free(RelOrders);
   free(BitOrders);
   free(PBitOrders);
END

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

        static Boolean DecodeReg(char *Asc, Word *Erg)
BEGIN
   Boolean io;
   char *s;

   if (FindRegDef(Asc,&s)) Asc=s;

   if ((strlen(Asc)<2) OR (strlen(Asc)>3) OR (toupper(*Asc)!='R')) return False;
   else
    BEGIN
     *Erg=ConstLongInt(Asc+1,&io);
     return ((io) AND (*Erg<32));
    END
END

	static Boolean DecodeMem(char * Asc, Word *Erg)
BEGIN
   if (strcasecmp(Asc,"X")==0) *Erg=0x1c;
   else if (strcasecmp(Asc,"X+")==0) *Erg=0x1d;
   else if (strcasecmp(Asc,"-X")==0) *Erg=0x1e;
   else if (strcasecmp(Asc,"Y")==0) *Erg=0x08;
   else if (strcasecmp(Asc,"Y+")==0) *Erg=0x19;
   else if (strcasecmp(Asc,"-Y")==0) *Erg=0x1a;
   else if (strcasecmp(Asc,"Z")==0) *Erg=0x00;
   else if (strcasecmp(Asc,"Z+")==0) *Erg=0x11;
   else if (strcasecmp(Asc,"-Z")==0) *Erg=0x12;
   else return False;
   return True;
END

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

	static Boolean DecodePseudo(void)
BEGIN
   Integer Size;
   int z,z2;
   Boolean ValOK;
   TempResult t;
   LongInt MinV,MaxV;

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

   if (Memo("RES"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       FirstPassUnknown=False;
       Size=EvalIntExpression(ArgStr[1],Int16,&ValOK);
       if (FirstPassUnknown) WrError(1820);
       if ((ValOK) AND (NOT FirstPassUnknown))
	BEGIN
	 DontPrint=True;
	 CodeLen=Size;
	 BookKeeping();
	END
      END
     return True;
    END

   if (Memo("DATA"))
    BEGIN
     MaxV=(ActPC==SegCode)?65535:255; MinV=(-((MaxV+1) >> 1));
     if (ArgCnt==0) WrError(1110);
     else
      BEGIN
       ValOK=True;
       for (z=1; z<=ArgCnt; z++)
	if (ValOK)
	 BEGIN
	  EvalExpression(ArgStr[z],&t);
          if ((FirstPassUnknown) AND (t.Typ==TempInt)) t.Contents.Int&=MaxV;
	  switch (t.Typ)
           BEGIN
	    case TempInt:
             if (ChkRange(t.Contents.Int,MinV,MaxV))
              if (ActPC==SegCode) WAsmCode[CodeLen++]=t.Contents.Int;
              else BAsmCode[CodeLen++]=t.Contents.Int;
             break;
	    case TempFloat:
             WrError(1135); ValOK=False;
	     break;
	    case TempString:
             for (z2=0; z2<strlen(t.Contents.Ascii); z2++)
	      BEGIN
               Size=CharTransTable[((usint) t.Contents.Ascii[z2])&0xff];
               if (ActPC!=SegCode) BAsmCode[CodeLen++]=Size;
               else if ((z2&1)==0) WAsmCode[CodeLen++]=Size;
               else WAsmCode[CodeLen-1]+=Size<<8;
	      END
             break;
	    default:
             ValOK=False;
	   END
	 END
       if (NOT ValOK) CodeLen=0;
      END
     return True;
    END

   if (Memo("REG"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else AddRegDef(LabPart,ArgStr[1]);
     return True;
    END

   return False;
END

        static void MakeCode_AVR(void)
BEGIN
   int z;
   LongInt AdrInt;
   Word Reg1,Reg2;
   Boolean OK;

   CodeLen=0; DontPrint=False;

   /* zu ignorierendes */

   if (Memo("")) return;

   /* Pseudoanweisungen */

   if (DecodePseudo()) return;

   /* kein Argument */

   for (z=0; z<FixedOrderCnt; z++)
    if (Memo(FixedOrders[z].Name))
     BEGIN
      if (ArgCnt!=0) WrError(1110);
      else if (MomCPU<FixedOrders[z].MinCPU) WrXError(1500,OpPart);
      else
       BEGIN
        WAsmCode[0]=FixedOrders[z].Code; CodeLen=1;
       END
      return;
     END

   /* nur Register */

   for (z=0; z<Reg1OrderCnt; z++)
    if (Memo(Reg1Orders[z].Name))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else if (MomCPU<Reg1Orders[z].MinCPU) WrXError(1500,OpPart);
      else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
      else
       BEGIN
        WAsmCode[0]=Reg1Orders[z].Code+(Reg1 << 4); CodeLen=1;
       END
      return;
     END

   for (z=0; z<Reg2OrderCnt; z++)
    if (Memo(Reg2Orders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else if (MomCPU<Reg2Orders[z].MinCPU) WrXError(1500,OpPart);
      else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
      else if (NOT DecodeReg(ArgStr[2],&Reg2)) WrXError(1445,ArgStr[2]);
      else
       BEGIN
        WAsmCode[0]=Reg2Orders[z].Code+(Reg2 & 15)+(Reg1 << 4)+
                     ((Reg2 & 16) << 5);
        CodeLen=1;
       END
      return;
     END

   for (z=0; z<Reg3OrderCnt; z++)
    if (Memo(Reg3Orders[z].Name))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
      else
       BEGIN
        WAsmCode[0]=Reg3Orders[z].Code+(Reg1 & 15)+(Reg1 << 4)+
                    ((Reg1 & 16) << 5);
        CodeLen=1;
       END
      return;
     END

   /* immediate mit Register */

   for (z=0; z<ImmOrderCnt; z++)
    if (Memo(ImmOrders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
      else if (Reg1<16) WrXError(1445,ArgStr[1]);
      else
       BEGIN
        Reg2=EvalIntExpression(ArgStr[2],Int8,&OK);
        if (OK)
         BEGIN
          WAsmCode[0]=ImmOrders[z].Code+((Reg2 & 0xf0) << 4)+(Reg2 & 0x0f)+
                      ((Reg1 & 0x0f) << 4);
          CodeLen=1;
         END
       END
      return;
     END

   if ((Memo("ADIW")) OR (Memo("SBIW")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (MomCPU<CPU90S2313) WrError(1500);
     else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
     else if ((Reg1<24) OR (Odd(Reg1))) WrXError(1445,ArgStr[1]);
     else
      BEGIN
       Reg2=EvalIntExpression(ArgStr[2],UInt6,&OK);
       if (OK)
	BEGIN
	 WAsmCode[0]=0x9600+(Ord(Memo("SBIW")) << 8)+((Reg1 & 6) << 3)+
		     (Reg2 & 15)+((Reg2 & 0x30) << 2);
	 CodeLen=1;
	END
      END
     return;
    END

   /* Transfer */

   if ((Memo("LD")) OR (Memo("ST")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (Memo("ST"))
        BEGIN
         strcpy(ArgStr[3],ArgStr[1]);
         strcpy(ArgStr[1],ArgStr[2]);
         strcpy(ArgStr[2],ArgStr[3]);
         z=0x200;
        END
       else z=0;
       if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
       else if (NOT DecodeMem(ArgStr[2],&Reg2)) WrError(1350);
       else if ((MomCPU<CPU90S2313) AND (Reg2!=0)) WrError(1351);
       else
        BEGIN
         WAsmCode[0]=0x8000+z+(Reg1 << 4)+(Reg2 & 0x0f)+((Reg2 & 0x10) << 8);
         CodeLen=1;
        END
      END
     return;
    END

   if ((Memo("LDD")) OR (Memo("STD")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (MomCPU<CPU90S2313) WrXError(1500,OpPart);
     else
      BEGIN
       if (Memo("STD"))
        BEGIN
         strcpy(ArgStr[3],ArgStr[1]);
         strcpy(ArgStr[1],ArgStr[2]);
         strcpy(ArgStr[2],ArgStr[3]);
         z=0x200;
        END
       else z=0;
       OK=True;
       if (toupper(*ArgStr[2])=='Y') z+=8;
       else if (toupper(*ArgStr[2])=='Z');
       else OK=False;
       if (NOT OK) WrError(1350);
       else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
       else
        BEGIN
         *ArgStr[2]='0';
         Reg2=EvalIntExpression(ArgStr[2],UInt6,&OK);
         if (OK)
          BEGIN
           WAsmCode[0]=0x8000+z+(Reg1 << 4)+(Reg2 & 7)+((Reg2 & 0x18) << 7)+((Reg2 & 0x20) << 8);
	   CodeLen=1;
          END
        END
      END
     return;
    END

   if ((Memo("IN")) OR (Memo("OUT")))
    BEGIN
     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]);
         z=0x800;
        END
       else z=0;
       if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
       else
        BEGIN
         Reg2=EvalIntExpression(ArgStr[2],UInt6,&OK);
         if (OK)
          BEGIN
           ChkSpace(SegIO);
           WAsmCode[0]=0xb000+z+(Reg1 << 4)+(Reg2 & 0x0f)+((Reg2 & 0xf0) << 5);
           CodeLen=1;
          END
        END
      END
     return;
    END

   if ((Memo("LDS")) OR (Memo("STS")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (MomCPU<CPU90S2313) WrError(1500);
     else
      BEGIN
       if (Memo("STS"))
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]);
         strcpy(ArgStr[1],ArgStr[2]);
         strcpy(ArgStr[2],ArgStr[3]);
	 z=0x200;
	END
       else z=0;
       if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
       else
	BEGIN
	 WAsmCode[1]=EvalIntExpression(ArgStr[2],UInt16,&OK);
	 if (OK)
	  BEGIN
           ChkSpace(SegData);
	   WAsmCode[0]=0x9000+z+(Reg1 << 4); 
	   CodeLen=2;
	  END
	END
      END
     return;
    END

   /* Bitoperationen */

   if ((Memo("BCLR")) OR (Memo("BSET")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       Reg1=EvalIntExpression(ArgStr[1],UInt3,&OK);
       if (OK)
        BEGIN
         WAsmCode[0]=0x9408+(Reg1 << 4)+(Ord(Memo("BCLR")) << 7);
         CodeLen=1;
        END
      END
     return;
    END

   for (z=0; z<BitOrderCnt; z++)
    if (Memo(BitOrders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
      else
       BEGIN
        Reg2=EvalIntExpression(ArgStr[2],UInt3,&OK);
        if (OK)
         BEGIN
          WAsmCode[0]=BitOrders[z].Code+(Reg1 << 4)+Reg2;
          CodeLen=1;
         END
       END
      return;
     END

   if (Memo("CBR"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
     else if (Reg1<16) WrXError(1445,ArgStr[1]);
     else
      BEGIN
       Reg2=EvalIntExpression(ArgStr[2],Int8,&OK) ^ 0xff;
       if (OK)
        BEGIN
         WAsmCode[0]=0x7000+((Reg2 & 0xf0) << 4)+(Reg2 & 0x0f)+
                      ((Reg1 & 0x0f) << 4);
         CodeLen=1;
        END
      END
     return;
    END

   if (Memo("SER"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (NOT DecodeReg(ArgStr[1],&Reg1)) WrXError(1445,ArgStr[1]);
     else if (Reg1<16) WrXError(1445,ArgStr[1]);
     else
      BEGIN
       WAsmCode[0]=0xef0f+((Reg1 & 0x0f) << 4);
       CodeLen=1;
      END
     return;
    END

   for (z=0; z<PBitOrderCnt; z++)
    if (Memo(PBitOrders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else
       BEGIN
	Reg1=EvalIntExpression(ArgStr[1],UInt5,&OK);
	if (OK)
	 BEGIN
	  ChkSpace(SegIO);
	  Reg2=EvalIntExpression(ArgStr[2],UInt3,&OK);
	  if (OK)
	   BEGIN
	    WAsmCode[0]=PBitOrders[z].Code+Reg2+(Reg1 << 3);
	    CodeLen=1;
           END
	 END
       END
      return;
     END

   /* Spruenge */

   for (z=0; z<RelOrderCnt; z++)
    if (Memo(RelOrders[z].Name))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else
       BEGIN
        AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+1);
        if (OK)
         BEGIN
          if (WrapFlag) AdrInt = CutAdr(AdrInt);
          if ((NOT SymbolQuestionable) AND ((AdrInt<-64) OR (AdrInt>63))) WrError(1370);
          else
           BEGIN
            ChkSpace(SegCode);
            WAsmCode[0]=RelOrders[z].Code+((AdrInt & 0x7f) << 3);
            CodeLen=1;
           END
         END
       END
      return;
     END

   if ((Memo("BRBC")) OR (Memo("BRBS")))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       Reg1=EvalIntExpression(ArgStr[1],UInt3,&OK);
       if (OK)
        BEGIN
         AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+1);
         if (OK)
          BEGIN
           if (WrapFlag) AdrInt = CutAdr(AdrInt);
           if ((NOT SymbolQuestionable) AND ((AdrInt<-64) OR (AdrInt>63))) WrError(1370);
           else
            BEGIN
             ChkSpace(SegCode);
             WAsmCode[0]=0xf000+(Ord(Memo("BRBC")) << 10)+((AdrInt & 0x7f) << 3)+Reg1;
             CodeLen=1;
            END
          END
        END
      END
     return;
    END

   if ((Memo("JMP")) OR (Memo("CALL")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (MomCPU<CPU90S8515+1) WrError(1500);
     else
      BEGIN
       AdrInt=EvalIntExpression(ArgStr[1],UInt22,&OK);
       if (OK)
        BEGIN
         ChkSpace(SegCode);
         WAsmCode[0]=0x940c+(Ord(Memo("CALL")) << 1)+((AdrInt & 0x3e0000) >> 13)+((AdrInt & 0x10000) >> 16);
         WAsmCode[1]=AdrInt & 0xffff;
         CodeLen=2;
        END
      END
     return;
    END

   if ((Memo("RJMP")) OR (Memo("RCALL")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       AdrInt=EvalIntExpression(ArgStr[1],UInt22,&OK)-(EProgCounter()+1);
       if (OK)
        BEGIN
         if (WrapFlag) AdrInt = CutAdr(AdrInt);
         if ((NOT SymbolQuestionable) AND ((AdrInt<-2048) OR (AdrInt>2047))) WrError(1370);
         else
          BEGIN
           ChkSpace(SegCode);
           WAsmCode[0]=0xc000+(Ord(Memo("RCALL")) << 12)+(AdrInt & 0xfff);
           CodeLen=1;
          END
        END
      END
     return;
    END

   WrXError(1200,OpPart);
END

        static Boolean IsDef_AVR(void)
BEGIN
   return (Memo("PORT") OR Memo("REG"));
END

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

        static void SwitchTo_AVR(void)
BEGIN
   TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=True;

   PCSymbol="*"; HeaderID=0x3b; NOPCode=0x0000;
   DivideChars=","; HasAttrs=False;

   ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
   Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
   Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=32;
   Grans[SegIO  ]=1; ListGrans[SegIO  ]=1; SegInits[SegIO  ]=0; SegLimits[SegIO] = 0x3f;

   if (MomCPU == CPU90S1200) SegLimits[SegCode] = 0x01ff;
   else if (MomCPU == CPU90S2313) SegLimits[SegCode] = 0x03ff;
   else if (MomCPU == CPU90S4414) SegLimits[SegCode] = 0x07ff;
   else SegLimits[SegCode] = 0xfff;

   if (MomCPU == CPU90S1200) SegLimits[SegData] = 0x5f;
   else if (MomCPU == CPU90S2313) SegLimits[SegData] = 0xdf;
   else SegLimits[SegData] = 0xffff;

   SignMask = (SegLimits[SegCode] + 1) >> 1;
   ORMask = ((LongInt) - 1) - SegLimits[SegCode];

   AddONOFF("WRAPMODE", &WrapFlag, WrapFlagName, False);
   SetFlag(&WrapFlag, WrapFlagName, False);

   MakeCode=MakeCode_AVR; IsDef=IsDef_AVR;
   SwitchFrom=SwitchFrom_AVR; InitFields();
END

	void codeavr_init(void)
BEGIN
   CPU90S1200=AddCPU("AT90S1200",SwitchTo_AVR);
   CPU90S2313=AddCPU("AT90S2313",SwitchTo_AVR);
   CPU90S4414=AddCPU("AT90S4414",SwitchTo_AVR);
   CPU90S8515=AddCPU("AT90S8515",SwitchTo_AVR);
END

