/* codemcore.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator MCORE-Familie                                               */
/*                                                                           */
/* Historie:  31. 1.1998 Grundsteinlegung                                    */
/*             3. 1.1999 ChkPC-Anpassung                                     */
/*                                                                           */
/*****************************************************************************/

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

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

/*--------------------------------------------------------------------------*/
/* Variablen */

#define FixedOrderCnt 7
#define OneRegOrderCnt 32
#define TwoRegOrderCnt 23
#define UImm5OrderCnt 13
#define LJmpOrderCnt 4
#define CRegCnt 13

typedef struct
         {
          Word Code;
          Boolean Priv;
         } FixedOrder;

typedef struct
         {
          Word Code;
          Word Min,Ofs;
         } ImmOrder;

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

static CPUVar CPUMCORE;
static Byte OpSize;

static FixedOrder *FixedOrders;
static FixedOrder *OneRegOrders;
static FixedOrder *TwoRegOrders;
static ImmOrder *UImm5Orders;
static FixedOrder *LJmpOrders;
static PInstTable InstTable;
static CReg *CRegs;

/*--------------------------------------------------------------------------*/
/* Hilfsdekoder */

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

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

   if (strcasecmp(Asc,"SP")==0)
    BEGIN
     *Erg=0; return True;
    END

   if (strcasecmp(Asc,"LR")==0)
    BEGIN
     *Erg=15; return True;
    END

   if (toupper(*Asc)!='R') return False;
   else
    BEGIN
     *Erg=strtol(Asc+1,&endptr,10);
     return ((*endptr=='\0') AND (*Erg<=15));
    END
END

	static Boolean DecodeCReg(char *Asc, Word *Erg)
BEGIN
   char *endptr;
   int z;

   for (z=0; z<CRegCnt; z++)
    if (strcasecmp(Asc,CRegs[z].Name)==0)
     BEGIN
      *Erg=CRegs[z].Code; return True;
     END

   if ((toupper(*Asc)!='C') OR (toupper(Asc[1])!='R')) return False;
   else
    BEGIN
     *Erg=strtol(Asc+2,&endptr,10);
     return ((*endptr=='\0') AND (*Erg<=31));
    END
END

	static Boolean DecodeAdr(char *Asc, Word *Erg)
BEGIN
   Word Base=0xff,Tmp;
   LongInt DispAcc=0,DMask=(1<<OpSize)-1,DMax=15<<OpSize;
   Boolean OK,FirstFlag=False;
   char *Pos;

   if (NOT IsIndirect(Asc))
    BEGIN
     WrError(1350); return False;
    END

   Asc++; Asc[strlen(Asc)-1]='\0';
   do 
    BEGIN
     Pos=QuotPos(Asc,',');
     if (Pos!=Nil) *Pos='\0';
     if (DecodeReg(Asc,&Tmp))
      BEGIN
       if (Base==0xff) Base=Tmp;
       else
        BEGIN
         WrError(1350); return False;
        END
      END
     else
      BEGIN
       FirstPassUnknown=FALSE;
       DispAcc+=EvalIntExpression(Asc,Int32,&OK);
       if (FirstPassUnknown) FirstFlag=True;
       if (NOT OK) return False;
      END
     if (Pos!=Nil) Asc=Pos+1;
    END
   while (Pos!=Nil);

   if (Base==0xff)
    BEGIN
     WrError(1350); return False;
    END
  
   if (FirstFlag)
    BEGIN
     DispAcc-=DispAcc&DMask;
     if (DispAcc<0) DispAcc=0;
     if (DispAcc>DMax) DispAcc=DMax;
    END

   if ((DispAcc&DMask)!=0)
    BEGIN
     WrError(1325); return False;
    END
   if (NOT ChkRange(DispAcc,0,DMax)) return False;
   *Erg=Base+((DispAcc>>OpSize)<<4); return True;
END

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

   return False;
END

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

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=0) WrError(1110);
   else
    BEGIN
     if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
     WAsmCode[0]=Instr->Code; CodeLen=2; 
    END
END

	static void DecodeOneReg(Word Index)
BEGIN
   FixedOrder *Instr=OneRegOrders+Index;
   Word RegX;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=1) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
    BEGIN
     if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
     WAsmCode[0]=Instr->Code+RegX; CodeLen=2; 
    END
END

	static void DecodeTwoReg(Word Index)
BEGIN
   FixedOrder *Instr=TwoRegOrders+Index;
   Word RegX,RegY;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
   else if (NOT DecodeReg(ArgStr[2],&RegY)) WrXError(1445,ArgStr[2]);
    BEGIN
     if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
     WAsmCode[0]=Instr->Code+(RegY<<4)+RegX; CodeLen=2; 
    END
END

        static void DecodeUImm5(Word Index)
BEGIN
   ImmOrder *Instr=UImm5Orders+Index;
   Word RegX,ImmV;
   Boolean OK;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
   else
    BEGIN
     FirstPassUnknown=False;
     ImmV=EvalIntExpression(ArgStr[2],(Instr->Ofs>0) ? UInt6 : UInt5,&OK);
     if ((Instr->Min>0) AND (ImmV<Instr->Min))
      if (FirstPassUnknown) ImmV=Instr->Min;
      else
       BEGIN
        WrError(1315); OK=False;
       END
     if ((Instr->Ofs>0) AND ((ImmV<Instr->Ofs) OR (ImmV>31+Instr->Ofs)))
      if (FirstPassUnknown) ImmV=Instr->Ofs;
      else
       BEGIN
        WrError((ImmV<Instr->Ofs) ? 1315 : 1320); 
        OK=False;
       END
     if (OK)
      BEGIN
       WAsmCode[0]=Instr->Code+((ImmV-Instr->Ofs)<<4)+RegX; CodeLen=2;
      END
    END
END

	static void DecodeLJmp(Word Index)
BEGIN
   FixedOrder *Instr=LJmpOrders+Index;
   LongInt Dest;
   Boolean OK;
   
   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=1) WrError(1110);
   else
    BEGIN
     Dest=EvalIntExpression(ArgStr[1],UInt32,&OK)-(EProgCounter()+2);
     if (OK)
      if ((NOT SymbolQuestionable) AND ((Dest&1)==1)) WrError(1375);
      else if ((NOT SymbolQuestionable) AND ((Dest>2046) OR (Dest<-2048))) WrError(1370);
      else
       BEGIN
        if ((Instr->Priv) AND (NOT SupAllowed)) WrError(50);
        WAsmCode[0]=Instr->Code+((Dest>>1)&0x7ff);
        CodeLen=2;
       END
    END
END

	static void DecodeSJmp(Word Index)
BEGIN
   LongInt Dest;
   Boolean OK;
   int l=0;
   
   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=1) WrError(1110);
   else if ((*ArgStr[1]!='[') OR (ArgStr[1][l=strlen(ArgStr[1])-1]!=']')) WrError(1350);
   else
    BEGIN
     ArgStr[1][l]='\0';
     Dest=EvalIntExpression(ArgStr[1]+1,UInt32,&OK);
     if (OK)
      if ((NOT SymbolQuestionable) AND ((Dest&3)!=0)) WrError(1325);
      else
       BEGIN
        Dest=(Dest-(EProgCounter()+2))>>2;
        if ((EProgCounter()&3)<2) Dest++;
        if ((NOT SymbolQuestionable) AND ((Dest<0) OR (Dest>255))) WrError(1370);
        else
         BEGIN
          WAsmCode[0]=0x7000+(Index<<8)+(Dest&0xff);
          CodeLen=2;
         END
       END
    END
END

	static void DecodeBGENI(Word Index)
BEGIN
   Word RegX,ImmV;
   Boolean OK;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
   else
    BEGIN
     ImmV=EvalIntExpression(ArgStr[2],UInt5,&OK);
     if (OK)
      BEGIN
       if (ImmV>6)
        WAsmCode[0]=0x3200+(ImmV<<4)+RegX;
       else
        WAsmCode[0]=0x6000+(1<<(4+ImmV))+RegX;
       CodeLen=2;
      END
    END
END

	static void DecodeBMASKI(Word Index)
BEGIN
   Word RegX,ImmV;
   Boolean OK;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
   else
    BEGIN
     FirstPassUnknown=False;
     ImmV=EvalIntExpression(ArgStr[2],UInt6,&OK);
     if ((FirstPassUnknown) AND ((ImmV<1) OR (ImmV>32))) ImmV=8;
     if (OK)
      if (ChkRange(ImmV,1,32))
       BEGIN
        ImmV&=31;
        if ((ImmV<1) OR (ImmV>7))
         WAsmCode[0]=0x2c00+(ImmV<<4)+RegX;
        else
         WAsmCode[0]=0x6000+(((1<<ImmV)-1)<<4)+RegX;
        CodeLen=2;
       END
    END
END

	static void DecodeLdSt(Word Index)
BEGIN
   Word RegX,RegZ,NSize;

   if ((*AttrPart!=0) AND (Lo(Index)!=0xff)) WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (OpSize>2) WrError(1130);
   else
    BEGIN
     if (Lo(Index)!=0xff) OpSize=Lo(Index);
     if (NOT DecodeReg(ArgStr[1],&RegZ)) WrXError(1445,ArgStr[1]);
     else if (DecodeAdr(ArgStr[2],&RegX))
      BEGIN
       NSize=(OpSize==2) ? 0 : OpSize+1;
       WAsmCode[0]=0x8000+(NSize<<13)+(Hi(Index)<<12)+(RegZ<<8)+RegX;
       CodeLen=2;
      END
    END
END

	static void DecodeLdStm(Word Index)
BEGIN
   char *p;
   int l;
   Word RegF,RegL,RegI;

   if (*AttrPart!=0) WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if ((*ArgStr[2]!='(') OR (ArgStr[2][l=strlen(ArgStr[2])-1]!=')')) WrError(1350);
   else
    BEGIN
     ArgStr[2][l]='\0';
     if (NOT DecodeReg(ArgStr[2]+1,&RegI)) WrXError(1445,ArgStr[2]+1);
     else if (RegI!=0) WrXError(1445,ArgStr[2]+1);
     else if ((p=strchr(ArgStr[1],'-'))==Nil) WrError(1350);
     else if (NOT DecodeReg(p+1,&RegL)) WrXError(1445,p+1);
     else if (RegL!=15) WrXError(1445,p+1);
     else
      BEGIN
       *p='\0';
       if (NOT DecodeReg(ArgStr[1],&RegF)) WrXError(1445,ArgStr[1]);
       else if ((RegF<1) OR (RegF>14)) WrXError(1445,ArgStr[1]);
       else
        BEGIN
         WAsmCode[0]=0x0060+(Index <<4)+RegF;
         CodeLen=2;
        END
      END
    END
END

	static void DecodeLdStq(Word Index)
BEGIN
   char *p;
   int l;
   Word RegF,RegL,RegX;

   if (*AttrPart!=0) WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if ((*ArgStr[2]!='(') OR (ArgStr[2][l=strlen(ArgStr[2])-1]!=')')) WrError(1350);
   else
    BEGIN
     ArgStr[2][l]='\0';
     if (NOT DecodeReg(ArgStr[2]+1,&RegX)) WrXError(1445,ArgStr[2]+1);
     else if ((RegX>=4) AND (RegX<=7)) WrXError(1445,ArgStr[2]+1);
     else if ((p=strchr(ArgStr[1],'-'))==Nil) WrError(1350);
     else if (NOT DecodeReg(p+1,&RegL)) WrXError(1445,p+1);
     else if (RegL!=7) WrXError(1445,p+1);
     else
      BEGIN
       *p='\0';
       if (NOT DecodeReg(ArgStr[1],&RegF)) WrXError(1445,ArgStr[1]);
       else if (RegF!=4) WrXError(1445,ArgStr[1]);
       else
        BEGIN
         WAsmCode[0]=0x0040+(Index <<4)+RegX;
         CodeLen=2;
        END
      END
    END
END

	static void DecodeLoopt(Word Index)
BEGIN
   Word RegY;
   LongInt Dest;
   Boolean OK;

   if (*AttrPart!=0) WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegY)) WrXError(1445,ArgStr[1]);
   else
    BEGIN
     Dest=EvalIntExpression(ArgStr[2],UInt32,&OK)-(EProgCounter()+2);
     if (OK)
      if ((NOT SymbolQuestionable) AND ((Dest&1)==1)) WrError(1375);
      else if ((NOT SymbolQuestionable) AND ((Dest>-2) OR (Dest<-32))) WrError(1370);
      else
       BEGIN
        WAsmCode[0]=0x0400+(RegY<<4)+((Dest>>1)&15);
        CodeLen=2;
       END
    END
END

	static void DecodeLrm(Word Index)
BEGIN
   LongInt Dest;
   Word RegZ;
   Boolean OK;
   int l=0;
   
   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegZ)) WrXError(1445,ArgStr[1]);
   else if ((RegZ==0) OR (RegZ==15)) WrXError(1445,ArgStr[1]);
   else if ((*ArgStr[2]!='[') OR (ArgStr[2][l=strlen(ArgStr[2])-1]!=']')) WrError(1350);
   else
    BEGIN
     ArgStr[2][l]='\0';
     Dest=EvalIntExpression(ArgStr[2]+1,UInt32,&OK);
     if (OK)
      if ((NOT SymbolQuestionable) AND ((Dest&3)!=0)) WrError(1325);
      else
       BEGIN
        Dest=(Dest-(EProgCounter()+2))>>2;
        if ((EProgCounter()&3)<2) Dest++;
        if ((NOT SymbolQuestionable) AND ((Dest<0) OR (Dest>255))) WrError(1370);
        else
         BEGIN
          WAsmCode[0]=0x7000+(RegZ<<8)+(Dest&0xff);
          CodeLen=2;
         END
       END
    END
END

	static void DecodeMcr(Word Index)
BEGIN
   Word RegX,CRegY;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
   else if (NOT DecodeCReg(ArgStr[2],&CRegY)) WrXError(1440,ArgStr[2]);
   else
    BEGIN
     if (NOT SupAllowed) WrError(50);
     WAsmCode[0]=0x1000+(Index<<11)+(CRegY<<4)+RegX;
     CodeLen=2;
    END
END

	static void DecodeMovi(Word Index)
BEGIN
   Word RegX,ImmV;
   Boolean OK;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=2) WrError(1110);
   else if (NOT DecodeReg(ArgStr[1],&RegX)) WrXError(1445,ArgStr[1]);
   else
    BEGIN
     ImmV=EvalIntExpression(ArgStr[2],UInt7,&OK);
     if (OK)
      BEGIN
       WAsmCode[0]=0x6000+((ImmV&127)<<4)+RegX;
       CodeLen=2;
      END
    END
END

	static void DecodeTrap(Word Index)
BEGIN
   Word ImmV;
   Boolean OK;

   if (*AttrPart!='\0') WrError(1100);
   else if (ArgCnt!=1) WrError(1110);
   else if (*ArgStr[1]!='#') WrError(1120);
   else
    BEGIN
     ImmV=EvalIntExpression(ArgStr[1]+1,UInt2,&OK);
     if (OK)
      BEGIN
       WAsmCode[0]=0x0008+ImmV;
        CodeLen=2;
      END
    END
END

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

static int InstrZ;

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

	static void AddOneReg(char *NName, Word NCode, Boolean NPriv)
BEGIN
   if (InstrZ>=OneRegOrderCnt) exit(255);
   else
    BEGIN
     OneRegOrders[InstrZ].Code=NCode;
     OneRegOrders[InstrZ].Priv=NPriv;
     AddInstTable(InstTable,NName,InstrZ++,DecodeOneReg);
    END
END

	static void AddTwoReg(char *NName, Word NCode, Boolean NPriv)
BEGIN
   if (InstrZ>=TwoRegOrderCnt) exit(255);
   else
    BEGIN
     TwoRegOrders[InstrZ].Code=NCode;
     TwoRegOrders[InstrZ].Priv=NPriv;
     AddInstTable(InstTable,NName,InstrZ++,DecodeTwoReg);
    END
END

	static void AddUImm5(char *NName, Word NCode, Word NMin, Word NOfs)
BEGIN
   if (InstrZ>=UImm5OrderCnt) exit(255);
   else
    BEGIN
     UImm5Orders[InstrZ].Code=NCode;
     UImm5Orders[InstrZ].Min=NMin;
     UImm5Orders[InstrZ].Ofs=NOfs;
     AddInstTable(InstTable,NName,InstrZ++,DecodeUImm5);
    END
END

	static void AddLJmp(char *NName, Word NCode, Boolean NPriv)
BEGIN
   if (InstrZ>=LJmpOrderCnt) exit(255);
   else
    BEGIN
     LJmpOrders[InstrZ].Code=NCode;
     LJmpOrders[InstrZ].Priv=NPriv;
     AddInstTable(InstTable,NName,InstrZ++,DecodeLJmp);
    END
END

	static void AddCReg(char *NName, Word NCode)
BEGIN
   if (InstrZ>=CRegCnt) exit(255);
   else
    BEGIN
     CRegs[InstrZ].Name=NName;
     CRegs[InstrZ++].Code=NCode;
    END
END

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

   InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt);
   AddFixed("BKPT" ,0x0000,False);
   AddFixed("DOZE" ,0x0006,True );
   AddFixed("RFI"  ,0x0003,True );
   AddFixed("RTE"  ,0x0002,True );
   AddFixed("STOP" ,0x0004,True );
   AddFixed("SYNC" ,0x0001,False);
   AddFixed("WAIT" ,0x0005,True );

   InstrZ=0; OneRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*OneRegOrderCnt);
   AddOneReg("ABS"  ,0x01e0,False);  AddOneReg("ASRC" ,0x3a00,False);
   AddOneReg("BREV" ,0x00f0,False);  AddOneReg("CLRF" ,0x01d0,False);
   AddOneReg("CLRT" ,0x01c0,False);  AddOneReg("DECF" ,0x0090,False);
   AddOneReg("DECGT",0x01a0,False);  AddOneReg("DECLT",0x0180,False);
   AddOneReg("DECNE",0x01b0,False);  AddOneReg("DECT" ,0x0080,False);
   AddOneReg("DIVS" ,0x3210,False);  AddOneReg("DIVU" ,0x2c10,False);
   AddOneReg("FF1"  ,0x00e0,False);  AddOneReg("INCF" ,0x00b0,False);
   AddOneReg("INCT" ,0x00a0,False);  AddOneReg("JMP"  ,0x00c0,False);
   AddOneReg("JSR"  ,0x00d0,False);  AddOneReg("LSLC" ,0x3c00,False);
   AddOneReg("LSRC" ,0x3e00,False);  AddOneReg("MVC"  ,0x0020,False);
   AddOneReg("MVCV" ,0x0030,False);  AddOneReg("NOT"  ,0x01f0,False);
   AddOneReg("SEXTB",0x0150,False);  AddOneReg("SEXTH",0x0170,False);
   AddOneReg("TSTNBZ",0x0190,False); AddOneReg("XSR"  ,0x3800,False);
   AddOneReg("XTRB0",0x0130,False);  AddOneReg("XTRB1",0x0120,False);
   AddOneReg("XTRB2",0x0110,False);  AddOneReg("XTRB3",0x0100,False);
   AddOneReg("ZEXTB",0x0140,False);  AddOneReg("ZEXTH",0x0160,False);

   InstrZ=0; TwoRegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*TwoRegOrderCnt);
   AddTwoReg("ADDC" ,0x0600,False);  AddTwoReg("ADDU" ,0x1c00,False);
   AddTwoReg("AND"  ,0x1600,False);  AddTwoReg("ANDN" ,0x1f00,False);
   AddTwoReg("ASR"  ,0x1a00,False);  AddTwoReg("BGENR",0x1300,False);
   AddTwoReg("CMPHS",0x0c00,False);  AddTwoReg("CMPLT",0x0d00,False);
   AddTwoReg("CMPNE",0x0f00,False);  AddTwoReg("IXH"  ,0x1d00,False);
   AddTwoReg("IXW"  ,0x1500,False);  AddTwoReg("LSL"  ,0x1b00,False);
   AddTwoReg("LSR"  ,0x0b00,False);  AddTwoReg("MOV"  ,0x1200,False);
   AddTwoReg("MOVF" ,0x0a00,False);  AddTwoReg("MOVT" ,0x0200,False);
   AddTwoReg("MULT" ,0x0300,False);  AddTwoReg("OR"   ,0x1e00,False);
   AddTwoReg("RSUB" ,0x1400,False);  AddTwoReg("SUBC" ,0x0700,False);
   AddTwoReg("SUBU" ,0x0500,False);  AddTwoReg("TST"  ,0x0e00,False);
   AddTwoReg("XOR"  ,0x1700,False);

   InstrZ=0; UImm5Orders=(ImmOrder *) malloc(sizeof(ImmOrder)*UImm5OrderCnt);
   AddUImm5("ADDI" ,0x2000,0,1);  AddUImm5("ANDI" ,0x2e00,0,0);
   AddUImm5("ASRI" ,0x3a00,1,0);  AddUImm5("BCLRI",0x3000,0,0);
   AddUImm5("BSETI",0x3400,0,0);  AddUImm5("BTSTI",0x3600,0,0);
   AddUImm5("CMPLTI",0x2200,0,1); AddUImm5("CMPNEI",0x2a00,0,0);
   AddUImm5("LSLI" ,0x3c00,1,0);  AddUImm5("LSRI" ,0x3e00,1,0);
   AddUImm5("ROTLI",0x3800,1,0);  AddUImm5("RSUBI",0x2800,0,0);
   AddUImm5("SUBI" ,0x2400,0,1);

   InstrZ=0; LJmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LJmpOrderCnt);
   AddLJmp("BF"   ,0xe800,False);  AddLJmp("BR"   ,0xf000,False);
   AddLJmp("BSR"  ,0xf800,False);  AddLJmp("BT"   ,0xe000,False);

   InstrZ=0; CRegs=(CReg *) malloc(sizeof(CReg)*CRegCnt);
   AddCReg("PSR" , 0); AddCReg("VBR" , 1);
   AddCReg("EPSR", 2); AddCReg("FPSR", 3);
   AddCReg("EPC" , 4); AddCReg("FPC",  5);
   AddCReg("SS0",  6); AddCReg("SS1",  7);
   AddCReg("SS2",  8); AddCReg("SS3",  9);
   AddCReg("SS4", 10); AddCReg("GCR", 11);
   AddCReg("GSR", 12);

   AddInstTable(InstTable,"BGENI" ,0,DecodeBGENI);
   AddInstTable(InstTable,"BMASKI",0,DecodeBMASKI);
   AddInstTable(InstTable,"JMPI"  ,0,DecodeSJmp);
   AddInstTable(InstTable,"JSRI"  ,0,DecodeSJmp);
   AddInstTable(InstTable,"LD"    ,0x0ff,DecodeLdSt);
   AddInstTable(InstTable,"LDB"   ,0x000,DecodeLdSt);
   AddInstTable(InstTable,"LDH"   ,0x001,DecodeLdSt);
   AddInstTable(InstTable,"LDW"   ,0x002,DecodeLdSt);
   AddInstTable(InstTable,"ST"    ,0x1ff,DecodeLdSt);
   AddInstTable(InstTable,"STB"   ,0x100,DecodeLdSt);
   AddInstTable(InstTable,"STH"   ,0x101,DecodeLdSt);
   AddInstTable(InstTable,"STW"   ,0x102,DecodeLdSt);
   AddInstTable(InstTable,"LDM"   ,0,DecodeLdStm);
   AddInstTable(InstTable,"STM"   ,1,DecodeLdStm);
   AddInstTable(InstTable,"LDQ"   ,0,DecodeLdStq);
   AddInstTable(InstTable,"STQ"   ,1,DecodeLdStq);
   AddInstTable(InstTable,"LOOPT" ,0,DecodeLoopt);
   AddInstTable(InstTable,"LRM"   ,0,DecodeLrm);
   AddInstTable(InstTable,"MFCR"  ,0,DecodeMcr);
   AddInstTable(InstTable,"MTCR"  ,1,DecodeMcr);
   AddInstTable(InstTable,"MOVI"  ,0,DecodeMovi);
   AddInstTable(InstTable,"TRAP"  ,0,DecodeTrap);
END

        static void DeinitFields(void)
BEGIN
   DestroyInstTable(InstTable);
   free(FixedOrders);
   free(OneRegOrders);
   free(TwoRegOrders);
   free(UImm5Orders);
   free(LJmpOrders);
   free(CRegs);
END

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

	static void MakeCode_MCORE(void)
BEGIN
   CodeLen=0;

   OpSize=2;
   DontPrint=False;

   if (*AttrPart!='\0')
    switch (toupper(*AttrPart))
     BEGIN
      case 'B': OpSize=0; break;
      case 'H': OpSize=1; break;
      case 'W': OpSize=2; break;
      case 'Q': OpSize=3; break;
      case 'S': OpSize=4; break;
      case 'D': OpSize=5; break;
      case 'X': OpSize=6; break;
      case 'P': OpSize=7; break;
      default: WrError(1107); return;
     END

   /* Nullanweisung */

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

   /* Pseudoanweisungen */

   if (DecodeMoto16Pseudo(OpSize,True)) return;

   if (DecodePseudo()) return;

   /* Befehlszaehler ungerade ? */

   if (Odd(EProgCounter())) WrError(180);

   /* alles aus der Tabelle */

   if (LookupInstTable(InstTable,OpPart)) return;

   /* unbekannter Befehl */

   WrXError(1200,OpPart);
END

	static Boolean IsDef_MCORE(void)
BEGIN
   return Memo("REG");
END

	static void SwitchFrom_MCORE(void)
BEGIN
   DeinitFields();
END

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

   PCSymbol="*"; HeaderID=0x03; NOPCode=0x1200; /* ==MOV r0,r0 */
   DivideChars=","; HasAttrs=True; AttrChars=".";

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

   MakeCode=MakeCode_MCORE; IsDef=IsDef_MCORE;

   SwitchFrom=SwitchFrom_MCORE; InitFields();
   AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName,False);
   AddMoto16PseudoONOFF();

   SetFlag(&DoPadding,DoPaddingName,True);
END

/*--------------------------------------------------------------------------*/
/* Initialisierung */

	void codemcore_init(void)
BEGIN
   CPUMCORE=AddCPU("MCORE",SwitchTo_MCORE);
END
