/* code96.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator MCS/96-Familie */ /* */ /* Historie: 10.11.1996 */ /* 16. 3.1997 80196N/80296 */ /* 3. 1.1999 ChkPC-Anpassung */ /* */ /*****************************************************************************/ #include "stdinc.h" #include #include "bpemu.h" #include "asmdef.h" #include "asmsub.h" #include "asmpars.h" #include "codepseudo.h" #include "codevars.h" typedef struct { char *Name; Byte Code; } FixedOrder; typedef struct { char *Name; Byte Code; CPUVar MinCPU,MaxCPU; } BaseOrder; typedef struct { char *Name; Byte Code; Boolean Reloc; } MacOrder; #define FixedOrderCnt 16 #define ALU3OrderCnt 5 #define ALU2OrderCnt 9 #define ALU1OrderCnt 6 #define ShiftOrderCnt 3 #define RelOrderCnt 16 #define MacOrderCnt 8 #define RptOrderCnt 34 static char *ShiftOrders[ShiftOrderCnt]={"SHR","SHL","SHRA"}; #define ModNone (-1) #define ModDir 0 #define MModDir (1 << ModDir) #define ModMem 1 #define MModMem (1 << ModMem) #define ModImm 2 #define MModImm (1 << ModImm) #define SFRStart 2 #define SFRStop 0x17 static BaseOrder *FixedOrders; static FixedOrder *ALU3Orders; static FixedOrder *ALU2Orders; static FixedOrder *ALU1Orders; static FixedOrder *RelOrders; static MacOrder *MacOrders; static FixedOrder *RptOrders; static CPUVar CPU8096,CPU80196,CPU80196N,CPU80296; static SimpProc SaveInitProc; static Byte AdrMode; static ShortInt AdrType; static Byte AdrVals[4]; static ShortInt OpSize; static LongInt WSRVal,WSR1Val; static Word WinStart,WinStop,WinEnd,WinBegin; static Word Win1Start,Win1Stop,Win1Begin,Win1End; IntType MemInt; /*---------------------------------------------------------------------------*/ static void AddFixed(char *NName, Byte NCode, CPUVar NMin, CPUVar NMax) BEGIN if (InstrZ>=FixedOrderCnt) exit(255); FixedOrders[InstrZ].Name=NName; FixedOrders[InstrZ].Code=NCode; FixedOrders[InstrZ].MinCPU=NMin; FixedOrders[InstrZ++].MaxCPU=NMax; END static void AddALU3(char *NName, Byte NCode) BEGIN if (InstrZ>=ALU3OrderCnt) exit(255); ALU3Orders[InstrZ].Name=NName; ALU3Orders[InstrZ++].Code=NCode; END static void AddALU2(char *NName, Byte NCode) BEGIN if (InstrZ>=ALU2OrderCnt) exit(255); ALU2Orders[InstrZ].Name=NName; ALU2Orders[InstrZ++].Code=NCode; END static void AddALU1(char *NName, Byte NCode) BEGIN if (InstrZ>=ALU1OrderCnt) exit(255); ALU1Orders[InstrZ].Name=NName; ALU1Orders[InstrZ++].Code=NCode; END static void AddRel(char *NName, Byte NCode) BEGIN if (InstrZ>=RelOrderCnt) exit(255); RelOrders[InstrZ].Name=NName; RelOrders[InstrZ++].Code=NCode; END static void AddMac(char *NName, Byte NCode, Boolean NRel) BEGIN if (InstrZ>=MacOrderCnt) exit(255); MacOrders[InstrZ].Name=NName; MacOrders[InstrZ].Code=NCode; MacOrders[InstrZ++].Reloc=NRel; END static void AddRpt(char *NName, Byte NCode) BEGIN if (InstrZ>=RptOrderCnt) exit(255); RptOrders[InstrZ].Name=NName; RptOrders[InstrZ++].Code=NCode; END static void InitFields(void) BEGIN FixedOrders=(BaseOrder *) malloc(sizeof(BaseOrder)*FixedOrderCnt); InstrZ=0; AddFixed("CLRC" ,0xf8,CPU8096 ,CPU80296 ); AddFixed("CLRVT",0xfc,CPU8096 ,CPU80296 ); AddFixed("DI" ,0xfa,CPU8096 ,CPU80296 ); AddFixed("DPTS" ,0xea,CPU80196 ,CPU80196N); AddFixed("EI" ,0xfb,CPU8096 ,CPU80296 ); AddFixed("EPTS" ,0xeb,CPU80196 ,CPU80196N); AddFixed("NOP" ,0xfd,CPU8096 ,CPU80296 ); AddFixed("POPA" ,0xf5,CPU80196 ,CPU80296 ); AddFixed("POPF" ,0xf3,CPU8096 ,CPU80296 ); AddFixed("PUSHA",0xf4,CPU80196 ,CPU80296 ); AddFixed("PUSHF",0xf2,CPU8096 ,CPU80296 ); AddFixed("RET" ,0xf0,CPU8096 ,CPU80296 ); AddFixed("RSC" ,0xff,CPU8096 ,CPU80296 ); AddFixed("SETC" ,0xf9,CPU8096 ,CPU80296 ); AddFixed("TRAP" ,0xf7,CPU8096 ,CPU80296 ); AddFixed("RETI" ,0xe5,CPU80196N,CPU80296 ); ALU3Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU3OrderCnt); InstrZ=0; AddALU3("ADD" , 0x01); AddALU3("AND" , 0x00); AddALU3("MUL" , 0x83); /* ** */ AddALU3("MULU", 0x03); AddALU3("SUB" , 0x02); ALU2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU2OrderCnt); InstrZ=0; AddALU2("ADDC", 0xa4); AddALU2("CMP" , 0x88); AddALU2("DIV" , 0x8c); /* ** */ AddALU2("DIVU", 0x8c); AddALU2("LD" , 0xa0); AddALU2("OR" , 0x80); AddALU2("ST" , 0xc0); AddALU2("SUBC", 0xa8); AddALU2("XOR" , 0x84); ALU1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*ALU1OrderCnt); InstrZ=0; AddALU1("CLR", 0x01); AddALU1("DEC", 0x05); AddALU1("EXT", 0x06); AddALU1("INC", 0x07); AddALU1("NEG", 0x03); AddALU1("NOT", 0x02); RelOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RelOrderCnt); InstrZ=0; AddRel("JC" , 0xdb); AddRel("JE" , 0xdf); AddRel("JGE" , 0xd6); AddRel("JGT" , 0xd2); AddRel("JH" , 0xd9); AddRel("JLE" , 0xda); AddRel("JLT" , 0xde); AddRel("JNC" , 0xd3); AddRel("JNE" , 0xd7); AddRel("JNH" , 0xd1); AddRel("JNST" , 0xd0); AddRel("JNV" , 0xd5); AddRel("JNVT" , 0xd4); AddRel("JST" , 0xd8); AddRel("JV" , 0xdd); AddRel("JVT" , 0xdc); MacOrders=(MacOrder *) malloc(sizeof(MacOrder)*MacOrderCnt); InstrZ=0; AddMac("MAC" ,0x00,False); AddMac("SMAC" ,0x01,False); AddMac("MACR" ,0x04,True ); AddMac("SMACR" ,0x05,True ); AddMac("MACZ" ,0x08,False); AddMac("SMACZ" ,0x09,False); AddMac("MACRZ" ,0x0c,True ); AddMac("SMACRZ",0x0d,True ); RptOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RptOrderCnt); InstrZ=0; AddRpt("RPT" ,0x00); AddRpt("RPTNST" ,0x10); AddRpt("RPTNH" ,0x11); AddRpt("RPTGT" ,0x12); AddRpt("RPTNC" ,0x13); AddRpt("RPTNVT" ,0x14); AddRpt("RPTNV" ,0x15); AddRpt("RPTGE" ,0x16); AddRpt("RPTNE" ,0x17); AddRpt("RPTST" ,0x18); AddRpt("RPTH" ,0x19); AddRpt("RPTLE" ,0x1a); AddRpt("RPTC" ,0x1b); AddRpt("RPTVT" ,0x1c); AddRpt("RPTV" ,0x1d); AddRpt("RPTLT" ,0x1e); AddRpt("RPTE" ,0x1f); AddRpt("RPTI" ,0x20); AddRpt("RPTINST",0x30); AddRpt("RPTINH" ,0x31); AddRpt("RPTIGT" ,0x32); AddRpt("RPTINC" ,0x33); AddRpt("RPTINVT",0x34); AddRpt("RPTINV" ,0x35); AddRpt("RPTIGE" ,0x36); AddRpt("RPTINE" ,0x37); AddRpt("RPTIST" ,0x38); AddRpt("RPTIH" ,0x39); AddRpt("RPTILE" ,0x3a); AddRpt("RPTIC" ,0x3b); AddRpt("RPTIVT" ,0x3c); AddRpt("RPTIV" ,0x3d); AddRpt("RPTILT" ,0x3e); AddRpt("RPTIE" ,0x3f); END static void DeinitFields(void) BEGIN free(FixedOrders); free(ALU3Orders); free(ALU2Orders); free(ALU1Orders); free(RelOrders); free(MacOrders); free(RptOrders); END /*-------------------------------------------------------------------------*/ static void ChkSFR(Word Adr) BEGIN if ((Adr>=SFRStart) & (Adr<=SFRStop)) WrError(190); END static void Chk296(Word Adr) BEGIN if ((MomCPU==CPU80296) AND (Adr<=1)) WrError(190); END static Boolean ChkWork(Word *Adr) BEGIN /* Registeradresse, die von Fenstern ueberdeckt wird ? */ if ((*Adr>=WinBegin) AND (*Adr<=WinEnd)) return False; else if ((*Adr>=Win1Begin) AND (*Adr<=Win1End)) return False; /* Speicheradresse in Fenster ? */ else if ((*Adr>=WinStart) AND (*Adr<=WinStop)) BEGIN *Adr=(*Adr)-WinStart+WinBegin; return True; END else if ((*Adr>=Win1Start) AND (*Adr<=Win1Stop)) BEGIN *Adr=(*Adr)-Win1Start+Win1Begin; return True; END /* Default */ else return (*Adr<=0xff); END static void ChkAlign(Byte Adr) BEGIN if (((OpSize==0) AND ((Adr & 1)!=0)) OR ((OpSize==1) AND ((Adr & 3)!=0))) WrError(180); END static void ChkAdr(Byte Mask) BEGIN if ((AdrType==ModDir) AND ((Mask & MModDir)==0)) BEGIN AdrType=ModMem; AdrMode=0; END if ((AdrType!=ModNone) AND ((Mask & (1 << AdrType))==0)) BEGIN WrError(1350); AdrType=ModNone; AdrCnt=0; END END static void DecodeAdr(char *Asc, Byte Mask, Boolean AddrWide) BEGIN LongInt AdrInt; LongWord AdrWord; Word BReg; Boolean OK; char *p,*p2; int l; Byte Reg; LongWord OMask; AdrType=ModNone; AdrCnt=0; OMask=(1 << OpSize)-1; 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; AdrMode=1; END break; case 1: AdrWord=EvalIntExpression(Asc+1,Int16,&OK); if (OK) BEGIN AdrType=ModImm; AdrCnt=2; AdrMode=1; AdrVals[0]=Lo(AdrWord); AdrVals[1]=Hi(AdrWord); END break; END ChkAdr(Mask); return; END p=QuotPos(Asc,'['); if (p!=Nil) BEGIN p2=RQuotPos(Asc,']'); l=strlen(Asc); if ((p2>Asc+l-1) OR (p2> 8) & 0xff; AdrVals[3]=(AdrInt >> 16) & 0xff; END else if ((AdrInt>=-128) AND (AdrInt<127)) BEGIN AdrType=ModMem; AdrMode=3; AdrCnt=2; AdrVals[0]=Reg; AdrVals[1]=Lo(AdrInt); END else BEGIN AdrType=ModMem; AdrMode=3; AdrCnt=3; AdrVals[0]=Reg+1; AdrVals[1]=Lo(AdrInt); AdrVals[2]=Hi(AdrInt); END END END END END else BEGIN FirstPassUnknown=False; AdrWord=EvalIntExpression(Asc,MemInt,&OK); if (FirstPassUnknown) AdrWord&=(0xffffffff-OMask); if (OK) if ((AdrWord & OMask)!=0) WrError(1325); else BEGIN BReg=AdrWord & 0xffff; if (((BReg & 0xffff0000)==0) AND (ChkWork(&BReg))) BEGIN AdrType=ModDir; AdrCnt=1; AdrVals[0]=Lo(BReg); END else if (AddrWide) BEGIN AdrType=ModMem; AdrMode=3; AdrCnt=4; AdrVals[0]=0; AdrVals[1]=AdrWord & 0xff; AdrVals[2]=(AdrWord >> 8) & 0xff; AdrVals[3]=(AdrWord >> 16) & 0xff; END else if (AdrWord>=0xff80) BEGIN AdrType=ModMem; AdrMode=3; AdrCnt=2; AdrVals[0]=0; AdrVals[1]=Lo(AdrWord); END else BEGIN AdrType=ModMem; AdrMode=3; AdrCnt=3; AdrVals[0]=1; AdrVals[1]=Lo(AdrWord); AdrVals[2]=Hi(AdrWord); END END END ChkAdr(Mask); END static void CalcWSRWindow(void) BEGIN if (WSRVal<=0x0f) BEGIN WinStart=0xffff; WinStop=0; WinBegin=0xff; WinEnd=0; END else if (WSRVal<=0x1f) BEGIN WinBegin=0x80; WinEnd=0xff; if (WSRVal<0x18) WinStart=(WSRVal-0x10) << 7; else WinStart=(WSRVal+0x20) << 7; WinStop=WinStart+0x7f; END else if (WSRVal<=0x3f) BEGIN WinBegin=0xc0; WinEnd=0xff; if (WSRVal<0x30) WinStart=(WSRVal-0x20) << 6; else WinStart=(WSRVal+0x40) << 6; WinStop=WinStart+0x3f; END else if (WSRVal<=0x7f) BEGIN WinBegin=0xe0; WinEnd=0xff; if (WSRVal<0x60) WinStart=(WSRVal-0x40) << 5; else WinStart=(WSRVal+0x80) << 5; WinStop=WinStart+0x1f; END if ((WinStop>0x1fdf) AND (MomCPU=CPU80296)?ASSUME96Count:1); WSRVal&=0x7f; CalcWSRWindow(); CalcWSR1Window(); return True; END return False; END static Boolean BMemo(char *Name) BEGIN int l; if (strncmp(OpPart,Name,l=strlen(Name))!=0) return False; switch (OpPart[l]) BEGIN case '\0': OpSize=1; return True; case 'B': if (OpPart[l+1]=='\0') BEGIN OpSize=0; return True; END else return False; default: return False; END END static Boolean LMemo(char *Name) BEGIN int l; if (strncmp(OpPart,Name,l=strlen(Name))!=0) return False; switch (OpPart[l]) BEGIN case '\0': OpSize=1; return True; case 'B': if (OpPart[l+1]=='\0') BEGIN OpSize=0; return True; END else return False; case 'L': if (OpPart[l+1]=='\0') BEGIN OpSize=2; return True; END else return False; default: return False; END END static void MakeCode_96(void) BEGIN Boolean OK,Special,IsShort; Word AdrWord; int z; LongInt AdrInt; Byte Start,HReg,Mask; CodeLen=0; DontPrint=False; OpSize=(-1); /* zu ignorierendes */ if (Memo("")) return; /* Pseudoanweisungen */ if (DecodePseudo()) return; if (DecodeIntelPseudo(False)) return; /* ohne Argument */ for (z=0; z15)) WrError(1320); else if ((AdrType==ModDir) AND (AdrVals[0]<16)) WrError(1315); else BEGIN BAsmCode[1]=AdrVals[0]; CodeLen=3; END END END return; END if (Memo("SKIP")) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN OpSize=0; DecodeAdr(ArgStr[1],MModDir,False); if (AdrType!=ModNone) BEGIN CodeLen=2; BAsmCode[0]=0; BAsmCode[1]=AdrVals[0]; END END return; END if ((BMemo("ELD")) OR (BMemo("EST"))) BEGIN if (ArgCnt!=2) WrError(1110); else if (MomCPU31) WrError(1320); else CodeLen=3; break; case ModDir: if (AdrVals[0]<32) WrError(1315); else CodeLen=3; END END END return; END for (z=0; z127))) WrError(1370); else BEGIN CodeLen=2; BAsmCode[0]=RelOrders[z].Code; BAsmCode[1]=AdrInt & 0xff; END END return; END if ((Memo("SCALL")) OR (Memo("LCALL")) OR (Memo("CALL"))) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN AdrWord=EvalIntExpression(ArgStr[1],MemInt,&OK); if (OK) BEGIN AdrInt=AdrWord-(EProgCounter()+2); if (Memo("SCALL")) IsShort=True; else if (Memo("LCALL")) IsShort=False; else IsShort=((AdrInt>=-1024) AND (AdrInt<1023)); if (IsShort) BEGIN if ((NOT SymbolQuestionable) AND ((AdrInt<-1024) OR (AdrInt>1023))) WrError(1370); else BEGIN CodeLen=2; BAsmCode[1]=AdrInt & 0xff; BAsmCode[0]=0x28+((AdrInt & 0x700) >> 8); END END else BEGIN CodeLen=3; BAsmCode[0]=0xef; AdrInt--; BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt); if ((NOT SymbolQuestionable) AND (AdrInt>=-1024) AND (AdrInt<=1023)) WrError(20); END END END return; END if ((Memo("BR")) OR (Memo("LJMP")) OR (Memo("SJMP"))) BEGIN OpSize=1; if (ArgCnt!=1) WrError(1110); else if ((Memo("BR")) AND (QuotPos(ArgStr[1],'[')!=Nil)) BEGIN DecodeAdr(ArgStr[1],MModMem,False); if (AdrType!=ModNone) if ((AdrMode!=2) OR ((AdrVals[0]&1)==1)) WrError(1350); else BEGIN CodeLen=2; BAsmCode[0]=0xe3; BAsmCode[1]=AdrVals[0]; END END else BEGIN AdrWord=EvalIntExpression(ArgStr[1],MemInt,&OK); if (OK) BEGIN AdrInt=AdrWord-(EProgCounter()+2); if (Memo("SJMP")) IsShort=True; else if (Memo("LJMP")) IsShort=False; else IsShort=((AdrInt>=-1024) AND (AdrInt<1023)); if (IsShort) BEGIN if ((NOT SymbolQuestionable) AND ((AdrInt<-1024) OR (AdrInt>1023))) WrError(1370); else BEGIN CodeLen=2; BAsmCode[1]=AdrInt & 0xff; BAsmCode[0]=0x20+((AdrInt & 0x700) >> 8); END END else BEGIN CodeLen=3; BAsmCode[0]=0xe7; AdrInt--; BAsmCode[1]=Lo(AdrInt); BAsmCode[2]=Hi(AdrInt); if ((NOT SymbolQuestionable) AND (AdrInt>=-1024) AND (AdrInt<=1023)) WrError(20); END END END return; END if (Memo("TIJMP")) BEGIN if (ArgCnt!=3) WrError(1110); else if (MomCPU127))) WrError(1370); else BEGIN CodeLen=3; BAsmCode[2]=AdrInt & 0xff; END END END return; END if ((Memo("JBC")) OR (Memo("JBS"))) BEGIN if (ArgCnt!=3) WrError(1110); else BEGIN BAsmCode[0]=EvalIntExpression(ArgStr[2],UInt3,&OK); if (OK) BEGIN BAsmCode[0]+=0x30+(Ord(Memo("JBS")) << 3); OpSize=0; DecodeAdr(ArgStr[1],MModDir,False); if (AdrType!=ModNone) BEGIN BAsmCode[1]=AdrVals[0]; AdrInt=EvalIntExpression(ArgStr[3],MemInt,&OK)-(EProgCounter()+3); if (OK) if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370); else BEGIN CodeLen=3; BAsmCode[2]=AdrInt & 0xff; END END END END return; END if (Memo("ECALL")) BEGIN if (ArgCnt!=1) WrError(1110); else if (MomCPU> 8) & 0xff; BAsmCode[3]=(AdrInt >> 16) & 0xff; CodeLen=4; END END return; END if ((Memo("EJMP")) OR (Memo("EBR"))) BEGIN OpSize=1; if (ArgCnt!=1) WrError(1110); else if (MomCPU> 8) & 0xff; BAsmCode[3]=(AdrInt >> 16) & 0xff; CodeLen=4; END END return; END WrXError(1200,OpPart); END static void InitCode_96(void) BEGIN SaveInitProc(); WSRVal=0; CalcWSRWindow(); WSR1Val=0; CalcWSR1Window(); END static Boolean IsDef_96(void) BEGIN return False; END static void SwitchFrom_96(void) BEGIN DeinitFields(); END static void SwitchTo_96(void) BEGIN TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False; PCSymbol="$"; HeaderID=0x39; NOPCode=0xfd; DivideChars=","; HasAttrs=False; ValidSegs=1<= CPU80196N) ? 0xffffffl : 0xffff; MakeCode=MakeCode_96; IsDef=IsDef_96; SwitchFrom=SwitchFrom_96; if (MomCPU>=CPU80196N) MemInt=UInt24; else MemInt=UInt16; InitFields(); END void code96_init(void) BEGIN CPU8096 =AddCPU("8096" ,SwitchTo_96); CPU80196 =AddCPU("80196" ,SwitchTo_96); CPU80196N=AddCPU("80196N",SwitchTo_96); CPU80296 =AddCPU("80296" ,SwitchTo_96); SaveInitProc=InitPassProc; InitPassProc=InitCode_96; END