dect
/
asl
Archived
13
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
asl/codemsp.c

540 lines
13 KiB
C

/* 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