diff options
Diffstat (limited to 'codemsp.c')
-rw-r--r-- | codemsp.c | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/codemsp.c b/codemsp.c new file mode 100644 index 0000000..b674efe --- /dev/null +++ b/codemsp.c @@ -0,0 +1,539 @@ +/* codemsp.c */ +/*****************************************************************************/ +/* AS-Portierung */ +/* */ +/* Codegenerator MSP430 */ +/* */ +/* Historie: */ +/* 18. 8.1998 BookKeeping-Aufruf bei BSS */ +/* 2. 1.1998 ChkPC umgestellt */ +/* */ +/*****************************************************************************/ + +#include "stdinc.h" + +#include <ctype.h> +#include <string.h> + +#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; z<TwoOpCount; z++) + if (Memo(TwoOpOrders[z].Name)) + BEGIN + if (ArgCnt!=2) WrError(1110); + else + BEGIN + PCDist=2; DecodeAdr(ArgStr[1],15,True); + if (AdrMode!=0xff) + BEGIN + AdrMode2=AdrMode; AdrPart2=AdrPart; AdrCnt2=AdrCnt; AdrVal2=AdrVal; + PCDist+=AdrCnt2 << 1; DecodeAdr(ArgStr[2],3,False); + if (AdrMode!=0xff) + BEGIN + WAsmCode[0]=TwoOpOrders[z].Code+(AdrPart2 << 8)+(AdrMode << 7) + +(OpSize << 6)+(AdrMode2 << 4)+AdrPart; + memcpy(WAsmCode+1,&AdrVal2,AdrCnt2 << 1); + memcpy(WAsmCode+1+AdrCnt2,&AdrVal,AdrCnt << 1); + CodeLen=(1+AdrCnt+AdrCnt2) << 1; + END + END + END + return; + END + + /* ein Operand */ + + for (z=0; z<OneOpCount; z++) + if (Memo(OneOpOrders[z].Name)) + BEGIN + if (ArgCnt!=1) WrError(1110); + else if ((OpSize==1) AND (NOT OneOpOrders[z].MayByte)) WrError(1130); + else + BEGIN + PCDist=2; DecodeAdr(ArgStr[1],15,False); + if (AdrMode!=0xff) + BEGIN + WAsmCode[0]=OneOpOrders[z].Code+(OpSize << 6)+(AdrMode << 4)+AdrPart; + memcpy(WAsmCode+1,&AdrVal,AdrCnt << 1); + CodeLen=(1+AdrCnt) << 1; + END + END + return; + END + + /* kein Operand */ + + if (Memo("RETI")) + BEGIN + if (ArgCnt!=0) WrError(1110); + else if (*AttrPart!='\0') WrError(1100); + else if (OpSize!=0) WrError(1130); + else + BEGIN + WAsmCode[0]=0x1300; CodeLen=2; + END + return; + END + + /* Spruenge */ + + for (z=0; z<JmpCount; z++) + if (Memo(JmpOrders[z].Name)) + BEGIN + if (ArgCnt!=1) WrError(1110); + else if (OpSize!=0) WrError(1130); + else + BEGIN + AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2); + if (OK) + if (Odd(AdrInt)) WrError(1375); + else if ((NOT SymbolQuestionable) AND ((AdrInt<-1024) OR (AdrInt>1022))) 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<<SegCode; + Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0; + SegLimits[SegCode] = 0xffff; + + AddONOFF("PADDING", &DoPadding, DoPaddingName,False); + + MakeCode=MakeCode_MSP; IsDef=IsDef_MSP; + SwitchFrom=SwitchFrom_MSP; InitFields(); +END + + void codemsp_init(void) +BEGIN + CPUMSP430=AddCPU("MSP430",SwitchTo_MSP); +END |