/* code78k0.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator 78K0-Familie */ /* */ /* Historie: 1.12.1996 Grundsteinlegung */ /* 3. 1.1999 ChkPC-Anpassung */ /* */ /*****************************************************************************/ #include "stdinc.h" #include #include #include "bpemu.h" #include "strutil.h" #include "asmdef.h" #include "asmsub.h" #include "asmpars.h" #include "codepseudo.h" #include "codevars.h" #define ModNone (-1) #define ModReg8 0 #define MModReg8 (1 << ModReg8) #define ModReg16 1 #define MModReg16 (1 << ModReg16) #define ModImm 2 #define MModImm (1 << ModImm) #define ModShort 3 #define MModShort (1 << ModShort) #define ModSFR 4 #define MModSFR (1 << ModSFR) #define ModAbs 5 #define MModAbs (1 << ModAbs) #define ModIReg 6 #define MModIReg (1 << ModIReg) #define ModIndex 7 #define MModIndex (1 << ModIndex) #define ModDisp 8 #define MModDisp (1 << ModDisp) #define AccReg 1 #define AccReg16 0 #define FixedOrderCount 11 #define AriOrderCount 8 #define Ari16OrderCount 3 #define ShiftOrderCount 4 #define Bit2OrderCount 3 #define RelOrderCount 4 #define BRelOrderCount 3 typedef struct { char *Name; Word Code; } FixedOrder; static FixedOrder *FixedOrders; static char **AriOrders; static char **Ari16Orders; static char **ShiftOrders; static char **Bit2Orders; static char **RelOrders; static char **BRelOrders; static Byte OpSize,AdrPart; static Byte AdrVals[2]; static ShortInt AdrMode; static CPUVar CPU78070; /*-------------------------------------------------------------------------*/ /* dynamische Codetabellenverwaltung */ static void AddFixed(char *NewName, Word NewCode) BEGIN if (InstrZ>=FixedOrderCount) exit(255); FixedOrders[InstrZ].Name=NewName; FixedOrders[InstrZ++].Code=NewCode; END static void AddAri(char *NewName) BEGIN if (InstrZ>=AriOrderCount) exit(255); AriOrders[InstrZ++]=NewName; END static void AddAri16(char *NewName) BEGIN if (InstrZ>=Ari16OrderCount) exit(255); Ari16Orders[InstrZ++]=NewName; END static void AddShift(char *NewName) BEGIN if (InstrZ>=ShiftOrderCount) exit(255); ShiftOrders[InstrZ++]=NewName; END static void AddBit2(char *NewName) BEGIN if (InstrZ>=Bit2OrderCount) exit(255); Bit2Orders[InstrZ++]=NewName; END static void AddRel(char *NewName) BEGIN if (InstrZ>=RelOrderCount) exit(255); RelOrders[InstrZ++]=NewName; END static void AddBRel(char *NewName) BEGIN if (InstrZ>=BRelOrderCount) exit(255); BRelOrders[InstrZ++]=NewName; END static void InitFields(void) BEGIN FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0; AddFixed("BRK" ,0x00bf); AddFixed("RET" ,0x00af); AddFixed("RETB" ,0x009f); AddFixed("RETI" ,0x008f); AddFixed("HALT" ,0x7110); AddFixed("STOP" ,0x7100); AddFixed("NOP" ,0x0000); AddFixed("EI" ,0x7a1e); AddFixed("DI" ,0x7b1e); AddFixed("ADJBA",0x6180); AddFixed("ADJBS",0x6190); AriOrders=(char **) malloc(sizeof(char *)*AriOrderCount); InstrZ=0; AddAri("ADD" ); AddAri("SUB" ); AddAri("ADDC"); AddAri("SUBC"); AddAri("CMP" ); AddAri("AND" ); AddAri("OR" ); AddAri("XOR" ); Ari16Orders=(char **) malloc(sizeof(char *)*Ari16OrderCount); InstrZ=0; AddAri16("ADDW"); AddAri16("SUBW"); AddAri16("CMPW"); ShiftOrders=(char **) malloc(sizeof(char *)*ShiftOrderCount); InstrZ=0; AddShift("ROR"); AddShift("RORC"); AddShift("ROL"); AddShift("ROLC"); Bit2Orders=(char **) malloc(sizeof(char *)*Bit2OrderCount); InstrZ=0; AddBit2("AND1"); AddBit2("OR1"); AddBit2("XOR1"); RelOrders=(char **) malloc(sizeof(char *)*RelOrderCount); InstrZ=0; AddRel("BC"); AddRel("BNC"); AddRel("BZ"); AddRel("BNZ"); BRelOrders=(char **) malloc(sizeof(char *)*BRelOrderCount); InstrZ=0; AddBRel("BTCLR"); AddBRel("BT"); AddBRel("BF"); END static void DeinitFields(void) BEGIN free(FixedOrders); free(AriOrders); free(Ari16Orders); free(ShiftOrders); free(Bit2Orders); free(RelOrders); free(BRelOrders); END /*-------------------------------------------------------------------------*/ /* Adressausdruck parsen */ static void ChkAdr(Word Mask) BEGIN if ((AdrMode!=ModNone) AND ((Mask & (1 << AdrMode))==0)) BEGIN WrError(1350); AdrMode=ModNone; AdrCnt=0; END END static void DecodeAdr(char *Asc, Word Mask) BEGIN static char *RegNames[8]={"X","A","C","B","E","D","L","H"}; Word AdrWord; int z; Boolean OK,LongFlag; AdrMode=ModNone; AdrCnt=0; /* Register */ for (z=0; z<8; z++) if (strcasecmp(Asc,RegNames[z])==0) BEGIN AdrMode=ModReg8; AdrPart=z; ChkAdr(Mask); return; END if (toupper(*Asc)=='R') if ((strlen(Asc)==2) AND (Asc[1]>='0') AND (Asc[1]<='7')) BEGIN AdrMode=ModReg8; AdrPart=Asc[1]-'0'; ChkAdr(Mask); return; END else if ((strlen(Asc)==3) AND (toupper(Asc[1])=='P') AND (Asc[2]>='0') AND (Asc[2]<='3')) BEGIN AdrMode=ModReg16; AdrPart=Asc[2]-'0'; ChkAdr(Mask); return; END if (strlen(Asc)==2) for (z=0; z<4; z++) if ((toupper(*Asc)==*RegNames[(z<<1)+1]) AND (toupper(Asc[1])==*RegNames[z<<1])) BEGIN AdrMode=ModReg16; AdrPart=z; ChkAdr(Mask); return; END /* immediate */ if (*Asc=='#') BEGIN switch (OpSize) BEGIN case 0: AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK); break; case 1: AdrWord=EvalIntExpression(Asc+1,Int16,&OK); if (OK) BEGIN AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); END break; END if (OK) BEGIN AdrMode=ModImm; AdrCnt=OpSize+1; END ChkAdr(Mask); return; END /* indirekt */ if ((*Asc=='[') AND (Asc[strlen(Asc)-1]==']')) BEGIN strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0'; if ((strcasecmp(Asc,"DE")==0) OR (strcasecmp(Asc,"RP2")==0)) BEGIN AdrMode=ModIReg; AdrPart=0; END else if ((strncasecmp(Asc,"HL",2)!=0) AND (strncasecmp(Asc,"RP3",3)!=0)) WrXError(1445,Asc); else BEGIN strcpy(Asc,Asc+2); if (*Asc=='3') strcpy(Asc,Asc+1); if ((strcasecmp(Asc,"+B")==0) OR (strcasecmp(Asc,"+R3")==0)) BEGIN AdrMode=ModIndex; AdrPart=1; END else if ((strcasecmp(Asc,"+C")==0) OR (strcasecmp(Asc,"+R2")==0)) BEGIN AdrMode=ModIndex; AdrPart=0; END else BEGIN AdrVals[0]=EvalIntExpression(Asc,UInt8,&OK); if (OK) if (AdrVals[0]==0) BEGIN AdrMode=ModIReg; AdrPart=1; END else BEGIN AdrMode=ModDisp; AdrCnt=1; END; END END ChkAdr(Mask); return; END /* erzwungen lang ? */ if (*Asc=='!') BEGIN LongFlag=True; strcpy(Asc,Asc+1); END else LongFlag=False; /* -->absolut */ FirstPassUnknown=True; AdrWord=EvalIntExpression(Asc,UInt16,&OK); if (FirstPassUnknown) BEGIN AdrWord&=0xffffe; if ((Mask & MModAbs)==0) AdrWord=(AdrWord | 0xff00) & 0xff1f; END if (OK) if ((NOT LongFlag) AND ((Mask & MModShort)!=0) AND (AdrWord>=0xfe20) AND (AdrWord<=0xff1f)) BEGIN AdrMode=ModShort; AdrCnt=1; AdrVals[0]=Lo(AdrWord); END else if ((NOT LongFlag) AND ((Mask & MModSFR)!=0) AND (((AdrWord>=0xff00) AND (AdrWord<=0xffcf)) OR (AdrWord>=0xffe0))) BEGIN AdrMode=ModSFR; AdrCnt=1; AdrVals[0]=Lo(AdrWord); END else BEGIN AdrMode=ModAbs; AdrCnt=2; AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); END ChkAdr(Mask); END static void ChkEven(void) BEGIN if ((AdrMode==ModAbs) OR (AdrMode==ModShort) OR (AdrMode==ModSFR)) if ((AdrVals[0]&1)==1) WrError(180); END static Boolean DecodeBitAdr(char *Asc, Byte *Erg) BEGIN char *p; Boolean OK; p=RQuotPos(Asc,'.'); if (p==Nil) BEGIN WrError(1510); return False; END *p='\0'; *Erg=EvalIntExpression(p+1,UInt3,&OK) << 4; if (NOT OK) return False; DecodeAdr(Asc,MModShort+MModSFR+MModIReg+MModReg8); switch (AdrMode) BEGIN case ModReg8: if (AdrPart!=AccReg) BEGIN WrError(1350); return False; END else BEGIN *Erg+=0x88; return True; END case ModShort: return True; case ModSFR: *Erg+=0x08; return True; case ModIReg: if (AdrPart==0) BEGIN WrError(1350); return False; END else BEGIN *Erg+=0x80; return True; END default: return False; END END /*-------------------------------------------------------------------------*/ static Boolean DecodePseudo(void) BEGIN return False; END static void MakeCode_78K0(void) BEGIN int z; Byte HReg; Word AdrWord; Integer AdrInt; Boolean OK; CodeLen=0; DontPrint=False; OpSize=0; /* zu ignorierendes */ if (Memo("")) return; /* Pseudoanweisungen */ if (DecodePseudo()) return; if (DecodeIntelPseudo(False)) return; /* ohne Argument */ for (z=0; z=-128) AND (AdrInt<127)) ? 2 : 1; END switch (HReg) BEGIN case 1: BAsmCode[0]=0x9b; BAsmCode[1]=Lo(AdrWord); BAsmCode[2]=Hi(AdrWord); CodeLen=3; break; case 2: AdrInt=AdrWord-(EProgCounter()+2); if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=0xfa; BAsmCode[1]=AdrInt & 0xff; CodeLen=2; END break; END END END return; END for (z=0; z127)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=0x8b+(z << 4); BAsmCode[1]=AdrInt & 0xff; CodeLen=2; END END return; END for (z=0; z127)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[HReg]=AdrInt & 0xff; CodeLen=HReg+1; END END return; END if (Memo("DBNZ")) BEGIN if (ArgCnt!=2) WrError(1110); else BEGIN DecodeAdr(ArgStr[1],MModReg8+MModShort); if ((AdrMode==ModReg8) AND ((AdrPart & 6)!=2)) WrError(1350); else if (AdrMode!=ModNone) BEGIN BAsmCode[0]=(AdrMode==ModReg8) ? 0x88+AdrPart : 0x04; BAsmCode[1]=AdrVals[0]; if (*ArgStr[2]=='$') strcpy(ArgStr[2],ArgStr[2]+1); AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+AdrCnt+2); if (OK) if (((AdrInt<-128) OR (AdrInt>127)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[AdrCnt+1]=AdrInt & 0xff; CodeLen=AdrCnt+2; END END END return; END /* Steueranweisungen */ if (Memo("SEL")) BEGIN if (ArgCnt!=1) WrError(1350); else if ((strlen(ArgStr[1])!=3) OR (strncasecmp(ArgStr[1],"RB",2)!=0)) WrError(1350); else BEGIN HReg=ArgStr[1][2]-'0'; if (ChkRange(HReg,0,3)) BEGIN BAsmCode[0]=0x61; BAsmCode[1]=0xd0+((HReg & 1) << 3)+((HReg & 2) << 4); CodeLen=2; END END return; END WrXError(1200,OpPart); END static Boolean IsDef_78K0(void) BEGIN return False; END static void SwitchFrom_78K0(void) BEGIN DeinitFields(); END static void SwitchTo_78K0(void) BEGIN TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False; PCSymbol="PC"; HeaderID=0x7c; NOPCode=0x00; DivideChars=","; HasAttrs=False; ValidSegs=1<