/* codemsp.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Codegenerator MSP430 */ /* */ /* Historie: */ /* 18. 8.1998 BookKeeping-Aufruf bei BSS */ /* 2. 1.1998 ChkPC umgestellt */ /* */ /*****************************************************************************/ #include "stdinc.h" #include #include #include "nls.h" #include "endian.h" #include "strutil.h" #include "bpemu.h" #include "chunks.h" #include "asmdef.h" #include "asmsub.h" #include "asmpars.h" #include "asmallg.h" #include "codepseudo.h" #include "codevars.h" #define TwoOpCount 12 #define OneOpCount 6 #define JmpCount 10 typedef struct { char *Name; Word Code; } FixedOrder; typedef struct { char *Name; Boolean MayByte; Word Code; } OneOpOrder; static CPUVar CPUMSP430; static FixedOrder *TwoOpOrders; static OneOpOrder *OneOpOrders; static FixedOrder *JmpOrders; static Word AdrMode,AdrMode2,AdrPart,AdrPart2; static Byte AdrCnt2; static Word AdrVal,AdrVal2; static Byte OpSize; static Word PCDist; /*-------------------------------------------------------------------------*/ static void AddTwoOp(char *NName, Word NCode) BEGIN if (InstrZ>=TwoOpCount) exit(255); TwoOpOrders[InstrZ].Name=NName; TwoOpOrders[InstrZ++].Code=NCode; END static void AddOneOp(char *NName, Boolean NMay, Word NCode) BEGIN if (InstrZ>=OneOpCount) exit(255); OneOpOrders[InstrZ].Name=NName; OneOpOrders[InstrZ].MayByte=NMay; OneOpOrders[InstrZ++].Code=NCode; END static void AddJmp(char *NName, Word NCode) BEGIN if (InstrZ>=JmpCount) exit(255); JmpOrders[InstrZ].Name=NName; JmpOrders[InstrZ++].Code=NCode; END static void InitFields(void) BEGIN TwoOpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*TwoOpCount); InstrZ=0; AddTwoOp("MOV" ,0x4000); AddTwoOp("ADD" ,0x5000); AddTwoOp("ADDC",0x6000); AddTwoOp("SUBC",0x7000); AddTwoOp("SUB" ,0x8000); AddTwoOp("CMP" ,0x9000); AddTwoOp("DADD",0xa000); AddTwoOp("BIT" ,0xb000); AddTwoOp("BIC" ,0xc000); AddTwoOp("BIS" ,0xd000); AddTwoOp("XOR" ,0xe000); AddTwoOp("AND" ,0xf000); OneOpOrders=(OneOpOrder *) malloc(sizeof(OneOpOrder)*OneOpCount); InstrZ=0; AddOneOp("RRC" ,True ,0x1000); AddOneOp("RRA" ,True ,0x1100); AddOneOp("PUSH",True ,0x1200); AddOneOp("SWPB",False,0x1080); AddOneOp("CALL",False,0x1280); AddOneOp("SXT" ,False,0x1180); JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpCount); InstrZ=0; AddJmp("JNE" ,0x2000); AddJmp("JNZ" ,0x2000); AddJmp("JE" ,0x2400); AddJmp("JZ" ,0x2400); AddJmp("JNC" ,0x2800); AddJmp("JC" ,0x2c00); AddJmp("JN" ,0x3000); AddJmp("JGE" ,0x3400); AddJmp("JL" ,0x3800); AddJmp("JMP" ,0x3C00); END static void DeinitFields(void) BEGIN free(TwoOpOrders); free(OneOpOrders); free(JmpOrders); END /*-------------------------------------------------------------------------*/ static void ResetAdr(void) BEGIN AdrMode=0xff; AdrCnt=0; END static void ChkAdr(Byte Mask) BEGIN if ((AdrMode!=0xff) AND ((Mask & (1 << AdrMode))==0)) BEGIN ResetAdr(); WrError(1350); END END static Boolean DecodeReg(char *Asc, Word *Erg) BEGIN Boolean OK; if (strcasecmp(Asc,"PC")==0) BEGIN *Erg=0; return True; END else if (strcasecmp(Asc,"SP")==0) BEGIN *Erg=1; return True; END else if (strcasecmp(Asc,"SR")==0) BEGIN *Erg=2; return True; END if ((toupper(*Asc)=='R') AND (strlen(Asc)>=2) AND (strlen(Asc)<=3)) BEGIN *Erg=ConstLongInt(Asc+1,&OK); return ((OK) AND (*Erg<16)); END return False; END static void DecodeAdr(char *Asc, Byte Mask, Boolean MayImm) BEGIN Word AdrWord; Boolean OK; char *p; ResetAdr(); /* immediate */ if (*Asc=='#') BEGIN if (NOT MayImm) WrError(1350); else BEGIN AdrWord=EvalIntExpression(Asc+1,(OpSize==1)?Int8:Int16,&OK); if (OK) BEGIN switch (AdrWord) BEGIN case 0: AdrPart=3; AdrMode=0; break; case 1: AdrPart=3; AdrMode=1; break; case 2: AdrPart=3; AdrMode=2; break; case 4: AdrPart=2; AdrMode=2; break; case 8: AdrPart=2; AdrMode=3; break; case 0xffff: AdrPart=3; AdrMode=3; break; default: AdrVal=AdrWord; AdrCnt=1; AdrPart=0; AdrMode=3; break; END END END ChkAdr(Mask); return; END /* absolut */ if (*Asc=='&') BEGIN AdrVal=EvalIntExpression(Asc+1,UInt16,&OK); if (OK) BEGIN AdrMode=1; AdrPart=2; AdrCnt=1; END ChkAdr(Mask); return; END /* Register */ if (DecodeReg(Asc,&AdrPart)) BEGIN if (AdrPart==3) WrXError(1445,Asc); else AdrMode=0; ChkAdr(Mask); return; END /* Displacement */ if (Asc[strlen(Asc)-1]==')') BEGIN Asc[strlen(Asc)-1]='\0'; p=RQuotPos(Asc,'('); if (p!=Nil) BEGIN if (DecodeReg(p+1,&AdrPart)) BEGIN *p='\0'; AdrVal=EvalIntExpression(Asc,Int16,&OK); if (OK) if ((AdrPart==2) OR (AdrPart==3)) WrXError(1445,Asc); else if ((AdrVal==0) AND ((Mask & 4)!=0)) AdrMode=2; else BEGIN AdrCnt=1; AdrMode=1; END *p='('; ChkAdr(Mask); return; END END Asc[strlen(Asc)]=')'; END /* indirekt mit/ohne Autoinkrement */ if ((*Asc=='@') OR (*Asc=='*')) BEGIN if (Asc[strlen(Asc)-1]=='+') BEGIN AdrWord=1; Asc[strlen(Asc)-1]='\0'; END else AdrWord=0; if (NOT DecodeReg(Asc+1,&AdrPart)) WrXError(1445,Asc); else if ((AdrPart==2) OR (AdrPart==3)) WrXError(1445,Asc); else if ((AdrWord==0) AND ((Mask & 4)==0)) BEGIN AdrVal=0; AdrCnt=1; AdrMode=1; END else AdrMode=2+AdrWord; ChkAdr(Mask); return; END /* bleibt PC-relativ */ AdrWord=EvalIntExpression(Asc,UInt16,&OK)-EProgCounter()-PCDist; if (OK) BEGIN AdrPart=0; AdrMode=1; AdrCnt=1; AdrVal=AdrWord; END ChkAdr(Mask); END /*-------------------------------------------------------------------------*/ static void PutByte(Byte Value) BEGIN if (((CodeLen&1)==1) AND (NOT BigEndian)) BEGIN BAsmCode[CodeLen]=BAsmCode[CodeLen-1]; BAsmCode[CodeLen-1]=Value; END else BEGIN BAsmCode[CodeLen]=Value; END CodeLen++; END static Boolean DecodePseudo(void) BEGIN TempResult t; Word HVal16; int z; char *p; Boolean OK; if (Memo("BYTE")) BEGIN if (ArgCnt==0) WrError(1110); else BEGIN z=1; OK=True; do BEGIN KillBlanks(ArgStr[z]); FirstPassUnknown=False; EvalExpression(ArgStr[z],&t); switch (t.Typ) BEGIN case TempInt: if (FirstPassUnknown) t.Contents.Int&=0xff; if (NOT RangeCheck(t.Contents.Int,Int8)) WrError(1320); else if (CodeLen==MaxCodeLen) BEGIN WrError(1920); OK=False; END else PutByte(t.Contents.Int); break; case TempFloat: WrError(1135); OK=False; break; case TempString: if (strlen(t.Contents.Ascii)+CodeLen>=MaxCodeLen) BEGIN WrError(1920); OK=False; END else BEGIN TranslateString(t.Contents.Ascii); for (p=t.Contents.Ascii; *p!='\0'; PutByte(*(p++))); END break; case TempNone: OK=False; break; END z++; END while ((z<=ArgCnt) AND (OK)); if (NOT OK) CodeLen=0; else if ((Odd(CodeLen)) AND (DoPadding)) PutByte(0); END return True; END if (Memo("WORD")) BEGIN if (ArgCnt==0) WrError(1110); else BEGIN z=1; OK=True; do BEGIN HVal16=EvalIntExpression(ArgStr[z],Int16,&OK); if (OK) BEGIN WAsmCode[CodeLen >> 1]=HVal16; CodeLen+=2; END z++; END while ((z<=ArgCnt) AND (OK)); if (NOT OK) CodeLen=0; END return True; END if (Memo("BSS")) BEGIN if (ArgCnt!=1) WrError(1110); else BEGIN FirstPassUnknown=False; HVal16=EvalIntExpression(ArgStr[1],Int16,&OK); if (FirstPassUnknown) WrError(1820); else if (OK) BEGIN if ((Odd(HVal16)) AND (DoPadding)) HVal16++; DontPrint=True; CodeLen=HVal16; BookKeeping(); END END return True; END /* float exp (8bit bias 128) sign mant (impl. norm.) double exp (8bit bias 128) sign mant (impl. norm.) */ return False; END static void MakeCode_MSP(void) BEGIN int z; Integer AdrInt; Boolean OK; CodeLen=0; DontPrint=False; /* zu ignorierendes */ if (Memo("")) return; /* Attribut bearbeiten */ if (*AttrPart=='\0') OpSize=0; else if (strlen(AttrPart)>1) WrError(1107); else switch (toupper(*AttrPart)) BEGIN case 'B': OpSize=1; break; case 'W': OpSize=0; break; default: WrError(1107); return; END /* Pseudoanweisungen */ if (DecodePseudo()) return; /* zwei Operanden */ for (z=0; z1022))) WrError(1370); else BEGIN WAsmCode[0]=JmpOrders[z].Code+((AdrInt >> 1) & 0x3ff); CodeLen=2; END END return; END WrXError(1200,OpPart); END static Boolean IsDef_MSP(void) BEGIN return False; END static void SwitchFrom_MSP(void) BEGIN DeinitFields(); ClearONOFF(); END static void SwitchTo_MSP(void) BEGIN TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False; PCSymbol="$"; HeaderID=0x4a; NOPCode=0x4303; /* = MOV #0,#0 */ DivideChars=","; HasAttrs=True; AttrChars="."; ValidSegs=1<