/* code65.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator 65xx/MELPS740 */ /* */ /* Historie: 17. 8.1996 Grundsteinlegung */ /* 17.11.1998 ungueltiges Register wurde bei Indizierung nicht ab- */ /* gefangen */ /* 2. 1.1999 ChkPC umgestellt */ /* */ /*****************************************************************************/ #include "stdinc.h" #include #include #include "bpemu.h" #include "strutil.h" #include "asmdef.h" #include "asmpars.h" #include "asmsub.h" #include "codepseudo.h" #include "codevars.h" /*---------------------------------------------------------------------------*/ #define ModZA 0 /* aa */ #define ModA 1 /* aabb */ #define ModZIX 2 /* aa,X */ #define ModIX 3 /* aabb,X */ #define ModZIY 4 /* aa,Y */ #define ModIY 5 /* aabb,Y */ #define ModIndX 6 /* (aa,X) */ #define ModIndY 7 /* (aa),Y */ #define ModInd16 8 /* (aabb) */ #define ModImm 9 /* #aa */ #define ModAcc 10 /* A */ #define ModNone 11 /* */ #define ModInd8 12 /* (aa) */ #define ModSpec 13 /* \aabb */ typedef struct { char *Name; Byte CPUFlag; Byte Code; } FixedOrder; typedef struct { char *Name; Integer Codes[ModSpec+1]; } NormOrder; typedef struct { char *Name; Byte CPUFlag; Byte Code; } CondOrder; #define FixedOrderCount 37 #define NormOrderCount 51 #define CondOrderCount 9 static Boolean CLI_SEI_Flag,ADC_SBC_Flag; static FixedOrder *FixedOrders; static NormOrder *NormOrders; static CondOrder *CondOrders; static SimpProc SaveInitProc; static CPUVar CPU6502,CPU65SC02,CPU65C02,CPUM740,CPU6502U; static LongInt SpecPage; static ShortInt ErgMode; static Byte AdrVals[2]; /*---------------------------------------------------------------------------*/ static void AddFixed(char *NName, Byte NFlag, Byte NCode) BEGIN if (InstrZ>=FixedOrderCount) exit(255); FixedOrders[InstrZ].Name=NName; FixedOrders[InstrZ].CPUFlag=NFlag; FixedOrders[InstrZ++].Code=NCode; END static void AddNorm(char *NName, Word ZACode, Word ACode, Word ZIXCode, Word IXCode, Word ZIYCode, Word IYCode, Word IndXCode, Word IndYCode, Word Ind16Code, Word ImmCode, Word AccCode, Word NoneCode, Word Ind8Code, Word SpecCode) BEGIN if (InstrZ>=NormOrderCount) exit(255); NormOrders[InstrZ].Name=NName; NormOrders[InstrZ].Codes[ModZA]=ZACode; NormOrders[InstrZ].Codes[ModA]=ACode; NormOrders[InstrZ].Codes[ModZIX]=ZIXCode; NormOrders[InstrZ].Codes[ModIX]=IXCode; NormOrders[InstrZ].Codes[ModZIY]=ZIYCode; NormOrders[InstrZ].Codes[ModIY]=IYCode; NormOrders[InstrZ].Codes[ModIndX]=IndXCode; NormOrders[InstrZ].Codes[ModIndY]=IndYCode; NormOrders[InstrZ].Codes[ModInd16]=Ind16Code; NormOrders[InstrZ].Codes[ModImm]=ImmCode; NormOrders[InstrZ].Codes[ModAcc]=AccCode; NormOrders[InstrZ].Codes[ModNone]=NoneCode; NormOrders[InstrZ].Codes[ModInd8]=Ind8Code; NormOrders[InstrZ++].Codes[ModSpec]=SpecCode; END static void AddCond(char *NName, Byte NFlag, Byte NCode) BEGIN if (InstrZ>=CondOrderCount) exit(255); CondOrders[InstrZ].Name=NName; CondOrders[InstrZ].CPUFlag=NFlag; CondOrders[InstrZ++].Code=NCode; END static void InitFields(void) BEGIN Boolean Is740=(MomCPU==CPUM740); FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0; AddFixed("RTS", 31, 0x60); AddFixed("RTI", 31, 0x40); AddFixed("TAX", 31, 0xaa); AddFixed("TXA", 31, 0x8a); AddFixed("TAY", 31, 0xa8); AddFixed("TYA", 31, 0x98); AddFixed("TXS", 31, 0x9a); AddFixed("TSX", 31, 0xba); AddFixed("DEX", 31, 0xca); AddFixed("DEY", 31, 0x88); AddFixed("INX", 31, 0xe8); AddFixed("INY", 31, 0xc8); AddFixed("PHA", 31, 0x48); AddFixed("PLA", 31, 0x68); AddFixed("PHP", 31, 0x08); AddFixed("PLP", 31, 0x28); AddFixed("PHX", 6, 0xda); AddFixed("PLX", 6, 0xfa); AddFixed("PHY", 6, 0x5a); AddFixed("PLY", 6, 0x7a); AddFixed("BRK", 31, 0x00); AddFixed("STP", 8, 0x42); AddFixed("SLW", 8, 0xc2); AddFixed("FST", 8, 0xe2); AddFixed("WIT", 8, 0xc2); AddFixed("CLI", 31, 0x58); AddFixed("SEI", 31, 0x78); AddFixed("CLC", 31, 0x18); AddFixed("SEC", 31, 0x38); AddFixed("CLD", 31, 0xd8); AddFixed("SED", 31, 0xf8); AddFixed("CLV", 31, 0xb8); AddFixed("CLT", 8, 0x12); AddFixed("SET", 8, 0x32); AddFixed("JAM", 16, 0x02); AddFixed("CRS", 16, 0x02); AddFixed("KIL", 16, 0x02); NormOrders=(NormOrder *) malloc(sizeof(NormOrder)*NormOrderCount); InstrZ=0; /* ZA A ZIX IX ZIY IY @X @Y (n16) imm ACC NON (n8) spec */ AddNorm("NOP",0x1004,0x100c,0x1014,0x101c, -1, -1, -1, -1, -1,0x1080, -1,0x1fea, -1, -1); AddNorm("LDA",0x1fa5,0x1fad,0x1fb5,0x1fbd, -1,0x1fb9,0x1fa1,0x1fb1, -1,0x1fa9, -1, -1,0x06b2, -1); AddNorm("LDX",0x1fa6,0x1fae, -1, -1,0x1fb6,0x1fbe, -1, -1, -1,0x1fa2, -1, -1, -1, -1); AddNorm("LDY",0x1fa4,0x1fac,0x1fb4,0x1fbc, -1, -1, -1, -1, -1,0x1fa0, -1, -1, -1, -1); AddNorm("STA",0x1f85,0x1f8d,0x1f95,0x1f9d, -1,0x1f99,0x1f81,0x1f91, -1, -1, -1, -1,0x0692, -1); AddNorm("STX",0x1f86,0x1f8e, -1, -1,0x1f96, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("STY",0x1f84,0x1f8c,0x1f94, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("STZ",0x0664,0x069c,0x0674,0x069e, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("ADC",0x1f65,0x1f6d,0x1f75,0x1f7d, -1,0x1f79,0x1f61,0x1f71, -1,0x1f69, -1, -1,0x0672, -1); AddNorm("SBC",0x1fe5,0x1fed,0x1ff5,0x1ffd, -1,0x1ff9,0x1fe1,0x1ff1, -1,0x1fe9, -1, -1,0x06f2, -1); AddNorm("MUL", -1, -1,0x0862, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("DIV", -1, -1,0x08e2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("AND",0x1f25,0x1f2d,0x1f35,0x1f3d, -1,0x1f39,0x1f21,0x1f31, -1,0x1f29, -1, -1,0x0632, -1); AddNorm("ORA",0x1f05,0x1f0d,0x1f15,0x1f1d, -1,0x1f19,0x1f01,0x1f11, -1,0x1f09, -1, -1,0x0612, -1); AddNorm("EOR",0x1f45,0x1f4d,0x1f55,0x1f5d, -1,0x1f59,0x1f41,0x1f51, -1,0x1f49, -1, -1,0x0652, -1); AddNorm("COM",0x0844, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("BIT",0x1f24,0x1f2c,0x0634,0x063c, -1, -1, -1, -1, -1,0x0689, -1, -1, -1, -1); AddNorm("TST",0x0864, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("ASL",0x1f06,0x1f0e,0x1f16,0x1f1e, -1, -1, -1, -1, -1, -1,0x1f0a,0x1f0a, -1, -1); AddNorm("LSR",0x1f46,0x1f4e,0x1f56,0x1f5e, -1, -1, -1, -1, -1, -1,0x1f4a,0x1f4a, -1, -1); AddNorm("ROL",0x1f26,0x1f2e,0x1f36,0x1f3e, -1, -1, -1, -1, -1, -1,0x1f2a,0x1f2a, -1, -1); AddNorm("ROR",0x1f66,0x1f6e,0x1f76,0x1f7e, -1, -1, -1, -1, -1, -1,0x1f6a,0x1f6a, -1, -1); AddNorm("RRF",0x0882, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("TSB",0x0604,0x060c, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("TRB",0x0614,0x061c, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("INC",0x1fe6,0x1fee,0x1ff6,0x1ffe, -1, -1, -1, -1, -1, -1,(Is740)?0x0e3a:0x0e1a, (Is740)?0x0e3a:0x0e1a, -1, -1); AddNorm("DEC",0x1fc6,0x1fce,0x1fd6,0x1fde, -1, -1, -1, -1, -1, -1,(Is740)?0x0e1a:0x0e3a, (Is740)?0x0e1a:0x0e3a, -1, -1); AddNorm("CMP",0x1fc5,0x1fcd,0x1fd5,0x1fdd, -1,0x1fd9,0x1fc1,0x1fd1, -1,0x1fc9, -1, -1,0x06d2, -1); AddNorm("CPX",0x1fe4,0x1fec, -1, -1, -1, -1, -1, -1, -1,0x1fe0, -1, -1, -1, -1); AddNorm("CPY",0x1fc4,0x1fcc, -1, -1, -1, -1, -1, -1, -1,0x1fc0, -1, -1, -1, -1); AddNorm("JMP", -1,0x1f4c, -1, -1, -1, -1,0x067c, -1,0x1f6c, -1, -1, -1,0x08b2, -1); AddNorm("JSR", -1,0x1f20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0x0802,0x0822); AddNorm("SLO",0x1007,0x100f,0x1017,0x101f, -1,0x101b,0x1003,0x1013, -1, -1, -1, -1, -1, -1); AddNorm("ANC", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x100b, -1, -1, -1, -1); AddNorm("RLA",0x1027,0x102f,0x1037,0x103f, -1,0x103b,0x1023,0x1033, -1, -1, -1, -1, -1, -1); AddNorm("SRE",0x1047,0x104f,0x1057,0x105f, -1,0x105b,0x1043,0x1053, -1, -1, -1, -1, -1, -1); AddNorm("ASR", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x104b, -1, -1, -1, -1); AddNorm("RRA",0x1067,0x106f,0x1077,0x107f, -1,0x107b,0x1063,0x1073, -1, -1, -1, -1, -1, -1); AddNorm("ARR", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x106b, -1, -1, -1, -1); AddNorm("SAX",0x1087,0x108f, -1, -1,0x1097, -1,0x1083, -1, -1, -1, -1, -1, -1, -1); AddNorm("ANE", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x108b, -1, -1, -1, -1); AddNorm("SHA", -1, -1, -1,0x1093, -1,0x109f, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("SHS", -1, -1, -1, -1, -1,0x109b, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("SHY", -1, -1, -1, -1, -1,0x109c, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("SHX", -1, -1, -1,0x109e, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("LAX",0x10a7,0x10af, -1, -1,0x10b7,0x10bf,0x10a3,0x10b3, -1, -1, -1, -1, -1, -1); AddNorm("LXA", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x10ab, -1, -1, -1, -1); AddNorm("LAE", -1, -1, -1, -1, -1,0x10bb, -1, -1, -1, -1, -1, -1, -1, -1); AddNorm("DCP",0x10c7,0x10cf,0x10d7,0x10df, -1,0x10db,0x10c3,0x10d3, -1, -1, -1, -1, -1, -1); AddNorm("SBX", -1, -1, -1, -1, -1, -1, -1, -1, -1,0x10cb, -1, -1, -1, -1); AddNorm("ISB",0x10e7,0x10ef,0x10f7,0x10ff, -1,0x10fb,0x10e3,0x10f3, -1, -1, -1, -1, -1, -1); CondOrders=(CondOrder *) malloc(sizeof(CondOrder)*CondOrderCount); InstrZ=0; AddCond("BEQ", 31, 0xf0); AddCond("BNE", 31, 0xd0); AddCond("BPL", 31, 0x10); AddCond("BMI", 31, 0x30); AddCond("BCC", 31, 0x90); AddCond("BCS", 31, 0xb0); AddCond("BVC", 31, 0x50); AddCond("BVS", 31, 0x70); AddCond("BRA", 14, 0x80); END static void DeinitFields(void) BEGIN free(FixedOrders); free(NormOrders); free(CondOrders); END /*---------------------------------------------------------------------------*/ static void ChkZero(char *Asc, Byte *erg) BEGIN if ((strlen(Asc)>1) AND ((*Asc=='<') OR (*Asc=='>'))) BEGIN *erg=Ord(*Asc=='<')+1; strcpy(Asc,Asc+1); END else *erg=0; END static Boolean DecodePseudo(void) BEGIN #define ASSUME740Count 1 static ASSUMERec ASSUME740s[ASSUME740Count]= {{"SP", &SpecPage, 0, 0xff, -1}}; if (Memo("ASSUME")) BEGIN if (MomCPU!=CPUM740) WrError(1500); else CodeASSUME(ASSUME740s,ASSUME740Count); return True; END return False; END static void ChkFlags(void) BEGIN /* Spezialflags ? */ CLI_SEI_Flag=(Memo("CLI") OR Memo("SEI")); ADC_SBC_Flag=(Memo("ADC") OR Memo("SBC")); END static Boolean CPUAllowed(Byte Flag) BEGIN return (((Flag >> (MomCPU-CPU6502))&1)==1); END static void InsNOP(void) BEGIN memmove(BAsmCode,BAsmCode+1,CodeLen); CodeLen++; BAsmCode[0]=NOPCode; END static Boolean IsAllowed(Word Val) BEGIN return (CPUAllowed(Hi(Val)) AND (Val!=0xffff)); END static void ChkZeroMode(ShortInt Mode) BEGIN int OrderZ; for (OrderZ=0; OrderZ127) OR (AdrInt<-128)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN CodeLen=2+Ord(b); BAsmCode[CodeLen-1]=AdrInt & 0xff; if (CLI_SEI_Flag) InsNOP(); END END END END ChkFlags(); return; END if (((strlen(OpPart)==4) AND (OpPart[3]>='0') AND (OpPart[3]<='7') AND ((strncmp(OpPart,"BBR",3)==0) OR (strncmp(OpPart,"BBS",3)==0)))) BEGIN if (ArgCnt!=2) WrError(1110); else if (MomCPU!=CPU65C02) WrError(1500); else BEGIN BAsmCode[1]=EvalIntExpression(ArgStr[1],UInt8,&ValOK); if (ValOK) BEGIN BAsmCode[0]=((OpPart[3]-'0') << 4)+(Ord(OpPart[2]=='S') << 7)+15; AdrInt=EvalIntExpression(ArgStr[2],UInt16,&ValOK)-(EProgCounter()+3); if (ValOK) if (((AdrInt>127) OR (AdrInt<-128)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN CodeLen=3; BAsmCode[2]=AdrInt & 0xff; END END END ChkFlags(); return; END if (((strlen(OpPart)==4) AND (OpPart[3]>='0') AND (OpPart[3]<='7') AND ((strncmp(OpPart,"RMB",3)==0) OR (strncmp(OpPart,"SMB",3)==0)))) BEGIN if (ArgCnt!=1) WrError(1110); else if (MomCPU!=CPU65C02) WrError(1500); else BEGIN BAsmCode[1]=EvalIntExpression(ArgStr[1],UInt8,&ValOK); if (ValOK) BEGIN BAsmCode[0]=((OpPart[3]-'0') << 4)+(Ord(*OpPart=='S') << 7)+7; CodeLen=2; END END ChkFlags(); return; END if (Memo("LDM")) BEGIN if (ArgCnt!=2) WrError(1110); else if (MomCPU!=CPUM740) WrError(1500); else BEGIN BAsmCode[0]=0x3c; BAsmCode[2]=EvalIntExpression(ArgStr[2],UInt8,&ValOK); if (ValOK) if (*ArgStr[1]!='#') WrError(1350); else BEGIN BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,Int8,&ValOK); if (ValOK) CodeLen=3; END END ChkFlags(); return; END /* normale Anweisungen: Adressausdruck parsen */ ErgMode=(-1); if (ArgCnt==0) BEGIN AdrCnt=0; ErgMode=ModNone; END else if (ArgCnt==1) BEGIN /* 1. Akkuadressierung */ if (strcasecmp(ArgStr[1],"A")==0) BEGIN AdrCnt=0; ErgMode=ModAcc; END /* 2. immediate ? */ else if (*ArgStr[1]=='#') BEGIN AdrVals[0]=EvalIntExpression(ArgStr[1]+1,Int8,&ValOK); if (ValOK) BEGIN ErgMode=ModImm; AdrCnt=1; END END /* 3. Special Page ? */ else if (*ArgStr[1]=='\\') BEGIN AdrWord=EvalIntExpression(ArgStr[1]+1,UInt16,&ValOK); if (ValOK) if (Hi(AdrWord)!=SpecPage) WrError(1315); else BEGIN ErgMode=ModSpec; AdrVals[0]=Lo(AdrWord); AdrCnt=1; END END /* 4. X-indirekt ? */ else if ((strlen(ArgStr[1])>=5) AND (strcasecmp(ArgStr[1]+strlen(ArgStr[1])-3,",X)")==0)) BEGIN if (*ArgStr[1]!='(') WrError(1350); else BEGIN strmaxcpy(s1,ArgStr[1]+1,255); s1[strlen(s1)-3]='\0'; ChkZero(s1,&ZeroMode); if (Memo("JMP")) BEGIN AdrWord=EvalIntExpression(s1,UInt16,&ValOK); if (ValOK) BEGIN AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); ErgMode=ModIndX; AdrCnt=2; END END else BEGIN AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK); if (ValOK) BEGIN ErgMode=ModIndX; AdrCnt=1; END END END END else BEGIN /* 5. indirekt absolut ? */ if (IsIndirect(ArgStr[1])) BEGIN strcpy(s1,ArgStr[1]+1); s1[strlen(s1)-1]='\0'; ChkZero(s1,&ZeroMode); if (ZeroMode==2) BEGIN AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK); if (ValOK) BEGIN ErgMode=ModInd8; AdrCnt=1; END END else BEGIN AdrWord=EvalIntExpression(s1,UInt16,&ValOK); if (ValOK) BEGIN ErgMode=ModInd16; AdrCnt=2; AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); if ((ZeroMode==0) AND (AdrVals[1]==0)) ChkZeroMode(ModInd8); END END END /* 6. absolut */ else BEGIN ChkZero(ArgStr[1],&ZeroMode); if (ZeroMode==2) BEGIN AdrVals[0]=EvalIntExpression(ArgStr[1],UInt8,&ValOK); if (ValOK) BEGIN ErgMode=ModZA; AdrCnt=1; END END else BEGIN AdrWord=EvalIntExpression(ArgStr[1],UInt16,&ValOK); if (ValOK) BEGIN ErgMode=ModA; AdrCnt=2; AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); if ((ZeroMode==0) AND (AdrVals[1]==0)) ChkZeroMode(ModZA); END END END END END else if (ArgCnt==2) BEGIN /* 7. Y-indirekt ? */ if ((IsIndirect(ArgStr[1])) AND (strcasecmp(ArgStr[2],"Y")==0)) BEGIN strcpy(s1,ArgStr[1]+1); s1[strlen(s1)-1]='\0'; ChkZero(s1,&ZeroMode); AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK); if (ValOK) BEGIN ErgMode=ModIndY; AdrCnt=1; END END /* 8. X,Y-indiziert ? */ else BEGIN strcpy(s1,ArgStr[1]); ChkZero(s1,&ZeroMode); if (ZeroMode==2) BEGIN AdrVals[0]=EvalIntExpression(s1,UInt8,&ValOK); if (ValOK) BEGIN AdrCnt=1; if (strcasecmp(ArgStr[2],"X")==0) ErgMode=ModZIX; else if (strcasecmp(ArgStr[2],"Y")==0) ErgMode=ModZIY; else WrXError(1445,ArgStr[2]); END END else BEGIN AdrWord=EvalIntExpression(s1,Int16,&ValOK); if (ValOK) BEGIN AdrCnt=2; AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); if (strcasecmp(ArgStr[2],"X")==0) ErgMode=ModIX; else if (strcasecmp(ArgStr[2],"Y")==0) ErgMode=ModIY; else WrXError(1445,ArgStr[2]); if (ErgMode != -1) BEGIN if ((AdrVals[1]==0) AND (ZeroMode==0)) ChkZeroMode((strcasecmp(ArgStr[2],"X")==0)?ModZIX:ModZIY); END END END END END else BEGIN WrError(1110); ChkFlags(); return; END; /* in Tabelle nach Opcode suchen */ for (OrderZ=0; OrderZ127) OR (AdrInt<-128)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=CondOrders[OrderZ].Code; BAsmCode[1]=AdrInt & 0xff; CodeLen=2; END ChkFlags(); return; END WrXError(1200,OpPart); END static void InitCode_65(void) BEGIN SaveInitProc(); CLI_SEI_Flag=False; ADC_SBC_Flag=False; END static Boolean IsDef_65(void) BEGIN return False; END static void SwitchFrom_65(void) BEGIN DeinitFields(); END static void SwitchTo_65(void) BEGIN TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=(MomCPU==CPUM740); PCSymbol="*"; HeaderID=0x11; NOPCode=0xea; DivideChars=","; HasAttrs=False; ValidSegs=1<