/* codem16c.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator M16C */ /* */ /* Historie: 17.12.1996 Grundsteinlegung */ /* 21. 9.1998 Kodierungsfehler: mov.b:s #0,...->dests vergessen */ /* mov.x:s #imm,reg->OpSize invertiert*/ /* sub.x:q #imm4,...->falscher Opcode */ /* 3. 1.1999 ChkPC-Anpassung */ /* {RMS} 6. 2.1999 Fixed remaining code generation errors - M16C is now */ /* 100% correct, validated against reference assemblers */ /* and official Mitsubishi documentation. */ /* Search for RMS: tags to see changes */ /* {RMS} 8. 2.1999 Fixed ChkPC SegLimit typo [M16s have 20 bits] */ /* {RMS} 10. 2.1999 Accomodate JMP.S crossing 64k boundary bug in M16C */ /* {RMS} 2. 4.1999 Made the JMP.S promotion fix CPU-dependent, and made */ /* repairs to the JMP.S handling for forward label refs */ /* so they now work. [JMP.S symbol] now works. */ /* */ /*****************************************************************************/ #include "stdinc.h" #include "string.h" #include #include "nls.h" #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 ModGen 0 #define MModGen (1 << ModGen) #define ModAbs20 1 #define MModAbs20 (1 << ModAbs20) #define ModAReg32 2 #define MModAReg32 (1 << ModAReg32) #define ModDisp20 3 #define MModDisp20 (1 << ModDisp20) #define ModReg32 4 #define MModReg32 (1 << ModReg32) #define ModIReg32 5 #define MModIReg32 (1 << ModIReg32) #define ModImm 6 #define MModImm (1 << ModImm) #define ModSPRel 7 #define MModSPRel (1 << ModSPRel) #define FixedOrderCnt 8 #define StringOrderCnt 4 #define Gen1OrderCnt 5 #define Gen2OrderCnt 6 #define DivOrderCnt 3 #define ConditionCnt 18 #define BCDOrderCnt 4 #define DirOrderCnt 4 #define BitOrderCnt 13 typedef struct { char *Name; Word Code; } FixedOrder; typedef struct { char *Name; Byte Code1,Code2,Code3; } Gen2Order; typedef struct { char *Name; Byte Code; } Condition; static char *Flags="CDZSBOIU"; static CPUVar CPUM16C,CPUM30600M8,CPUM30610,CPUM30620; static String Format; static Byte FormatCode; static ShortInt OpSize; static Byte AdrMode,AdrMode2; static ShortInt AdrType,AdrType2; static Byte AdrCnt2; static Byte AdrVals[3],AdrVals2[3]; static FixedOrder *FixedOrders; static FixedOrder *StringOrders; static FixedOrder *Gen1Orders; static Gen2Order *Gen2Orders; static Gen2Order *DivOrders; static Condition *Conditions; static char **BCDOrders; static char **DirOrders; static FixedOrder *BitOrders; /*------------------------------------------------------------------------*/ static void AddFixed(char *NName, Word NCode) BEGIN if (InstrZ>=FixedOrderCnt) exit(255); FixedOrders[InstrZ].Name=NName; FixedOrders[InstrZ++].Code=NCode; END static void AddString(char *NName, Word NCode) BEGIN if (InstrZ>=StringOrderCnt) exit(255); StringOrders[InstrZ].Name=NName; StringOrders[InstrZ++].Code=NCode; END static void AddGen1(char *NName, Word NCode) BEGIN if (InstrZ>=Gen1OrderCnt) exit(255); Gen1Orders[InstrZ].Name=NName; Gen1Orders[InstrZ++].Code=NCode; END static void AddGen2(char *NName, Byte NCode1, Byte NCode2, Byte NCode3) BEGIN if (InstrZ>=Gen2OrderCnt) exit(255); Gen2Orders[InstrZ].Name=NName; Gen2Orders[InstrZ].Code1=NCode1; Gen2Orders[InstrZ].Code2=NCode2; Gen2Orders[InstrZ++].Code3=NCode3; END static void AddDiv(char *NName, Byte NCode1, Byte NCode2, Byte NCode3) BEGIN if (InstrZ>=DivOrderCnt) exit(255); DivOrders[InstrZ].Name=NName; DivOrders[InstrZ].Code1=NCode1; DivOrders[InstrZ].Code2=NCode2; DivOrders[InstrZ++].Code3=NCode3; END static void AddCondition(char *NName, Word NCode) BEGIN if (InstrZ>=ConditionCnt) exit(255); Conditions[InstrZ].Name=NName; Conditions[InstrZ++].Code=NCode; END static void AddBCD(char *NName) BEGIN if (InstrZ>=BCDOrderCnt) exit(255); BCDOrders[InstrZ++]=NName; END static void AddDir(char *NName) BEGIN if (InstrZ>=DirOrderCnt) exit(255); DirOrders[InstrZ++]=NName; END static void AddBit(char *NName, Word NCode) BEGIN if (InstrZ>=BitOrderCnt) exit(255); BitOrders[InstrZ].Name=NName; BitOrders[InstrZ++].Code=NCode; END static void InitFields(void) BEGIN InstrZ=0; FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); AddFixed("BRK" ,0x0000); AddFixed("EXITD" ,0x7df2); AddFixed("INTO" ,0x00f6); AddFixed("NOP" ,0x0004); AddFixed("REIT" ,0x00fb); AddFixed("RTS" ,0x00f3); AddFixed("UND" ,0x00ff); AddFixed("WAIT" ,0x7df3); InstrZ=0; StringOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*StringOrderCnt); AddString("RMPA" ,0x7cf1); AddString("SMOVB",0x7ce9); AddString("SMOVF",0x7ce8); AddString("SSTR" ,0x7cea); InstrZ=0; Gen1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Gen1OrderCnt); AddGen1("ABS" ,0x76f0); AddGen1("ADCF",0x76e0); AddGen1("NEG" ,0x7450); AddGen1("ROLC",0x76a0); AddGen1("RORC",0x76b0); InstrZ=0; Gen2Orders=(Gen2Order *) malloc(sizeof(Gen2Order)*Gen2OrderCnt); AddGen2("ADC" ,0xb0,0x76,0x60); AddGen2("SBB" ,0xb8,0x76,0x70); AddGen2("TST" ,0x80,0x76,0x00); AddGen2("XOR" ,0x88,0x76,0x10); AddGen2("MUL" ,0x78,0x7c,0x50); AddGen2("MULU",0x70,0x7c,0x40); InstrZ=0; DivOrders=(Gen2Order *) malloc(sizeof(Gen2Order)*DivOrderCnt); AddDiv("DIV" ,0xe1,0x76,0xd0); AddDiv("DIVU",0xe0,0x76,0xc0); AddDiv("DIVX",0xe3,0x76,0x90); InstrZ=0; Conditions=(Condition *) malloc(sizeof(Condition)*ConditionCnt); AddCondition("GEU", 0); AddCondition("C" , 0); AddCondition("GTU", 1); AddCondition("EQ" , 2); AddCondition("Z" , 2); AddCondition("N" , 3); AddCondition("LTU", 4); AddCondition("NC" , 4); AddCondition("LEU", 5); AddCondition("NE" , 6); AddCondition("NZ" , 6); AddCondition("PZ" , 7); AddCondition("LE" , 8); AddCondition("O" , 9); AddCondition("GE" ,10); AddCondition("GT" ,12); AddCondition("NO" ,13); AddCondition("LT" ,14); InstrZ=0; BCDOrders=(char **) malloc(sizeof(char *)*BCDOrderCnt); AddBCD("DADD"); AddBCD("DSUB"); AddBCD("DADC"); AddBCD("DSBB"); InstrZ=0; DirOrders=(char **) malloc(sizeof(char *)*DirOrderCnt); AddDir("MOVLL"); AddDir("MOVHL"); AddDir("MOVLH"); AddDir("MOVHH"); InstrZ=0; BitOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*BitOrderCnt); AddBit("BAND" , 4); AddBit("BNAND" , 5); AddBit("BNOR" , 7); AddBit("BNTST" , 3); AddBit("BNXOR" ,13); AddBit("BOR" , 6); AddBit("BTSTC" , 0); AddBit("BTSTS" , 1); AddBit("BXOR" ,12); AddBit("BCLR" , 8); AddBit("BNOT" ,10); AddBit("BSET" , 9); AddBit("BTST" ,11); END static void DeinitFields(void) BEGIN free(FixedOrders); free(StringOrders); free(Gen1Orders); free(Gen2Orders); free(DivOrders); free(Conditions); free(BCDOrders); free(DirOrders); free(BitOrders); END /*------------------------------------------------------------------------*/ /* Adressparser */ static void SetOpSize(ShortInt NSize) BEGIN if (OpSize==-1) OpSize=NSize; else if (NSize!=OpSize) BEGIN WrError(1131); AdrCnt=0; AdrType=ModNone; END END static void ChkAdr(Word Mask) BEGIN if ((AdrType!=ModNone) AND ((Mask & (1 << AdrType))==0)) BEGIN AdrCnt=0; AdrType=ModNone; WrError(1350); END END static void DecodeAdr(char *Asc, Word Mask) BEGIN LongInt DispAcc; String RegPart; char *p; Boolean OK; AdrCnt=0; AdrType=ModNone; /* Datenregister 8 Bit */ if ((strlen(Asc)==3) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='1') AND ((toupper(Asc[2])=='L') OR (toupper(Asc[2])=='H'))) BEGIN AdrType=ModGen; AdrMode=((Asc[1]-'0') << 1)+Ord(toupper(Asc[2])=='H'); SetOpSize(0); ChkAdr(Mask); return; END; /* Datenregister 16 Bit */ if ((strlen(Asc)==2) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='3')) BEGIN AdrType=ModGen; AdrMode=Asc[1]-'0'; SetOpSize(1); ChkAdr(Mask); return; END /* Datenregister 32 Bit */ if (strcasecmp(Asc,"R2R0")==0) BEGIN AdrType=ModReg32; AdrMode=0; SetOpSize(2); ChkAdr(Mask); return; END; if (strcasecmp(Asc,"R3R1")==0) BEGIN AdrType=ModReg32; AdrMode=1; SetOpSize(2); ChkAdr(Mask); return; END /* Adressregister */ if ((strlen(Asc)==2) AND (toupper(*Asc)=='A') AND (Asc[1]>='0') AND (Asc[1]<='1')) BEGIN AdrType=ModGen; AdrMode=Asc[1]-'0'+4; ChkAdr(Mask); return; END /* Adressregister 32 Bit */ if (strcasecmp(Asc,"A1A0")==0) BEGIN AdrType=ModAReg32; SetOpSize(2); ChkAdr(Mask); return; END /* indirekt */ p=strchr(Asc,'['); if ((p!=Nil) AND (Asc[strlen(Asc)-1]==']')) BEGIN strmaxcpy(RegPart,p+1,255); RegPart[strlen(RegPart)-1]='\0'; if ((strcasecmp(RegPart,"A0")==0) OR (strcasecmp(RegPart,"A1")==0)) BEGIN *p='\0'; DispAcc=EvalIntExpression(Asc,((Mask & MModDisp20)==0)?Int16:Int20,&OK); if (OK) if ((DispAcc==0) AND ((Mask & MModGen)!=0)) BEGIN AdrType=ModGen; AdrMode=RegPart[1]-'0'+6; END else if ((DispAcc>=0) AND (DispAcc<=255) AND ((Mask & MModGen)!=0)) BEGIN AdrType=ModGen; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; AdrMode=RegPart[1]-'0'+8; END else if ((DispAcc>=-32768) AND (DispAcc<=65535) AND ((Mask & MModGen)!=0)) BEGIN AdrType=ModGen; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; AdrMode=RegPart[1]-'0'+12; END else if (strcasecmp(RegPart,"A0")!=0) WrError(1350); else BEGIN AdrType=ModDisp20; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrVals[2]=(DispAcc >> 16) & 0x0f; AdrCnt=3; AdrMode=RegPart[1]-'0'; END END else if (strcasecmp(RegPart,"SB")==0) BEGIN *p='\0'; DispAcc=EvalIntExpression(Asc,Int16,&OK); if (OK) if ((DispAcc>=0) AND (DispAcc<=255)) BEGIN AdrType=ModGen; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; AdrMode=10; END else BEGIN AdrType=ModGen; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; AdrMode=14; END END else if (strcasecmp(RegPart,"FB")==0) BEGIN *p='\0'; DispAcc=EvalIntExpression(Asc,SInt8,&OK); if (OK) BEGIN AdrType=ModGen; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; AdrMode=11; END END else if (strcasecmp(RegPart,"SP")==0) BEGIN *p='\0'; DispAcc=EvalIntExpression(Asc,SInt8,&OK); if (OK) BEGIN AdrType=ModSPRel; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; END END else if (strcasecmp(RegPart,"A1A0")==0) BEGIN *p='\0'; DispAcc=EvalIntExpression(Asc,SInt8,&OK); if (OK) if (DispAcc!=0) WrError(1320); else AdrType=ModIReg32; END ChkAdr(Mask); return; END /* immediate */ if (*Asc=='#') BEGIN switch (OpSize) BEGIN case -1: WrError(1132); break; case 0: AdrVals[0]=EvalIntExpression(Asc+1,Int8,&OK); if (OK) BEGIN AdrType=ModImm; AdrCnt=1; END break; case 1: DispAcc=EvalIntExpression(Asc+1,Int16,&OK); if (OK) BEGIN AdrType=ModImm; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; END break; END ChkAdr(Mask); return; END /* dann absolut */ DispAcc=EvalIntExpression(Asc,((Mask & MModAbs20)==0)?UInt16:UInt20,&OK); if ((DispAcc<=0xffff) AND ((Mask & MModGen)!=0)) BEGIN AdrType=ModGen; AdrMode=15; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; END else BEGIN AdrType=ModAbs20; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrVals[2]=(DispAcc >> 16) & 0x0f; AdrCnt=3; END ChkAdr(Mask); END static Boolean DecodeReg(char *Asc, Byte *Erg) BEGIN if (strcasecmp(Asc,"FB")==0) *Erg=7; else if (strcasecmp(Asc,"SB")==0) *Erg=6; else if ((strlen(Asc)==2) AND (toupper(*Asc)=='A') AND (Asc[1]>='0') AND (Asc[1]<='1')) *Erg=Asc[1]-'0'+4; else if ((strlen(Asc)==2) AND (toupper(*Asc)=='R') AND (Asc[1]>='0') AND (Asc[1]<='3')) *Erg=Asc[1]-'0'; else return False; return True; END static Boolean DecodeCReg(char *Asc, Byte *Erg) BEGIN if (strcasecmp(Asc,"INTBL")==0) *Erg=1; else if (strcasecmp(Asc,"INTBH")==0) *Erg=2; else if (strcasecmp(Asc,"FLG")==0) *Erg=3; else if (strcasecmp(Asc,"ISP")==0) *Erg=4; else if (strcasecmp(Asc,"SP")==0) *Erg=5; else if (strcasecmp(Asc,"SB")==0) *Erg=6; else if (strcasecmp(Asc,"FB")==0) *Erg=7; else BEGIN WrXError(1440,Asc); return False; END return True; END static void DecodeDisp(char *Asc, IntType Type1, IntType Type2, LongInt *DispAcc, Boolean *OK) BEGIN if (ArgCnt==2) *DispAcc+=EvalIntExpression(Asc,Type2,OK)*8; else *DispAcc=EvalIntExpression(Asc,Type1,OK); END static Boolean DecodeBitAdr(Boolean MayShort) BEGIN LongInt DispAcc; Boolean OK; char *Pos1; String Asc,Reg; AdrCnt=0; /* Nur 1 oder 2 Argumente zugelassen */ if ((ArgCnt<1) OR (ArgCnt>2)) BEGIN WrError(1110); return False; END /* Ist Teil 1 ein Register ? */ if ((DecodeReg(ArgStr[ArgCnt],&AdrMode))) if (AdrMode<6) BEGIN if (ArgCnt!=2) WrError(1110); else BEGIN AdrVals[0]=EvalIntExpression(ArgStr[1],UInt4,&OK); if (OK) BEGIN AdrCnt=1; return True; END END return False; END /* Bitnummer ? */ if (ArgCnt==2) BEGIN DispAcc=EvalIntExpression(ArgStr[1],UInt16,&OK); /* RMS 02: The displacement can be 16 bits */ if (NOT OK) return False; END else DispAcc=0; /* Registerangabe ? */ strmaxcpy(Asc,ArgStr[ArgCnt],255); Pos1=QuotPos(Asc,'['); /* nein->absolut */ if (Pos1==Nil) BEGIN DecodeDisp(Asc,UInt16,UInt13,&DispAcc,&OK); if ((OK) && (DispAcc<0x10000)) /* RMS 09: This is optional, it detects rollover of the bit address. */ BEGIN AdrMode=15; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; return True; END WrError(1510); /* RMS 08: Notify user there's a problem with address */ return False; END /* Register abspalten */ if (Asc[strlen(Asc)-1]!=']') BEGIN WrError(1350); return False; END *Pos1='\0'; strmaxcpy(Reg,Pos1+1,255); Reg[strlen(Reg)-1]='\0'; if ((strlen(Reg)==2) AND (toupper(*Reg)=='A') AND (Reg[1]>='0') AND (Reg[1]<='1')) BEGIN AdrMode=Reg[1]-'0'; DecodeDisp(Asc,UInt16,UInt16,&DispAcc,&OK); /* RMS 03: The offset is a full 16 bits */ if (OK) BEGIN if (DispAcc==0) AdrMode+=6; else if ((DispAcc>0) AND (DispAcc<256)) BEGIN AdrMode+=8; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; END else BEGIN AdrMode+=12; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; END return True; END WrError(1510); /* RMS 08: Notify user there's a problem with the offset */ return False; END else if (strcasecmp(Reg,"SB")==0) BEGIN DecodeDisp(Asc,UInt13,UInt16,&DispAcc,&OK); if (OK) BEGIN if ((MayShort) AND (DispAcc<0x7ff)) BEGIN AdrMode=16+(DispAcc & 7); AdrVals[0]=DispAcc >> 3; AdrCnt=1; END else if ((DispAcc>0) AND (DispAcc<256)) BEGIN AdrMode=10; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; END else BEGIN AdrMode=14; AdrVals[0]=DispAcc & 0xff; AdrVals[1]=(DispAcc >> 8) & 0xff; AdrCnt=2; END return True; END WrError(1510); /* RMS 08: Notify user there's a problem with the offset */ return False; END else if (strcasecmp(Reg,"FB")==0) BEGIN DecodeDisp(Asc,SInt5,SInt8,&DispAcc,&OK); if (OK) BEGIN AdrMode=11; AdrVals[0]=DispAcc & 0xff; AdrCnt=1; return True; END WrError(1510); /* RMS 08: Notify user there's a problem with the offset */ return False; END else BEGIN WrXError(1445,Reg); return False; END END /*------------------------------------------------------------------------*/ static Boolean CheckFormat(char *FSet) BEGIN char *p; if (strcmp(Format," ")==0) BEGIN FormatCode=0; return True; END else BEGIN p=strchr(FSet,*Format); if (p==Nil) WrError(1090); else FormatCode=p-FSet+1; return (p!=0); END END static Integer ImmVal(void) BEGIN if (OpSize==0) return (ShortInt)AdrVals[0]; else return (((Integer)AdrVals[1]) << 8)+AdrVals[0]; END static Boolean IsShort(Byte GenMode, Byte *SMode) BEGIN switch (GenMode) BEGIN case 0: *SMode=4; break; case 1: *SMode=3; break; case 10: *SMode=5; break; case 11: *SMode=6; break; case 15: *SMode=7; break; default: return False; END return True; END /*------------------------------------------------------------------------*/ static Boolean DecodePseudo(void) BEGIN return False; END static void CopyAdr(void) BEGIN AdrType2=AdrType; AdrMode2=AdrMode; AdrCnt2=AdrCnt; memcpy(AdrVals2,AdrVals,AdrCnt2); END static void CodeGen(Byte GenCode,Byte Imm1Code,Byte Imm2Code) BEGIN if (AdrType==ModImm) BEGIN BAsmCode[0]=Imm1Code+OpSize; BAsmCode[1]=Imm2Code+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); memcpy(BAsmCode+2+AdrCnt2,AdrVals,AdrCnt); END else BEGIN BAsmCode[0]=GenCode+OpSize; BAsmCode[1]=(AdrMode << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals,AdrCnt); memcpy(BAsmCode+2+AdrCnt,AdrVals2,AdrCnt2); END CodeLen=2+AdrCnt+AdrCnt2; END static Boolean CodeData(void) BEGIN Integer Num1; int z; Boolean OK; Byte SMode; if (Memo("MOV")) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("GSQZ")) BEGIN DecodeAdr(ArgStr[2],MModGen+MModSPRel); if (AdrType!=ModNone) BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModGen+MModSPRel+MModImm); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130); else BEGIN if (FormatCode==0) if ((AdrType2==ModSPRel) OR (AdrType==ModSPRel)) FormatCode=1; else if ((OpSize==0) AND (AdrType==ModImm) AND (IsShort(AdrMode2,&SMode))) FormatCode=(ImmVal()==0) ? 4 : 2; else if ((AdrType==ModImm) AND (ImmVal()>=-8) AND (ImmVal()<=7)) FormatCode=3; else if ((AdrType==ModImm) AND ((AdrMode2 & 14)==4)) FormatCode=2; else if ((OpSize==0) AND (AdrType==ModGen) AND (IsShort(AdrMode,&SMode)) AND ((AdrMode2 & 14)==4) AND ((AdrMode>=2) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=2; else if ((OpSize==0) AND (AdrType==ModGen) AND (AdrMode<=1) AND (IsShort(AdrMode2,&SMode)) AND ((AdrMode2>=2) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=2; else if ((OpSize==0) AND (AdrMode2<=1) AND (AdrType==ModGen) AND (IsShort(AdrMode,&SMode)) AND ((AdrMode>=2) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=2; else FormatCode=1; switch (FormatCode) BEGIN case 1: if (AdrType==ModSPRel) BEGIN BAsmCode[0]=0x74+OpSize; BAsmCode[1]=0xb0+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); memcpy(BAsmCode+2+AdrCnt2,AdrVals,AdrCnt); CodeLen=2+AdrCnt+AdrCnt2; END else if (AdrType2==ModSPRel) BEGIN BAsmCode[0]=0x74+OpSize; BAsmCode[1]=0x30+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); memcpy(BAsmCode+2+AdrCnt,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2+AdrCnt; END else CodeGen(0x72,0x74,0xc0); break; case 2: if (AdrType==ModImm) if (AdrType2!=ModGen) WrError(1350); else if ((AdrMode2 & 14)==4) BEGIN BAsmCode[0]=0xe2-(OpSize << 6)+((AdrMode2 & 1) << 3); memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END else if (IsShort(AdrMode2,&SMode)) if (OpSize!=0) WrError(1130); else BEGIN BAsmCode[0]=0xc0+SMode; memcpy(BAsmCode+1,AdrVals,AdrCnt); memcpy(BAsmCode+1+AdrCnt,AdrVals2,AdrCnt2); CodeLen=1+AdrCnt+AdrCnt2; END else WrError(1350); else if ((AdrType==ModGen) AND (IsShort(AdrMode,&SMode))) if (AdrType2!=ModGen) WrError(1350); else if ((AdrMode2 & 14)==4) if ((AdrMode<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x30+((AdrMode2 & 1) << 2)+(SMode & 3); memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END else if ((AdrMode2 & 14)==0) if ((AdrMode<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x08+((AdrMode2 & 1) << 2)+(SMode & 3); memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END else if (((AdrMode & 14)!=0) OR (NOT IsShort(AdrMode2,&SMode))) WrError(1350); else if ((AdrMode2<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x00+((AdrMode & 1) << 2)+(SMode & 3); memcpy(BAsmCode+1,AdrVals,AdrCnt2); CodeLen=1+AdrCnt2; END else WrError(1350); break; case 3: if (AdrType!=ModImm) WrError(1350); else BEGIN Num1=ImmVal(); if (ChkRange(Num1,-8,7)) BEGIN BAsmCode[0]=0xd8+OpSize; BAsmCode[1]=(Num1 << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END break; case 4: if (OpSize!=0) WrError(1130); else if (AdrType!=ModImm) WrError(1350); else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350); else BEGIN Num1=ImmVal(); if (ChkRange(Num1,0,0)) BEGIN BAsmCode[0]=0xb0+SMode; memcpy(BAsmCode+1,AdrVals2,AdrCnt2); CodeLen=1+AdrCnt2; END END break; END END; END; END return True; END if ((Memo("LDC")) OR (Memo("STC"))) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN if (Memo("STC")) BEGIN strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]); z=1; END else z=0; if (strcasecmp(ArgStr[2],"PC")==0) if (Memo("LDC")) WrError(1350); else BEGIN DecodeAdr(ArgStr[1],MModGen+MModReg32+MModAReg32); if (AdrType==ModAReg32) AdrMode=4; if ((AdrType==ModGen) AND (AdrMode<6)) WrError(1350); else BEGIN BAsmCode[0]=0x7c; BAsmCode[1]=0xc0+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END END else if (DecodeCReg(ArgStr[2],&SMode)) BEGIN SetOpSize(1); DecodeAdr(ArgStr[1],MModGen+(Memo("LDC")?MModImm:0)); if (AdrType==ModImm) BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=SMode << 4; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END else if (AdrType==ModGen) BEGIN BAsmCode[0]=0x7a+z; BAsmCode[1]=0x80+(SMode << 4)+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END END END return True; END if ((Memo("LDCTX")) OR (Memo("STCTX"))) BEGIN if (ArgCnt!=2) WrError(1110); else if (*AttrPart!='\0') WrError(1100); else BEGIN DecodeAdr(ArgStr[1],MModGen); if (AdrType==ModGen) if (AdrMode!=15) WrError(1350); else BEGIN memcpy(BAsmCode+2,AdrVals,AdrCnt); DecodeAdr(ArgStr[2],MModAbs20); if (AdrType==ModAbs20) BEGIN memcpy(BAsmCode+4,AdrVals,AdrCnt); BAsmCode[0]=0x7c+Ord(Memo("STCTX")); BAsmCode[1]=0xf0; CodeLen=7; END END END return True; END if ((Memo("LDE")) OR (Memo("STE"))) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN if (Memo("LDE")) BEGIN strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]); z=1; END else z=0; DecodeAdr(ArgStr[1],MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else BEGIN CopyAdr(); DecodeAdr(ArgStr[2],MModAbs20+MModDisp20+MModIReg32); if (AdrType!=ModNone) BEGIN BAsmCode[0]=0x74+OpSize; BAsmCode[1]=(z << 7)+AdrMode2; switch (AdrType) BEGIN case ModDisp20: BAsmCode[1]+=0x10; break; case ModIReg32: BAsmCode[1]+=0x20; break; END memcpy(BAsmCode+2,AdrVals2,AdrCnt2); memcpy(BAsmCode+2+AdrCnt2,AdrVals,AdrCnt); CodeLen=2+AdrCnt2+AdrCnt; END END END return True; END if (Memo("MOVA")) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN DecodeAdr(ArgStr[1],MModGen); if (AdrType!=ModNone) if (AdrMode<8) WrError(1350); else BEGIN CopyAdr(); DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) if (AdrMode>5) WrError(1350); else BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=(AdrMode << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END END return True; END for (z=0; z0) WrError(1130); else if (CheckFormat("G")) BEGIN OK=True; Num1=0; if (strcasecmp(ArgStr[2],"R0L")==0); else if (strcasecmp(ArgStr[1],"R0L")==0) Num1=1; else OK=False; if (NOT OK) WrError(1350); else BEGIN DecodeAdr(ArgStr[Num1+1],MModGen); if (AdrType!=ModNone) if (((AdrMode & 14)==4) OR ((AdrMode==0) AND (Num1==1))) WrError(1350); else BEGIN BAsmCode[0]=0x7c; BAsmCode[1]=(Num1 << 7)+(z << 4)+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END END END return True; END if ((Memo("PUSH")) OR (Memo("POP"))) BEGIN if (ArgCnt!=1) WrError(1110); else if (CheckFormat("GS")) BEGIN z=Ord(Memo("POP")); DecodeAdr(ArgStr[1],MModGen+((Memo("PUSH"))?MModImm:0)); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else BEGIN if (FormatCode==0) if ((AdrType!=ModGen)) FormatCode=1; else if ((OpSize==0) AND (AdrMode<2)) FormatCode=2; else if ((OpSize==1) AND ((AdrMode & 14)==4)) FormatCode=2; else FormatCode=1; switch (FormatCode) BEGIN case 1: if (AdrType==ModImm) BEGIN BAsmCode[0]=0x7c+OpSize; BAsmCode[1]=0xe2; END else BEGIN BAsmCode[0]=0x74+OpSize; BAsmCode[1]=0x40+(z*0x90)+AdrMode; END memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; break; case 2: if (AdrType!=ModGen) WrError(1350); else if ((OpSize==0) AND (AdrMode<2)) BEGIN BAsmCode[0]=0x82+(AdrMode << 3)+(z << 4); CodeLen=1; END else if ((OpSize==1) AND ((AdrMode & 14)==4)) BEGIN BAsmCode[0]=0xc2+((AdrMode & 1) << 3)+(z << 4); CodeLen=1; END else WrError(1350); break; END END END return True; END if ((Memo("PUSHC")) OR (Memo("POPC"))) BEGIN if (ArgCnt!=1) WrError(1110); else if (CheckFormat("G")) if (DecodeCReg(ArgStr[1],&SMode)) BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=0x02+Ord(Memo("POPC"))+(SMode << 4); CodeLen=2; END return True; END if ((Memo("PUSHM")) OR (Memo("POPM"))) BEGIN if (ArgCnt<1) WrError(1110); else BEGIN BAsmCode[1]=0; OK=True; z=1; while ((OK) AND (z<=ArgCnt)) BEGIN OK=DecodeReg(ArgStr[z],&SMode); if (OK) BEGIN BAsmCode[1]|=(1<<((Memo("POPM"))?SMode:7-SMode)); z++; END END if (NOT OK) WrXError(1440,ArgStr[z]); else BEGIN BAsmCode[0]=0xec+Ord(Memo("POPM")); CodeLen=2; END END return True; END if (Memo("PUSHA")) BEGIN if (ArgCnt!=1) WrError(1110); else if (CheckFormat("G")) BEGIN DecodeAdr(ArgStr[1],MModGen); if (AdrType!=ModNone) if (AdrMode<8) WrError(1350); else BEGIN BAsmCode[0]=0x7d; BAsmCode[1]=0x90+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END END return True; END if (Memo("XCHG")) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN DecodeAdr(ArgStr[1],MModGen); if (AdrType!=ModNone) BEGIN CopyAdr(); DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else if (AdrMode<4) BEGIN BAsmCode[0]=0x7a+OpSize; BAsmCode[1]=(AdrMode << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if (AdrMode2<4) BEGIN BAsmCode[0]=0x7a+OpSize; BAsmCode[1]=(AdrMode2 << 4)+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END else WrError(1350); END END return True; END if ((Memo("STZ")) OR (Memo("STNZ"))) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN if (OpSize==-1) OpSize++; DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) if (NOT IsShort(AdrMode,&SMode)) WrError(1350); else BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModImm); if (AdrType!=ModNone) BEGIN BAsmCode[0]=0xc8+(Ord(Memo("STNZ")) << 3)+SMode; BAsmCode[1]=AdrVals[0]; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END END return True; END if ((Memo("STZX"))) BEGIN if (ArgCnt!=3) WrError(1110); else if (CheckFormat("G")) BEGIN if (OpSize==-1) OpSize++; DecodeAdr(ArgStr[3],MModGen); if (AdrType!=ModNone) if (NOT IsShort(AdrMode,&SMode)) WrError(1350); else BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModImm); if (AdrType!=ModNone) BEGIN Num1=AdrVals[0]; DecodeAdr(ArgStr[2],MModImm); if (AdrType!=ModNone) BEGIN BAsmCode[0]=0xd8+SMode; BAsmCode[1]=Num1; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); BAsmCode[2+AdrCnt2]=AdrVals[0]; CodeLen=3+AdrCnt2; END END END END return True; END return False; END static void MakeCode_M16C(void) BEGIN Integer Num1; int z; char *p; LongInt AdrLong,Diff; Boolean OK,MayShort; Byte SMode; ShortInt OpSize2; OpSize=(-1); /* zu ignorierendes */ if (Memo("")) return; /* Formatangabe abspalten */ switch (AttrSplit) BEGIN case '.': p=strchr(AttrPart,':'); if (p!=Nil) BEGIN if (p1) WrError(1130); else BEGIN AdrLong=ImmVal(); if (FormatCode==0) if ((AdrLong>=-8) AND (AdrLong<=7)) FormatCode=2; else FormatCode=1; switch (FormatCode) BEGIN case 1: BAsmCode[0]=0x7c+OpSize; BAsmCode[1]=0xeb; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; break; case 2: if (ChkRange(AdrLong,-8,7)) BEGIN BAsmCode[0]=0x7d; BAsmCode[1]=0xb0+(AdrLong & 15); CodeLen=2; END break; END END END END else if (CheckFormat("GQS")) BEGIN DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModImm+MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130); else BEGIN if (FormatCode==0) if (AdrType==ModImm) if ((ImmVal()>=-8) AND (ImmVal()<=7)) FormatCode=2; else if ((IsShort(AdrMode2,&SMode)) AND (OpSize==0)) FormatCode=3; else FormatCode=1; else if ((OpSize==0) AND (IsShort(AdrMode,&SMode)) AND (AdrMode2<=1) AND ((AdrMode>1) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=3; else FormatCode=1; switch (FormatCode) BEGIN case 1: CodeGen(0xa0,0x76,0x40); break; case 2: if (AdrType!=ModImm) WrError(1350); else BEGIN Num1=ImmVal(); if (ChkRange(Num1,-8,7)) BEGIN BAsmCode[0]=0xc8+OpSize; BAsmCode[1]=(Num1 << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END break; case 3: if (OpSize!=0) WrError(1130); else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350); else if (AdrType==ModImm) BEGIN BAsmCode[0]=0x80+SMode; BAsmCode[1]=AdrVals[0]; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if ((AdrMode2>=2) OR (NOT IsShort(AdrMode,&SMode))) WrError(1350); else if ((AdrMode<2) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x20+((AdrMode2 & 1) << 2)+(SMode & 3); /* RMS 05: Just like #04 */ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END break; END END END END return; END if (Memo("CMP")) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("GQS")) BEGIN DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModImm+MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130); else BEGIN if (FormatCode==0) if (AdrType==ModImm) if ((ImmVal()>=-8) AND (ImmVal()<=7)) FormatCode=2; else if ((IsShort(AdrMode2,&SMode)) AND (OpSize==0)) FormatCode=3; else FormatCode=1; else if ((OpSize==0) AND (IsShort(AdrMode,&SMode)) AND (AdrMode2<=1) AND ((AdrMode>1) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=3; else FormatCode=1; switch (FormatCode) BEGIN case 1: CodeGen(0xc0,0x76,0x80); break; case 2: if (AdrType!=ModImm) WrError(1350); else BEGIN Num1=ImmVal(); if (ChkRange(Num1,-8,7)) BEGIN BAsmCode[0]=0xd0+OpSize; BAsmCode[1]=(Num1 << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END break; case 3: if (OpSize!=0) WrError(1130); else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350); else if (AdrType==ModImm) BEGIN BAsmCode[0]=0xe0+SMode; BAsmCode[1]=AdrVals[0]; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if ((AdrMode2>=2) OR (NOT IsShort(AdrMode,&SMode))) WrError(1350); else if ((AdrMode<2) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x38+((AdrMode2 & 1) << 2)+(SMode & 3); /* RMS 04: destination reg is bit 2! */ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END break; END END END END return; END if (Memo("SUB")) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("GQS")) BEGIN DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModImm+MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if ((OpSize!=0) AND (OpSize!=1)) WrError(1130); else BEGIN if (FormatCode==0) if (AdrType==ModImm) if ((ImmVal()>=-7) AND (ImmVal()<=8)) FormatCode=2; else if ((IsShort(AdrMode2,&SMode)) AND (OpSize==0)) FormatCode=3; else FormatCode=1; else if ((OpSize==0) AND (IsShort(AdrMode,&SMode)) AND (AdrMode2<=1) AND ((AdrMode>1) OR (Odd(AdrMode ^ AdrMode2)))) FormatCode=3; else FormatCode=1; switch (FormatCode) BEGIN case 1: CodeGen(0xa8,0x76,0x50); break; case 2: if (AdrType!=ModImm) WrError(1350); else BEGIN Num1=ImmVal(); if (ChkRange(Num1,-7,8)) BEGIN BAsmCode[0]=0xc8+OpSize; BAsmCode[1]=((-Num1) << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END break; case 3: if (OpSize!=0) WrError(1130); else if (NOT IsShort(AdrMode2,&SMode)) WrError(1350); else if (AdrType==ModImm) BEGIN BAsmCode[0]=0x88+SMode; BAsmCode[1]=AdrVals[0]; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if ((AdrMode2>=2) OR (NOT IsShort(AdrMode,&SMode))) WrError(1350); else if ((AdrMode<2) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x28+((AdrMode2 & 1) << 2)+(SMode & 3); /* RMS 06: just like RMS 04 */ memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END break; END END END END return; END for (z=0; z=3) AND (AdrMode<=5))) WrError(1350); else BEGIN BAsmCode[0]=0x7c; BAsmCode[1]=0x60+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END else if (OpSize==1) if (AdrMode!=0) WrError(1350); else BEGIN BAsmCode[0]=0x7c; BAsmCode[1]=0xf3; CodeLen=2; END else WrError(1130); END return; END if (Memo("NOT")) BEGIN if (ArgCnt!=1) WrError(1110); else if (CheckFormat("GS")) BEGIN DecodeAdr(ArgStr[1],MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else BEGIN if (FormatCode==0) if ((OpSize==0) AND (IsShort(AdrMode,&SMode))) FormatCode=2; else FormatCode=1; switch (FormatCode) BEGIN case 1: BAsmCode[0]=0x74+OpSize; BAsmCode[1]=0x70+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; break; case 2: if (OpSize!=0) WrError(1130); else if (NOT IsShort(AdrMode,&SMode)) WrError(1350); else BEGIN BAsmCode[0]=0xb8+SMode; memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END break; END END END return; END /* Logik*/ if ((Memo("AND")) OR (Memo("OR"))) BEGIN z=Ord(Memo("OR")); if (ArgCnt!=2) WrError(1110); else if (CheckFormat("GS")) /* RMS 01: The format codes are G and S, not G and Q */ BEGIN DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) BEGIN CopyAdr(); DecodeAdr(ArgStr[1],MModGen+MModImm); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else BEGIN if (FormatCode==0) if (AdrType==ModImm) if ((OpSize==0) AND (IsShort(AdrMode2,&SMode))) FormatCode=2; else FormatCode=1; else if ((AdrMode2<=1) AND (IsShort(AdrMode,&SMode)) AND ((AdrMode>1) OR Odd(AdrMode ^ AdrMode2))) FormatCode=2; else FormatCode=1; switch (FormatCode) BEGIN case 1: CodeGen(0x90+(z << 3),0x76,0x20+(z << 4)); break; case 2: if (OpSize!=0) WrError(1130); else if (AdrType==ModImm) if (NOT IsShort(AdrMode2,&SMode)) WrError(1350); else BEGIN BAsmCode[0]=0x90+(z << 3)+SMode; BAsmCode[1]=ImmVal(); memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if ((NOT IsShort(AdrMode,&SMode)) OR (AdrMode2>1)) WrError(1350); else if ((AdrMode<=1) AND (NOT Odd(AdrMode ^ AdrMode2))) WrError(1350); else BEGIN if (SMode==3) SMode++; BAsmCode[0]=0x10+(z << 3)+((AdrMode2 & 1) << 2)+(SMode & 3); memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; END END END END END return; END if (Memo("ROT")) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else BEGIN OpSize2=OpSize; OpSize=0; CopyAdr(); DecodeAdr(ArgStr[1],MModGen+MModImm); if (AdrType==ModGen) if (AdrMode!=3) WrError(1350); else if (AdrMode2+2*OpSize2==3) WrError(1350); else BEGIN BAsmCode[0]=0x74+OpSize2; BAsmCode[1]=0x60+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if (AdrType==ModImm) BEGIN Num1=ImmVal(); if (Num1==0) WrError(1315); else if (ChkRange(Num1,-8,8)) BEGIN if (Num1>0) Num1--; else Num1=(-9)-Num1; BAsmCode[0]=0xe0+OpSize2; BAsmCode[1]=(Num1 << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt); CodeLen=2+AdrCnt2; END END END END return; END if ((Memo("SHA")) OR (Memo("SHL"))) BEGIN if (ArgCnt!=2) WrError(1110); else if (CheckFormat("G")) BEGIN z=Ord(Memo("SHA")); DecodeAdr(ArgStr[2],MModGen+MModReg32); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if ((OpSize>2) OR ((OpSize==2) AND (AdrType==ModGen))) WrError(1130); else BEGIN CopyAdr(); OpSize2=OpSize; OpSize=0; DecodeAdr(ArgStr[1],MModImm+MModGen); if (AdrType==ModGen) if (AdrMode!=3) WrError(1350); else if (AdrMode2*2+OpSize2==3) WrError(1350); else BEGIN if (OpSize2==2) BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=0x01+(AdrMode2 << 4)+(z << 5); END else BEGIN BAsmCode[0]=0x74+OpSize2; BAsmCode[1]=0xe0+(z << 4)+AdrMode2; END memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END else if (AdrType==ModImm) BEGIN Num1=ImmVal(); if (Num1==0) WrError(1315); else if (ChkRange(Num1,-8,8)) BEGIN if (Num1>0) Num1--; else Num1=(-9)-Num1; if (OpSize2==2) BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=0x80+(AdrMode2 << 4)+(z << 5)+(Num1 & 15); END else BEGIN BAsmCode[0]=0xe8+(z << 3)+OpSize2; BAsmCode[1]=(Num1 << 4)+AdrMode2; END memcpy(BAsmCode+2,AdrVals2,AdrCnt2); CodeLen=2+AdrCnt2; END END END END return; END /* Bitoperationen */ for (z=0; z=16) BEGIN BAsmCode[0]=0x40+((BitOrders[z].Code-8) << 3)+(AdrMode & 7); BAsmCode[1]=AdrVals[0]; CodeLen=2; END else BEGIN BAsmCode[0]=0x7e; BAsmCode[1]=(BitOrders[z].Code << 4)+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END return; END if (strncmp(OpPart,"BM",2)==0) for (z=0; z=4) AND (z<12)) z^=12; if (z>=8) z+=0xf0; BAsmCode[2+AdrCnt]=z; CodeLen=3+AdrCnt; END return; END if ((Memo("FCLR")) OR (Memo("FSET"))) BEGIN if (ArgCnt!=1) WrError(1110); else if (strlen(ArgStr[1])!=1) WrError(1350); else BEGIN p=strchr(Flags,toupper(*ArgStr[1])); if (p==Nil) WrXError(1440,ArgStr[1]); else BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=0x04+Ord(Memo("FCLR"))+((p-Flags) << 4); CodeLen=2; END END return; END /* Spruenge */ if (Memo("JMP")) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN FirstPassUnknown=False; /* RMS 12: Mod to allow JMP.S to work */ AdrLong=EvalIntExpression(ArgStr[1],UInt20,&OK); Diff=AdrLong-EProgCounter(); /* RMS 12: Repaired JMP.S forward-label as follows: If it's an unknown symbol, make PC+2 the "safe" value, otherwise the user will get OUT OF RANGE errors on every attempt to use JMP.S Since the instruction can only branch forward, and AS stuffs the PC back for a "temp" forward reference value, the range-checking will always fail. One side-effect also is that for auto-determination purposes, one fewer pass is needed. Before, the first pass would signal JMP.B, then once the forward reference is known, it'd signal JMP.S, which would cause a "phase error" forcing another pass. */ if ( (FirstPassUnknown) AND (Diff == 0) ) Diff = 2; if (OpSize==-1) BEGIN if ((Diff>=2) AND (Diff<=9)) OpSize=4; else if ((Diff>=-127) AND (Diff<=128)) OpSize=0; else if ((Diff>=-32767) AND (Diff<=32768)) OpSize=1; else OpSize=7; END /* The following code is to deal with a silicon bug in the first generation of M16C CPUs (the so-called M16C/60 group). It has been observed that this silicon bug has been fixed as of the M16C/61, so we disable JMP.S promotion to JMP.B when the target crosses a 64k boundary for those CPUs. Since M16C is a "generic" specification, we do JMP.S promotion for that CPU specification, as follows: RMS 11: According to Mitsubishi App Note M16C-06-9612 JMP.S cannot cross a 64k boundary.. so trim up to JMP.B It is admittedly a very low likelihood of occurrence [JMP.S has only 8 possible targets, being a 3 bit "jump addressing mode"], but since the occurrence of this bug could cause such evil debugging issues, I have taken the liberty of addressing it in the assembler. Heck, it's JUST one extra byte. One byte's worth the peace of mind, isn't it? :) */ if (!( ( strcmp(MomCPUIdent,"M16C") ) && ( strcmp(MomCPUIdent,"M30600M8")))) if (OpSize == 4) BEGIN if ( (AdrLong & 0x0f0000) != (EProgCounter() & 0x0f0000) ) OpSize = 0; END /* NOTE! This not an ASX bug, but rather in the CPU!! */ switch (OpSize) BEGIN case 4: if (((Diff<2) OR (Diff>9)) AND (NOT SymbolQuestionable) ) WrError(1370); else BEGIN BAsmCode[0]=0x60+((Diff-2) & 7); CodeLen=1; END break; case 0: if (((Diff<-127) OR (Diff>128)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=0xfe; BAsmCode[1]=(Diff-1) & 0xff; CodeLen=2; END break; case 1: if (((Diff<-32767) OR (Diff>32768)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=0xf4; Diff--; BAsmCode[1]=Diff & 0xff; BAsmCode[2]=(Diff >> 8) & 0xff; CodeLen=3; END break; case 7: BAsmCode[0]=0xfc; BAsmCode[1]=AdrLong & 0xff; BAsmCode[2]=(AdrLong >> 8) & 0xff; BAsmCode[3]=(AdrLong >> 16) & 0xff; CodeLen=4; break; default: WrError(1130); END END return; END if (Memo("JSR")) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN AdrLong=EvalIntExpression(ArgStr[1],UInt20,&OK); Diff=AdrLong-EProgCounter(); if (OpSize==-1) BEGIN if ((Diff>=-32767) AND (Diff<=32768)) OpSize=1; else OpSize=7; END switch (OpSize) BEGIN case 1: if (((Diff<-32767) OR (Diff>32768)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=0xf5; Diff--; BAsmCode[1]=Diff & 0xff; BAsmCode[2]=(Diff >> 8) & 0xff; CodeLen=3; END break; case 7: BAsmCode[0]=0xfd; BAsmCode[1]=AdrLong & 0xff; BAsmCode[2]=(AdrLong >> 8) & 0xff; BAsmCode[3]=(AdrLong >> 16) & 0xff; CodeLen=4; break; default: WrError(1130); END END return; END if ((Memo("JMPI")) OR (Memo("JSRI"))) BEGIN if (ArgCnt!=1) WrError(1110); else if (CheckFormat("G")) BEGIN if (OpSize==7) OpSize=2; DecodeAdr(ArgStr[1],MModGen+MModDisp20+MModReg32+MModAReg32); if ((AdrType==ModGen) AND ((AdrMode & 14)==12)) AdrVals[AdrCnt++]=0; if ((AdrType==ModGen) AND ((AdrMode & 14)==4)) if (OpSize==-1) OpSize=1; else if (OpSize!=1) BEGIN AdrType=ModNone; WrError(1131); END if (AdrType==ModAReg32) AdrMode=4; if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if ((OpSize!=1) AND (OpSize!=2)) WrError(1130); else BEGIN BAsmCode[0]=0x7d; BAsmCode[1]=(Ord(Memo("JSRI")) << 4)+(Ord(OpSize==1) << 5)+AdrMode; memcpy(BAsmCode+2,AdrVals,AdrCnt); CodeLen=2+AdrCnt; END END return; END if ((Memo("JMPS")) OR (Memo("JSRS"))) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN OpSize=0; FirstPassUnknown=False; DecodeAdr(ArgStr[1],MModImm); if ((FirstPassUnknown) AND (AdrVals[0]<18)) AdrVals[0]=18; if (AdrType!=ModNone) if (AdrVals[0]<18) WrError(1315); else BEGIN BAsmCode[0]=0xee + Ord(Memo("JSRS")); /* ANSI :-O */ BAsmCode[1]=AdrVals[0]; CodeLen=2; END END return; END if (*OpPart=='J') for (z=0; z=8); if (ArgCnt!=1) WrError(1110); else if (*AttrPart!='\0') WrError(1100); else if (strcmp(Format," ")!=0) WrError(1090); else BEGIN AdrLong=EvalIntExpression(ArgStr[1],UInt20,&OK)-(EProgCounter()+Num1); if (OK) if ((NOT SymbolQuestionable) AND ((AdrLong>127) OR (AdrLong<-128))) WrError(1370); else if (Conditions[z].Code>=8) BEGIN BAsmCode[0]=0x7d; BAsmCode[1]=0xc0+Conditions[z].Code; BAsmCode[2]=AdrLong & 0xff; CodeLen=3; END else BEGIN BAsmCode[0]=0x68+Conditions[z].Code; BAsmCode[1]=AdrLong & 0xff; CodeLen=2; END END return; END if ((Memo("ADJNZ")) OR (Memo("SBJNZ"))) BEGIN if (ArgCnt!=3) WrError(1110); else if (CheckFormat("G")) BEGIN DecodeAdr(ArgStr[2],MModGen); if (AdrType!=ModNone) if (OpSize==-1) WrError(1132); else if (OpSize>1) WrError(1130); else BEGIN CopyAdr(); OpSize2=OpSize; OpSize=0; FirstPassUnknown=False; DecodeAdr(ArgStr[1],MModImm); Num1=ImmVal(); if (FirstPassUnknown) Num1=0; if (Memo("SBJNZ")) Num1=(-Num1); if (ChkRange(Num1,-8,7)) BEGIN AdrLong=EvalIntExpression(ArgStr[3],UInt20,&OK)-(EProgCounter()+2); if (OK) if (((AdrLong<-128) OR (AdrLong>127)) AND (NOT SymbolQuestionable)) WrError(1370); else BEGIN BAsmCode[0]=0xf8+OpSize2; BAsmCode[1]=(Num1 << 4)+AdrMode2; memcpy(BAsmCode+2,AdrVals2,AdrCnt2); BAsmCode[2+AdrCnt2]=AdrLong & 0xff; CodeLen=3+AdrCnt2; END END END END return; END if (Memo("INT")) BEGIN if (ArgCnt!=1) WrError(1110); else if (*AttrPart!='\0') WrError(1100); else if (*ArgStr[1]!='#') WrError(1350); else BEGIN BAsmCode[1]=0xc0+EvalIntExpression(ArgStr[1]+1,UInt6,&OK); if (OK) BEGIN BAsmCode[0]=0xeb; CodeLen=2; END END return; END /* Miszellaneen */ if (Memo("ENTER")) BEGIN if (ArgCnt!=1) WrError(1110); else if (*AttrPart!='\0') WrError(1100); else if (*ArgStr[1]!='#') WrError(1350); else BEGIN BAsmCode[2]=EvalIntExpression(ArgStr[1]+1,UInt8,&OK); if (OK) BEGIN BAsmCode[0]=0x7c; BAsmCode[1]=0xf2; CodeLen=3; END END return; END if (Memo("LDINTB")) BEGIN if (ArgCnt!=1) WrError(1110); else if (*AttrPart!='\0') WrError(1100); else if (*ArgStr[1]!='#') WrError(1350); else BEGIN AdrLong=EvalIntExpression(ArgStr[1]+1,UInt20,&OK); if (OK) BEGIN BAsmCode[0]=0xeb; BAsmCode[1]=0x20; BAsmCode[2]=(AdrLong >> 16) & 0xff; BAsmCode[3]=0; BAsmCode[4]=0xeb; BAsmCode[5]=0x10; BAsmCode[7]=(AdrLong >> 8) & 0xff; BAsmCode[6]=AdrLong & 0xff; /* RMS 07: needs to be LSB, MSB order */ CodeLen=8; END END return; END if (Memo("LDIPL")) BEGIN if (ArgCnt!=1) WrError(1110); else if (*AttrPart!='\0') WrError(1100); else if (*ArgStr[1]!='#') WrError(1350); else BEGIN BAsmCode[1]=0xa0+EvalIntExpression(ArgStr[1]+1,UInt3,&OK); if (OK) BEGIN BAsmCode[0]=0x7d; CodeLen=2; END END return; END WrXError(1200,OpPart); END static Boolean IsDef_M16C(void) BEGIN return False; END static void SwitchFrom_M16C(void) BEGIN DeinitFields(); END static void SwitchTo_M16C(void) BEGIN TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False; PCSymbol="$"; HeaderID=0x14; NOPCode=0x04; DivideChars=","; HasAttrs=True; AttrChars=".:"; ValidSegs=1<