aboutsummaryrefslogtreecommitdiffstats
path: root/codemsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'codemsp.c')
-rw-r--r--codemsp.c539
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