/* codez80.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator Zilog Z80/180/380 */ /* */ /* Historie: 26. 8.1996 Grundsteinlegung */ /* 1. 2.1998 ChkPC ersetzt */ /* */ /*****************************************************************************/ #include "stdinc.h" #include #include #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='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=4) AND (*Asc_O=='(') AND (Asc_O[strlen(Asc_O)-1]==')')) for (z=0; z=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 ((zConditionCnt) 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=0xff80)); END static Boolean CodeAri(void) BEGIN int z; Byte AdrByte; Boolean OK; for (z=0; z0) /* 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 (MomCPU0) /* 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 (MomCPU0) /* 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; z2)) 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 ((MomCPU0) 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> 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> 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> 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 (MomCPU0)) 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 (MomCPU0xffffff) 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> 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=-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=-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=-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 (MomCPU3) WrError(1320); else if ((AdrByte==3) AND (MomCPU=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) 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