/* code7000.c */
/*****************************************************************************/
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator SH7x00                                                      */
/*                                                                           */
/* Historie: 25.12.1996 Grundsteinlegung                                     */
/*           12. 4.1998 SH7700-Erweiterungen                                 */
/*            3. 1.1999 ChkPC-Anpassung                                      */
/*                                                                           */
/*****************************************************************************/

#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 "asmallg.h"
#include "codepseudo.h"
#include "codevars.h"


#define FixedOrderCount 13
#define OneRegOrderCount 22
#define TwoRegOrderCount 20
#define MulRegOrderCount 3
#define BWOrderCount 3
#define LogOrderCount 4


#define ModNone (-1)
#define ModReg 0
#define MModReg (1 << ModReg)
#define ModIReg 1
#define MModIReg (1 << ModIReg)
#define ModPreDec 2
#define MModPreDec (1 << ModPreDec)
#define ModPostInc 3
#define MModPostInc (1 << ModPostInc)
#define ModIndReg 4
#define MModIndReg (1 << ModIndReg)
#define ModR0Base 5
#define MModR0Base (1 << ModR0Base)
#define ModGBRBase 6
#define MModGBRBase (1 << ModGBRBase)
#define ModGBRR0 7
#define MModGBRR0 (1 << ModGBRR0)
#define ModPCRel 8
#define MModPCRel (1 << ModPCRel)
#define ModImm 9
#define MModImm (1 << ModImm)


#define CompLiteralsName "COMPRESSEDLITERALS"

typedef struct
         {
          char *Name;
          CPUVar MinCPU;
          Boolean Priv;
          Word Code;
         } FixedOrder;

typedef struct
         {
          char *Name;
          CPUVar MinCPU;
          Boolean Priv;
          Word Code;
          ShortInt DefSize;
         } TwoRegOrder;

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

   typedef struct _TLiteral
            {
             struct _TLiteral *Next;
             LongInt Value,FCount;
             Boolean Is32,IsForward;
             Integer PassNo;
             LongInt DefSection;
            } *PLiteral,TLiteral;

static ShortInt OpSize;     /* Groesse=8*(2^OpSize) */
static ShortInt AdrMode;    /* Ergebnisadressmodus */
static Word AdrPart;        /* Adressierungsmodusbits im Opcode */

static PLiteral FirstLiteral;
static LongInt ForwardCount;
static SimpProc SaveInitProc;

static CPUVar CPU7000,CPU7600,CPU7700;

static FixedOrder *FixedOrders;
static FixedMinOrder *OneRegOrders;
static TwoRegOrder *TwoRegOrders;
static FixedMinOrder *MulRegOrders;
static FixedOrder *BWOrders;
static char **LogOrders;

static Boolean CurrDelayed,PrevDelayed,CompLiterals;
static LongInt DelayedAdr;

/*-------------------------------------------------------------------------*/
/* dynamische Belegung/Freigabe Codetabellen */

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

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

	static void AddTwoReg(char *NName, Word NCode, Boolean NPriv, CPUVar NMin, ShortInt NDef)
BEGIN
   if (InstrZ>=TwoRegOrderCount) exit(255);
   TwoRegOrders[InstrZ].Name=NName;
   TwoRegOrders[InstrZ].Priv=NPriv;
   TwoRegOrders[InstrZ].DefSize=NDef;
   TwoRegOrders[InstrZ].MinCPU=NMin;
   TwoRegOrders[InstrZ++].Code=NCode;
END

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

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

	static void InitFields(void)
BEGIN
   FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
   AddFixed("CLRT"  ,0x0008,False,CPU7000);
   AddFixed("CLRMAC",0x0028,False,CPU7000);
   AddFixed("NOP"   ,0x0009,False,CPU7000);
   AddFixed("RTE"   ,0x002b,False,CPU7000);
   AddFixed("SETT"  ,0x0018,False,CPU7000);
   AddFixed("SLEEP" ,0x001b,False,CPU7000);
   AddFixed("RTS"   ,0x000b,False,CPU7000);
   AddFixed("DIV0U" ,0x0019,False,CPU7000);
   AddFixed("BRK"   ,0x0000,True ,CPU7000);
   AddFixed("RTB"   ,0x0001,True ,CPU7000);
   AddFixed("CLRS"  ,0x0048,False,CPU7700);
   AddFixed("SETS"  ,0x0058,False,CPU7700);
   AddFixed("LDTLB" ,0x0038,True ,CPU7700);

   OneRegOrders=(FixedMinOrder *) malloc(sizeof(FixedMinOrder)*OneRegOrderCount); InstrZ=0;
   AddOneReg("MOVT"  ,0x0029,CPU7000); AddOneReg("CMP/PZ",0x4011,CPU7000);
   AddOneReg("CMP/PL",0x4015,CPU7000); AddOneReg("ROTL"  ,0x4004,CPU7000);
   AddOneReg("ROTR"  ,0x4005,CPU7000); AddOneReg("ROTCL" ,0x4024,CPU7000);
   AddOneReg("ROTCR" ,0x4025,CPU7000); AddOneReg("SHAL"  ,0x4020,CPU7000);
   AddOneReg("SHAR"  ,0x4021,CPU7000); AddOneReg("SHLL"  ,0x4000,CPU7000);
   AddOneReg("SHLR"  ,0x4001,CPU7000); AddOneReg("SHLL2" ,0x4008,CPU7000);
   AddOneReg("SHLR2" ,0x4009,CPU7000); AddOneReg("SHLL8" ,0x4018,CPU7000);
   AddOneReg("SHLR8" ,0x4019,CPU7000); AddOneReg("SHLL16",0x4028,CPU7000);
   AddOneReg("SHLR16",0x4029,CPU7000); AddOneReg("LDBR"  ,0x0021,CPU7000);
   AddOneReg("STBR"  ,0x0020,CPU7000); AddOneReg("DT"    ,0x4010,CPU7600);
   AddOneReg("BRAF"  ,0x0032,CPU7600); AddOneReg("BSRF"  ,0x0003,CPU7600);

   TwoRegOrders=(TwoRegOrder *) malloc(sizeof(TwoRegOrder)*TwoRegOrderCount); InstrZ=0;
   AddTwoReg("XTRCT" ,0x200d,False,CPU7000,2);
   AddTwoReg("ADDC"  ,0x300e,False,CPU7000,2);
   AddTwoReg("ADDV"  ,0x300f,False,CPU7000,2);
   AddTwoReg("CMP/HS",0x3002,False,CPU7000,2);
   AddTwoReg("CMP/GE",0x3003,False,CPU7000,2);
   AddTwoReg("CMP/HI",0x3006,False,CPU7000,2);
   AddTwoReg("CMP/GT",0x3007,False,CPU7000,2);
   AddTwoReg("CMP/STR",0x200c,False,CPU7000,2);
   AddTwoReg("DIV1"  ,0x3004,False,CPU7000,2);
   AddTwoReg("DIV0S" ,0x2007,False,CPU7000,-1);
   AddTwoReg("MULS"  ,0x200f,False,CPU7000,1);
   AddTwoReg("MULU"  ,0x200e,False,CPU7000,1);
   AddTwoReg("NEG"   ,0x600b,False,CPU7000,2);
   AddTwoReg("NEGC"  ,0x600a,False,CPU7000,2);
   AddTwoReg("SUB"   ,0x3008,False,CPU7000,2);
   AddTwoReg("SUBC"  ,0x300a,False,CPU7000,2);
   AddTwoReg("SUBV"  ,0x300b,False,CPU7000,2);
   AddTwoReg("NOT"   ,0x6007,False,CPU7000,2);
   AddTwoReg("SHAD"  ,0x400c,False,CPU7700,2);
   AddTwoReg("SHLD"  ,0x400d,False,CPU7700,2);

   MulRegOrders=(FixedMinOrder *) malloc(sizeof(FixedMinOrder)*MulRegOrderCount); InstrZ=0;
   AddMulReg("MUL"   ,0x0007,CPU7600);
   AddMulReg("DMULU" ,0x3005,CPU7600);
   AddMulReg("DMULS" ,0x300d,CPU7600);

   BWOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BWOrderCount); InstrZ=0;
   AddBW("SWAP",0x6008); AddBW("EXTS",0x600e); AddBW("EXTU",0x600c);

   LogOrders=(char **) malloc(sizeof(char *)*LogOrderCount); InstrZ=0;
   LogOrders[InstrZ++]="TST"; LogOrders[InstrZ++]="AND";
   LogOrders[InstrZ++]="XOR"; LogOrders[InstrZ++]="OR" ;
END

	static void DeinitFields(void)
BEGIN
   free(FixedOrders);
   free(OneRegOrders);
   free(TwoRegOrders);
   free(MulRegOrders);
   free(BWOrders);
   free(LogOrders);
END

/*-------------------------------------------------------------------------*/
/* die PC-relative Adresse: direkt nach verzoegerten Spruengen = Sprungziel+2 */

	static LongInt PCRelAdr(void)
BEGIN
   if (PrevDelayed) return DelayedAdr+2;
   else return EProgCounter()+4;
END

	static void ChkDelayed(void)
BEGIN
   if (PrevDelayed) WrError(200);
END

/*-------------------------------------------------------------------------*/
/* Adressparsing */

	static char *LiteralName(PLiteral Lit)
BEGIN
   String Tmp;
   static String Result;

   if (Lit->IsForward) sprintf(Tmp,"F_%s",HexString(Lit->FCount,8));
   else if (Lit->Is32) sprintf(Tmp,"L_%s",HexString(Lit->Value,8));
   else sprintf(Tmp,"W_%s",HexString(Lit->Value,4));
   sprintf(Result,"LITERAL_%s_%s",Tmp,HexString(Lit->PassNo,0));
   return Result;
END
/*
	static void PrintLiterals(void)
BEGIN
   PLiteral Lauf;

   WrLstLine("LiteralList");
   Lauf=FirstLiteral;
   while (Lauf!=Nil)
    BEGIN
     WrLstLine(LiteralName(Lauf)); Lauf=Lauf->Next;
    END
END
*/
	static void SetOpSize(ShortInt Size)
BEGIN
   if (OpSize==-1) OpSize=Size;
   else if (Size!=OpSize)
    BEGIN
     WrError(1131); AdrMode=ModNone;
    END
END

	static Boolean DecodeReg(char *Asc, Byte *Erg)
BEGIN
   Boolean Err;

   if (strcasecmp(Asc,"SP")==0)
    BEGIN
     *Erg=15; return True;
    END
   else if ((strlen(Asc)<2) OR (strlen(Asc)>3) OR (toupper(*Asc)!='R')) return False;
   else
    BEGIN
     *Erg=ConstLongInt(Asc+1,&Err);
     return (Err AND (*Erg<=15));
    END
END

	static Boolean DecodeCtrlReg(char *Asc, Byte *Erg)
BEGIN
   CPUVar MinCPU=CPU7000;

   *Erg=0xff;
   if (strcasecmp(Asc,"SR")==0) *Erg=0;
   else if (strcasecmp(Asc,"GBR")==0) *Erg=1;
   else if (strcasecmp(Asc,"VBR")==0) *Erg=2;
   else if (strcasecmp(Asc,"SSR")==0)
    BEGIN
     *Erg=3; MinCPU=CPU7700;
    END
   else if (strcasecmp(Asc,"SPC")==0)
    BEGIN
     *Erg=4; MinCPU=CPU7700;
    END
   else if ((strlen(Asc)==7) AND (toupper(*Asc)=='R')
       AND (strcasecmp(Asc+2,"_BANK")==0)
       AND (Asc[1]>='0') AND (Asc[1]<='7'))
    BEGIN
     *Erg=Asc[1]-'0'+8; MinCPU=CPU7700;
    END
   if ((*Erg==0xff) OR (MomCPU<MinCPU))
    BEGIN
     WrXError(1440,Asc); return False;
    END
   else return True;
END

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

   	static LongInt ExtOp(LongInt Inp, Byte Src, Boolean Signed)
BEGIN
   switch (Src)
    BEGIN
     case 0: Inp&=0xff; break;
     case 1: Inp&=0xffff; break;
    END
   if (Signed)
    BEGIN
     if (Src<1)
      if ((Inp & 0x80)==0x80) Inp+=0xff00;
     if (Src<2)
      if ((Inp & 0x8000)==0x8000) Inp+=0xffff0000;
    END
   return Inp;
END

	static LongInt OpMask(ShortInt OpSize)
BEGIN
   switch (OpSize)
    BEGIN
     case 0: return 0xff;
     case 1: return 0xffff;
     case 2: return 0xffffffff;
     default: return 0;
    END
END

	static void DecodeAdr(char *Asc, Word Mask, Boolean Signed)
BEGIN
#define RegNone (-1)
#define RegPC (-2)
#define RegGBR (-3)

   Byte p,HReg;
   char *pos;
   ShortInt BaseReg,IndReg,DOpSize;
   LongInt DispAcc;
   String AdrStr,LStr;
   Boolean OK,FirstFlag,NIs32,Critical,Found,LDef;
   PLiteral Lauf,Last;

   AdrMode=ModNone;

   if (DecodeReg(Asc,&HReg))
    BEGIN
     AdrPart=HReg; AdrMode=ModReg; ChkAdr(Mask); return;
    END

   if (*Asc=='@')
    BEGIN
     strcpy(Asc,Asc+1);
     if (IsIndirect(Asc))
      BEGIN
       strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
       BaseReg=RegNone; IndReg=RegNone;
       DispAcc=0; FirstFlag=False; OK=True;
       while ((*Asc!='\0') AND (OK))
	BEGIN
	 pos=QuotPos(Asc,',');
         if (pos==Nil)
          BEGIN
           strmaxcpy(AdrStr,Asc,255); *Asc='\0';
          END
         else
          BEGIN
           *pos='\0'; strmaxcpy(AdrStr,Asc,255); strcpy(Asc,pos+1);
          END
	 if (strcasecmp(AdrStr,"PC")==0)
	  if (BaseReg==RegNone) BaseReg=RegPC;
	  else
	   BEGIN
	    WrError(1350); OK=False;
	   END
	 else if (strcasecmp(AdrStr,"GBR")==0)
	  if (BaseReg==RegNone) BaseReg=RegGBR;
	  else
	   BEGIN
	    WrError(1350); OK=False;
	   END
	 else if (DecodeReg(AdrStr,&HReg))
	  if (IndReg==RegNone) IndReg=HReg;
	  else if ((BaseReg==RegNone) AND (HReg==0)) BaseReg=0;
	  else if ((IndReg==0) AND (BaseReg==RegNone))
	   BEGIN
	    BaseReg=0; IndReg=HReg;
	   END
	  else
	   BEGIN
	    WrError(1350); OK=False;
	   END
	 else
	  BEGIN
	   FirstPassUnknown=False;
	   DispAcc+=EvalIntExpression(AdrStr,Int32,&OK);
	   if (FirstPassUnknown) FirstFlag=True;
	  END
	END
       if (FirstFlag) DispAcc=0;
       if ((OK) AND ((DispAcc & ((1 << OpSize)-1))!=0))
	BEGIN
	 WrError(1325); OK=False;
	END
       else if ((OK) AND (DispAcc<0))
	BEGIN
	 WrXError(1315,"Disp<0"); OK=False;
	END
       else DispAcc=DispAcc >> OpSize;
       if (OK)
	BEGIN
	 switch (BaseReg)
          BEGIN
	   case 0:
	    if ((IndReg<0) OR (DispAcc!=0)) WrError(1350);
	    else
	     BEGIN
	      AdrMode=ModR0Base; AdrPart=IndReg;
	     END
            break;
	   case RegGBR:
	    if ((IndReg==0) AND (DispAcc==0)) AdrMode=ModGBRR0;
	    else if (IndReg!=RegNone) WrError(1350);
	    else if (DispAcc>255) WrError(1320);
	    else
	     BEGIN
	      AdrMode=ModGBRBase; AdrPart=DispAcc;
	     END
            break;
	   case RegNone:
	    if (IndReg==RegNone) WrError(1350);
	    else if (DispAcc>15) WrError(1320);
	    else
	     BEGIN
	      AdrMode=ModIndReg; AdrPart=(IndReg << 4)+DispAcc;
	     END
            break;
	   case RegPC:
	    if (IndReg!=RegNone) WrError(1350);
	    else if (DispAcc>255) WrError(1320);
	    else
	     BEGIN
	      AdrMode=ModPCRel; AdrPart=DispAcc;
	     END
	    break;
          END
	END
       ChkAdr(Mask); return;
      END
     else
      BEGIN
       if (DecodeReg(Asc,&HReg))
	BEGIN
	 AdrPart=HReg; AdrMode=ModIReg;
	END
       else if ((strlen(Asc)>1) AND (*Asc=='-') AND (DecodeReg(Asc+1,&HReg)))
	BEGIN
	 AdrPart=HReg; AdrMode=ModPreDec;
	END
       else if ((strlen(Asc)>1) AND (Asc[strlen(Asc)-1]=='+'))
        BEGIN
         strmaxcpy(AdrStr,Asc,255); AdrStr[strlen(AdrStr)-1]='\0';
         if (DecodeReg(AdrStr,&HReg))
	  BEGIN
	   AdrPart=HReg; AdrMode=ModPostInc;
	  END
         else WrError(1350);
        END
       else WrError(1350);
       ChkAdr(Mask); return;
      END
    END

   if (*Asc=='#')
    BEGIN
     FirstPassUnknown=False;
     switch (OpSize)
      BEGIN
       case 0: DispAcc=EvalIntExpression(Asc+1,Int8,&OK); break;
       case 1: DispAcc=EvalIntExpression(Asc+1,Int16,&OK); break;
       case 2: DispAcc=EvalIntExpression(Asc+1,Int32,&OK); break;
       default: DispAcc=0; OK=True;
      END
     Critical=FirstPassUnknown OR UsesForwards;
     if (OK)
      BEGIN
       /* minimale Groesse optimieren */
       DOpSize=(OpSize==0) ? 0 : Ord(Critical);
       while (((ExtOp(DispAcc,DOpSize,Signed) ^ DispAcc) & OpMask(OpSize))!=0) DOpSize++;
       if (DOpSize==0)
        BEGIN
	 AdrPart=DispAcc & 0xff;
	 AdrMode=ModImm;
        END
       else if ((Mask & MModPCRel)!=0)
	BEGIN
	 /* Literalgroesse ermitteln */
         NIs32=(DOpSize==2);
	 if (NOT NIs32) DispAcc&=0xffff;
	 /* Literale sektionsspezifisch */
         strcpy(AdrStr,"[PARENT0]");
	 /* schon vorhanden ? */
	 Lauf=FirstLiteral; p=0; OK=False; Last=Nil; Found=False;
	 while ((Lauf!=Nil) AND (NOT Found))
	  BEGIN
	   Last=Lauf;
           if ((NOT Critical) AND (NOT Lauf->IsForward)
	   AND (Lauf->DefSection==MomSectionHandle))
            if (((Lauf->Is32==NIs32) AND (DispAcc==Lauf->Value))
            OR  ((Lauf->Is32) AND (NOT NIs32) AND (DispAcc==(Lauf->Value >> 16)))) Found=True;
            else if ((Lauf->Is32) AND (NOT NIs32) AND (DispAcc==(Lauf->Value & 0xffff)))
             BEGIN
              Found=True; p=2;
             END
	   if (NOT Found) Lauf=Lauf->Next;
	  END
	 /* nein - erzeugen */
	 if (NOT Found)
	  BEGIN
	   Lauf=(PLiteral) malloc(sizeof(TLiteral));
	   Lauf->Is32=NIs32; Lauf->Value=DispAcc;
           Lauf->IsForward=Critical;
           if (Critical) Lauf->FCount=ForwardCount++;
	   Lauf->Next=Nil; Lauf->PassNo=1; Lauf->DefSection=MomSectionHandle;
           do
            BEGIN
             sprintf(LStr,"%s%s",LiteralName(Lauf),AdrStr);
             LDef=IsSymbolDefined(LStr);
             if (LDef) Lauf->PassNo++;
            END
           while (LDef);
           if (Last==Nil) FirstLiteral=Lauf; else Last->Next=Lauf;
	  END
	 /* Distanz abfragen - im naechsten Pass... */
	 FirstPassUnknown=False;
         sprintf(LStr,"%s%s",LiteralName(Lauf),AdrStr);
         DispAcc=EvalIntExpression(LStr,Int32,&OK)+p;
	 if (OK)
	  BEGIN
	   if (FirstPassUnknown)
	    DispAcc=0;
           else if (NIs32)
	    DispAcc=(DispAcc-(PCRelAdr() & 0xfffffffc)) >> 2;
           else
	    DispAcc=(DispAcc-PCRelAdr()) >> 1;
	   if (DispAcc<0)
	    BEGIN
	     WrXError(1315,"Disp<0"); OK=False;
	    END
           else if ((DispAcc>255) AND (NOT SymbolQuestionable)) WrError(1330);
	   else
	    BEGIN
	     AdrMode=ModPCRel; AdrPart=DispAcc; OpSize=Ord(NIs32)+1;
	    END
	  END
	END
       else WrError(1350);
      END
     ChkAdr(Mask); return;
    END

   /* absolut ueber PC-relativ abwickeln */

   if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
   else
    BEGIN
     FirstPassUnknown=False;
     DispAcc=EvalIntExpression(Asc,Int32,&OK);
     if (FirstPassUnknown) DispAcc=0;
     else if (OpSize==2) DispAcc-=(PCRelAdr() & 0xfffffffc);
     else DispAcc-=PCRelAdr();
     if (DispAcc<0) WrXError(1315,"Disp<0");
     else if ((DispAcc & ((1 << OpSize)-1))!=0) WrError(1325);
     else
      BEGIN
       DispAcc=DispAcc >> OpSize;
       if (DispAcc>255) WrError(1320);
       else
        BEGIN
	 AdrMode=ModPCRel; AdrPart=DispAcc;
        END
      END
    END

   ChkAdr(Mask);
END

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

	static void LTORG_16(void)
BEGIN
   PLiteral Lauf;

   Lauf=FirstLiteral;
   while (Lauf!=Nil)
    BEGIN
     if ((NOT Lauf->Is32) AND (Lauf->DefSection==MomSectionHandle))
      BEGIN
       WAsmCode[CodeLen >> 1]=Lauf->Value;
       EnterIntSymbol(LiteralName(Lauf),EProgCounter()+CodeLen,SegCode,False);
       Lauf->PassNo=(-1);
       CodeLen+=2;
      END
     Lauf=Lauf->Next;
    END
END

	static void LTORG_32(void)
BEGIN
   PLiteral Lauf,EqLauf;

   Lauf=FirstLiteral;
   while (Lauf!=Nil)
    BEGIN
     if ((Lauf->Is32) AND (Lauf->DefSection==MomSectionHandle) AND (Lauf->PassNo>=0))
      BEGIN
       if (((EProgCounter()+CodeLen) & 2)!=0)
        BEGIN
         WAsmCode[CodeLen >> 1]=0; CodeLen+=2;
        END
       WAsmCode[CodeLen >> 1]=(Lauf->Value >> 16);
       WAsmCode[(CodeLen >> 1)+1]=(Lauf->Value & 0xffff);
       EnterIntSymbol(LiteralName(Lauf),EProgCounter()+CodeLen,SegCode,False);
       Lauf->PassNo=(-1);
       if (CompLiterals)
        BEGIN
         EqLauf=Lauf->Next;
         while (EqLauf!=Nil)
          BEGIN
           if ((EqLauf->Is32) AND (EqLauf->PassNo>=0) AND
               (EqLauf->DefSection==MomSectionHandle) AND
               (EqLauf->Value==Lauf->Value))
            BEGIN
             EnterIntSymbol(LiteralName(EqLauf),EProgCounter()+CodeLen,SegCode,False);
             EqLauf->PassNo=(-1);
            END
           EqLauf=EqLauf->Next;
          END
        END
       CodeLen+=4;
      END
     Lauf=Lauf->Next;
    END
END

	static Boolean DecodePseudo(void)
BEGIN
   PLiteral Lauf,Tmp,Last;

   /* ab hier (und weiter in der Hauptroutine) stehen die Befehle,
      die Code erzeugen, deshalb wird der Merker fuer verzoegerte
      Spruenge hier weiter geschaltet. */

   PrevDelayed=CurrDelayed; CurrDelayed=False;

   if (Memo("LTORG"))
    BEGIN
     if (ArgCnt!=0) WrError(1110);
     else if (*AttrPart!='\0') WrError(1100);
     else
      BEGIN
       if ((EProgCounter() & 3)==0)
	BEGIN
	 LTORG_32(); LTORG_16();
	END
       else
	BEGIN
	 LTORG_16(); LTORG_32();
	END
       Lauf=FirstLiteral; Last=Nil;
       while (Lauf!=Nil)
	BEGIN
	 if ((Lauf->DefSection==MomSectionHandle) AND (Lauf->PassNo<0))
	  BEGIN
	   Tmp=Lauf->Next;
	   if (Last==Nil) FirstLiteral=Tmp; else Last->Next=Tmp;
	   free(Lauf); Lauf=Tmp;
	  END
	 else
	  BEGIN
	   Last=Lauf; Lauf=Lauf->Next;
	  END
	END
      END
     return True;
    END

   return False;
END

	static void SetCode(Word Code)
BEGIN
   CodeLen=2; WAsmCode[0]=Code;
END

	static void MakeCode_7000(void)
BEGIN
   int z;
   LongInt AdrLong;
   Boolean OK;
   Byte HReg;

   CodeLen=0; DontPrint=False; OpSize=(-1);

   /* zu ignorierendes */

   if (Memo("")) return;

   /* Pseudoanweisungen */

   if (DecodePseudo()) return;

   /* Attribut verwursten */

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

   if (DecodeMoto16Pseudo(OpSize,True)) return;

   /* Anweisungen ohne Argument */

   for (z=0; z<FixedOrderCount; z++)
    if (Memo(FixedOrders[z].Name))
     BEGIN
      if (ArgCnt!=0) WrError(1110);
      else if (*AttrPart!='\0') WrError(1100);
      else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
        SetCode(FixedOrders[z].Code);
        if ((NOT SupAllowed) AND (FixedOrders[z].Priv)) WrError(50);
       END
      return;
     END

   /* Datentransfer */

   if (Memo("MOV"))
    BEGIN
     if (OpSize==-1) SetOpSize(2);
     if (ArgCnt!=2) WrError(1110);
     else if (OpSize>2) WrError(1130);
     else if (DecodeReg(ArgStr[1],&HReg))
      BEGIN
       DecodeAdr(ArgStr[2],MModReg+MModIReg+MModPreDec+MModIndReg+MModR0Base+MModGBRBase,True);
       switch (AdrMode)
        BEGIN
         case ModReg:
	  if (OpSize!=2) WrError(1130);
	  else SetCode(0x6003+(HReg << 4)+(AdrPart << 8));
          break;
         case ModIReg:
	  SetCode(0x2000+(HReg << 4)+(AdrPart << 8)+OpSize);
          break;
         case ModPreDec:
	  SetCode(0x2004+(HReg << 4)+(AdrPart << 8)+OpSize);
          break;
         case ModIndReg:
	  if (OpSize==2)
	   SetCode(0x1000+(HReg << 4)+(AdrPart & 15)+((AdrPart & 0xf0) << 4));
	  else if (HReg!=0) WrError(1350);
	  else SetCode(0x8000+AdrPart+(((Word)OpSize) << 8));
          break;
         case ModR0Base:
	  SetCode(0x0004+(AdrPart << 8)+(HReg << 4)+OpSize);
          break;
         case ModGBRBase:
	  if (HReg!=0) WrError(1350);
	  else SetCode(0xc000+AdrPart+(((Word)OpSize) << 8));
          break;
        END
      END
     else if (DecodeReg(ArgStr[2],&HReg))
      BEGIN
       DecodeAdr(ArgStr[1],MModImm+MModPCRel+MModIReg+MModPostInc+MModIndReg+MModR0Base+MModGBRBase,True);
       switch (AdrMode)
        BEGIN
         case ModIReg:
	  SetCode(0x6000+(AdrPart << 4)+(((Word)HReg) << 8)+OpSize);
          break;
         case ModPostInc:
	  SetCode(0x6004+(AdrPart << 4)+(((Word)HReg) << 8)+OpSize);
          break;
         case ModIndReg:
	  if (OpSize==2)
	   SetCode(0x5000+(((Word)HReg) << 8)+AdrPart);
	  else if (HReg!=0) WrError(1350);
	  else SetCode(0x8400+AdrPart+(((Word)OpSize) << 8));
          break;
         case ModR0Base:
	  SetCode(0x000c+(AdrPart << 4)+(((Word)HReg) << 8)+OpSize);
          break;
         case ModGBRBase:
	  if (HReg!=0) WrError(1350);
	  else SetCode(0xc400+AdrPart+(((Word)OpSize) << 8));
          break;
         case ModPCRel:
	  if (OpSize==0) WrError(1350);
	  else SetCode(0x9000+(((Word)OpSize-1) << 14)+(((Word)HReg) << 8)+AdrPart);
          break;
         case ModImm:
	  SetCode(0xe000+(((Word)HReg) << 8)+AdrPart);
          break;
        END
      END
     else WrError(1350);
     return;
    END

   if (Memo("MOVA"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (NOT DecodeReg(ArgStr[2],&HReg)) WrError(1350);
     else if (HReg!=0) WrError(1350);
     else
      BEGIN
       SetOpSize(2);
       DecodeAdr(ArgStr[1],MModPCRel,False);
       if (AdrMode!=ModNone)
        BEGIN
         CodeLen=2; WAsmCode[0]=0xc700+AdrPart;
        END
      END
     return;
    END

   if (Memo("PREF"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*AttrPart!='\0') WrError(1100);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModIReg,False);
       if (AdrMode!=ModNone)
        BEGIN
         CodeLen=2; WAsmCode[0]=0x0083+(AdrPart << 8);
        END;
      END;
     return;
    END

   if ((Memo("LDC")) OR (Memo("STC")))
    BEGIN
     if (OpSize==-1) SetOpSize(2);
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (Memo("LDC"))
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]);
         strcpy(ArgStr[1],ArgStr[2]);
         strcpy(ArgStr[2],ArgStr[3]);
	END
       if (DecodeCtrlReg(ArgStr[1],&HReg))
	BEGIN
         DecodeAdr(ArgStr[2],MModReg+((Memo("LDC"))?MModPostInc:MModPreDec),False);
	 switch (AdrMode)
          BEGIN
	   case ModReg:
	    if (Memo("LDC")) SetCode(0x400e + (AdrPart << 8)+(HReg << 4)); /* ANSI :-0 */
	    else SetCode(0x0002+(AdrPart << 8)+(HReg << 4));
            break;
	   case ModPostInc:
	    SetCode(0x4007+(AdrPart << 8)+(HReg << 4));
            break;
	   case ModPreDec:
	    SetCode(0x4003+(AdrPart << 8)+(HReg << 4));
            break;
	  END
         if ((AdrMode!=ModNone) AND (NOT SupAllowed)) WrError(50);
	END
      END
     return;
    END

   if ((Memo("LDS")) OR (Memo("STS")))
    BEGIN
     if (OpSize==-1) SetOpSize(2);
     if (ArgCnt!=2) WrError(1110);
     else
      BEGIN
       if (Memo("LDS"))
	BEGIN
	 strcpy(ArgStr[3],ArgStr[1]);
         strcpy(ArgStr[1],ArgStr[2]);
         strcpy(ArgStr[2],ArgStr[3]);
	END
       if (strcasecmp(ArgStr[1],"MACH")==0) HReg=0;
       else if (strcasecmp(ArgStr[1],"MACL")==0) HReg=1;
       else if (strcasecmp(ArgStr[1],"PR")==0) HReg=2;
       else
	BEGIN
	 WrError(1440); HReg=0xff;
	END
       if (HReg<0xff)
	BEGIN
         DecodeAdr(ArgStr[2],MModReg+((Memo("LDS"))?MModPostInc:MModPreDec),False);
	 switch (AdrMode)
          BEGIN
	   case ModReg:
	    if (Memo("LDS")) SetCode(0x400a+(AdrPart << 8)+(HReg << 4));
	    else SetCode(0x000a+(AdrPart << 8)+(HReg << 4));
            break;
	   case ModPostInc:
	    SetCode(0x4006+(AdrPart << 8)+(HReg << 4));
            break;
	   case ModPreDec:
	    SetCode(0x4002+(AdrPart << 8)+(HReg << 4));
            break;
	  END
	END
      END
     return;
    END

   /* nur ein Register als Argument */

   for (z=0; z<OneRegOrderCount; z++)
    if (Memo(OneRegOrders[z].Name))
     BEGIN
      if (ArgCnt!=1) WrError(1110);
      else if (*AttrPart!='\0') WrError(1100);
      else if (MomCPU<OneRegOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
	DecodeAdr(ArgStr[1],MModReg,False);
	if (AdrMode!=ModNone)
	 SetCode(OneRegOrders[z].Code+(AdrPart << 8));
	if ((NOT SupAllowed) AND ((Memo("STBR")) OR (Memo("LDBR")))) WrError(50);
        if (*OpPart=='B')
         BEGIN
          CurrDelayed=True; DelayedAdr=0x7fffffff;
          ChkDelayed();
         END
       END
      return;
     END

   if (Memo("TAS"))
    BEGIN
     if (OpSize==-1) SetOpSize(0);
     if (ArgCnt!=1) WrError(1110);
     else if (OpSize!=0) WrError(1130);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModIReg,False);
       if (AdrMode!=ModNone) SetCode(0x401b+(AdrPart << 8));
      END
     return;
    END

   /* zwei Register */

   for (z=0; z<TwoRegOrderCount; z++)
    if (Memo(TwoRegOrders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else if ((*AttrPart!='\0') AND (OpSize!=TwoRegOrders[z].DefSize)) WrError(1100);
      else if (MomCPU<TwoRegOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
        DecodeAdr(ArgStr[1],MModReg,False);
        if (AdrMode!=ModNone)
         BEGIN
          WAsmCode[0]=TwoRegOrders[z].Code+(AdrPart << 4);
          DecodeAdr(ArgStr[2],MModReg,False);
          if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
          if ((NOT SupAllowed) AND (TwoRegOrders[z].Priv)) WrError(50);
         END
       END
      return;
     END

   for (z=0; z<MulRegOrderCount; z++)
    if (Memo(MulRegOrders[z].Name))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else if (MomCPU<MulRegOrders[z].MinCPU) WrError(1500);
      else
       BEGIN
        if (*AttrPart=='\0') OpSize=2;
        if (OpSize!=2) WrError(1130);
        else
         BEGIN
          DecodeAdr(ArgStr[1],MModReg,False);
          if (AdrMode!=ModNone)
           BEGIN
            WAsmCode[0]=MulRegOrders[z].Code+(AdrPart << 4);
            DecodeAdr(ArgStr[2],MModReg,False);
            if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
           END
         END
       END
      return;
     END

   for (z=0; z<BWOrderCount; z++)
    if (Memo(BWOrders[z].Name))
     BEGIN
      if (OpSize==-1) SetOpSize(1);
      if (ArgCnt!=2) WrError(1110);
      else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130);
      else
       BEGIN
        DecodeAdr(ArgStr[1],MModReg,False);
        if (AdrMode!=ModNone)
         BEGIN
          WAsmCode[0]=BWOrders[z].Code+OpSize+(AdrPart << 4);
          DecodeAdr(ArgStr[2],MModReg,False);
          if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
         END
       END
      return;
     END

   if (Memo("MAC"))
    BEGIN
     if (OpSize==-1) SetOpSize(1);
     if (ArgCnt!=2) WrError(1110);
     else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130);
     else if ((OpSize==2) AND (MomCPU<CPU7600)) WrError(1500);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModPostInc,False);
       if (AdrMode!=ModNone)
	BEGIN
	 WAsmCode[0]=0x000f+(AdrPart << 4)+(((Word)2-OpSize) << 14);
	 DecodeAdr(ArgStr[2],MModPostInc,False);
	 if (AdrMode!=ModNone) SetCode(WAsmCode[0]+(((Word)AdrPart) << 8));
	END
      END
     return;
    END

   if (Memo("ADD"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (*AttrPart!='\0') WrError(1100);
     else
      BEGIN
       DecodeAdr(ArgStr[2],MModReg,False);
       if (AdrMode!=ModNone)
	BEGIN
         HReg=AdrPart; OpSize=2;
	 DecodeAdr(ArgStr[1],MModReg+MModImm,True);
	 switch (AdrMode)
          BEGIN
	   case ModReg:
	    SetCode(0x300c+(((Word)HReg) << 8)+(AdrPart << 4));
            break;
	   case ModImm:
	    SetCode(0x7000+AdrPart+(((Word)HReg) << 8));
            break;
	  END
	END
      END
     return;
    END

   if (Memo("CMP/EQ"))
    BEGIN
     if (ArgCnt!=2) WrError(1110);
     else if (*AttrPart!='\0') WrError(1100);
     else
      BEGIN
       DecodeAdr(ArgStr[2],MModReg,False);
       if (AdrMode!=ModNone)
	BEGIN
         HReg=AdrPart; OpSize=2; DecodeAdr(ArgStr[1],MModReg+MModImm,True);
	 switch (AdrMode)
          BEGIN
	   case ModReg:
	    SetCode(0x3000+(((Word)HReg) << 8)+(AdrPart << 4));
            break;
	   case ModImm:
	    if (HReg!=0) WrError(1350);
	    else SetCode(0x8800+AdrPart);
            break;
	  END
	END
      END
     return;
    END

   for (z=0; z<LogOrderCount; z++)
    if (Memo(LogOrders[z]))
     BEGIN
      if (ArgCnt!=2) WrError(1110);
      else
       BEGIN
	DecodeAdr(ArgStr[2],MModReg+MModGBRR0,False);
	switch (AdrMode)
         BEGIN
	  case ModReg:
	   if ((*AttrPart!='\0') AND (OpSize!=2)) WrError(1130);
	   else
	    BEGIN
             OpSize=2;
	     HReg=AdrPart; DecodeAdr(ArgStr[1],MModReg+MModImm,False);
	     switch (AdrMode)
              BEGIN
	       case ModReg:
	        SetCode(0x2008+z+(((Word)HReg) << 8)+(AdrPart << 4));
                break;
	       case ModImm:
	        if (HReg!=0) WrError(1350);
	        else SetCode(0xc800+(z << 8)+AdrPart);
                break;
	      END
	    END
           break;
	  case ModGBRR0:
	   DecodeAdr(ArgStr[1],MModImm,False);
	   if (AdrMode!=ModNone)
	    SetCode(0xcc00+(z << 8)+AdrPart);
	   break;
	 END
       END
      return;
     END

   /* Miszellaneen.. */

   if (Memo("TRAPA"))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*AttrPart!='\0') WrError(1100);
     else
      BEGIN
       OpSize=0;
       DecodeAdr(ArgStr[1],MModImm,False);
       if (AdrMode==ModImm) SetCode(0xc300+AdrPart);
       ChkDelayed();
      END
     return;
    END

   /* Spruenge */

   if ((Memo("BF")) OR (Memo("BT"))
   OR  (Memo("BF/S")) OR (Memo("BT/S")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*AttrPart!='\0') WrError(1110);
     else if ((strlen(OpPart)==4) AND (MomCPU<CPU7600)) WrError(1500);
     else
      BEGIN
       DelayedAdr=EvalIntExpression(ArgStr[1],Int32,&OK);
       AdrLong=DelayedAdr-(EProgCounter()+4);
       if (OK)
	if (Odd(AdrLong)) WrError(1375);
        else if (((AdrLong<-256) OR (AdrLong>254)) AND (NOT SymbolQuestionable)) WrError(1370);
	else
	 BEGIN
	  WAsmCode[0]=0x8900+((AdrLong >> 1) & 0xff);
	  if (OpPart[1]=='F') WAsmCode[0]+=0x200;
          if (strlen(OpPart)==4)
	   BEGIN
	    WAsmCode[0]+=0x400; CurrDelayed=True;
           END
	  CodeLen=2;
          ChkDelayed();
	 END
      END
     return;
    END

   if ((Memo("BRA")) OR (Memo("BSR")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*AttrPart!='\0') WrError(1110);
     else
      BEGIN
       DelayedAdr=EvalIntExpression(ArgStr[1],Int32,&OK);
       AdrLong=DelayedAdr-(EProgCounter()+4);
       if (OK)
	if (Odd(AdrLong)) WrError(1375);
        else if (((AdrLong<-4096) OR (AdrLong>4094)) AND (NOT SymbolQuestionable)) WrError(1370);
	else
	 BEGIN
	  WAsmCode[0]=0xa000+((AdrLong >> 1) & 0xfff);
	  if (Memo("BSR")) WAsmCode[0]+=0x1000;
	  CodeLen=2;
          CurrDelayed=True; ChkDelayed();
	 END
      END
     return;
    END

   if ((Memo("JSR")) OR (Memo("JMP")))
    BEGIN
     if (ArgCnt!=1) WrError(1110);
     else if (*AttrPart!='\0') WrError(1130);
     else
      BEGIN
       DecodeAdr(ArgStr[1],MModIReg,False);
       if (AdrMode!=ModNone)
        BEGIN
         SetCode(0x400b+(AdrPart << 8)+(Ord(Memo("JMP")) << 5));
         CurrDelayed=True; DelayedAdr=0x7fffffff;
         ChkDelayed();
        END
      END
     return;
    END

   WrXError(1200,OpPart);
END

	static void InitCode_7000(void)
BEGIN
   SaveInitProc();
   FirstLiteral=Nil; ForwardCount=0;
END

	static Boolean IsDef_7000(void)
BEGIN
   return False;
END

	static void SwitchFrom_7000(void)
BEGIN
   DeinitFields();
   if (FirstLiteral!=Nil) WrError(1495);
   ClearONOFF();
END

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

   PCSymbol="*"; HeaderID=0x6c; NOPCode=0x0009;
   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_7000; IsDef=IsDef_7000;
   SwitchFrom=SwitchFrom_7000; InitFields();
   AddONOFF("SUPMODE",      &SupAllowed,   SupAllowedName  ,False);
   AddONOFF("COMPLITERALS", &CompLiterals, CompLiteralsName,False);
   AddMoto16PseudoONOFF();

   CurrDelayed=False; PrevDelayed=False;

   SetFlag(&DoPadding,DoPaddingName,False);
END

	void code7000_init(void)
BEGIN
   CPU7000=AddCPU("SH7000",SwitchTo_7000);
   CPU7600=AddCPU("SH7600",SwitchTo_7000);
   CPU7700=AddCPU("SH7700",SwitchTo_7000);

   SaveInitProc=InitPassProc; InitPassProc=InitCode_7000;
   FirstLiteral=Nil;
END
