dect
/
asl
Archived
13
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
asl/codez80.c

2815 lines
74 KiB
C

/* codez80.c */
/*****************************************************************************/
/* AS-Portierung */
/* */
/* Codegenerator Zilog Z80/180/380 */
/* */
/* Historie: 26. 8.1996 Grundsteinlegung */
/* 1. 2.1998 ChkPC ersetzt */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "nls.h"
#include "strutil.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmcode.h"
#include "asmallg.h"
#include "codepseudo.h"
#include "codevars.h"
/*-------------------------------------------------------------------------*/
/* Instruktionsgruppendefinitionen */
typedef struct
{
char *Name;
CPUVar MinCPU;
Byte Len;
Word Code;
} BaseOrder;
typedef struct
{
char *Name;
Byte Code;
} Condition;
typedef struct
{
char *Name;
Byte Code;
} ALUOrder;
/*-------------------------------------------------------------------------*/
/* Praefixtyp */
typedef enum {Pref_IN_N,Pref_IN_W ,Pref_IB_W ,Pref_IW_W ,Pref_IB_N ,
Pref_IN_LW,Pref_IB_LW,Pref_IW_LW,Pref_IW_N} PrefType;
#define ExtFlagName "INEXTMODE" /* Flag-Symbolnamen */
#define LWordFlagName "INLWORDMODE"
#define ModNone (-1)
#define ModReg8 1
#define ModReg16 2
#define ModIndReg16 3
#define ModImm 4
#define ModAbs 5
#define ModRef 6
#define ModInt 7
#define ModSPRel 8
#define FixedOrderCnt 53
#define AccOrderCnt 3
#define HLOrderCnt 3
#define ALUOrderCnt 5
#define ShiftOrderCnt 8
#define BitOrderCnt 3
#define ConditionCnt 12
#define IXPrefix 0xdd
#define IYPrefix 0xfd
/*-------------------------------------------------------------------------*/
static Byte PrefixCnt;
static Byte AdrPart,OpSize;
static Byte AdrVals[4];
static ShortInt AdrMode;
static BaseOrder *FixedOrders;
static BaseOrder *AccOrders;
static BaseOrder *HLOrders;
static ALUOrder *ALUOrders;
static char **ShiftOrders;
static char **BitOrders;
static Condition *Conditions;
static SimpProc SaveInitProc;
static CPUVar CPUZ80,CPUZ80U,CPUZ180,CPUZ380;
static Boolean MayLW, /* Instruktion erlaubt 32 Bit */
ExtFlag, /* Prozessor im 4GByte-Modus ? */
LWordFlag; /* 32-Bit-Verarbeitung ? */
static PrefType CurrPrefix, /* mom. explizit erzeugter Praefix */
LastPrefix; /* von der letzten Anweisung generierter Praefix */
/*==========================================================================*/
/* Codetabellenerzeugung */
static void AddFixed(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
BEGIN
if (InstrZ>=FixedOrderCnt) exit(255);
FixedOrders[InstrZ].Name=NewName;
FixedOrders[InstrZ].MinCPU=NewMin;
FixedOrders[InstrZ].Len=NewLen;
FixedOrders[InstrZ++].Code=NewCode;
END
static void AddAcc(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
BEGIN
if (InstrZ>=AccOrderCnt) exit(255);
AccOrders[InstrZ].Name=NewName;
AccOrders[InstrZ].MinCPU=NewMin;
AccOrders[InstrZ].Len=NewLen;
AccOrders[InstrZ++].Code=NewCode;
END
static void AddHL(char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
BEGIN
if (InstrZ>=HLOrderCnt) exit(255);
HLOrders[InstrZ].Name=NewName;
HLOrders[InstrZ].MinCPU=NewMin;
HLOrders[InstrZ].Len=NewLen;
HLOrders[InstrZ++].Code=NewCode;
END
static void AddALU(char *NewName, Byte NCode)
BEGIN
if (InstrZ>=ALUOrderCnt) exit(255);
ALUOrders[InstrZ].Name=NewName;
ALUOrders[InstrZ++].Code=NCode;
END
static void AddShift(char *NName)
BEGIN
if (InstrZ>=ShiftOrderCnt) exit(255);
ShiftOrders[InstrZ++]=NName;
END
static void AddBit(char *NName)
BEGIN
if (InstrZ>=BitOrderCnt) exit(255);
BitOrders[InstrZ++]=NName;
END
static void AddCondition(char *NewName, Byte NewCode)
BEGIN
if (InstrZ>=ConditionCnt) exit(255);
Conditions[InstrZ].Name=NewName;
Conditions[InstrZ++].Code=NewCode;
END
static void InitFields(void)
BEGIN
InstrZ=0; Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt);
AddCondition("NZ",0); AddCondition("Z" ,1);
AddCondition("NC",2); AddCondition("C" ,3);
AddCondition("PO",4); AddCondition("NV",4);
AddCondition("PE",5); AddCondition("V" ,5);
AddCondition("P" ,6); AddCondition("NS",6);
AddCondition("M" ,7); AddCondition("S" ,7);
InstrZ=0; FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt);
AddFixed("EXX" ,CPUZ80 ,1,0x00d9); AddFixed("LDI" ,CPUZ80 ,2,0xeda0);
AddFixed("LDIR" ,CPUZ80 ,2,0xedb0); AddFixed("LDD" ,CPUZ80 ,2,0xeda8);
AddFixed("LDDR" ,CPUZ80 ,2,0xedb8); AddFixed("CPI" ,CPUZ80 ,2,0xeda1);
AddFixed("CPIR" ,CPUZ80 ,2,0xedb1); AddFixed("CPD" ,CPUZ80 ,2,0xeda9);
AddFixed("CPDR" ,CPUZ80 ,2,0xedb9); AddFixed("RLCA" ,CPUZ80 ,1,0x0007);
AddFixed("RRCA" ,CPUZ80 ,1,0x000f); AddFixed("RLA" ,CPUZ80 ,1,0x0017);
AddFixed("RRA" ,CPUZ80 ,1,0x001f); AddFixed("RLD" ,CPUZ80 ,2,0xed6f);
AddFixed("RRD" ,CPUZ80 ,2,0xed67); AddFixed("DAA" ,CPUZ80 ,1,0x0027);
AddFixed("CCF" ,CPUZ80 ,1,0x003f); AddFixed("SCF" ,CPUZ80 ,1,0x0037);
AddFixed("NOP" ,CPUZ80 ,1,0x0000); AddFixed("HALT" ,CPUZ80 ,1,0x0076);
AddFixed("RETI" ,CPUZ80 ,2,0xed4d); AddFixed("RETN" ,CPUZ80 ,2,0xed45);
AddFixed("INI" ,CPUZ80 ,2,0xeda2); AddFixed("INIR" ,CPUZ80 ,2,0xedb2);
AddFixed("IND" ,CPUZ80 ,2,0xedaa); AddFixed("INDR" ,CPUZ80 ,2,0xedba);
AddFixed("OUTI" ,CPUZ80 ,2,0xeda3); AddFixed("OTIR" ,CPUZ80 ,2,0xedb3);
AddFixed("OUTD" ,CPUZ80 ,2,0xedab); AddFixed("OTDR" ,CPUZ80 ,2,0xedbb);
AddFixed("SLP" ,CPUZ180,2,0xed76); AddFixed("OTIM" ,CPUZ180,2,0xed83);
AddFixed("OTIMR",CPUZ180,2,0xed93); AddFixed("OTDM" ,CPUZ180,2,0xed8b);
AddFixed("OTDMR",CPUZ180,2,0xed9b); AddFixed("BTEST",CPUZ380,2,0xedcf);
AddFixed("EXALL",CPUZ380,2,0xedd9); AddFixed("EXXX" ,CPUZ380,2,0xddd9);
AddFixed("EXXY" ,CPUZ380,2,0xfdd9); AddFixed("INDW" ,CPUZ380,2,0xedea);
AddFixed("INDRW",CPUZ380,2,0xedfa); AddFixed("INIW" ,CPUZ380,2,0xede2);
AddFixed("INIRW",CPUZ380,2,0xedf2); AddFixed("LDDW" ,CPUZ380,2,0xede8);
AddFixed("LDDRW",CPUZ380,2,0xedf8); AddFixed("LDIW" ,CPUZ380,2,0xede0);
AddFixed("LDIRW",CPUZ380,2,0xedf0); AddFixed("MTEST",CPUZ380,2,0xddcf);
AddFixed("OTDRW",CPUZ380,2,0xedfb); AddFixed("OTIRW",CPUZ380,2,0xedf3);
AddFixed("OUTDW",CPUZ380,2,0xedeb); AddFixed("OUTIW",CPUZ380,2,0xede3);
AddFixed("RETB" ,CPUZ380,2,0xed55);
InstrZ=0; AccOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*AccOrderCnt);
AddAcc("CPL" ,CPUZ80 ,1,0x002f); AddAcc("NEG" ,CPUZ80 ,2,0xed44);
AddAcc("EXTS" ,CPUZ380,2,0xed65);
InstrZ=0; HLOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*HLOrderCnt);
AddHL("CPLW" ,CPUZ380,2,0xdd2f); AddHL("NEGW" ,CPUZ380,2,0xed54);
AddHL("EXTSW",CPUZ380,2,0xed75);
InstrZ=0; ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt);
AddALU("SUB", 2); AddALU("AND", 4);
AddALU("OR" , 6); AddALU("XOR", 5);
AddALU("CP" , 7);
InstrZ=0; ShiftOrders=(char **) malloc(sizeof(char *)*ShiftOrderCnt);
AddShift("RLC"); AddShift("RRC"); AddShift("RL"); AddShift("RR");
AddShift("SLA"); AddShift("SRA"); AddShift("SLIA"); AddShift("SRL");
InstrZ=0; BitOrders=(char **) malloc(sizeof(char *)*BitOrderCnt);
AddBit("BIT"); AddBit("RES"); AddBit("SET");
END
static void DeinitFields(void)
BEGIN
free(Conditions);
free(FixedOrders);
free(AccOrders);
free(HLOrders);
free(ALUOrders);
free(ShiftOrders);
free(BitOrders);
END
/*==========================================================================*/
/* Adressbereiche */
static LargeWord CodeEnd(void)
BEGIN
#ifdef __STDC__
if (ExtFlag) return 0xfffffffflu;
#else
if (ExtFlag) return 0xffffffffl;
#endif
else if (MomCPU==CPUZ180) return 0x7ffffl;
else return 0xffff;
END
static LargeWord PortEnd(void)
BEGIN
#ifdef __STDC__
if (ExtFlag) return 0xfffffffflu;
#else
if (ExtFlag) return 0xffffffffl;
#endif
else return 0xff;
END
/*==========================================================================*/
/* Praefix dazuaddieren */
static Boolean ExtendPrefix(PrefType *Dest, char *AddArg)
BEGIN
Byte SPart,IPart;
switch (*Dest)
BEGIN
case Pref_IB_N:
case Pref_IB_W:
case Pref_IB_LW: IPart=1; break;
case Pref_IW_N:
case Pref_IW_W:
case Pref_IW_LW: IPart=2; break;
default: IPart=0;
END
switch (*Dest)
BEGIN
case Pref_IN_W:
case Pref_IB_W:
case Pref_IW_W: SPart=1; break;
case Pref_IN_LW:
case Pref_IB_LW:
case Pref_IW_LW: SPart=2; break;
default: SPart=0;
END
if (strcmp(AddArg,"W")==0) /* Wortverarbeitung */
SPart=1;
else if (strcmp(AddArg,"LW")==0) /* Langwortverarbeitung */
SPart=2;
else if (strcmp(AddArg,"IB")==0) /* ein Byte im Argument mehr */
IPart=1;
else if (strcmp(AddArg,"IW")==0) /* ein Wort im Argument mehr */
IPart=2;
else return False;
switch ((IPart << 4)+SPart)
BEGIN
case 0x00:*Dest=Pref_IN_N; break;
case 0x01:*Dest=Pref_IN_W; break;
case 0x02:*Dest=Pref_IN_LW; break;
case 0x10:*Dest=Pref_IB_N; break;
case 0x11:*Dest=Pref_IB_W; break;
case 0x12:*Dest=Pref_IB_LW; break;
case 0x20:*Dest=Pref_IW_N; break;
case 0x21:*Dest=Pref_IW_W; break;
case 0x22:*Dest=Pref_IW_LW; break;
END
return True;
END
/*--------------------------------------------------------------------------*/
/* Code fuer Praefix bilden */
static void GetPrefixCode(PrefType inp, Byte *b1 ,Byte *b2)
BEGIN
int z;
z=((int)inp)-1;
*b1=0xdd+((z & 4) << 3);
*b2=0xc0+(z & 3);
END
/*--------------------------------------------------------------------------*/
/* DD-Praefix addieren, nur EINMAL pro Instruktion benutzen! */
static void ChangeDDPrefix(char *Add)
BEGIN
PrefType ActPrefix;
int z;
ActPrefix=LastPrefix;
if (ExtendPrefix(&ActPrefix,Add))
if (LastPrefix!=ActPrefix)
BEGIN
if (LastPrefix!=Pref_IN_N) RetractWords(2);
for (z=PrefixCnt-1; z>=0; z--) BAsmCode[2+z]=BAsmCode[z];
PrefixCnt+=2;
GetPrefixCode(ActPrefix,BAsmCode+0,BAsmCode+1);
END
END
/*--------------------------------------------------------------------------*/
/* Wortgroesse ? */
static Boolean InLongMode(void)
BEGIN
switch (LastPrefix)
BEGIN
case Pref_IN_W:
case Pref_IB_W:
case Pref_IW_W: return False;
case Pref_IN_LW:
case Pref_IB_LW:
case Pref_IW_LW: return MayLW;
default: return LWordFlag AND MayLW;
END
END
/*--------------------------------------------------------------------------*/
/* absolute Adresse */
static LongWord EvalAbsAdrExpression(char *inp, Boolean *OK)
BEGIN
return EvalIntExpression(inp,ExtFlag?Int32:UInt16,OK);
END
/*==========================================================================*/
/* Adressparser */
static Boolean DecodeReg8(char *Asc, Byte *Erg)
BEGIN
#define Reg8Cnt 7
static char *Reg8Names[Reg8Cnt]={"B","C","D","E","H","L","A"};
int z;
for (z=0; z<Reg8Cnt; z++)
if (strcasecmp(Asc,Reg8Names[z])==0)
BEGIN
*Erg=z; if (z==6) (*Erg)++;
return True;
END
return False;
END
static Boolean IsSym(char ch)
BEGIN
return ((ch=='_') OR ((ch>='0') AND (ch<='9')) OR ((ch>='A') AND (ch<='Z')) OR ((ch>='a') AND (ch<='z')));
END
static void DecodeAdr(char *Asc_O)
BEGIN
#define Reg8XCnt 4
static char *Reg8XNames[Reg8XCnt]={"IXU","IXL","IYU","IYL"};
#define Reg16Cnt 6
static char *Reg16Names[Reg16Cnt]={"BC","DE","HL","SP","IX","IY"};
int z;
Integer AdrInt;
LongInt AdrLong;
Boolean OK;
String Asc;
AdrMode=ModNone; AdrCnt=0; AdrPart=0;
/* 0. Sonderregister */
if (strcasecmp(Asc_O,"R")==0)
BEGIN
AdrMode=ModRef; return;
END
if (strcasecmp(Asc_O,"I")==0)
BEGIN
AdrMode=ModInt; return;
END
/* 1. 8-Bit-Register ? */
if (DecodeReg8(Asc_O,&AdrPart))
BEGIN
AdrMode=ModReg8;
return;
END
/* 1a. 8-Bit-Haelften von IX/IY ? (nur Z380, sonst als Symbole zulassen) */
if ((MomCPU>=CPUZ380) OR (MomCPU==CPUZ80U))
for (z=0; z<Reg8XCnt; z++)
if (strcasecmp(Asc_O,Reg8XNames[z])==0)
BEGIN
AdrMode=ModReg8;
BAsmCode[PrefixCnt++]=(z<=1)?IXPrefix:IYPrefix;
AdrPart=4+(z & 1); /* = H /L */
return;
END
/* 2. 16-Bit-Register ? */
for (z=0; z<Reg16Cnt; z++)
if (strcasecmp(Asc_O,Reg16Names[z])==0)
BEGIN
AdrMode=ModReg16;
if (z<=3) AdrPart=z;
else
BEGIN
BAsmCode[PrefixCnt++]=(z==4)?IXPrefix:IYPrefix;
AdrPart=2; /* = HL */
END
return;
END
/* 3. 16-Bit-Register indirekt ? */
if ((strlen(Asc_O)>=4) AND (*Asc_O=='(') AND (Asc_O[strlen(Asc_O)-1]==')'))
for (z=0; z<Reg16Cnt; z++)
if ((strncasecmp(Asc_O+1,Reg16Names[z],2)==0)
AND (NOT IsSym(Asc_O[3])))
BEGIN
if (z<3)
BEGIN
if (strlen(Asc_O)!=4)
BEGIN
WrError(1350); return;
END
switch (z)
BEGIN
case 0:
case 1: /* BC,DE */
AdrMode=ModIndReg16; AdrPart=z;
break;
case 2: /* HL=M-Register */
AdrMode=ModReg8; AdrPart=6;
break;
END
END
else
BEGIN /* SP,IX,IY */
strmaxcpy(Asc,Asc_O+3,255); Asc[strlen(Asc)-1]='\0';
if (*Asc=='+') strcpy(Asc,Asc+1);
AdrLong=EvalIntExpression(Asc,(MomCPU>=CPUZ380)?SInt24:SInt8,&OK);
if (OK)
BEGIN
if (z==3) AdrMode=ModSPRel;
else
BEGIN
AdrMode=ModReg8; AdrPart=6;
BAsmCode[PrefixCnt++]=(z==4)?IXPrefix:IYPrefix;
END
AdrVals[AdrCnt++]=AdrLong & 0xff;
if ((AdrLong>=-0x80l) AND (AdrLong<=0x7fl));
else
BEGIN
AdrVals[AdrCnt++]=(AdrLong >> 8) & 0xff;
if ((AdrLong>=-0x8000l) AND (AdrLong<=0x7fffl)) ChangeDDPrefix("IB");
else
BEGIN
AdrVals[AdrCnt++]=(AdrLong >> 16) & 0xff;
ChangeDDPrefix("IW");
END
END
END
END
return;
END
/* absolut ? */
if (IsIndirect(Asc_O))
BEGIN
AdrLong=EvalAbsAdrExpression(Asc_O,&OK);
if (OK)
BEGIN
ChkSpace(SegCode);
AdrMode=ModAbs;
AdrVals[0]=AdrLong & 0xff;
AdrVals[1]=(AdrLong >> 8) & 0xff;
AdrCnt=2;
#ifdef __STDC__
if ((AdrLong & 0xffff0000u)==0);
#else
if ((AdrLong & 0xffff0000)==0);
#endif
else
BEGIN
AdrVals[AdrCnt++]=((AdrLong >> 16) & 0xff);
#ifdef __STDC__
if ((AdrLong & 0xff000000u)==0) ChangeDDPrefix("IB");
#else
if ((AdrLong & 0xff000000)==0) ChangeDDPrefix("IB");
#endif
else
BEGIN
AdrVals[AdrCnt++]=((AdrLong >> 24) & 0xff);
ChangeDDPrefix("IW");
END
END
END
return;
END
/* ...immediate */
switch (OpSize)
BEGIN
case 0xff:
WrError(1132);
break;
case 0:
AdrVals[0]=EvalIntExpression(Asc_O,Int8,&OK);
if (OK)
BEGIN
AdrMode=ModImm; AdrCnt=1;
END;
break;
case 1:
if (InLongMode())
BEGIN
AdrLong=EvalIntExpression(Asc_O,Int32,&OK);
if (OK)
BEGIN
AdrVals[0]=Lo(AdrLong); AdrVals[1]=Hi(AdrLong);
AdrMode=ModImm; AdrCnt=2;
#ifdef __STDC__
if ((AdrLong & 0xffff0000u)==0);
#else
if ((AdrLong & 0xffff0000)==0);
#endif
else
BEGIN
AdrVals[AdrCnt++]=(AdrLong >> 16) & 0xff;
#ifdef __STDC__
if ((AdrLong & 0xff000000u)==0) ChangeDDPrefix("IB");
#else
if ((AdrLong & 0xff000000)==0) ChangeDDPrefix("IB");
#endif
else
BEGIN
AdrVals[AdrCnt++]=(AdrLong >> 24) & 0xff;
ChangeDDPrefix("IW");
END
END
END
END
else
BEGIN
AdrInt=EvalIntExpression(Asc_O,Int16,&OK);
if (OK)
BEGIN
AdrVals[0]=Lo(AdrInt); AdrVals[1]=Hi(AdrInt);
AdrMode=ModImm; AdrCnt=2;
END
END
break;
END
END
/*-------------------------------------------------------------------------*/
/* Bedingung entschluesseln */
static Boolean DecodeCondition(char *Name, int *Erg)
BEGIN
int z;
String Name_N;
strmaxcpy(Name_N,Name,255); NLS_UpString(Name_N);
z=0;
while ((z<ConditionCnt) AND (strcmp(Conditions[z].Name,Name_N)!=0)) z++;
if (z>ConditionCnt) return False;
else
BEGIN
*Erg=Conditions[z].Code; return True;
END
END
/*-------------------------------------------------------------------------*/
/* Sonderregister dekodieren */
static Boolean DecodeSFR(char *Inp, Byte *Erg)
BEGIN
if (strcasecmp(Inp,"SR")==0) *Erg=1;
else if (strcasecmp(Inp,"XSR")==0) *Erg=5;
else if (strcasecmp(Inp,"DSR")==0) *Erg=6;
else if (strcasecmp(Inp,"YSR")==0) *Erg=7;
else return False;
return True;
END
/*=========================================================================*/
static Boolean DecodePseudo(void)
BEGIN
if (Memo("PORT"))
BEGIN
CodeEquate(SegIO,0,PortEnd());
return True;
END
/* Kompatibilitaet zum M80 */
if (Memo("DEFB")) strmaxcpy(OpPart,"DB",255);
if (Memo("DEFW")) strmaxcpy(OpPart,"DW",255);
return False;
END
static void DecodeLD(void)
BEGIN
Byte AdrByte,HLen;
int z;
Byte HVals[5];
if (ArgCnt!=2) WrError(1110);
else
BEGIN
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if (AdrPart==7) /* LD A,... */
BEGIN
OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8: /* LD A,R8/RX8/(HL)/(XY+D) */
BAsmCode[PrefixCnt]=0x78+AdrPart;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
break;
case ModIndReg16: /* LD A,(BC)/(DE) */
BAsmCode[0]=0x0a+(AdrPart << 4); CodeLen=1;
break;
case ModImm: /* LD A,imm8 */
BAsmCode[0]=0x3e; BAsmCode[1]=AdrVals[0]; CodeLen=2;
break;
case ModAbs: /* LD a,(adr) */
BAsmCode[PrefixCnt]=0x3a;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
break;
case ModRef: /* LD A,R */
BAsmCode[0]=0xed; BAsmCode[1]=0x5f;
CodeLen=2;
break;
case ModInt: /* LD A,I */
BAsmCode[0]=0xed; BAsmCode[1]=0x57;
CodeLen=2;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else if ((AdrPart!=6) AND (PrefixCnt==0)) /* LD R8,... */
BEGIN
AdrByte=AdrPart; OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8: /* LD R8,R8/RX8/(HL)/(XY+D) */
if (((AdrByte==4) OR (AdrByte==5)) AND (PrefixCnt==1) AND (AdrCnt==0)) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0x40+(AdrByte << 3)+AdrPart;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
END
break;
case ModImm: /* LD R8,imm8 */
BAsmCode[0]=0x06+(AdrByte << 3); BAsmCode[1]=AdrVals[0];
CodeLen=2;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else if ((AdrPart==4) OR (AdrPart==5)) /* LD RX8,... */
BEGIN
AdrByte=AdrPart; OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8: /* LD RX8,R8/RX8 */
if (AdrPart==6) WrError(1350);
else if ((AdrPart>=4) AND (AdrPart<=5) AND (PrefixCnt!=2)) WrError(1350);
else if ((AdrPart>=4) AND (AdrPart<=5) AND (BAsmCode[0]!=BAsmCode[1])) WrError(1350);
else
BEGIN
if (PrefixCnt==2) PrefixCnt--;
BAsmCode[PrefixCnt]=0x40+(AdrByte << 3)+AdrPart;
CodeLen=PrefixCnt+1;
END
break;
case ModImm: /* LD RX8,imm8 */
BAsmCode[PrefixCnt]=0x06+(AdrByte << 3);
BAsmCode[PrefixCnt+1]=AdrVals[0];
CodeLen=PrefixCnt+2;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else /* LD (HL)/(XY+d),... */
BEGIN
HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt); z=PrefixCnt;
if ((z==0) AND (Memo("LDW")))
BEGIN
OpSize=1; MayLW=True;
END
else OpSize=0;
DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8: /* LD (HL)/(XY+D),R8 */
if ((PrefixCnt!=z) OR (AdrPart==6)) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0x70+AdrPart;
memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
CodeLen=PrefixCnt+1+HLen;
END
break;
case ModImm: /* LD (HL)/(XY+D),imm8:16:32 */
if ((z==0) AND (Memo("LDW")))
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0x36;
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
END
else
BEGIN
BAsmCode[PrefixCnt]=0x36;
memcpy(BAsmCode+1+PrefixCnt,HVals,HLen);
BAsmCode[PrefixCnt+1+HLen]=AdrVals[0];
CodeLen=PrefixCnt+1+HLen+AdrCnt;
END
break;
case ModReg16: /* LD (HL)/(XY+D),R16/XY */
if (MomCPU<CPUZ380) WrError(1500);
else if (AdrPart==3) WrError(1350);
else if (HLen==0)
if (PrefixCnt==z) /* LD (HL),R16 */
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xfd; BAsmCode[1]=0x0f+(AdrPart << 4);
CodeLen=2;
END
else /* LD (HL),XY */
BEGIN
CodeLen=PrefixCnt+1; BAsmCode[PrefixCnt]=0x31;
CodeLen=1+PrefixCnt;
END
else
if (PrefixCnt==z) /* LD (XY+D),R16 */
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
BAsmCode[PrefixCnt+1+HLen]=0x0b+(AdrPart << 4);
CodeLen=PrefixCnt+1+HLen+1;
END
else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
else
BEGIN
PrefixCnt--;
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
BAsmCode[PrefixCnt+1+HLen]=0x2b;
CodeLen=PrefixCnt+1+HLen+1;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
case ModReg16:
if (AdrPart==3) /* LD SP,... */
BEGIN
OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg16: /* LD SP,HL/XY */
if (AdrPart!=2) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0xf9; CodeLen=PrefixCnt+1;
END
break;
case ModImm: /* LD SP,imm16:32 */
BAsmCode[PrefixCnt]=0x31;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
break;
case ModAbs: /* LD SP,(adr) */
BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0x7b;
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else if (PrefixCnt==0) /* LD R16,... */
BEGIN
AdrByte=(AdrPart==2) ? 3 : AdrPart;
OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModInt: /* LD HL,I */
if (MomCPU<CPUZ380) WrError(1500);
else if (AdrByte!=3) WrError(1350);
else
BEGIN
BAsmCode[0]=0xdd; BAsmCode[1]=0x57; CodeLen=2;
END
break;
case ModReg8:
if (AdrPart!=6) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if (PrefixCnt==0) /* LD R16,(HL) */
BEGIN
BAsmCode[0]=0xdd; BAsmCode[1]=0x0f+(AdrByte << 4);
CodeLen=2;
END
else /* LD R16,(XY+d) */
BEGIN
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=0x03+(AdrByte << 4);
CodeLen=PrefixCnt+1+AdrCnt+1;
END
break;
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if (PrefixCnt==0) /* LD R16,R16 */
BEGIN
if (AdrPart==2) AdrPart=3;
else if (AdrPart==0) AdrPart=2;
BAsmCode[0]=0xcd+(AdrPart << 4);
BAsmCode[1]=0x02+(AdrByte << 4);
CodeLen=2;
END
else /* LD R16,XY */
BEGIN
BAsmCode[PrefixCnt]=0x0b+(AdrByte << 4);
CodeLen=PrefixCnt+1;
END
break;
case ModIndReg16: /* LD R16,(R16) */
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
CodeLen=2; BAsmCode[0]=0xdd;
BAsmCode[1]=0x0c+(AdrByte << 4)+AdrPart;
END
break;
case ModImm: /* LD R16,imm */
if (AdrByte==3) AdrByte=2;
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0x01+(AdrByte << 4);
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
break;
case ModAbs: /* LD R16,(adr) */
if (AdrByte==3)
BEGIN
BAsmCode[PrefixCnt]=0x2a;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=1+PrefixCnt+AdrCnt;
END
else
BEGIN
BAsmCode[PrefixCnt]=0xed;
BAsmCode[PrefixCnt+1]=0x4b+(AdrByte << 4);
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
END
break;
case ModSPRel: /* LD R16,(SP+D) */
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[PrefixCnt]=0xdd;
BAsmCode[PrefixCnt+1]=0xcb;
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+2+AdrCnt]=0x01+(AdrByte << 4);
CodeLen=PrefixCnt+3+AdrCnt;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else /* LD XY,... */
BEGIN
OpSize=1; MayLW=True; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8:
if (AdrPart!=6) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if (AdrCnt==0) /* LD XY,(HL) */
BEGIN
BAsmCode[PrefixCnt]=0x33; CodeLen=PrefixCnt+1;
END
else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
else /* LD XY,(XY+D) */
BEGIN
BAsmCode[0]=BAsmCode[1]; PrefixCnt--;
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=0x23;
CodeLen=PrefixCnt+1+AdrCnt+1;
END
break;
case ModReg16:
if (MomCPU<CPUZ380) WrError(1500);
else if (AdrPart==3) WrError(1350);
else if (PrefixCnt==1) /* LD XY,R16 */
BEGIN
if (AdrPart==2) AdrPart=3;
CodeLen=1+PrefixCnt;
BAsmCode[PrefixCnt]=0x07+(AdrPart << 4);
END
else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
else /* LD XY,XY */
BEGIN
BAsmCode[--PrefixCnt]=0x27;
CodeLen=1+PrefixCnt;
END
break;
case ModIndReg16:
if (MomCPU<CPUZ380) WrError(1500);
else /* LD XY,(R16) */
BEGIN
BAsmCode[PrefixCnt]=0x03+(AdrPart << 4);
CodeLen=PrefixCnt+1;
END
break;
case ModImm: /* LD XY,imm16:32 */
BAsmCode[PrefixCnt]=0x21;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
break;
case ModAbs: /* LD XY,(adr) */
BAsmCode[PrefixCnt]=0x2a;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
break;
case ModSPRel: /* LD XY,(SP+D) */
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=0x21;
CodeLen=PrefixCnt+1+AdrCnt+1;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
case ModIndReg16:
AdrByte=AdrPart;
if (Memo("LDW"))
BEGIN
OpSize=1; MayLW=True;
END
else OpSize=0;
DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8: /* LD (R16),A */
if (AdrPart!=7) WrError(1350);
else
BEGIN
CodeLen=1; BAsmCode[0]=0x02+(AdrByte << 4);
END
break;
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if (PrefixCnt==0) /* LD (R16),R16 */
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xfd; BAsmCode[1]=0x0c+AdrByte+(AdrPart << 4);
CodeLen=2;
END
else /* LD (R16),XY */
BEGIN
BAsmCode[PrefixCnt]=0x01+(AdrByte << 4);
CodeLen=PrefixCnt+1;
END
break;
case ModImm:
if (NOT Memo("LDW")) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[PrefixCnt]=0xed;
BAsmCode[PrefixCnt+1]=0x06+(AdrByte << 4);
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
break;
case ModAbs:
HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt);
OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8: /* LD (adr),A */
if (AdrPart!=7) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0x32;
memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
CodeLen=PrefixCnt+1+HLen;
END
break;
case ModReg16:
if (AdrPart==2) /* LD (adr),HL/XY */
BEGIN
BAsmCode[PrefixCnt]=0x22;
memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
CodeLen=PrefixCnt+1+HLen;
END
else /* LD (adr),R16 */
BEGIN
BAsmCode[PrefixCnt]=0xed;
BAsmCode[PrefixCnt+1]=0x43+(AdrPart << 4);
memcpy(BAsmCode+PrefixCnt+2,HVals,HLen);
CodeLen=PrefixCnt+2+HLen;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
break;
case ModInt:
if (strcasecmp(ArgStr[2],"A")==0) /* LD I,A */
BEGIN
CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x47;
END
else if (strcasecmp(ArgStr[2],"HL")==0) /* LD I,HL */
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
CodeLen=2; BAsmCode[0]=0xdd; BAsmCode[1]=0x47;
END
else WrError(1350);
break;
case ModRef:
if (strcasecmp(ArgStr[2],"A")==0) /* LD R,A */
BEGIN
CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x4f;
END
else WrError(1350);
break;
case ModSPRel:
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
HLen=AdrCnt; memcpy(HVals,AdrVals,AdrCnt);
OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (PrefixCnt==0) /* LD (SP+D),R16 */
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[PrefixCnt]=0xdd;
BAsmCode[PrefixCnt+1]=0xcb;
memcpy(BAsmCode+PrefixCnt+2,HVals,HLen);
BAsmCode[PrefixCnt+2+HLen]=0x09+(AdrPart << 4);
CodeLen=PrefixCnt+2+HLen+1;
END
else /* LD (SP+D),XY */
BEGIN
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,HVals,HLen);
BAsmCode[PrefixCnt+1+HLen]=0x29;
CodeLen=PrefixCnt+1+HLen+1;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END /* outer switch */
END
END
static Boolean ParPair(char *Name1, char *Name2)
BEGIN
return (((strcasecmp(ArgStr[1],Name1)==0) AND (strcasecmp(ArgStr[2],Name2)==0)) OR
((strcasecmp(ArgStr[1],Name2)==0) AND (strcasecmp(ArgStr[2],Name1)==0)));
END
static Boolean ImmIs8(void)
BEGIN
Word tmp;
if (AdrCnt<2) return True;
tmp=(Word) AdrVals[AdrCnt-2];
return ((tmp<=255) OR (tmp>=0xff80));
END
static Boolean CodeAri(void)
BEGIN
int z;
Byte AdrByte;
Boolean OK;
for (z=0; z<ALUOrderCnt; z++)
if (Memo(ALUOrders[z].Name))
BEGIN
if (ArgCnt==1)
BEGIN
strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"A",255); ArgCnt=2;
END
if (ArgCnt!=2) WrError(1110);
else if (strcasecmp(ArgStr[1],"HL")==0)
BEGIN
if (NOT Memo("SUB")) WrError(1350);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModAbs:
BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0xd6;
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
END
else if (strcasecmp(ArgStr[1],"SP")==0)
BEGIN
if (NOT Memo("SUB")) WrError(1350);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModImm:
BAsmCode[0]=0xed; BAsmCode[1]=0x92;
memcpy(BAsmCode+2,AdrVals,AdrCnt);
CodeLen=2+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
END
else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
else
BEGIN
OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8:
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0x80+(ALUOrders[z].Code << 3)+AdrPart;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
break;
case ModImm:
if (NOT ImmIs8()) WrError(1320);
else
BEGIN
CodeLen=2;
BAsmCode[0]=0xc6+(ALUOrders[z].Code << 3);
BAsmCode[1]=AdrVals[0];
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
else if ((strncmp(ALUOrders[z].Name,OpPart,strlen(ALUOrders[z].Name))==0) AND (OpPart[strlen(OpPart)-1]=='W'))
BEGIN
if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
switch (AdrMode)
BEGIN
case ModReg16:
if (PrefixCnt>0) /* wenn Register, dann nie DDIR! */
BEGIN
BAsmCode[PrefixCnt]=0x87+(ALUOrders[z].Code << 3);
CodeLen=1+PrefixCnt;
END
else if (AdrPart==3) WrError(1350);
else
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0x84+(ALUOrders[z].Code << 3)+AdrPart;
CodeLen=2;
END
break;
case ModReg8:
if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0xc6+(ALUOrders[z].Code << 3);
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
END
break;
case ModImm:
BAsmCode[0]=0xed; BAsmCode[1]=0x86+(ALUOrders[z].Code << 3);
memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if (Memo("ADD"))
BEGIN
if (ArgCnt!=2) WrError(1110);
else
BEGIN
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if (AdrPart!=7) WrError(1350);
else
BEGIN
OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8:
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0x80+AdrPart;
memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
break;
case ModImm:
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0xc6;
memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
case ModReg16:
if (AdrPart==3) /* SP */
BEGIN
OpSize=1; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModImm:
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x82;
memcpy(BAsmCode+2,AdrVals,AdrCnt);
CodeLen=2+AdrCnt;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else if (AdrPart!=2) WrError(1350);
else
BEGIN
z=PrefixCnt; /* merkt, ob Indexregister */
OpSize=1; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg16:
if ((AdrPart==2) AND (PrefixCnt!=0) AND ((PrefixCnt!=2) OR (BAsmCode[0]!=BAsmCode[1]))) WrError(1350);
else
BEGIN
if (PrefixCnt==2) PrefixCnt--; CodeLen=1+PrefixCnt;
BAsmCode[PrefixCnt]=0x09+(AdrPart << 4);
END
break;
case ModAbs:
if (z!=0) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[PrefixCnt]=0xed; BAsmCode[PrefixCnt+1]=0xc2;
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if (Memo("ADDW"))
BEGIN
if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
switch (AdrMode)
BEGIN
case ModReg16:
if (PrefixCnt>0) /* wenn Register, dann nie DDIR! */
BEGIN
BAsmCode[PrefixCnt]=0x87;
CodeLen=1+PrefixCnt;
END
else if (AdrPart==3) WrError(1350);
else
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0x84+AdrPart;
CodeLen=2;
END
break;
case ModReg8:
if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0xc6;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
END
break;
case ModImm:
BAsmCode[0]=0xed; BAsmCode[1]=0x86;
memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if ((Memo("ADC")) OR (Memo("SBC")))
BEGIN
if (ArgCnt!=2) WrError(1110);
else
BEGIN
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if (AdrPart!=7) WrError(1350);
else
BEGIN
OpSize=0; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8:
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0x88+AdrPart;
memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
break;
case ModImm:
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0xce;
memcpy(BAsmCode+1+PrefixCnt,AdrVals,AdrCnt);
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
if ((Memo("SBC")) AND (CodeLen!=0)) BAsmCode[PrefixCnt]+=0x10;
END
break;
case ModReg16:
if ((AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg16:
if (PrefixCnt!=0) WrError(1350);
else
BEGIN
CodeLen=2; BAsmCode[0]=0xed;
BAsmCode[1]=0x42+(AdrPart << 4);
if (Memo("ADC")) BAsmCode[1]+=8;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if ((Memo("ADCW")) OR (Memo("SBCW")))
BEGIN
if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else if ((ArgCnt==2) AND (strcasecmp(ArgStr[1],"HL")!=0)) WrError(1350);
else
BEGIN
z=Ord(Memo("SBCW")) << 4;
OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
switch (AdrMode)
BEGIN
case ModReg16:
if (PrefixCnt>0) /* wenn Register, dann nie DDIR! */
BEGIN
BAsmCode[PrefixCnt]=0x8f+z;
CodeLen=1+PrefixCnt;
END
else if (AdrPart==3) WrError(1350);
else
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0x8c+z+AdrPart;
CodeLen=2;
END
break;
case ModReg8:
if ((AdrPart!=6) OR (AdrCnt==0)) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0xce + z; /* ANSI :-0 */
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
CodeLen=PrefixCnt+1+AdrCnt;
END
break;
case ModImm:
BAsmCode[0]=0xed; BAsmCode[1]=0x8e + z;
memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if ((Memo("INC")) OR (Memo("DEC")) OR (Memo("INCW")) OR (Memo("DECW")))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
z=Ord((Memo("DEC")) OR (Memo("DECW")));
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if (OpPart[strlen(OpPart)-1]=='W') WrError(1350);
else
BEGIN
CodeLen=PrefixCnt+1+AdrCnt;
BAsmCode[PrefixCnt]=0x04+(AdrPart << 3)+z;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
END
break;
case ModReg16:
CodeLen=1+PrefixCnt;
BAsmCode[PrefixCnt]=0x03+(AdrPart << 4)+(z << 3);
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
for (z=0; z<ShiftOrderCnt; z++)
if (Memo(ShiftOrders[z]))
BEGIN
if ((ArgCnt==0) OR (ArgCnt>2)) WrError(1110);
else if ((z==6) AND (MomCPU!=CPUZ80U)) WrError(1500); /* SLIA undok. Z80 */
else
BEGIN
OpSize=0;
DecodeAdr(ArgStr[ArgCnt]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((PrefixCnt>0) AND (AdrPart!=6)) WrError(1350); /* IXL..IYU verbieten */
else
BEGIN
if (ArgCnt==1) OK=True;
else if (MomCPU!=CPUZ80U)
BEGIN
WrError(1500); OK=False;
END
else if ((AdrPart!=6) OR (PrefixCnt!=1) OR (NOT DecodeReg8(ArgStr[1],&AdrPart)))
BEGIN
WrError(1350); OK=False;
END
else OK=True;
if (OK)
BEGIN
CodeLen=PrefixCnt+1+AdrCnt+1;
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=AdrPart+(z << 3);
if ((AdrPart==7) AND (z<4)) WrError(10);
END
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
else if ((strncmp(OpPart,ShiftOrders[z],strlen(ShiftOrders[z]))==0) AND (OpPart[strlen(OpPart)-1]=='W'))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if ((MomCPU<CPUZ380) OR (z==6)) WrError(1500);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg16:
if (PrefixCnt>0)
BEGIN
BAsmCode[2]=0x04+(z << 3)+((BAsmCode[0] >> 5) & 1);
BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
CodeLen=3;
END
else if (AdrPart==3) WrError(1350);
else
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
BAsmCode[2]=(z << 3)+AdrPart;
CodeLen=3;
END
break;
case ModReg8:
if (AdrPart!=6) WrError(1350);
else
BEGIN
if (AdrCnt==0)
BEGIN
BAsmCode[0]=0xed; PrefixCnt=1;
END
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=0x02+(z << 3);
CodeLen=PrefixCnt+1+AdrCnt+1;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
for (z=0; z<BitOrderCnt; z++)
if (Memo(BitOrders[z]))
BEGIN
if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
else
BEGIN
DecodeAdr(ArgStr[ArgCnt]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((AdrPart!=6) AND (PrefixCnt!=0)) WrError(1350);
else
BEGIN
AdrByte=EvalIntExpression(ArgStr[ArgCnt-1],UInt3,&OK);
if (OK)
BEGIN
if (ArgCnt==2) OK=True;
else if (MomCPU!=CPUZ80U)
BEGIN
WrError(1500); OK=False;
END
else if ((AdrPart!=6) OR (PrefixCnt!=1) OR (z==0) OR (NOT DecodeReg8(ArgStr[1],&AdrPart)))
BEGIN
WrError(1350); OK=False;
END
else OK=True;
if (OK)
BEGIN
CodeLen=PrefixCnt+2+AdrCnt;
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=AdrPart+(AdrByte << 3)+((z+1) << 6);
END
END
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if (Memo("MLT"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (MomCPU<CPUZ180) WrError(1500);
else
BEGIN
DecodeAdr(ArgStr[1]);
if ((AdrMode!=ModReg16) OR (PrefixCnt!=0)) WrError(1350);
else
BEGIN
BAsmCode[CodeLen]=0xed; BAsmCode[CodeLen+1]=0x4c+(AdrPart << 4);
CodeLen=2;
END
END
return True;
END
if ((Memo("DIVUW")) OR (Memo("MULTW")) OR (Memo("MULTUW")))
BEGIN
if (ArgCnt==1)
BEGIN
strcpy(ArgStr[2],ArgStr[1]); strmaxcpy(ArgStr[1],"HL",255); ArgCnt=2;
END
if (MomCPU<CPUZ380) WrError(1500);
else if (ArgCnt!=2) WrError(1110);
else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
else
BEGIN
AdrByte=Ord(*OpPart=='D');
z=Ord(OpPart[strlen(OpPart)-2]=='U');
OpSize=1; DecodeAdr(ArgStr[ArgCnt]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((AdrPart!=6) OR (PrefixCnt==0)) WrError(1350);
else
BEGIN
BAsmCode[PrefixCnt]=0xcb;
memcpy(BAsmCode+PrefixCnt+1,AdrVals,AdrCnt);
BAsmCode[PrefixCnt+1+AdrCnt]=0x92+(z << 3)+(AdrByte << 5);
CodeLen=PrefixCnt+1+AdrCnt+1;
END
break;
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (PrefixCnt==0)
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
BAsmCode[2]=0x90+AdrPart+(z << 3)+(AdrByte << 5);
CodeLen=3;
END
else
BEGIN
BAsmCode[2]=0x94+((BAsmCode[0] >> 5) & 1)+(z << 3)+(AdrByte << 5);
BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
CodeLen=3;
END
break;
case ModImm:
BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
BAsmCode[2]=0x97+(z << 3)+(AdrByte << 5);
memcpy(BAsmCode+3,AdrVals,AdrCnt);
CodeLen=3+AdrCnt;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if (Memo("TST"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (MomCPU<CPUZ180) WrError(1500);
else
BEGIN
OpSize=0; DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if (PrefixCnt!=0) WrError(1350);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=4+(AdrPart << 3);
CodeLen=2;
END
break;
case ModImm:
BAsmCode[0]=0xed; BAsmCode[1]=0x64; BAsmCode[2]=AdrVals[0];
CodeLen=3;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
if (Memo("SWAP"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (PrefixCnt==0)
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0x0e + (AdrPart << 4); /*?*/
CodeLen=2;
END
else
BEGIN
BAsmCode[PrefixCnt]=0x3e; CodeLen=PrefixCnt+1;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return True;
END
return False;
END
static void MakeCode_Z80(void)
BEGIN
Boolean OK;
LongWord AdrLong;
LongInt AdrLInt;
Byte AdrByte;
int z;
CodeLen=0; DontPrint=False; PrefixCnt=0; OpSize=0xff; MayLW=False;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodePseudo()) return;
/* letzten Praefix umkopieren */
LastPrefix=CurrPrefix; CurrPrefix=Pref_IN_N;
/* evtl. Datenablage */
if (DecodeIntelPseudo(False)) return;
/*--------------------------------------------------------------------------*/
/* Instruktionspraefix */
if (Memo("DDIR"))
BEGIN
if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
OK=True;
for (z=1; z<=ArgCnt; z++)
if (OK)
BEGIN
NLS_UpString(ArgStr[z]);
OK=ExtendPrefix(&CurrPrefix,ArgStr[z]);
if (NOT OK) WrError(1135);
END
if (OK)
BEGIN
GetPrefixCode(CurrPrefix,BAsmCode+0,BAsmCode+1);
CodeLen=2;
END
END
return;
END
/*--------------------------------------------------------------------------*/
/* mit Sicherheit am haeufigsten... */
if ((Memo("LD")) OR (Memo("LDW")))
BEGIN
DecodeLD();
return;
END
/*--------------------------------------------------------------------------*/
/* ohne Operanden */
for (z=0; z<FixedOrderCnt; z++)
if (Memo(FixedOrders[z].Name))
BEGIN
if (ArgCnt!=0) WrError(1110);
else if (MomCPU<FixedOrders[z].MinCPU) WrError(1500);
else
BEGIN
if ((CodeLen=FixedOrders[z].Len)==2)
BEGIN
BAsmCode[0]=Hi(FixedOrders[z].Code);
BAsmCode[1]=Lo(FixedOrders[z].Code);
END
else BAsmCode[0]=Lo(FixedOrders[z].Code);
END;
return;
END
/* nur Akku zugelassen */
for (z=0; z<AccOrderCnt; z++)
if (Memo(AccOrders[z].Name))
BEGIN
if (ArgCnt==0)
BEGIN
ArgCnt=1; strmaxcpy(ArgStr[1],"A",255);
END
if (ArgCnt!=1) WrError(1110);
else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
else if (MomCPU<AccOrders[z].MinCPU) WrError(1500);
else
BEGIN
if ((CodeLen=AccOrders[z].Len)==2)
BEGIN
BAsmCode[0]=Hi(AccOrders[z].Code);
BAsmCode[1]=Lo(AccOrders[z].Code);
END
else BAsmCode[0]=Lo(AccOrders[z].Code);
END
return;
END
for (z=0; z<HLOrderCnt; z++)
if (Memo(HLOrders[z].Name))
BEGIN
if (ArgCnt==0)
BEGIN
ArgCnt=1; strmaxcpy(ArgStr[1],"HL",255);
END;
if (ArgCnt!=1) WrError(1110);
else if (strcasecmp(ArgStr[1],"HL")!=0) WrError(1350);
else if (MomCPU<HLOrders[z].MinCPU) WrError(1500);
else
BEGIN
if ((CodeLen=HLOrders[z].Len)==2)
BEGIN
BAsmCode[0]=Hi(HLOrders[z].Code);
BAsmCode[1]=Lo(HLOrders[z].Code);
END
else BAsmCode[0]=Lo(HLOrders[z].Code);
END
return;
END
/*-------------------------------------------------------------------------*/
/* Datentransfer */
if ((Memo("PUSH")) OR (Memo("POP")))
BEGIN
z=Ord(Memo("PUSH")) << 2;
if (ArgCnt!=1) WrError(1110);
else if (strcasecmp(ArgStr[1],"SR")==0)
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0xc1+z;
END
else
BEGIN
if (strcasecmp(ArgStr[1],"SP")==0) strmaxcpy(ArgStr[1],"A",255);
if (strcasecmp(ArgStr[1],"AF")==0) strmaxcpy(ArgStr[1],"SP",255);
OpSize=1; MayLW=True;
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg16:
CodeLen=1+PrefixCnt;
BAsmCode[PrefixCnt]=0xc1+(AdrPart << 4)+z;
break;
case ModImm:
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[PrefixCnt]=0xfd; BAsmCode[PrefixCnt+1]=0xf5;
memcpy(BAsmCode+PrefixCnt+2,AdrVals,AdrCnt);
CodeLen=PrefixCnt+2+AdrCnt;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return;
END
if (Memo("EX"))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (ParPair("DE","HL"))
BEGIN
CodeLen=1; BAsmCode[0]=0xeb;
END
else if (ParPair("AF","AF\'"))
BEGIN
CodeLen=1; BAsmCode[0]=0x08;
END
else if (ParPair("AF","AF`"))
BEGIN
CodeLen=1; BAsmCode[0]=0x08;
END
else if (ParPair("(SP)","HL"))
BEGIN
CodeLen=1; BAsmCode[0]=0xe3;
END
else if (ParPair("(SP)","IX"))
BEGIN
CodeLen=2; BAsmCode[0]=IXPrefix; BAsmCode[1]=0xe3;
END
else if (ParPair("(SP)","IY"))
BEGIN
CodeLen=2; BAsmCode[0]=IYPrefix; BAsmCode[1]=0xe3;
END
else if (ParPair("(HL)","A"))
BEGIN
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x37;
END
END
else
BEGIN
if (ArgStr[2][strlen(ArgStr[2])-1]=='\'')
BEGIN
OK=True; ArgStr[2][strlen(ArgStr[2])-1]='\0';
END
else OK=False;
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
else
BEGIN
AdrByte=AdrPart;
DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if ((AdrByte==7) AND (NOT OK))
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x07+(AdrPart << 3);
CodeLen=2;
END
else if ((AdrPart==7) AND (NOT OK))
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x07+(AdrByte << 3);
CodeLen=2;
END
else if ((OK) AND (AdrPart==AdrByte))
BEGIN
BAsmCode[0]=0xcb; BAsmCode[1]=0x30+AdrPart;
CodeLen=2;
END
else WrError(1350);
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (PrefixCnt==0) /* EX R16,... */
BEGIN
if (AdrPart==2) AdrByte=3; else AdrByte=AdrPart;
DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if (OK)
BEGIN
if (AdrPart==2) AdrPart=3;
if ((PrefixCnt!=0) OR (AdrPart!=AdrByte)) WrError(1350);
else
BEGIN
CodeLen=3; BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
BAsmCode[2]=0x30+AdrByte;
END
END
else if (PrefixCnt==0)
BEGIN
if (AdrByte==0)
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[0]=0xed; BAsmCode[1]=0x01+(AdrPart << 2);
CodeLen=2;
END
else if (AdrPart==0)
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x01+(AdrByte << 2);
CodeLen=2;
END
END
else
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[1]=0x03+((BAsmCode[0] >> 2) & 8)+(AdrByte << 4);
BAsmCode[0]=0xed;
CodeLen=2;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else /* EX XY,... */
BEGIN
DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg16:
if (AdrPart==3) WrError(1350);
else if (MomCPU<CPUZ380) WrError(1500);
else if (OK)
if ((PrefixCnt!=2) OR (BAsmCode[0]!=BAsmCode[1])) WrError(1350);
else
BEGIN
CodeLen=3; BAsmCode[2]=((BAsmCode[0] >> 5) & 1)+0x34;
BAsmCode[0]=0xed; BAsmCode[1]=0xcb;
END
else if (PrefixCnt==1)
BEGIN
if (AdrPart==2) AdrPart=3;
BAsmCode[1]=((BAsmCode[0] >> 2) & 8)+3+(AdrPart << 4);
BAsmCode[0]=0xed;
CodeLen=2;
END
else if (BAsmCode[0]==BAsmCode[1]) WrError(1350);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x2b; CodeLen=2;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
return;
END
/*-------------------------------------------------------------------------*/
/* Arithmetik */
if (CodeAri()) return;
/*-------------------------------------------------------------------------*/
/* Ein/Ausgabe */
if (Memo("TSTI"))
BEGIN
if (MomCPU!=CPUZ80U) WrError(1500);
else if (ArgCnt!=0) WrError(1110);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x70; CodeLen=2;
END
return;
END
if ((Memo("IN")) OR (Memo("OUT")))
BEGIN
if ((ArgCnt==1) AND (Memo("IN")))
BEGIN
if (MomCPU!=CPUZ80U) WrError(1500);
else if (strcasecmp(ArgStr[1],"(C)")!=0) WrError(1350);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x70; CodeLen=2;
END
END
else if (ArgCnt!=2) WrError(1110);
else
BEGIN
if (Memo("OUT"))
BEGIN
strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
END
if (strcasecmp(ArgStr[2],"(C)")==0)
BEGIN
OpSize=0; DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((AdrPart==6) OR (PrefixCnt!=0)) WrError(1350);
else
BEGIN
CodeLen=2;
BAsmCode[0]=0xed; BAsmCode[1]=0x40+(AdrPart << 3);
if (Memo("OUT")) BAsmCode[1]++;
END
break;
case ModImm:
if (Memo("IN")) WrError(1350);
else if ((MomCPU==CPUZ80U) AND (AdrVals[0]==0))
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x71; CodeLen=2;
END
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x71; BAsmCode[2]=AdrVals[0];
CodeLen=3;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else if (strcasecmp(ArgStr[1],"A")!=0) WrError(1350);
else
BEGIN
BAsmCode[1]=EvalIntExpression(ArgStr[2],UInt8,&OK);
if (OK)
BEGIN
ChkSpace(SegIO);
CodeLen=2;
BAsmCode[0]=(Memo("OUT")) ? 0xd3 : 0xdb;
END
END
END
return;
END
if ((Memo("INW")) OR (Memo("OUTW")))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
if (Memo("OUTW"))
BEGIN
strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
END;
if (strcasecmp(ArgStr[2],"(C)")!=0) WrError(1350);
else
BEGIN
OpSize=1; DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg16:
if ((AdrPart==3) OR (PrefixCnt>0)) WrError(1350);
else
BEGIN
switch (AdrPart)
BEGIN
case 1: AdrPart=2; break;
case 2: AdrPart=7; break;
END
BAsmCode[0]=0xdd; BAsmCode[1]=0x40+(AdrPart << 3);
if (Memo("OUTW")) BAsmCode[1]++;
CodeLen=2;
END
break;
case ModImm:
if (Memo("INW")) WrError(1350);
else
BEGIN
BAsmCode[0]=0xfd; BAsmCode[1]=0x79;
memcpy(BAsmCode+2,AdrVals,AdrCnt);
CodeLen=2+AdrCnt;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
END
return;
END
if ((Memo("IN0")) OR (Memo("OUT0")))
BEGIN
if ((ArgCnt!=2) AND (ArgCnt!=1)) WrError(1110);
else if ((ArgCnt==1) AND (Memo("OUT0"))) WrError(1110);
else if (MomCPU<CPUZ180) WrError(1500);
else
BEGIN
if (Memo("OUT0"))
BEGIN
strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
END
OpSize=0;
if (ArgCnt==1)
BEGIN
AdrPart=6; OK=True;
END
else
BEGIN
DecodeAdr(ArgStr[1]);
if ((AdrMode==ModReg8) AND (AdrPart!=6) AND (PrefixCnt==0)) OK=True;
else
BEGIN
OK=False; if (AdrMode!=ModNone) WrError(1350);
END
END
if (OK)
BEGIN
BAsmCode[2]=EvalIntExpression(ArgStr[ArgCnt],UInt8,&OK);
if (OK)
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=AdrPart << 3;
if (Memo("OUT0")) BAsmCode[1]++;
CodeLen=3;
END
END
END
return;
END
if ((Memo("INA")) OR (Memo("INAW")) OR (Memo("OUTA")) OR (Memo("OUTAW")))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
if (*OpPart=='O')
BEGIN
strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
END
OpSize=Ord(OpPart[strlen(OpPart)-1]=='W');
if (((OpSize==0) AND (strcasecmp(ArgStr[1],"A")!=0))
OR ((OpSize==1) AND (strcasecmp(ArgStr[1],"HL")!=0))) WrError(1350);
else
BEGIN
AdrLong=EvalIntExpression(ArgStr[2],ExtFlag?Int32:UInt8,&OK);
if (OK)
BEGIN
ChkSpace(SegIO);
if (AdrLong>0xffffff) ChangeDDPrefix("IW");
else if (AdrLong>0xffff) ChangeDDPrefix("IB");
BAsmCode[PrefixCnt]=0xed+(OpSize << 4);
BAsmCode[PrefixCnt+1]=0xd3+(Ord(*OpPart=='I') << 3);
BAsmCode[PrefixCnt+2]=AdrLong & 0xff;
BAsmCode[PrefixCnt+3]=(AdrLong >> 8) & 0xff;
CodeLen=PrefixCnt+4;
if (AdrLong>0xffff)
BAsmCode[CodeLen++]=(AdrLong >> 16) & 0xff;
if (AdrLong>0xffffff)
BAsmCode[CodeLen++]=(AdrLong >> 24) & 0xff;
END
END
END
return;
END
if (Memo("TSTIO"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (MomCPU<CPUZ180) WrError(1500);
else
BEGIN
BAsmCode[2]=EvalIntExpression(ArgStr[1],Int8,&OK);
if (OK)
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0x74;
CodeLen=3;
END
END
return;
END
/*-------------------------------------------------------------------------*/
/* Spruenge */
if (Memo("RET"))
BEGIN
if (ArgCnt==0)
BEGIN
CodeLen=1; BAsmCode[0]=0xc9;
END
else if (ArgCnt!=1) WrError(1110);
else if (NOT DecodeCondition(ArgStr[1],&z)) WrError(1360);
else
BEGIN
CodeLen=1; BAsmCode[0]=0xc0+(z << 3);
END
return;
END
if (Memo("JP"))
BEGIN
if (ArgCnt==1)
BEGIN
if (strcasecmp(ArgStr[1],"(HL)")==0)
BEGIN
CodeLen=1; BAsmCode[0]=0xe9; OK=False;
END
else if (strcasecmp(ArgStr[1],"(IX)")==0)
BEGIN
CodeLen=2; BAsmCode[0]=IXPrefix; BAsmCode[1]=0xe9; OK=False;
END
else if (strcasecmp(ArgStr[1],"(IY)")==0)
BEGIN
CodeLen=2; BAsmCode[0]=IYPrefix; BAsmCode[1]=0xe9; OK=False;
END
else
BEGIN
z=1; OK=True;
END
END
else if (ArgCnt==2)
BEGIN
OK=DecodeCondition(ArgStr[1],&z);
if (OK) z<<=3; else WrError(1360);
END
else
BEGIN
WrError(1110); OK=False;
END
if (OK)
BEGIN
AdrLong=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
if (OK)
#ifdef __STDC__
if ((AdrLong & 0xffff0000u)==0)
#else
if ((AdrLong & 0xffff0000)==0)
#endif
BEGIN
CodeLen=3; BAsmCode[0]=0xc2+z;
BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
END
#ifdef __STDC__
else if ((AdrLong & 0xff000000u)==0)
#else
else if ((AdrLong & 0xff000000)==0)
#endif
BEGIN
ChangeDDPrefix("IB");
CodeLen=4+PrefixCnt; BAsmCode[PrefixCnt]=0xc2+z;
BAsmCode[PrefixCnt+1]=Lo(AdrLong);
BAsmCode[PrefixCnt+2]=Hi(AdrLong);
BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
END
else
BEGIN
ChangeDDPrefix("IW");
CodeLen=5+PrefixCnt; BAsmCode[PrefixCnt]=0xc2+z;
BAsmCode[PrefixCnt+1]=Lo(AdrLong);
BAsmCode[PrefixCnt+2]=Hi(AdrLong);
BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
BAsmCode[PrefixCnt+4]=Hi(AdrLong >> 16);
END
END
return;
END
if (Memo("CALL"))
BEGIN
if (ArgCnt==1)
BEGIN
z=9; OK=True;
END
else if (ArgCnt==2)
BEGIN
OK=DecodeCondition(ArgStr[1],&z);
if (OK) z<<=3; else WrError(1360);
END
else
BEGIN
WrError(1110); OK=False;
END
if (OK)
BEGIN
AdrLong=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
if (OK)
#ifdef __STDC__
if ((AdrLong & 0xffff0000u)==0)
#else
if ((AdrLong & 0xffff0000)==0)
#endif
BEGIN
CodeLen=3; BAsmCode[0]=0xc4+z;
BAsmCode[1]=Lo(AdrLong); BAsmCode[2]=Hi(AdrLong);
END
#ifdef __STDC__
else if ((AdrLong & 0xff000000u)==0)
#else
else if ((AdrLong & 0xff000000)==0)
#endif
BEGIN
ChangeDDPrefix("IB");
CodeLen=4+PrefixCnt; BAsmCode[PrefixCnt]=0xc4+z;
BAsmCode[PrefixCnt+1]=Lo(AdrLong);
BAsmCode[PrefixCnt+2]=Hi(AdrLong);
BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
END
else
BEGIN
ChangeDDPrefix("IW");
CodeLen=5+PrefixCnt; BAsmCode[PrefixCnt]=0xc4+z;
BAsmCode[PrefixCnt+1]=Lo(AdrLong);
BAsmCode[PrefixCnt+2]=Hi(AdrLong);
BAsmCode[PrefixCnt+3]=Hi(AdrLong >> 8);
BAsmCode[PrefixCnt+4]=Hi(AdrLong >> 16);
END
END
return;
END
if (Memo("JR"))
BEGIN
if (ArgCnt==1)
BEGIN
z=3; OK=True;
END
else if (ArgCnt==2)
BEGIN
OK=DecodeCondition(ArgStr[1],&z);
if ((OK) AND (z>3)) OK=False;
if (OK) z+=4; else WrError(1360);
END
else
BEGIN
WrError(1110); OK=False;
END
if (OK)
BEGIN
AdrLInt=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
if (OK)
BEGIN
AdrLInt-=EProgCounter()+2;
if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
BEGIN
CodeLen=2; BAsmCode[0]=z << 3;
BAsmCode[1]=AdrLInt & 0xff;
END
else
if (MomCPU<CPUZ380) WrError(1370);
else
BEGIN
AdrLInt-=2;
if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
BEGIN
CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=z << 3;
BAsmCode[2]=AdrLInt & 0xff;
BAsmCode[3]=(AdrLInt >> 8) & 0xff;
END
else
BEGIN
AdrLInt--;
if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
BEGIN
CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=z << 3;
BAsmCode[2]=AdrLInt & 0xff;
BAsmCode[3]=(AdrLInt >> 8) & 0xff;
BAsmCode[4]=(AdrLInt >> 16) & 0xff;
END
else WrError(1370);
END
END
END
END
return;
END
if (Memo("CALR"))
BEGIN
if (ArgCnt==1)
BEGIN
z=9; OK=True;
END
else if (ArgCnt==2)
BEGIN
OK=DecodeCondition(ArgStr[1],&z);
if (OK) z<<=3; else WrError(1360);
END
else
BEGIN
WrError(1110); OK=False;
END
if (OK)
if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
AdrLInt=EvalAbsAdrExpression(ArgStr[ArgCnt],&OK);
if (OK)
BEGIN
AdrLInt-=EProgCounter()+3;
if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
BEGIN
CodeLen=3; BAsmCode[0]=0xed; BAsmCode[1]=0xc4+z;
BAsmCode[2]=AdrLInt & 0xff;
END
else
BEGIN
AdrLInt--;
if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
BEGIN
CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=0xc4+z;
BAsmCode[2]=AdrLInt & 0xff;
BAsmCode[3]=(AdrLInt >> 8) & 0xff;
END
else
BEGIN
AdrLInt--;
if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
BEGIN
CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=0xc4+z;
BAsmCode[2]=AdrLInt & 0xff;
BAsmCode[3]=(AdrLInt >> 8) & 0xff;
BAsmCode[4]=(AdrLInt >> 16) & 0xff;
END
else WrError(1370);
END
END
END
END
return;
END
if (Memo("DJNZ"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
AdrLInt=EvalAbsAdrExpression(ArgStr[1],&OK);
if (OK)
BEGIN
AdrLInt-=EProgCounter()+2;
if ((AdrLInt<=0x7fl) AND (AdrLInt>=-0x80l))
BEGIN
CodeLen=2; BAsmCode[0]=0x10; BAsmCode[1]=Lo(AdrLInt);
END
else if (MomCPU<CPUZ380) WrError(1370);
else
BEGIN
AdrLInt-=2;
if ((AdrLInt<=0x7fffl) AND (AdrLInt>=-0x8000l))
BEGIN
CodeLen=4; BAsmCode[0]=0xdd; BAsmCode[1]=0x10;
BAsmCode[2]=AdrLInt & 0xff;
BAsmCode[3]=(AdrLInt >> 8) & 0xff;
END
else
BEGIN
AdrLInt--;
if ((AdrLInt<=0x7fffffl) AND (AdrLInt>=-0x800000l))
BEGIN
CodeLen=5; BAsmCode[0]=0xfd; BAsmCode[1]=0x10;
BAsmCode[2]=AdrLInt & 0xff;
BAsmCode[3]=(AdrLInt >> 8) & 0xff;
BAsmCode[4]=(AdrLInt >> 16) & 0xff;
END
else WrError(1370);
END
END
END
END
return;
END
if (Memo("RST"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
FirstPassUnknown=False;
AdrByte=EvalIntExpression(ArgStr[1],Int8,&OK);
if (FirstPassUnknown) AdrByte=AdrByte & 0x38;
if (OK)
if ((AdrByte>0x38) OR ((AdrByte & 7)!=0)) WrError(1320);
else
BEGIN
CodeLen=1; BAsmCode[0]=0xc7+AdrByte;
END
END
return;
END
/*-------------------------------------------------------------------------*/
/* Sonderbefehle */
if ((Memo("EI")) OR (Memo("DI")))
BEGIN
if (ArgCnt==0)
BEGIN
BAsmCode[0]=0xf3+(Ord(Memo("EI")) << 3);
CodeLen=1;
END
else if (ArgCnt!=1) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
BAsmCode[2]=EvalIntExpression(ArgStr[1],UInt8,&OK);
if (OK)
BEGIN
BAsmCode[0]=0xdd; BAsmCode[1]=0xf3+(Ord(Memo("EI")) << 3);
CodeLen=3;
END
END
return;
END
if (Memo("IM"))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
AdrByte=EvalIntExpression(ArgStr[1],UInt2,&OK);
if (OK)
if (AdrByte>3) WrError(1320);
else if ((AdrByte==3) AND (MomCPU<CPUZ380)) WrError(1500);
else
BEGIN
if (AdrByte==3) AdrByte=1;
else if (AdrByte>=1) AdrByte++;
CodeLen=2; BAsmCode[0]=0xed; BAsmCode[1]=0x46+(AdrByte << 3);
END
END
return;
END
if (Memo("LDCTL"))
BEGIN
OpSize=0;
if (ArgCnt!=2) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else if (DecodeSFR(ArgStr[1],&AdrByte))
BEGIN
DecodeAdr(ArgStr[2]);
switch (AdrMode)
BEGIN
case ModReg8:
if (AdrPart!=7) WrError(1350);
else
BEGIN
BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
BAsmCode[1]=0xc8+((AdrByte & 4) << 2);
CodeLen=2;
END
break;
case ModReg16:
if ((AdrByte!=1) OR (AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0xc8; CodeLen=2;
END
break;
case ModImm:
BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
BAsmCode[1]=0xca+((AdrByte & 4) << 2);
BAsmCode[2]=AdrVals[0];
CodeLen=3;
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else if (DecodeSFR(ArgStr[2],&AdrByte))
BEGIN
DecodeAdr(ArgStr[1]);
switch (AdrMode)
BEGIN
case ModReg8:
if ((AdrPart!=7) OR (AdrByte==1)) WrError(1350);
else
BEGIN
BAsmCode[0]=0xcd+((AdrByte & 3) << 4);
BAsmCode[1]=0xd0;
CodeLen=2;
END
break;
case ModReg16:
if ((AdrByte!=1) OR (AdrPart!=2) OR (PrefixCnt!=0)) WrError(1350);
else
BEGIN
BAsmCode[0]=0xed; BAsmCode[1]=0xc0; CodeLen=2;
END
break;
default: if (AdrMode!=ModNone) WrError(1350);
END
END
else WrError(1350);
return;
END
if ((Memo("RESC")) OR (Memo("SETC")))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (MomCPU<CPUZ380) WrError(1500);
else
BEGIN
AdrByte=0xff; NLS_UpString(ArgStr[1]);
if (strcmp(ArgStr[1],"LW")==0) AdrByte=1;
else if (strcmp(ArgStr[1],"LCK")==0) AdrByte=2;
else if (strcmp(ArgStr[1],"XM")==0) AdrByte=3;
else WrError(1440);
if (AdrByte!=0xff)
BEGIN
CodeLen=2; BAsmCode[0]=0xcd+(AdrByte << 4);
BAsmCode[1]=0xf7+(Ord(Memo("RESC")) << 3);
END
END
return;
END
WrXError(1200,OpPart);
END
static void InitCode_Z80(void)
BEGIN
SaveInitProc();
SetFlag(&ExtFlag,ExtFlagName,False);
SetFlag(&LWordFlag,LWordFlagName,False);
END
static Boolean IsDef_Z80(void)
BEGIN
return Memo("PORT");
END
static void SwitchFrom_Z80(void)
BEGIN
DeinitFields(); ClearONOFF();
END
static void SwitchTo_Z80(void)
BEGIN
TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=True;
PCSymbol="$"; HeaderID=0x51; NOPCode=0x00;
DivideChars=","; HasAttrs=False;
ValidSegs=(1<<SegCode)+(1<<SegIO);
Grans[SegCode]=1; ListGrans[SegCode]=1; SegInits[SegCode]=0;
SegLimits[SegCode] = CodeEnd();
Grans[SegIO ]=1; ListGrans[SegIO ]=1; SegInits[SegIO ]=0;
SegLimits[SegIO ] = PortEnd();
MakeCode=MakeCode_Z80; IsDef=IsDef_Z80;
SwitchFrom=SwitchFrom_Z80; InitFields();
/* erweiterte Modi nur bei Z380 */
if (MomCPU>=CPUZ380)
BEGIN
AddONOFF("EXTMODE", &ExtFlag , ExtFlagName ,False);
AddONOFF("LWORDMODE", &LWordFlag , LWordFlagName ,False);
END
SetFlag(&ExtFlag,ExtFlagName,False);
SetFlag(&LWordFlag,LWordFlagName,False);
END
void codez80_init(void)
BEGIN
CPUZ80 =AddCPU("Z80" ,SwitchTo_Z80);
CPUZ80U=AddCPU("Z80UNDOC",SwitchTo_Z80);
CPUZ180=AddCPU("Z180",SwitchTo_Z80);
CPUZ380=AddCPU("Z380",SwitchTo_Z80);
SaveInitProc=InitPassProc; InitPassProc=InitCode_Z80;
END