/* codest9.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator SGS-Thomson ST9                                             */
/*                                                                           */
/* Historie: 10. 2.1997 Grundsteinlegung                                     */
/*            1. 7.1998 Warnungen bei is...()-Funktionen beseitigt           */
/*            2. 1.1999 ChkPC umgestellt                                     */
/*           30. 1.1999 Formate maschinenunabhaengig gemacht                 */
/*                                                                           */
/*****************************************************************************/

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

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


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

typedef struct
         {
          char *Name;
          int len;
          Word Code;
         } ALUOrder;


#define WorkOfs 0xd0

#define ModNone (-1)
#define ModReg 0          
#define MModReg (1l << ModReg)                  /* Rn */
#define ModWReg 1         
#define MModWReg (1l << ModWReg)                /* rn */
#define ModRReg 2         
#define MModRReg (1l << ModRReg)                /* RRn */
#define ModWRReg 3        
#define MModWRReg (1l << ModWRReg)              /* rrn */
#define ModIReg 4         
#define MModIReg (1l << ModIReg)                /* (Rn) */
#define ModIWReg 5        
#define MModIWReg (1l << ModIWReg)              /* (rn) */
#define ModIRReg 6        
#define MModIRReg (1l << ModIRReg)              /* (RRn) */
#define ModIWRReg 7       
#define MModIWRReg (1l << ModIWRReg)            /* (rrn) */
#define ModIncWReg 8      
#define MModIncWReg (1l << ModIncWReg)          /* (rn)+ */
#define ModIncWRReg 9     
#define MModIncWRReg (1l << ModIncWRReg)        /* (rrn)+ */
#define ModDecWRReg 10    
#define MModDecWRReg (1l << ModDecWRReg)        /* -(rrn) */
#define ModDisp8WReg 11   
#define MModDisp8WReg (1l << ModDisp8WReg)      /* d8(rn) */
#define ModDisp8WRReg 12  
#define MModDisp8WRReg (1l << ModDisp8WRReg)    /* d8(rrn) */
#define ModDisp16WRReg 13 
#define MModDisp16WRReg (1l << ModDisp16WRReg)  /* d16(rrn) */
#define ModDispRWRReg 14  
#define MModDispRWRReg (1l << ModDispRWRReg)    /* rrm(rrn */
#define ModAbs 15         
#define MModAbs (1l << ModAbs)                  /* NN */
#define ModImm 16         
#define MModImm (1l << ModImm)                  /* #N/#NN */
#define ModDisp8RReg 17   
#define MModDisp8RReg (1l << ModDisp8RReg)      /* d8(RRn) */
#define ModDisp16RReg 18  
#define MModDisp16RReg (1l << ModDisp16RReg)    /* d16(RRn) */

#define FixedOrderCnt 12
#define ALUOrderCnt 10
#define RegOrderCnt 13
#define Reg16OrderCnt 8
#define Bit2OrderCnt 4
#define Bit1OrderCnt 4
#define ConditionCnt 20
#define LoadOrderCnt 4


static CPUVar CPUST9020,CPUST9030,CPUST9040,CPUST9050;

static FixedOrder *FixedOrders;
static ALUOrder *ALUOrders;
static FixedOrder *RegOrders;
static FixedOrder *Reg16Orders;
static FixedOrder *Bit2Orders;
static FixedOrder *Bit1Orders;
static FixedOrder *Conditions;
static FixedOrder *LoadOrders;

static ShortInt AdrMode,AbsSeg;
static Byte AdrPart,OpSize;
static Byte AdrVals[3];

static SimpProc SaveInitProc;
static LongInt DPAssume;

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

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

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

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

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

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

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

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

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

	static void InitFields(void)
BEGIN
   FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
   AddFixed("CCF" ,0x0061); AddFixed("DI"  ,0x0010);
   AddFixed("EI"  ,0x0000); AddFixed("HALT",0xbf01);
   AddFixed("IRET",0x00d3); AddFixed("NOP" ,0x00ff);
   AddFixed("RCF" ,0x0011); AddFixed("RET" ,0x0046);
   AddFixed("SCF" ,0x0001); AddFixed("SDM" ,0x00fe);
   AddFixed("SPM" ,0x00ee); AddFixed("WFI" ,0xef01);

   ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt); InstrZ=0;
   AddALU("ADC", 3); AddALU("ADD", 4); AddALU("AND", 1);
   AddALU("CP" , 9); AddALU("OR" , 0); AddALU("SBC", 2);
   AddALU("SUB", 5); AddALU("TCM", 8); AddALU("TM" ,10);
   AddALU("XOR", 6);

   RegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RegOrderCnt); InstrZ=0;
   AddReg("CLR" ,0x90); AddReg("CPL" ,0x80); AddReg("DA"  ,0x70);
   AddReg("DEC" ,0x40); AddReg("INC" ,0x50); AddReg("POP" ,0x76);
   AddReg("POPU",0x20); AddReg("RLC" ,0xb0); AddReg("ROL" ,0xa0);
   AddReg("ROR" ,0xc0); AddReg("RRC" ,0xd0); AddReg("SRA" ,0xe0);
   AddReg("SWAP",0xf0);

   Reg16Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Reg16OrderCnt); InstrZ=0;
   AddReg16("DECW" ,0xcf); AddReg16("EXT"  ,0xc6);
   AddReg16("INCW" ,0xdf); AddReg16("POPUW",0xb7);
   AddReg16("POPW" ,0x75); AddReg16("RLCW" ,0x8f);
   AddReg16("RRCW" ,0x36); AddReg16("SRAW" ,0x2f);

   Bit2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit2OrderCnt); InstrZ=0;
   AddBit2("BAND",0x1f); AddBit2("BLD" ,0xf2);
   AddBit2("BOR" ,0x0f); AddBit2("BXOR",0x6f);

   Bit1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit1OrderCnt); InstrZ=0;
   AddBit1("BCPL",0x6f); AddBit1("BRES" ,0x1f);
   AddBit1("BSET",0x0f); AddBit1("BTSET",0xf2);

   Conditions=(FixedOrder *) malloc(sizeof(FixedOrder)*ConditionCnt); InstrZ=0;
   AddCondition("F"   ,0x0); AddCondition("T"   ,0x8);
   AddCondition("C"   ,0x7); AddCondition("NC"  ,0xf);
   AddCondition("Z"   ,0x6); AddCondition("NZ"  ,0xe);
   AddCondition("PL"  ,0xd); AddCondition("MI"  ,0x5);
   AddCondition("OV"  ,0x4); AddCondition("NOV" ,0xc);
   AddCondition("EQ"  ,0x6); AddCondition("NE"  ,0xe);
   AddCondition("GE"  ,0x9); AddCondition("LT"  ,0x1);
   AddCondition("GT"  ,0xa); AddCondition("LE"  ,0x2);
   AddCondition("UGE" ,0xf); AddCondition("UL"  ,0x7);
   AddCondition("UGT" ,0xb); AddCondition("ULE" ,0x3);

   LoadOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LoadOrderCnt); InstrZ=0;
   AddLoad("LDPP",0x00); AddLoad("LDDP",0x10);
   AddLoad("LDPD",0x01); AddLoad("LDDD",0x11);
END

	static void DeinitFields(void)
BEGIN
   free(FixedOrders);
   free(ALUOrders);
   free(RegOrders);
   free(Reg16Orders);
   free(Bit2Orders);
   free(Bit1Orders);
   free(Conditions);
   free(LoadOrders);
END

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

	static Boolean DecodeReg(char *Asc_O, Byte *Erg, Byte *Size)
BEGIN
   Boolean Res;
   char *Asc;

   Asc=Asc_O;

   if (strlen(Asc)<2) return False;
   if (*Asc!='r') return False; Asc++;
   if (*Asc=='r') 
    BEGIN
     if (strlen(Asc)<2) return False;
     *Size=1; Asc++;
    END
   else *Size=0;

   *Erg=ConstLongInt(Asc,&Res);
   if ((NOT Res) OR (*Erg>15)) return False;
   if ((*Size==1) AND (Odd(*Erg))) return False;

   return True;
END

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

	static void DecodeAdr(char *Asc_O, LongWord Mask)
BEGIN
   Word AdrWord;
   int level;
   Byte flg,Size;
   Boolean OK;
   String Reg,Asc;
   char *p;

   AdrMode=ModNone; AdrCnt=0;
   strmaxcpy(Asc,Asc_O,255); 

   /* immediate */

   if (*Asc=='#') 
    BEGIN
     switch (OpSize)
      BEGIN
       case 0:
        AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK);
        break;
       case 1:
        AdrWord=EvalIntExpression(Asc+1,Int16,&OK);
        AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
        break;
      END
     if (OK) 
      BEGIN
       AdrMode=ModImm; AdrCnt=OpSize+1;
      END
     ChkAdr(Mask); return;
    END

   /* Arbeitsregister */

   if (DecodeReg(Asc,&AdrPart,&Size)) 
    BEGIN
     if (Size==0) 
      if ((Mask & MModWReg)!=0) AdrMode=ModWReg;
      else
       BEGIN
        AdrVals[0]=WorkOfs+AdrPart; AdrCnt=1; AdrMode=ModReg;
       END
     else
      if ((Mask & MModWRReg)!=0)  AdrMode=ModWRReg;
      else
       BEGIN
        AdrVals[0]=WorkOfs+AdrPart; AdrCnt=1; AdrMode=ModRReg;
       END
     ChkAdr(Mask); return;
    END

   /* Postinkrement */

   if (Asc[strlen(Asc)-1]=='+') 
    BEGIN
     if ((*Asc!='(') OR (Asc[strlen(Asc)-2]!=')')) WrError(1350);
     else
      BEGIN
       strcpy(Asc,Asc+1); Asc[strlen(Asc)-2]='\0';
       if (NOT DecodeReg(Asc,&AdrPart,&Size)) WrXError(1445,Asc);
       AdrMode=(Size==0) ? ModIncWReg : ModIncWRReg;
      END
     ChkAdr(Mask); return;
    END

   /* Predekrement */

   if ((*Asc=='-') AND (Asc[1]=='(') AND (Asc[strlen(Asc)-1]==')')) 
    BEGIN
     strcpy(Reg,Asc+2); Reg[strlen(Reg)-1]='\0';
     if (DecodeReg(Reg,&AdrPart,&Size)) 
      BEGIN
       if (Size==0) WrError(1350); else AdrMode=ModDecWRReg;
       ChkAdr(Mask); return;
      END
    END

   /* indirekt<->direkt */

   if ((Asc[strlen(Asc)-1]!=')') OR (strlen(Asc)<3))
    BEGIN
     OK=False; p=Asc;
    END
   else
    BEGIN
     level=0; p=Asc+strlen(Asc)-2; flg=0;
     while ((p>=Asc) AND (level>=0))
      BEGIN
       switch (*p)
        BEGIN
         case '(': if (flg==0) level--; break;
         case ')': if (flg==0) level++; break;
         case '\'': if (((flg & 2)==0))  flg^=1; break;
         case '"': if (((flg & 1)==0))  flg^=2; break;
        END
       p--;
      END
     OK=(level==-1) AND ((p<Asc) OR ((*p=='.') OR (*p=='_') OR (isdigit(((unsigned int)*p)&0xff)) OR (isalpha(((unsigned int)*p)&0xff))));
    END

   /* indirekt */

   if (OK) 
    BEGIN
     strcpy(Reg,p+2); Reg[strlen(Reg)-1]='\0'; p[1]='\0';
     if (DecodeReg(Reg,&AdrPart,&Size)) 
      if (Size==0)   /* d(r) */
       BEGIN
        AdrVals[0]=EvalIntExpression(Asc,Int8,&OK);
        if (OK) 
         BEGIN
          if (((Mask & MModIWReg)!=0) AND (AdrVals[0]==0)) AdrMode=ModIWReg;
          else if (((Mask & MModIReg)!=0) AND (AdrVals[0]==0)) 
           BEGIN
            AdrVals[0]=WorkOfs+AdrPart; AdrMode=ModIReg; AdrCnt=1;
           END
          else
           BEGIN
            AdrMode=ModDisp8WReg; AdrCnt=1;
           END
         END
       END
      else            /* ...(rr) */
       BEGIN
        if (DecodeReg(Asc,AdrVals,&Size)) 
         BEGIN        /* rr(rr) */
          if (Size!=1) WrError(1350);
          else
           BEGIN
            AdrMode=ModDispRWRReg; AdrCnt=1;
           END
         END
        else
         BEGIN        /* d(rr) */
          AdrWord=EvalIntExpression(Asc,Int16,&OK);
          if ((AdrWord==0) AND ((Mask & (MModIRReg+MModIWRReg))!=0)) 
           BEGIN
            if (((Mask & MModIWRReg)!=0)) AdrMode=ModIWRReg;
            else
             BEGIN
              AdrMode=ModIRReg; AdrVals[0]=AdrPart+WorkOfs; AdrCnt=1;
             END
           END
          else if ((AdrWord<0x100) AND ((Mask & (MModDisp8WRReg+MModDisp8RReg))!=0)) 
           BEGIN
            if (((Mask & MModDisp8WRReg)!=0)) 
             BEGIN
              AdrVals[0]=Lo(AdrWord); AdrCnt=1; AdrMode=ModDisp8WRReg;
             END
            else
             BEGIN
              AdrVals[0]=AdrPart+WorkOfs; AdrVals[1]=Lo(AdrWord);
              AdrCnt=2; AdrMode=ModDisp8RReg;
             END
           END
          else if (((Mask & MModDisp16WRReg)!=0)) 
           BEGIN
            AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
	    AdrCnt=2; AdrMode=ModDisp16WRReg;
           END
          else
           BEGIN
            AdrVals[0]=AdrPart+WorkOfs;
            AdrVals[2]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
            AdrCnt=3; AdrMode=ModDisp16RReg;
           END
         END
       END

     else             /* ...(RR) */
      BEGIN
       AdrWord=EvalIntExpression(Reg,UInt9,&OK);
       if (((TypeFlag & (1 << SegReg))==0))  WrError(1350);
       else if (AdrWord<0xff) 
        BEGIN
         AdrVals[0]=Lo(AdrWord);
         AdrWord=EvalIntExpression(Asc,Int8,&OK);
         if (AdrWord!=0) WrError(1320);
         else
          BEGIN
           AdrCnt=1; AdrMode=ModIReg;
          END
        END
       else if ((AdrWord>0x1ff) OR (Odd(AdrWord))) WrError(1350);
       else
        BEGIN
         AdrVals[0]=Lo(AdrWord);
         AdrWord=EvalIntExpression(Asc,Int16,&OK);
         if ((AdrWord==0) AND ((Mask & MModIRReg)!=0)) 
          BEGIN
           AdrCnt=1; AdrMode=ModIRReg;
          END
         else if ((AdrWord<0x100) AND ((Mask & MModDisp8RReg)!=0)) 
          BEGIN
           AdrVals[1]=Lo(AdrWord); AdrCnt=2; AdrMode=ModDisp8RReg;
          END
         else
          BEGIN
           AdrVals[2]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
           AdrCnt=3; AdrMode=ModDisp16RReg;
          END
        END
      END
     ChkAdr(Mask); return;
    END

   /* direkt */

   AdrWord=EvalIntExpression(Asc,UInt16,&OK);
   if (OK) 
    if (((TypeFlag & (1 << SegReg)))==0) 
     BEGIN
      AdrMode=ModAbs;
      AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord);
      AdrCnt=2; ChkSpace(AbsSeg);
     END
    else if (AdrWord<0xff) 
     BEGIN
      AdrMode=ModReg; AdrVals[0]=Lo(AdrWord); AdrCnt=1;
     END
    else if ((AdrWord>0x1ff) OR (Odd(AdrWord))) WrError(1350);
    else
     BEGIN
      AdrMode=ModRReg; AdrVals[0]=Lo(AdrWord); AdrCnt=1;
     END

   ChkAdr(Mask);
END

        static Boolean SplitBit(char *Asc, Byte *Erg)
BEGIN
   char *p;
   Integer val;
   Boolean OK,Inv;

   p=RQuotPos(Asc,'.');
   if ((p==Nil) OR (p==Asc+strlen(Asc)+1)) 
    BEGIN
     if (*Asc=='!') 
      BEGIN
       Inv=True; strcpy(Asc,Asc+1);
      END
     else Inv=False;
     val=EvalIntExpression(Asc,UInt8,&OK);
     if (OK) 
      BEGIN
       *Erg=val & 15; if (Inv) *Erg^=1;
       sprintf(Asc, "r%d", (int)(val >> 4));
       return True;
      END
     return False;
    END

   if (p[1]=='!') 
    *Erg=1+(EvalIntExpression(p+2,UInt3,&OK) << 1);
   else
    *Erg=EvalIntExpression(p+1,UInt3,&OK) << 1;
   *p='\0';
   return OK;
END

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

	static Boolean DecodePseudo(void)
BEGIN
#define ASSUMEST9Count 1
static ASSUMERec ASSUMEST9s[ASSUMEST9Count]=
               {{"DP", &DPAssume, 0,  1, 0x0}};
   Byte Bit;

   if (Memo("REG")) 
    BEGIN
     CodeEquate(SegReg,0,0x1ff);
     return True;
    END

   if (Memo("BIT")) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (SplitBit(ArgStr[1],&Bit)) 
      BEGIN
       DecodeAdr(ArgStr[1],MModWReg);
       if (AdrMode==ModWReg) 
        BEGIN
         PushLocHandle(-1);
         EnterIntSymbol(LabPart,(AdrPart << 4)+Bit,SegNone,False);
         PopLocHandle();
         sprintf(ListLine,"=r%d.%s%c", (int)AdrPart,
                 (Odd(Bit))?"!":"", (Bit >> 1)+AscOfs);
        END
      END
     return True;
    END

   if (Memo("ASSUME")) 
    BEGIN
     CodeASSUME(ASSUMEST9s,ASSUMEST9Count);
     return True;
    END

   return False;
END

        static void MakeCode_ST9(void)
BEGIN
   Integer AdrInt;
   int z;
   Boolean OK;
   Byte HReg,HPart;
   Word Mask1,Mask2,AdrWord;

   CodeLen=0; DontPrint=False; OpSize=0;
   AbsSeg=(DPAssume==1) ? SegData : SegCode;

   /* zu ignorierendes */

   if (Memo("")) return;

   /* Pseudoanweisungen */

   if (DecodePseudo()) return;

   if (DecodeIntelPseudo(True)) return;

   /* ohne Argument */

   for (z=0; z<FixedOrderCnt; z++)
    if (Memo(FixedOrders[z].Name)) 
     BEGIN
      if (ArgCnt!=0) WrError(1110);
      else
       BEGIN
        OK=Hi(FixedOrders[z].Code)!=0;
        if (OK) BAsmCode[0]=Hi(FixedOrders[z].Code);
        CodeLen=Ord(OK);
        BAsmCode[CodeLen++]=Lo(FixedOrders[z].Code);
       END
      return;
     END

   /* Datentransfer */

   if ((Memo("LD")) OR (Memo("LDW"))) 
    BEGIN
     if (ArgCnt!=2)  WrError(1110);
     else
      BEGIN
       if (OpPart[strlen(OpPart)-1]=='W') 
        BEGIN
         OpSize=1; Mask1=MModWRReg; Mask2=MModRReg;
        END
       else
        BEGIN
         Mask1=MModWReg; Mask2=MModReg;
        END;
       DecodeAdr(ArgStr[1],Mask1+Mask2+MModIWReg+MModDisp8WReg+MModIncWReg+
                           MModIWRReg+MModIncWRReg+MModDecWRReg+MModDisp8WRReg+
                           MModDisp16WRReg+MModDispRWRReg+MModAbs+MModIRReg);
       switch (AdrMode)
        BEGIN
         case ModWReg:
         case ModWRReg:
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask1+Mask2+MModIWReg+MModDisp8WReg+MModIWRReg+
                              MModIncWRReg+MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+
                              MModDisp16WRReg+MModAbs+MModImm);
          switch (AdrMode)
           BEGIN
            case ModWReg:
             BAsmCode[0]=(HReg << 4)+8; BAsmCode[1]=WorkOfs+AdrPart;
             CodeLen=2;
             break;
            case ModWRReg:
             BAsmCode[0]=0xe3; BAsmCode[1]=(HReg << 4)+AdrPart;
             CodeLen=2;
             break;
            case ModReg:
             BAsmCode[0]=(HReg << 4)+8; BAsmCode[1]=AdrVals[0];
             CodeLen=2;
             break;
            case ModRReg:
             BAsmCode[0]=0xef; BAsmCode[1]=AdrVals[0];
             BAsmCode[2]=HReg+WorkOfs; CodeLen=3;
             break;
            case ModIWReg:
             if (OpSize==0) 
              BEGIN
               BAsmCode[0]=0xe4; BAsmCode[1]=(HReg << 4)+AdrPart;
               CodeLen=2;
              END
             else
              BEGIN
               BAsmCode[0]=0xa6; BAsmCode[1]=0xf0+AdrPart;
               BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
              END
             break;
            case ModDisp8WReg:
             BAsmCode[0]=0xb3+(OpSize*0x2b);
             BAsmCode[1]=(HReg << 4)+AdrPart;
             BAsmCode[2]=AdrVals[0]; CodeLen=3;
             break;
            case ModIWRReg:
             BAsmCode[0]=0xb5+(OpSize*0x2e);
             BAsmCode[1]=(HReg << 4)+AdrPart+OpSize;
             CodeLen=2;
             break;
            case ModIncWRReg:
             BAsmCode[0]=0xb4+(OpSize*0x21);
             BAsmCode[1]=0xf1+AdrPart;
             BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
             break;
            case ModDecWRReg:
             BAsmCode[0]=0xc2+OpSize;
             BAsmCode[1]=0xf1+AdrPart;
             BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
             break;
            case ModDispRWRReg:
             BAsmCode[0]=0x60;
             BAsmCode[1]=(0x10*(1-OpSize))+(AdrVals[0] << 4)+AdrPart;
             BAsmCode[2]=0xf0+HReg; CodeLen=3;
             break;
            case ModDisp8WRReg:
             BAsmCode[0]=0x7f+(OpSize*7);
             BAsmCode[1]=0xf1+AdrPart;
             BAsmCode[2]=AdrVals[0]; BAsmCode[3]=HReg+WorkOfs;
             CodeLen=4;
             break;
            case ModDisp16WRReg:
             BAsmCode[0]=0x7f+(OpSize*7);
             BAsmCode[1]=0xf0+AdrPart;
             memcpy(BAsmCode+2,AdrVals,AdrCnt); BAsmCode[2+AdrCnt]=HReg+WorkOfs;
             CodeLen=3+AdrCnt;
             break;
            case ModAbs:
             BAsmCode[0]=0xc4+(OpSize*0x1e);
             BAsmCode[1]=0xf0+AdrPart;
             memcpy(BAsmCode+2,AdrVals,AdrCnt);
             CodeLen=2+AdrCnt;
             break;
            case ModImm:
             if (OpSize==0) 
              BEGIN
               BAsmCode[0]=(HReg << 4)+0x0c;
               memcpy(BAsmCode+1,AdrVals,AdrCnt);
               CodeLen=1+AdrCnt;
              END
             else
              BEGIN
               BAsmCode[0]=0xbf; BAsmCode[1]=WorkOfs+HReg;
               memcpy(BAsmCode+2,AdrVals,AdrCnt);
               CodeLen=2+AdrCnt;
              END
             break;
           END
          break;
         case ModReg:
         case ModRReg:
          HReg=AdrVals[0];
          DecodeAdr(ArgStr[2],Mask1+Mask2+MModIWReg+MModIWRReg+MModIncWRReg+
                              MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+MModDisp16WRReg+
                              MModImm);
          switch (AdrMode)
           BEGIN
            case ModWReg:
             BAsmCode[0]=(AdrPart << 4)+0x09; BAsmCode[1]=HReg; CodeLen=2;
             break;
            case ModWRReg:
             BAsmCode[0]=0xef; BAsmCode[1]=WorkOfs+AdrPart;
             BAsmCode[2]=HReg; CodeLen=3;
             break;
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0xf4-(OpSize*5);
             BAsmCode[1]=AdrVals[0];
             BAsmCode[2]=HReg; CodeLen=3;
             break;
            case ModIWReg:
             BAsmCode[0]=0xe7-(0x41*OpSize); BAsmCode[1]=0xf0+AdrPart;
             BAsmCode[2]=HReg; CodeLen=3;
             break;
            case ModIWRReg:
             BAsmCode[0]=0x72+(OpSize*12);
             BAsmCode[1]=0xf1+AdrPart-OpSize; BAsmCode[2]=HReg;
             CodeLen=3;
             break;
            case ModIncWRReg:
             BAsmCode[0]=0xb4+(0x21*OpSize);
             BAsmCode[1]=0xf1+AdrPart; BAsmCode[2]=HReg;
             CodeLen=3;
             break;
            case ModDecWRReg:
             BAsmCode[0]=0xc2+OpSize;
             BAsmCode[1]=0xf1+AdrPart; BAsmCode[2]=HReg;
             CodeLen=3;
             break;
            case ModDisp8WRReg:
             BAsmCode[0]=0x7f+(OpSize*7);
             BAsmCode[1]=0xf1+AdrPart;
             BAsmCode[2]=AdrVals[0];
             BAsmCode[3]=HReg; CodeLen=4;
             break;
            case ModDisp16WRReg:
             BAsmCode[0]=0x7f+(OpSize*7);
             BAsmCode[1]=0xf0+AdrPart;
             memcpy(BAsmCode+2,AdrVals,AdrCnt);
             BAsmCode[2+AdrCnt]=HReg; CodeLen=3+AdrCnt;
             break;
            case ModImm:
             BAsmCode[0]=0xf5-(OpSize*0x36);
             BAsmCode[1]=HReg;
             memcpy(BAsmCode+2,AdrVals,2); CodeLen=2+AdrCnt;
             break;
           END
          break;
         case ModIWReg:
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask2+Mask1);
          switch (AdrMode)
           BEGIN
            case ModWReg:
             BAsmCode[0]=0xe5; BAsmCode[1]=(HReg << 4)+AdrPart; CodeLen=2;
             break;
            case ModWRReg:
             BAsmCode[0]=0x96; BAsmCode[1]=WorkOfs+AdrPart;
             BAsmCode[2]=0xf0+HReg; CodeLen=3;
             break;
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0xe6-(0x50*OpSize); BAsmCode[1]=AdrVals[0];
             BAsmCode[2]=0xf0+HReg; CodeLen=3;
             break;
           END
          break;
         case ModDisp8WReg:
          BAsmCode[2]=AdrVals[0]; HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask1);
          switch (AdrMode)
           BEGIN
            case ModWReg:
            case ModWRReg:
             BAsmCode[0]=0xb2+(OpSize*0x2c);
             BAsmCode[1]=(AdrPart << 4)+(OpSize << 4)+HReg;
             CodeLen=3;
             break;
           END
          break;
         case ModIncWReg:
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],MModIncWRReg*(1-OpSize));
          switch (AdrMode)
           BEGIN
            case ModIncWRReg:
             BAsmCode[0]=0xd7; BAsmCode[1]=(HReg << 4)+AdrPart+1; CodeLen=2;
             break;
           END
          break;
         case ModIWRReg:
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],(MModIWReg*(1-OpSize))+Mask1+Mask2+MModIWRReg+MModImm);
          switch (AdrMode)
           BEGIN
            case ModIWReg:
             BAsmCode[0]=0xb5; BAsmCode[1]=(AdrPart << 4)+HReg+1; CodeLen=2;
             break;
            case ModWReg:
             BAsmCode[0]=0x72; BAsmCode[1]=0xf0+HReg;
             BAsmCode[2]=AdrPart+WorkOfs;
             CodeLen=3;
             break;
            case ModWRReg:
             BAsmCode[0]=0xe3; BAsmCode[1]=(HReg << 4)+0x10+AdrPart;
             CodeLen=2;
             break;
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0x72+(OpSize*0x4c);
             BAsmCode[1]=0xf0+HReg+OpSize; BAsmCode[2]=AdrVals[0];
             CodeLen=3;
             break;
            case ModIWRReg:
             if (OpSize==0) 
              BEGIN
               BAsmCode[0]=0x73;
               BAsmCode[1]=0xf0+AdrPart;
               BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
              END
             else
              BEGIN
               BAsmCode[0]=0xe3; BAsmCode[1]=0x11+(HReg << 4)+AdrPart;
               CodeLen=2;
              END
             break;
            case ModImm:
             BAsmCode[0]=0xf3-(OpSize*0x35);
             BAsmCode[1]=0xf0+HReg;
             memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
             break;
           END
          break;
         case ModIncWRReg:
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask2+(MModIncWReg*(1-OpSize)));
          switch (AdrMode)
           BEGIN
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0xb4+(OpSize*0x21);
             BAsmCode[1]=0xf0+HReg; BAsmCode[2]=AdrVals[0];
             CodeLen=3;
             break;
            case ModIncWReg:
             BAsmCode[0]=0xd7; BAsmCode[1]=(AdrPart << 4)+HReg;
             CodeLen=2;
             break;
           END;
          break;
         case ModDecWRReg:
          HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask2);
          switch (AdrMode)
           BEGIN
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0xc2+OpSize;
             BAsmCode[1]=0xf0+HReg; BAsmCode[2]=AdrVals[0];
             CodeLen=3;
             break;
           END
          break;
         case ModDispRWRReg:
          HReg=AdrPart; HPart=AdrVals[0];
          DecodeAdr(ArgStr[2],Mask1);
          switch (AdrMode)
           BEGIN
            case ModWReg:
            case ModWRReg:
             BAsmCode[0]=0x60;
             BAsmCode[1]=(0x10*(1-OpSize))+0x01+(HPart << 4)+HReg;
             BAsmCode[2]=0xf0+AdrPart;
             CodeLen=3;
             break;
           END
          break;
         case ModDisp8WRReg:
          BAsmCode[2]=AdrVals[0]; HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
          switch (AdrMode)
           BEGIN
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0x26+(OpSize*0x60);
             BAsmCode[1]=0xf1+HReg; BAsmCode[3]=AdrVals[0];
             CodeLen=4;
             break;
            case ModImm:
             BAsmCode[0]=0x06; BAsmCode[1]=0xf1+HReg;
             memcpy(BAsmCode+3,AdrVals,AdrCnt); CodeLen=3+AdrCnt;
             break;
           END
          break;
         case ModDisp16WRReg:
          memcpy(BAsmCode+2,AdrVals,2); HReg=AdrPart;
          DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
          switch (AdrMode)
           BEGIN
            case ModReg:
            case ModRReg:
             BAsmCode[0]=0x26+(OpSize*0x60);
             BAsmCode[1]=0xf0+HReg; BAsmCode[4]=AdrVals[0];
             CodeLen=5;
             break;
            case ModImm:
             BAsmCode[0]=0x06; BAsmCode[1]=0xf0+HReg;
             memcpy(BAsmCode+4,AdrVals,AdrCnt); CodeLen=4+AdrCnt;
             break;
           END
          break;
         case ModAbs:
          memcpy(BAsmCode+2,AdrVals,2);
          DecodeAdr(ArgStr[2],Mask1+MModImm);
          switch (AdrMode)
           BEGIN
            case ModWReg:
            case ModWRReg:
             BAsmCode[0]=0xc5+(OpSize*0x1d);
             BAsmCode[1]=0xf0+AdrPart+OpSize;
             CodeLen=4;
             break;
            case ModImm:
             memmove(BAsmCode+2+AdrCnt,BAsmCode+2,2); BAsmCode[0]=0x2f+(OpSize*7);
             BAsmCode[1]=0xf1; memcpy(BAsmCode+2,AdrVals,AdrCnt);
             CodeLen=4+AdrCnt;
             break;
           END
          break;
         case ModIRReg:
          HReg=AdrVals[0];
          DecodeAdr(ArgStr[2],MModIWRReg*(1-OpSize));
          switch (AdrMode)
           BEGIN
            case ModIWRReg:
             BAsmCode[0]=0x73; BAsmCode[1]=0xf0+AdrPart; BAsmCode[2]=HReg;
             CodeLen=3;
             break;
           END
          break;
        END
      END
     return;
    END

   for (z=0; z<LoadOrderCnt; z++)
    if (Memo(LoadOrders[z].Name)) 
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else
       BEGIN
        DecodeAdr(ArgStr[1],MModIncWRReg);
        if (AdrMode==ModIncWRReg)
         BEGIN
          HReg=AdrPart << 4;
          DecodeAdr(ArgStr[2],MModIncWRReg);
          if (AdrMode==ModIncWRReg)
           BEGIN
            BAsmCode[0]=0xd6;
            BAsmCode[1]=LoadOrders[z].Code+HReg+AdrPart;
            CodeLen=2;
           END
         END
       END
      return;
     END

   if ((Memo("PEA")) OR (Memo("PEAU"))) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModDisp8RReg+MModDisp16RReg);
       if (AdrMode!=ModNone)
        BEGIN
         BAsmCode[0]=0x8f;
         BAsmCode[1]=0x01+(2*Ord(Memo("PEAU")));
         memcpy(BAsmCode+2,AdrVals,AdrCnt);
         BAsmCode[2]+=AdrCnt-2;
         CodeLen=2+AdrCnt;
        END
      END
     return;
    END

   if ((Memo("PUSH")) OR (Memo("PUSHU"))) 
    BEGIN
     z=Ord(Memo("PUSHU"));
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModReg+MModIReg+MModImm);
       switch (AdrMode)
        BEGIN
         case ModReg:
          BAsmCode[0]=0x66-(z*0x36); BAsmCode[1]=AdrVals[0];
          CodeLen=2;
          break;
         case ModIReg:
          BAsmCode[0]=0xf7-(z*0xc6); BAsmCode[1]=AdrVals[0];
          CodeLen=2;
          break;
         case ModImm:
          BAsmCode[0]=0x8f; BAsmCode[1]=0xf1+(z*2);
          BAsmCode[2]=AdrVals[0]; CodeLen=3;
          break;
        END
      END
     return;
    END

   if ((Memo("PUSHW")) OR (Memo("PUSHUW"))) 
    BEGIN
     z=Ord(Memo("PUSHUW")); OpSize=1;
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModRReg+MModImm);
       switch (AdrMode)
        BEGIN
         case ModRReg:
          BAsmCode[0]=0x74+(z*0x42); BAsmCode[1]=AdrVals[0];
          CodeLen=2;
          break;
         case ModImm:
          BAsmCode[0]=0x8f; BAsmCode[1]=0xc1+(z*2);
          memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
          break;
        END
      END
     return;
    END

   if (Memo("XCH")) 
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModReg);
       if (AdrMode==ModReg)
        BEGIN
         BAsmCode[2]=AdrVals[0];
         DecodeAdr(ArgStr[2],MModReg);
         if (AdrMode==ModReg)
          BEGIN
           BAsmCode[1]=AdrVals[0];
           BAsmCode[0]=0x16;
           CodeLen=3;
          END
        END
      END
     return;
    END

   /* Arithmetik */

   for (z=0; z<ALUOrderCnt; z++)
    if ((strncmp(OpPart,ALUOrders[z].Name,ALUOrders[z].len)==0) AND ((OpPart[ALUOrders[z].len]=='\0') OR (OpPart[ALUOrders[z].len]=='W')))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else
       BEGIN
        if (OpPart[strlen(OpPart)-1]=='W') 
         BEGIN
          OpSize=1; Mask1=MModWRReg; Mask2=MModRReg;
         END
        else
         BEGIN
          Mask1=MModWReg; Mask2=MModReg;
         END
        DecodeAdr(ArgStr[1],Mask1+Mask2+MModIWReg+MModIWRReg+MModIncWRReg+
                            MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+MModDisp16WRReg+
                            MModAbs+MModIRReg);
        switch (AdrMode)
         BEGIN
          case ModWReg:
          case ModWRReg:
           HReg=AdrPart;
           DecodeAdr(ArgStr[2],Mask1+MModIWReg+Mask2+MModIWRReg+MModIncWRReg+
                               MModDecWRReg+MModDispRWRReg+MModDisp8WRReg+MModDisp16WRReg+
                               MModAbs+MModImm);
           switch (AdrMode)
            BEGIN
             case ModWReg:
             case ModWRReg:
              BAsmCode[0]=(ALUOrders[z].Code << 4)+2+(OpSize*12);
              BAsmCode[1]=(HReg << 4)+AdrPart;
              CodeLen=2;
              break;
             case ModIWReg:
              if (OpSize==0) 
               BEGIN
                BAsmCode[0]=(ALUOrders[z].Code << 4)+3; BAsmCode[1]=(HReg << 4)+AdrPart;
                CodeLen=2;
               END
              else
               BEGIN
                BAsmCode[0]=0xa6; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
                BAsmCode[2]=WorkOfs+HReg; CodeLen=3;
               END
              break;
             case ModReg:
             case ModRReg:
              BAsmCode[0]=(ALUOrders[z].Code << 4)+4+(OpSize*3);
              BAsmCode[1]=AdrVals[0]; BAsmCode[2]=HReg+WorkOfs;
              CodeLen=3;
              break;
             case ModIWRReg:
              if (OpSize==0) 
               BEGIN
                BAsmCode[0]=0x72; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
     	        BAsmCode[2]=HReg+WorkOfs;
                CodeLen=3;
               END
              else
               BEGIN
                BAsmCode[0]=(ALUOrders[z].Code << 4)+0x0e;
                BAsmCode[1]=(HReg << 4)+AdrPart+1;
                CodeLen=2;
               END
              break;
             case ModIncWRReg:
              BAsmCode[0]=0xb4+(OpSize*0x21);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
              BAsmCode[2]=HReg+WorkOfs;
              CodeLen=3;
              break;
             case ModDecWRReg:
              BAsmCode[0]=0xc2+OpSize;
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
              BAsmCode[2]=HReg+WorkOfs;
              CodeLen=3;
              break;
             case ModDispRWRReg:
              BAsmCode[0]=0x60;
              BAsmCode[1]=0x10*(1-OpSize)+(AdrVals[0] << 4)+AdrPart;
              BAsmCode[2]=(ALUOrders[z].Code << 4)+HReg;
              CodeLen=3;
              break;
             case ModDisp8WRReg:
              BAsmCode[0]=0x7f+(OpSize*7);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
              BAsmCode[2]=AdrVals[0]; BAsmCode[3]=WorkOfs+HReg;
              CodeLen=4;
              break;
             case ModDisp16WRReg:
              BAsmCode[0]=0x7f+(OpSize*7);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
              memcpy(BAsmCode+2,AdrVals,AdrCnt);
              BAsmCode[2+AdrCnt]=WorkOfs+HReg;
              CodeLen=3+AdrCnt;
              break;
             case ModAbs:
              BAsmCode[0]=0xc4+(OpSize*30);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
              memcpy(BAsmCode+2,AdrVals,AdrCnt);
              CodeLen=2+AdrCnt;
              break;
             case ModImm:
              BAsmCode[0]=(ALUOrders[z].Code << 4)+5+(OpSize*2);
              BAsmCode[1]=WorkOfs+HReg+OpSize;
              memcpy(BAsmCode+2,AdrVals,AdrCnt);
              CodeLen=2+AdrCnt;
              break;
            END
           break;
          case ModReg:
          case ModRReg:
           HReg=AdrVals[0];
           DecodeAdr(ArgStr[2],Mask2+MModIWReg+MModIWRReg+MModIncWRReg+MModDecWRReg+
                               MModDisp8WRReg+MModDisp16WRReg+MModImm);
           switch (AdrMode)
            BEGIN
             case ModReg:
             case ModRReg:
              BAsmCode[0]=(ALUOrders[z].Code << 4)+4+(OpSize*3); CodeLen=3;
              BAsmCode[1]=AdrVals[0]; BAsmCode[2]=HReg;
              break;
             case ModIWReg:
              BAsmCode[0]=0xa6+65*(1-OpSize);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
              BAsmCode[2]=HReg; CodeLen=3;
              break;
             case ModIWRReg:
              BAsmCode[0]=0x72+(OpSize*12);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+(1-OpSize);
              BAsmCode[2]=HReg; CodeLen=3;
              break;
             case ModIncWRReg:
              BAsmCode[0]=0xb4+(OpSize*0x21);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
              BAsmCode[2]=HReg; CodeLen=3;
              break;
             case ModDecWRReg:
              BAsmCode[0]=0xc2+OpSize;
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
              BAsmCode[2]=HReg; CodeLen=3;
              break;
             case ModDisp8WRReg:
              BAsmCode[0]=0x7f+(OpSize*7);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+1;
              BAsmCode[2]=AdrVals[0]; BAsmCode[3]=HReg; CodeLen=4;
              break;
             case ModDisp16WRReg:
              BAsmCode[0]=0x7f+(OpSize*7);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
              memcpy(BAsmCode+2,AdrVals,AdrCnt); BAsmCode[2+AdrCnt]=HReg;
              CodeLen=3+AdrCnt;
              break;
             case ModImm:
              BAsmCode[0]=(ALUOrders[z].Code << 4)+5+(OpSize*2);
              memcpy(BAsmCode+2,AdrVals,AdrCnt); BAsmCode[1]=HReg+OpSize;
              CodeLen=2+AdrCnt;
              break;
            END
           break;
          case ModIWReg:
           HReg=AdrPart;
           DecodeAdr(ArgStr[2],Mask2);
           switch (AdrMode)
            BEGIN
             case ModReg:
             case ModRReg:
              BAsmCode[0]=0xe6-(OpSize*0x50); BAsmCode[1]=AdrVals[0];
              BAsmCode[2]=(ALUOrders[z].Code << 4)+HReg; CodeLen=3;
              break;
            END
           break;
          case ModIWRReg:
           HReg=AdrPart;
           DecodeAdr(ArgStr[2],(OpSize*MModWRReg)+Mask2+MModIWRReg+MModImm);
           switch (AdrMode)
            BEGIN
             case ModWRReg:
              BAsmCode[0]=(ALUOrders[z].Code << 4)+0x0e;
              BAsmCode[1]=(HReg << 4)+0x10+AdrPart; CodeLen=2;
              break;
             case ModReg:
             case ModRReg:
              BAsmCode[0]=0x72+(OpSize*76);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg+OpSize;
              BAsmCode[2]=AdrVals[0]; CodeLen=3;
              break;
             case ModIWRReg:
              if (OpSize==0) 
               BEGIN
                BAsmCode[0]=0x73; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
                BAsmCode[2]=HReg+WorkOfs; CodeLen=3;
               END
              else
               BEGIN
                BAsmCode[0]=(ALUOrders[z].Code << 4)+0x0e;
                BAsmCode[1]=0x11+(HReg << 4)+AdrPart;
                CodeLen=2;
               END
              break;
             case ModImm:
              BAsmCode[0]=0xf3-(OpSize*0x35);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
              memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
              break;
            END
           break;
          case ModIncWRReg:
           HReg=AdrPart;
           DecodeAdr(ArgStr[2],Mask2);
           switch (AdrMode)
            BEGIN
             case ModReg:
             case ModRReg:
              BAsmCode[0]=0xb4+(OpSize*0x21);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
              BAsmCode[2]=AdrVals[0]; CodeLen=3;
              break;
            END
           break;
          case ModDecWRReg:
           HReg=AdrPart;
           DecodeAdr(ArgStr[2],Mask2);
           switch (AdrMode)
            BEGIN
             case ModReg:
             case ModRReg:
              BAsmCode[0]=0xc2+OpSize;
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
              BAsmCode[2]=AdrVals[0]; CodeLen=3;
              break;
            END
           break;
          case ModDispRWRReg:
           HReg=AdrPart; HPart=AdrVals[0];
           DecodeAdr(ArgStr[2],Mask1);
           switch (AdrMode)
            BEGIN
             case ModWReg:
             case ModWRReg:
              BAsmCode[0]=0x60;
              BAsmCode[1]=0x11-(OpSize*0x10)+(HPart << 4)+HReg;
              BAsmCode[2]=(ALUOrders[z].Code << 4)+AdrPart; CodeLen=3;
              break;
            END
           break;
          case ModDisp8WRReg:
           HReg=AdrPart; BAsmCode[2]=AdrVals[0];
           DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
           switch (AdrMode)
            BEGIN
             case ModReg:
             case ModRReg:
              BAsmCode[0]=0x26+(OpSize*0x60);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg+1;
              BAsmCode[3]=AdrVals[0]+OpSize; CodeLen=4;
              break;
             case ModImm:
              BAsmCode[0]=0x06; BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg+1;
              memcpy(BAsmCode+3,AdrVals,AdrCnt); CodeLen=3+AdrCnt;
              break;
            END
           break;
          case ModDisp16WRReg:
           HReg=AdrPart; memcpy(BAsmCode+2,AdrVals,2);
           DecodeAdr(ArgStr[2],Mask2+(OpSize*MModImm));
           switch (AdrMode)
            BEGIN
             case ModReg:
             case ModRReg:
              BAsmCode[0]=0x26+(OpSize*0x60);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
              BAsmCode[4]=AdrVals[0]+OpSize; CodeLen=5;
              break;
             case ModImm:
              BAsmCode[0]=0x06; BAsmCode[1]=(ALUOrders[z].Code << 4)+HReg;
              memcpy(BAsmCode+4,AdrVals,AdrCnt); CodeLen=4+AdrCnt;
              break;
            END
           break;
          case ModAbs:
           memcpy(BAsmCode+2,AdrVals,2);
           DecodeAdr(ArgStr[2],Mask1+MModImm);
           switch (AdrMode)
            BEGIN
             case ModWReg:
             case ModWRReg:
              BAsmCode[0]=0xc5+(OpSize*29);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart+OpSize;
              CodeLen=4;
              break;
             case ModImm:
              memmove(BAsmCode+2+AdrCnt,BAsmCode+2,2); memcpy(BAsmCode+2,AdrVals,AdrCnt);
              BAsmCode[0]=0x2f+(OpSize*7);
              BAsmCode[1]=(ALUOrders[z].Code << 4)+1;
              CodeLen=4+AdrCnt;
              break;
            END
           break;
          case ModIRReg:
           HReg=AdrVals[0];
           DecodeAdr(ArgStr[2],MModIWRReg*(1-OpSize));
           switch (AdrMode)
            BEGIN
             case ModIWRReg:
              BAsmCode[0]=0x73; BAsmCode[1]=(ALUOrders[z].Code << 4)+AdrPart;
              BAsmCode[2]=HReg; CodeLen=3;
              break;
            END
           break;
         END
       END
      return;
     END

   for (z=0; z<RegOrderCnt; z++)
    if (Memo(RegOrders[z].Name)) 
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else
       BEGIN
        DecodeAdr(ArgStr[1],MModReg+MModIReg);
        switch (AdrMode)
         BEGIN
          case ModReg:
           BAsmCode[0]=RegOrders[z].Code; BAsmCode[1]=AdrVals[0]; CodeLen=2;
           break;
          case ModIReg:
           BAsmCode[0]=RegOrders[z].Code+1; BAsmCode[1]=AdrVals[0]; CodeLen=2;
           break;
         END
       END
      return;
     END

   for (z=0; z<Reg16OrderCnt; z++)
    if (Memo(Reg16Orders[z].Name)) 
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else
       BEGIN
        DecodeAdr(ArgStr[1],MModRReg);
        switch (AdrMode)
         BEGIN
          case ModRReg:
           BAsmCode[0]=Reg16Orders[z].Code; BAsmCode[1]=AdrVals[0]+Ord(Memo("EXT"));
           CodeLen=2;
           break;
         END
       END
      return;
     END

   if ((Memo("DIV")) OR (Memo("MUL"))) 
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModWRReg);
       if (AdrMode==ModWRReg) 
        BEGIN
         HReg=AdrPart;
         DecodeAdr(ArgStr[2],MModWReg);
         if (AdrMode==ModWReg) 
          BEGIN
           BAsmCode[0]=0x5f-(0x10*Ord(Memo("MUL")));
           BAsmCode[1]=(HReg << 4)+AdrPart;
           CodeLen=2;
          END
        END
      END
     return;
    END

   if (Memo("DIVWS")) 
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModWRReg);
       if (AdrMode==ModWRReg) 
        BEGIN
         HReg=AdrPart;
         DecodeAdr(ArgStr[2],MModWRReg);
         if (AdrMode==ModWRReg) 
          BEGIN
           BAsmCode[2]=(HReg << 4)+AdrPart;
           DecodeAdr(ArgStr[3],MModRReg);
           if (AdrMode==ModRReg) 
            BEGIN
             BAsmCode[0]=0x56; BAsmCode[1]=AdrVals[0];
             CodeLen=3;
            END
          END
        END
      END
     return;
    END

   /* Bitoperationen */

   for (z=0; z<Bit2OrderCnt; z++)
    if (Memo(Bit2Orders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else if (SplitBit(ArgStr[1],&HReg))
       if (Odd(HReg)) WrError(1350);
       else
        BEGIN
         DecodeAdr(ArgStr[1],MModWReg);
         if (AdrMode==ModWReg)
          BEGIN
           HReg=(HReg << 4)+AdrPart;
           if (SplitBit(ArgStr[2],&HPart))
            BEGIN
             DecodeAdr(ArgStr[2],MModWReg);
             if (AdrMode==ModWReg)
              BEGIN
               HPart=(HPart << 4)+AdrPart;
               BAsmCode[0]=Bit2Orders[z].Code;
               if (Memo("BLD"))
                BEGIN
                 BAsmCode[1]=HPart | 0x10; BAsmCode[2]=HReg | (HPart & 0x10);
                END
               else if (Memo("BXOR"))
                BEGIN
                 BAsmCode[1]=0x10+HReg; BAsmCode[2]=HPart;
                END
               else
                BEGIN
                 BAsmCode[1]=0x10+HReg; BAsmCode[2]=HPart ^ 0x10;
                END
               CodeLen=3;
              END
            END
          END
        END
      return;
     END

   for (z=0; z<Bit1OrderCnt; z++)
    if (Memo(Bit1Orders[z].Name))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else if (SplitBit(ArgStr[1],&HReg))
       if (Odd(HReg)) WrError(1350);
       else
        BEGIN
         DecodeAdr(ArgStr[1],MModWReg+(Ord(Memo("BTSET"))*MModIWRReg));
         switch (AdrMode)
          BEGIN
           case ModWReg:
            BAsmCode[0]=Bit1Orders[z].Code; BAsmCode[1]=(HReg << 4)+AdrPart;
            CodeLen=2;
            break;
           case ModIWRReg:
            BAsmCode[0]=0xf6; BAsmCode[1]=(HReg << 4)+AdrPart;
            CodeLen=2;
            break;
          END
        END
      return;
     END

   /* Spruenge */

   if ((Memo("BTJF")) OR (Memo("BTJT"))) 
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (SplitBit(ArgStr[1],&HReg)) 
      if (Odd(HReg)) WrError(1350);
      else
       BEGIN
        DecodeAdr(ArgStr[1],MModWReg);
        if (AdrMode==ModWReg) 
         BEGIN
          BAsmCode[1]=(HReg << 4)+AdrPart+(Ord(Memo("BTJF")) << 4);
          AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3);
          if (OK) 
           if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
           else
            BEGIN
             BAsmCode[0]=0xaf; BAsmCode[2]=AdrInt & 0xff; CodeLen=3;
             ChkSpace(SegCode);
            END
         END
       END
     return;
    END

   if ((Memo("JP")) OR (Memo("CALL"))) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       AbsSeg=SegCode;
       DecodeAdr(ArgStr[1],MModIRReg+MModAbs);
       switch (AdrMode)
        BEGIN
         case ModIRReg:
          BAsmCode[0]=0x74+(Ord(Memo("JP"))*0x60);
          BAsmCode[1]=AdrVals[0]+Ord(Memo("CALL")); CodeLen=2;
          break;
         case ModAbs:
          BAsmCode[0]=0x8d+(Ord(Memo("CALL"))*0x45);
          memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt;
          break;
        END
      END
     return;
    END

   if ((Memo("CPJFI")) OR (Memo("CPJTI"))) 
    BEGIN
     if (ArgCnt!=3) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModWReg);
       if (AdrMode==ModWReg) 
        BEGIN
         HReg=AdrPart;
         DecodeAdr(ArgStr[2],MModIWRReg);
         if (AdrMode==ModIWRReg) 
          BEGIN
           BAsmCode[1]=(AdrPart << 4)+(Ord(Memo("CPJTI")) << 4)+HReg;
           AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+3);
           if (OK) 
            if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
            else
             BEGIN
              ChkSpace(SegCode);
              BAsmCode[0]=0x9f; BAsmCode[2]=AdrInt & 0xff;
              CodeLen=3;
             END
          END
        END
      END
     return;
    END

   if (Memo("DJNZ")) 
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModWReg);
       if (AdrMode==ModWReg) 
        BEGIN
         BAsmCode[0]=(AdrPart << 4)+0x0a;
         AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+2);
         if (OK) 
          if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
          else
           BEGIN
            ChkSpace(SegCode);
            BAsmCode[1]=AdrInt & 0xff;
            CodeLen=2;
           END
        END
      END
     return;
    END

   if (Memo("DWJNZ")) 
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModRReg);
       if (AdrMode==ModRReg) 
        BEGIN
         BAsmCode[1]=AdrVals[0];
         AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3);
         if (OK) 
          if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
          else
           BEGIN
            ChkSpace(SegCode);
            BAsmCode[0]=0xc6; BAsmCode[2]=AdrInt & 0xff;
            CodeLen=3;
           END
        END
      END
     return;
    END

   for (z=0; z<ConditionCnt; z++)
    if ((*OpPart=='J') AND (OpPart[1]=='P') AND (strcmp(OpPart+2,Conditions[z].Name)==0))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else
       BEGIN
        AdrWord=EvalIntExpression(ArgStr[1],UInt16,&OK);
        if (OK)
         BEGIN
          ChkSpace(SegCode);
          BAsmCode[0]=0x0d+(Conditions[z].Code << 4);
          BAsmCode[1]=Hi(AdrWord); BAsmCode[2]=Lo(AdrWord);
          CodeLen=3;
         END
       END
      return;
     END
    else if ((*OpPart=='J') AND (OpPart[1]=='R') AND (strcmp(OpPart+2,Conditions[z].Name)==0))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else
       BEGIN
        AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
        if (OK)
         if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370);
         else
          BEGIN
           ChkSpace(SegCode);
           BAsmCode[0]=0x0b+(Conditions[z].Code << 4); BAsmCode[1]=AdrInt & 0xff;
           CodeLen=2;
          END
       END
      return;
     END

   /* Besonderheiten */

   if (Memo("SPP")) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*ArgStr[1]!='#') WrError(1350);
     else
      BEGIN
       BAsmCode[1]=(EvalIntExpression(ArgStr[1]+1,UInt6,&OK) << 2)+0x02;
       if (OK) 
        BEGIN
         BAsmCode[0]=0xc7; CodeLen=2;
        END
      END
     return;
    END

   if ((Memo("SRP")) OR (Memo("SRP0")) OR (Memo("SRP1"))) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*ArgStr[1]!='#') WrError(1350);
     else
      BEGIN
       BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,UInt5,&OK) << 3;
       if (OK)
        BEGIN
         BAsmCode[0]=0xc7; CodeLen=2;
         if (strlen(OpPart)==4) BAsmCode[1]+=4;
         if (OpPart[strlen(OpPart)-1]=='1') BAsmCode[1]++;
        END
      END
     return;
    END

   /* Fakes... */

   if (Memo("SLA")) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModWReg+MModReg+MModIWRReg);
       switch (AdrMode)
        BEGIN
         case ModWReg:
          BAsmCode[0]=0x42; BAsmCode[1]=(AdrPart << 4)+AdrPart;
          CodeLen=2;
          break;
         case ModReg:
          BAsmCode[0]=0x44;
          BAsmCode[1]=AdrVals[0];
          BAsmCode[2]=AdrVals[0];
          CodeLen=3;
          break;
         case ModIWRReg:
          BAsmCode[0]=0x73; BAsmCode[1]=0x40+AdrPart;
          BAsmCode[2]=WorkOfs+AdrPart; CodeLen=3;
          break;
        END
      END
     return;
    END

   if (Memo("SLAW")) 
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModWRReg+MModRReg+MModIWRReg);
       switch (AdrMode)
        BEGIN
         case ModWRReg:
          BAsmCode[0]=0x4e; BAsmCode[1]=(AdrPart << 4)+AdrPart;
          CodeLen=2;
          break;
         case ModRReg:
          BAsmCode[0]=0x47;
          BAsmCode[1]=AdrVals[0];
          BAsmCode[2]=AdrVals[0];
          CodeLen=3;
          break;
         case ModIWRReg:
          BAsmCode[0]=0x4e; BAsmCode[1]=0x11+(AdrPart << 4)+AdrPart;
          CodeLen=2;
          break;
        END
      END
     return;
    END

   WrXError(1200,OpPart);
END

        static void InitCode_ST9(void)
BEGIN
   SaveInitProc();

   DPAssume=0;
END

        static Boolean IsDef_ST9(void)
BEGIN
   return (Memo("REG") OR Memo("BIT"));
END

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

        static void InternSymbol_ST9(char *Asc, TempResult *Erg)
BEGIN
   String h;
   Boolean Err;
   Boolean Pair;

   Erg->Typ=TempNone;
   if ((strlen(Asc)<2) OR (*Asc!='R')) return;

   strmaxcpy(h,Asc+1,255);
   if (*h=='R')
    BEGIN
     if (strlen(h)<2) return;
     Pair=True; strcpy(h,h+1);
    END
   else Pair=False;
   Erg->Contents.Int=ConstLongInt(h,&Err);
   if ((NOT Err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>255)) return;
   if ((Erg->Contents.Int & 0xf0)==0xd0) return;
   if ((Pair) AND (Odd(Erg->Contents.Int))) return;

   if (Pair) Erg->Contents.Int+=0x100;
   Erg->Typ=TempInt; TypeFlag|=(1 << SegReg);
END

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

   PCSymbol="PC"; HeaderID=0x32; NOPCode=0xff;
   DivideChars=","; HasAttrs=False;

   ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegReg);
   Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
   SegLimits[SegCode] = 0xffff;
   Grans[SegData]=1; ListGrans[SegData]=1; SegInits[SegData]=0;
   SegLimits[SegData] = 0xffff;
   Grans[SegReg ]=1; ListGrans[SegReg ]=1; SegInits[SegReg ]=0;
   SegLimits[SegReg ] = 0xff;

   MakeCode=MakeCode_ST9; IsDef=IsDef_ST9;
   SwitchFrom=SwitchFrom_ST9; InternSymbol=InternSymbol_ST9;

   InitFields();
END

	void codest9_init(void)
BEGIN
   CPUST9020=AddCPU("ST9020",SwitchTo_ST9);
   CPUST9030=AddCPU("ST9030",SwitchTo_ST9);
   CPUST9040=AddCPU("ST9040",SwitchTo_ST9);
   CPUST9050=AddCPU("ST9050",SwitchTo_ST9);
   SaveInitProc=InitPassProc; InitPassProc=InitCode_ST9;
END


