/* codest9.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator SGS-Thomson ST9 */ /* */ /* Historie: 10. 2.1997 Grundsteinlegung */ /* 1. 7.1998 Warnungen bei is...()-Funktionen beseitigt */ /* 2. 1.1999 ChkPC umgestellt */ /* 30. 1.1999 Formate maschinenunabhaengig gemacht */ /* */ /*****************************************************************************/ #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" typedef struct { char *Name; Word Code; } FixedOrder; typedef struct { char *Name; int len; Word Code; } ALUOrder; #define WorkOfs 0xd0 #define ModNone (-1) #define ModReg 0 #define MModReg (1l << ModReg) /* Rn */ #define ModWReg 1 #define MModWReg (1l << ModWReg) /* rn */ #define ModRReg 2 #define MModRReg (1l << ModRReg) /* RRn */ #define ModWRReg 3 #define MModWRReg (1l << ModWRReg) /* rrn */ #define ModIReg 4 #define MModIReg (1l << ModIReg) /* (Rn) */ #define ModIWReg 5 #define MModIWReg (1l << ModIWReg) /* (rn) */ #define ModIRReg 6 #define MModIRReg (1l << ModIRReg) /* (RRn) */ #define ModIWRReg 7 #define MModIWRReg (1l << ModIWRReg) /* (rrn) */ #define ModIncWReg 8 #define MModIncWReg (1l << ModIncWReg) /* (rn)+ */ #define ModIncWRReg 9 #define MModIncWRReg (1l << ModIncWRReg) /* (rrn)+ */ #define ModDecWRReg 10 #define MModDecWRReg (1l << ModDecWRReg) /* -(rrn) */ #define ModDisp8WReg 11 #define MModDisp8WReg (1l << ModDisp8WReg) /* d8(rn) */ #define ModDisp8WRReg 12 #define MModDisp8WRReg (1l << ModDisp8WRReg) /* d8(rrn) */ #define ModDisp16WRReg 13 #define MModDisp16WRReg (1l << ModDisp16WRReg) /* d16(rrn) */ #define ModDispRWRReg 14 #define MModDispRWRReg (1l << ModDispRWRReg) /* rrm(rrn */ #define ModAbs 15 #define MModAbs (1l << ModAbs) /* NN */ #define ModImm 16 #define MModImm (1l << ModImm) /* #N/#NN */ #define ModDisp8RReg 17 #define MModDisp8RReg (1l << ModDisp8RReg) /* d8(RRn) */ #define ModDisp16RReg 18 #define MModDisp16RReg (1l << ModDisp16RReg) /* d16(RRn) */ #define FixedOrderCnt 12 #define ALUOrderCnt 10 #define RegOrderCnt 13 #define Reg16OrderCnt 8 #define Bit2OrderCnt 4 #define Bit1OrderCnt 4 #define ConditionCnt 20 #define LoadOrderCnt 4 static CPUVar CPUST9020,CPUST9030,CPUST9040,CPUST9050; static FixedOrder *FixedOrders; static ALUOrder *ALUOrders; static FixedOrder *RegOrders; static FixedOrder *Reg16Orders; static FixedOrder *Bit2Orders; static FixedOrder *Bit1Orders; static FixedOrder *Conditions; static FixedOrder *LoadOrders; static ShortInt AdrMode,AbsSeg; static Byte AdrPart,OpSize; static Byte AdrVals[3]; static SimpProc SaveInitProc; static LongInt DPAssume; /*--------------------------------------------------------------------------*/ static void AddFixed(char *NName, Word NCode) BEGIN if (InstrZ>=FixedOrderCnt) exit(255); FixedOrders[InstrZ].Name=NName; FixedOrders[InstrZ++].Code=NCode; END static void AddALU(char *NName, Word NCode) BEGIN if (InstrZ>=ALUOrderCnt) exit(255); ALUOrders[InstrZ].Name=NName; ALUOrders[InstrZ].len=strlen(NName); ALUOrders[InstrZ++].Code=NCode; END static void AddReg(char *NName, Word NCode) BEGIN if (InstrZ>=RegOrderCnt) exit(255); RegOrders[InstrZ].Name=NName; RegOrders[InstrZ++].Code=NCode; END static void AddReg16(char *NName, Word NCode) BEGIN if (InstrZ>=Reg16OrderCnt) exit(255); Reg16Orders[InstrZ].Name=NName; Reg16Orders[InstrZ++].Code=NCode; END static void AddBit2(char *NName, Word NCode) BEGIN if (InstrZ>=Bit2OrderCnt) exit(255); Bit2Orders[InstrZ].Name=NName; Bit2Orders[InstrZ++].Code=NCode; END static void AddBit1(char *NName, Word NCode) BEGIN if (InstrZ>=Bit1OrderCnt) exit(255); Bit1Orders[InstrZ].Name=NName; Bit1Orders[InstrZ++].Code=NCode; 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 AddLoad(char *NName, Word NCode) BEGIN if (InstrZ>=LoadOrderCnt) exit(255); LoadOrders[InstrZ].Name=NName; LoadOrders[InstrZ++].Code=NCode; END static void InitFields(void) BEGIN FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0; AddFixed("CCF" ,0x0061); AddFixed("DI" ,0x0010); AddFixed("EI" ,0x0000); AddFixed("HALT",0xbf01); AddFixed("IRET",0x00d3); AddFixed("NOP" ,0x00ff); AddFixed("RCF" ,0x0011); AddFixed("RET" ,0x0046); AddFixed("SCF" ,0x0001); AddFixed("SDM" ,0x00fe); AddFixed("SPM" ,0x00ee); AddFixed("WFI" ,0xef01); ALUOrders=(ALUOrder *) malloc(sizeof(ALUOrder)*ALUOrderCnt); InstrZ=0; AddALU("ADC", 3); AddALU("ADD", 4); AddALU("AND", 1); AddALU("CP" , 9); AddALU("OR" , 0); AddALU("SBC", 2); AddALU("SUB", 5); AddALU("TCM", 8); AddALU("TM" ,10); AddALU("XOR", 6); RegOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*RegOrderCnt); InstrZ=0; AddReg("CLR" ,0x90); AddReg("CPL" ,0x80); AddReg("DA" ,0x70); AddReg("DEC" ,0x40); AddReg("INC" ,0x50); AddReg("POP" ,0x76); AddReg("POPU",0x20); AddReg("RLC" ,0xb0); AddReg("ROL" ,0xa0); AddReg("ROR" ,0xc0); AddReg("RRC" ,0xd0); AddReg("SRA" ,0xe0); AddReg("SWAP",0xf0); Reg16Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Reg16OrderCnt); InstrZ=0; AddReg16("DECW" ,0xcf); AddReg16("EXT" ,0xc6); AddReg16("INCW" ,0xdf); AddReg16("POPUW",0xb7); AddReg16("POPW" ,0x75); AddReg16("RLCW" ,0x8f); AddReg16("RRCW" ,0x36); AddReg16("SRAW" ,0x2f); Bit2Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit2OrderCnt); InstrZ=0; AddBit2("BAND",0x1f); AddBit2("BLD" ,0xf2); AddBit2("BOR" ,0x0f); AddBit2("BXOR",0x6f); Bit1Orders=(FixedOrder *) malloc(sizeof(FixedOrder)*Bit1OrderCnt); InstrZ=0; AddBit1("BCPL",0x6f); AddBit1("BRES" ,0x1f); AddBit1("BSET",0x0f); AddBit1("BTSET",0xf2); Conditions=(FixedOrder *) malloc(sizeof(FixedOrder)*ConditionCnt); InstrZ=0; AddCondition("F" ,0x0); AddCondition("T" ,0x8); AddCondition("C" ,0x7); AddCondition("NC" ,0xf); AddCondition("Z" ,0x6); AddCondition("NZ" ,0xe); AddCondition("PL" ,0xd); AddCondition("MI" ,0x5); AddCondition("OV" ,0x4); AddCondition("NOV" ,0xc); AddCondition("EQ" ,0x6); AddCondition("NE" ,0xe); AddCondition("GE" ,0x9); AddCondition("LT" ,0x1); AddCondition("GT" ,0xa); AddCondition("LE" ,0x2); AddCondition("UGE" ,0xf); AddCondition("UL" ,0x7); AddCondition("UGT" ,0xb); AddCondition("ULE" ,0x3); LoadOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LoadOrderCnt); InstrZ=0; AddLoad("LDPP",0x00); AddLoad("LDDP",0x10); AddLoad("LDPD",0x01); AddLoad("LDDD",0x11); END static void DeinitFields(void) BEGIN free(FixedOrders); free(ALUOrders); free(RegOrders); free(Reg16Orders); free(Bit2Orders); free(Bit1Orders); free(Conditions); free(LoadOrders); END /*--------------------------------------------------------------------------*/ static Boolean DecodeReg(char *Asc_O, Byte *Erg, Byte *Size) BEGIN Boolean Res; char *Asc; Asc=Asc_O; if (strlen(Asc)<2) return False; if (*Asc!='r') return False; Asc++; if (*Asc=='r') BEGIN if (strlen(Asc)<2) return False; *Size=1; Asc++; END else *Size=0; *Erg=ConstLongInt(Asc,&Res); if ((NOT Res) OR (*Erg>15)) return False; if ((*Size==1) AND (Odd(*Erg))) return False; return True; END static void ChkAdr(LongWord Mask) BEGIN if ((AdrMode!=ModNone) AND (((1l << AdrMode) & Mask)==0)) BEGIN WrError(1350); AdrMode=ModNone; AdrCnt=0; END END static void DecodeAdr(char *Asc_O, LongWord Mask) BEGIN Word AdrWord; int level; Byte flg,Size; Boolean OK; String Reg,Asc; char *p; AdrMode=ModNone; AdrCnt=0; strmaxcpy(Asc,Asc_O,255); /* 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); AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord); break; END if (OK) BEGIN AdrMode=ModImm; AdrCnt=OpSize+1; END ChkAdr(Mask); return; END /* Arbeitsregister */ if (DecodeReg(Asc,&AdrPart,&Size)) BEGIN if (Size==0) if ((Mask & MModWReg)!=0) AdrMode=ModWReg; else BEGIN AdrVals[0]=WorkOfs+AdrPart; AdrCnt=1; AdrMode=ModReg; END else if ((Mask & MModWRReg)!=0) AdrMode=ModWRReg; else BEGIN AdrVals[0]=WorkOfs+AdrPart; AdrCnt=1; AdrMode=ModRReg; END ChkAdr(Mask); return; END /* Postinkrement */ if (Asc[strlen(Asc)-1]=='+') BEGIN if ((*Asc!='(') OR (Asc[strlen(Asc)-2]!=')')) WrError(1350); else BEGIN strcpy(Asc,Asc+1); Asc[strlen(Asc)-2]='\0'; if (NOT DecodeReg(Asc,&AdrPart,&Size)) WrXError(1445,Asc); AdrMode=(Size==0) ? ModIncWReg : ModIncWRReg; END ChkAdr(Mask); return; END /* Predekrement */ if ((*Asc=='-') AND (Asc[1]=='(') AND (Asc[strlen(Asc)-1]==')')) BEGIN strcpy(Reg,Asc+2); Reg[strlen(Reg)-1]='\0'; if (DecodeReg(Reg,&AdrPart,&Size)) BEGIN if (Size==0) WrError(1350); else AdrMode=ModDecWRReg; ChkAdr(Mask); return; END END /* indirekt<->direkt */ if ((Asc[strlen(Asc)-1]!=')') OR (strlen(Asc)<3)) BEGIN OK=False; p=Asc; END else BEGIN level=0; p=Asc+strlen(Asc)-2; flg=0; while ((p>=Asc) AND (level>=0)) BEGIN switch (*p) BEGIN case '(': if (flg==0) level--; break; case ')': if (flg==0) level++; break; case '\'': if (((flg & 2)==0)) flg^=1; break; case '"': if (((flg & 1)==0)) flg^=2; break; END p--; END OK=(level==-1) AND ((p0x1ff) OR (Odd(AdrWord))) WrError(1350); else BEGIN AdrVals[0]=Lo(AdrWord); AdrWord=EvalIntExpression(Asc,Int16,&OK); if ((AdrWord==0) AND ((Mask & MModIRReg)!=0)) BEGIN AdrCnt=1; AdrMode=ModIRReg; END else if ((AdrWord<0x100) AND ((Mask & MModDisp8RReg)!=0)) BEGIN AdrVals[1]=Lo(AdrWord); AdrCnt=2; AdrMode=ModDisp8RReg; END else BEGIN AdrVals[2]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord); AdrCnt=3; AdrMode=ModDisp16RReg; END END END ChkAdr(Mask); return; END /* direkt */ AdrWord=EvalIntExpression(Asc,UInt16,&OK); if (OK) if (((TypeFlag & (1 << SegReg)))==0) BEGIN AdrMode=ModAbs; AdrVals[0]=Hi(AdrWord); AdrVals[1]=Lo(AdrWord); AdrCnt=2; ChkSpace(AbsSeg); END else if (AdrWord<0xff) BEGIN AdrMode=ModReg; AdrVals[0]=Lo(AdrWord); AdrCnt=1; END else if ((AdrWord>0x1ff) OR (Odd(AdrWord))) WrError(1350); else BEGIN AdrMode=ModRReg; AdrVals[0]=Lo(AdrWord); AdrCnt=1; END ChkAdr(Mask); END static Boolean SplitBit(char *Asc, Byte *Erg) BEGIN char *p; Integer val; Boolean OK,Inv; p=RQuotPos(Asc,'.'); if ((p==Nil) OR (p==Asc+strlen(Asc)+1)) BEGIN if (*Asc=='!') BEGIN Inv=True; strcpy(Asc,Asc+1); END else Inv=False; val=EvalIntExpression(Asc,UInt8,&OK); if (OK) BEGIN *Erg=val & 15; if (Inv) *Erg^=1; sprintf(Asc, "r%d", (int)(val >> 4)); return True; END return False; END if (p[1]=='!') *Erg=1+(EvalIntExpression(p+2,UInt3,&OK) << 1); else *Erg=EvalIntExpression(p+1,UInt3,&OK) << 1; *p='\0'; return OK; END /*--------------------------------------------------------------------------*/ static Boolean DecodePseudo(void) BEGIN #define ASSUMEST9Count 1 static ASSUMERec ASSUMEST9s[ASSUMEST9Count]= {{"DP", &DPAssume, 0, 1, 0x0}}; Byte Bit; if (Memo("REG")) BEGIN CodeEquate(SegReg,0,0x1ff); return True; END if (Memo("BIT")) BEGIN if (ArgCnt!=1) WrError(1110); else if (SplitBit(ArgStr[1],&Bit)) BEGIN DecodeAdr(ArgStr[1],MModWReg); if (AdrMode==ModWReg) BEGIN PushLocHandle(-1); EnterIntSymbol(LabPart,(AdrPart << 4)+Bit,SegNone,False); PopLocHandle(); sprintf(ListLine,"=r%d.%s%c", (int)AdrPart, (Odd(Bit))?"!":"", (Bit >> 1)+AscOfs); END END return True; END if (Memo("ASSUME")) BEGIN CodeASSUME(ASSUMEST9s,ASSUMEST9Count); return True; END return False; END static void MakeCode_ST9(void) BEGIN Integer AdrInt; int z; Boolean OK; Byte HReg,HPart; Word Mask1,Mask2,AdrWord; CodeLen=0; DontPrint=False; OpSize=0; AbsSeg=(DPAssume==1) ? SegData : SegCode; /* zu ignorierendes */ if (Memo("")) return; /* Pseudoanweisungen */ if (DecodePseudo()) return; if (DecodeIntelPseudo(True)) return; /* ohne Argument */ for (z=0; z127))) WrError(1370); else BEGIN BAsmCode[0]=0xaf; BAsmCode[2]=AdrInt & 0xff; CodeLen=3; ChkSpace(SegCode); END END END return; END if ((Memo("JP")) OR (Memo("CALL"))) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN AbsSeg=SegCode; DecodeAdr(ArgStr[1],MModIRReg+MModAbs); switch (AdrMode) BEGIN case ModIRReg: BAsmCode[0]=0x74+(Ord(Memo("JP"))*0x60); BAsmCode[1]=AdrVals[0]+Ord(Memo("CALL")); CodeLen=2; break; case ModAbs: BAsmCode[0]=0x8d+(Ord(Memo("CALL"))*0x45); memcpy(BAsmCode+1,AdrVals,AdrCnt); CodeLen=1+AdrCnt; break; END END return; END if ((Memo("CPJFI")) OR (Memo("CPJTI"))) BEGIN if (ArgCnt!=3) WrError(1110); else BEGIN DecodeAdr(ArgStr[1],MModWReg); if (AdrMode==ModWReg) BEGIN HReg=AdrPart; DecodeAdr(ArgStr[2],MModIWRReg); if (AdrMode==ModIWRReg) BEGIN BAsmCode[1]=(AdrPart << 4)+(Ord(Memo("CPJTI")) << 4)+HReg; AdrInt=EvalIntExpression(ArgStr[3],UInt16,&OK)-(EProgCounter()+3); if (OK) if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370); else BEGIN ChkSpace(SegCode); BAsmCode[0]=0x9f; BAsmCode[2]=AdrInt & 0xff; CodeLen=3; END END END END return; END if (Memo("DJNZ")) BEGIN if (ArgCnt!=2) WrError(1110); else BEGIN DecodeAdr(ArgStr[1],MModWReg); if (AdrMode==ModWReg) BEGIN BAsmCode[0]=(AdrPart << 4)+0x0a; AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+2); if (OK) if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370); else BEGIN ChkSpace(SegCode); BAsmCode[1]=AdrInt & 0xff; CodeLen=2; END END END return; END if (Memo("DWJNZ")) BEGIN if (ArgCnt!=2) WrError(1110); else BEGIN DecodeAdr(ArgStr[1],MModRReg); if (AdrMode==ModRReg) BEGIN BAsmCode[1]=AdrVals[0]; AdrInt=EvalIntExpression(ArgStr[2],UInt16,&OK)-(EProgCounter()+3); if (OK) if ((NOT SymbolQuestionable) AND ((AdrInt<-128) OR (AdrInt>127))) WrError(1370); else BEGIN ChkSpace(SegCode); BAsmCode[0]=0xc6; BAsmCode[2]=AdrInt & 0xff; CodeLen=3; END END END return; END for (z=0; z127))) WrError(1370); else BEGIN ChkSpace(SegCode); BAsmCode[0]=0x0b+(Conditions[z].Code << 4); BAsmCode[1]=AdrInt & 0xff; CodeLen=2; END END return; END /* Besonderheiten */ if (Memo("SPP")) BEGIN if (ArgCnt!=1) WrError(1110); else if (*ArgStr[1]!='#') WrError(1350); else BEGIN BAsmCode[1]=(EvalIntExpression(ArgStr[1]+1,UInt6,&OK) << 2)+0x02; if (OK) BEGIN BAsmCode[0]=0xc7; CodeLen=2; END END return; END if ((Memo("SRP")) OR (Memo("SRP0")) OR (Memo("SRP1"))) BEGIN if (ArgCnt!=1) WrError(1110); else if (*ArgStr[1]!='#') WrError(1350); else BEGIN BAsmCode[1]=EvalIntExpression(ArgStr[1]+1,UInt5,&OK) << 3; if (OK) BEGIN BAsmCode[0]=0xc7; CodeLen=2; if (strlen(OpPart)==4) BAsmCode[1]+=4; if (OpPart[strlen(OpPart)-1]=='1') BAsmCode[1]++; END END return; END /* Fakes... */ if (Memo("SLA")) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN DecodeAdr(ArgStr[1],MModWReg+MModReg+MModIWRReg); switch (AdrMode) BEGIN case ModWReg: BAsmCode[0]=0x42; BAsmCode[1]=(AdrPart << 4)+AdrPart; CodeLen=2; break; case ModReg: BAsmCode[0]=0x44; BAsmCode[1]=AdrVals[0]; BAsmCode[2]=AdrVals[0]; CodeLen=3; break; case ModIWRReg: BAsmCode[0]=0x73; BAsmCode[1]=0x40+AdrPart; BAsmCode[2]=WorkOfs+AdrPart; CodeLen=3; break; END END return; END if (Memo("SLAW")) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN DecodeAdr(ArgStr[1],MModWRReg+MModRReg+MModIWRReg); switch (AdrMode) BEGIN case ModWRReg: BAsmCode[0]=0x4e; BAsmCode[1]=(AdrPart << 4)+AdrPart; CodeLen=2; break; case ModRReg: BAsmCode[0]=0x47; BAsmCode[1]=AdrVals[0]; BAsmCode[2]=AdrVals[0]; CodeLen=3; break; case ModIWRReg: BAsmCode[0]=0x4e; BAsmCode[1]=0x11+(AdrPart << 4)+AdrPart; CodeLen=2; break; END END return; END WrXError(1200,OpPart); END static void InitCode_ST9(void) BEGIN SaveInitProc(); DPAssume=0; END static Boolean IsDef_ST9(void) BEGIN return (Memo("REG") OR Memo("BIT")); END static void SwitchFrom_ST9(void) BEGIN DeinitFields(); END static void InternSymbol_ST9(char *Asc, TempResult *Erg) BEGIN String h; Boolean Err; Boolean Pair; Erg->Typ=TempNone; if ((strlen(Asc)<2) OR (*Asc!='R')) return; strmaxcpy(h,Asc+1,255); if (*h=='R') BEGIN if (strlen(h)<2) return; Pair=True; strcpy(h,h+1); END else Pair=False; Erg->Contents.Int=ConstLongInt(h,&Err); if ((NOT Err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>255)) return; if ((Erg->Contents.Int & 0xf0)==0xd0) return; if ((Pair) AND (Odd(Erg->Contents.Int))) return; if (Pair) Erg->Contents.Int+=0x100; Erg->Typ=TempInt; TypeFlag|=(1 << SegReg); END static void SwitchTo_ST9(void) BEGIN TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False; PCSymbol="PC"; HeaderID=0x32; NOPCode=0xff; DivideChars=","; HasAttrs=False; ValidSegs=(1<