560 lines
14 KiB
C
560 lines
14 KiB
C
/* code8x30x.c */
|
|
/*****************************************************************************/
|
|
/* AS-Portierung */
|
|
/* */
|
|
/* Codegenerator Signetics 8X30x */
|
|
/* */
|
|
/* Historie: 25. 6.1997 Grundsteinlegung */
|
|
/* 3. 1.1999 ChkPC-Anpassung */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#include "stdinc.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "nls.h"
|
|
#include "chunks.h"
|
|
#include "bpemu.h"
|
|
#include "strutil.h"
|
|
|
|
#include "asmdef.h"
|
|
#include "asmsub.h"
|
|
#include "asmpars.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define AriOrderCnt 4
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Code;
|
|
} FixedOrder;
|
|
|
|
static CPUVar CPU8x300,CPU8x305;
|
|
static FixedOrder *AriOrders;
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static int InstrZ;
|
|
|
|
static void AddAri(char *NName, Word NCode)
|
|
BEGIN
|
|
if (InstrZ>=AriOrderCnt) exit(255);
|
|
AriOrders[InstrZ].Name=NName;
|
|
AriOrders[InstrZ++].Code=NCode;
|
|
END
|
|
|
|
static void InitFields(void)
|
|
BEGIN
|
|
AriOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*AriOrderCnt); InstrZ=0;
|
|
AddAri("MOVE",0); AddAri("ADD",1); AddAri("AND",2); AddAri("XOR",3);
|
|
END
|
|
|
|
static void DeinitFields(void)
|
|
BEGIN
|
|
free(AriOrders);
|
|
END
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static Boolean DecodeReg(char *Asc, Word *Erg, ShortInt *ErgLen)
|
|
BEGIN
|
|
Boolean OK;
|
|
Word Acc;
|
|
LongInt Adr;
|
|
char *z;
|
|
|
|
*ErgLen=(-1);
|
|
|
|
if (strcasecmp(Asc,"AUX")==0)
|
|
BEGIN
|
|
*Erg=0; return True;
|
|
END
|
|
|
|
if (strcasecmp(Asc,"OVF")==0)
|
|
BEGIN
|
|
*Erg=8; return True;
|
|
END
|
|
|
|
if (strcasecmp(Asc,"IVL")==0)
|
|
BEGIN
|
|
*Erg=7; return True;
|
|
END
|
|
|
|
if (strcasecmp(Asc,"IVR")==0)
|
|
BEGIN
|
|
*Erg=15; return True;
|
|
END
|
|
|
|
if ((toupper(*Asc)=='R') AND (strlen(Asc)>1) AND (strlen(Asc)<4))
|
|
BEGIN
|
|
Acc=0; OK=True;
|
|
for (z=Asc+1; *z!='\0'; z++)
|
|
if (OK)
|
|
if ((*z<'0') OR (*z>'7')) OK=False;
|
|
else Acc=(Acc << 3)+(*z-'0');
|
|
if ((OK) AND (Acc<32))
|
|
BEGIN
|
|
if ((MomCPU==CPU8x300) AND (Acc>9) AND (Acc<15))
|
|
BEGIN
|
|
WrXError(1445,Asc); return False;
|
|
END
|
|
else *Erg=Acc;
|
|
return True;
|
|
END
|
|
END
|
|
|
|
if ((strlen(Asc)==4) AND (strncasecmp(Asc+1,"IV",2)==0) AND (Asc[3]>='0') AND (Asc[3]<='7'))
|
|
if (toupper(*Asc)=='L')
|
|
BEGIN
|
|
*Erg=Asc[3]-'0'+0x10; return True;
|
|
END
|
|
else if (toupper(*Asc)=='R')
|
|
BEGIN
|
|
*Erg=Asc[3]-'0'+0x18; return True;
|
|
END
|
|
|
|
/* IV - Objekte */
|
|
|
|
Adr=EvalIntExpression(Asc,UInt24,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
*ErgLen=Adr & 7;
|
|
*Erg=0x10+((Adr & 0x10) >> 1)+((Adr & 0x700) >> 8);
|
|
return True;
|
|
END
|
|
else return False;
|
|
END
|
|
|
|
static char *HasDisp(char *Asc)
|
|
BEGIN
|
|
int Lev;
|
|
char *z;
|
|
int l=strlen(Asc);
|
|
|
|
if (Asc[l-1]==')')
|
|
BEGIN
|
|
z=Asc+l-2; Lev=0;
|
|
while ((z>=Asc) AND (Lev!=-1))
|
|
BEGIN
|
|
switch (*z)
|
|
BEGIN
|
|
case '(': Lev--; break;
|
|
case ')': Lev++; break;
|
|
END
|
|
if (Lev!=-1) z--;
|
|
END
|
|
if (Lev!=-1)
|
|
BEGIN
|
|
WrError(1300); return Nil;
|
|
END
|
|
END
|
|
else z=Nil;
|
|
|
|
return z;
|
|
END
|
|
|
|
static Boolean GetLen(char *Asc, Word *Erg)
|
|
BEGIN
|
|
Boolean OK;
|
|
|
|
FirstPassUnknown=False;
|
|
*Erg=EvalIntExpression(Asc,UInt4,&OK); if (NOT OK) return False;
|
|
if (FirstPassUnknown) *Erg=8;
|
|
if (NOT ChkRange(*Erg,1,8)) return False;
|
|
*Erg&=7; return True;
|
|
END
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/* Symbol: 00AA0ORL */
|
|
|
|
static Boolean DecodePseudo(void)
|
|
BEGIN
|
|
LongInt Adr,Ofs,Erg;
|
|
Word Len;
|
|
Boolean OK;
|
|
|
|
if ((Memo("LIV")) OR (Memo("RIV")))
|
|
BEGIN
|
|
Erg=0x10*Ord(Memo("RIV"));
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
Adr=EvalIntExpression(ArgStr[1],UInt8,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
Ofs=EvalIntExpression(ArgStr[2],UInt3,&OK);
|
|
if (OK)
|
|
if (GetLen(ArgStr[3],&Len))
|
|
BEGIN
|
|
PushLocHandle(-1);
|
|
EnterIntSymbol(LabPart,Erg+(Adr << 16)+(Ofs << 8)+(Len & 7),SegNone,False);
|
|
PopLocHandle();
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
return False;
|
|
END
|
|
|
|
static void MakeCode_8x30X(void)
|
|
BEGIN
|
|
Boolean OK;
|
|
Word SrcReg,DestReg;
|
|
ShortInt SrcLen,DestLen;
|
|
LongInt Op;
|
|
Word Rot,Adr;
|
|
int z;
|
|
char *p;
|
|
String tmp;
|
|
|
|
CodeLen=0; DontPrint=False;
|
|
|
|
/* zu ignorierendes */
|
|
|
|
if (Memo("")) return;
|
|
|
|
/* Pseudoanweisungen */
|
|
|
|
if (DecodePseudo()) return;
|
|
|
|
/* eingebaute Makros */
|
|
|
|
if (Memo("NOP")) /* NOP = MOVE AUX,AUX */
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x0000; CodeLen=1;
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("HALT")) /* HALT = JMP * */
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0xe000+(EProgCounter() & 0x1fff); CodeLen=1;
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("XML")) OR (Memo("XMR")))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (MomCPU<CPU8x305) WrError(1500);
|
|
else
|
|
BEGIN
|
|
Adr=EvalIntExpression(ArgStr[1],Int8,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]=0xca00+(Ord(Memo("XER")) << 8)+(Adr & 0xff);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Datentransfer */
|
|
|
|
if (Memo("SEL"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
Op=EvalIntExpression(ArgStr[1],UInt24,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]=0xc700+((Op & 0x10) << 7)+((Op >> 16) & 0xff);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("XMIT"))
|
|
BEGIN
|
|
if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
|
|
else if (DecodeReg(ArgStr[2],&SrcReg,&SrcLen))
|
|
if (SrcReg<16)
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
Adr=EvalIntExpression(ArgStr[1],Int8,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]=0xc000+(SrcReg << 8)+(Adr & 0xff);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
else
|
|
BEGIN
|
|
if (ArgCnt==2)
|
|
BEGIN
|
|
Rot=0xffff; OK=True;
|
|
END
|
|
else OK=GetLen(ArgStr[3],&Rot);
|
|
if (OK)
|
|
BEGIN
|
|
if (Rot==0xffff)
|
|
Rot=(SrcLen==-1) ? 0 : SrcLen;
|
|
if ((SrcLen!=-1) AND (Rot!=SrcLen)) WrError(1131);
|
|
else
|
|
BEGIN
|
|
Adr=EvalIntExpression(ArgStr[1],Int5,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]=0xc000+(SrcReg << 8)+(Rot << 5)+(Adr & 0x1f);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Arithmetik */
|
|
|
|
for (z=0; z<AriOrderCnt; z++)
|
|
if (Memo(AriOrders[z].Name))
|
|
BEGIN
|
|
if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
|
|
else if (DecodeReg(ArgStr[ArgCnt],&DestReg,&DestLen))
|
|
if (DestReg<16) /* Ziel Register */
|
|
BEGIN
|
|
if (ArgCnt==2) /* wenn nur zwei Operanden und Ziel Register... */
|
|
BEGIN
|
|
p=HasDisp(ArgStr[1]); /* kann eine Rotation dabei sein */
|
|
if (p!=Nil)
|
|
BEGIN /* jau! */
|
|
strcpy(tmp,p+1); tmp[strlen(tmp)-1]='\0';
|
|
Rot=EvalIntExpression(tmp,UInt3,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
*p='\0';
|
|
if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
|
|
if (SrcReg>=16) WrXError(1445,ArgStr[1]);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+(Rot << 5)+DestReg;
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
else /* noi! */
|
|
BEGIN
|
|
if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
|
|
BEGIN
|
|
WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+DestReg;
|
|
if ((SrcReg>=16) AND (SrcLen!=-1)) WAsmCode[0]+=SrcLen << 5;
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
else /* 3 Operanden --> Quelle ist I/O */
|
|
BEGIN
|
|
if (GetLen(ArgStr[2],&Rot))
|
|
if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
|
|
if (SrcReg<16) WrXError(1445,ArgStr[1]);
|
|
else if ((SrcLen!=-1) AND (SrcLen!=Rot)) WrError(1131);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+(Rot << 5)+DestReg;
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
else /* Ziel I/O */
|
|
BEGIN
|
|
if (ArgCnt==2) /* 2 Argumente: Laenge=Laenge Ziel */
|
|
BEGIN
|
|
Rot=DestLen; OK=True;
|
|
END
|
|
else /* 3 Argumente: Laenge=Laenge Ziel+Angabe */
|
|
BEGIN
|
|
OK=GetLen(ArgStr[2],&Rot);
|
|
if (OK)
|
|
BEGIN
|
|
if (FirstPassUnknown) Rot=DestLen;
|
|
if (DestLen==-1) DestLen=Rot;
|
|
OK=Rot==DestLen;
|
|
if (NOT OK) WrError(1131);
|
|
END
|
|
END
|
|
if (OK)
|
|
if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
|
|
BEGIN
|
|
if ((Rot==0xffff))
|
|
Rot=((SrcLen==-1)) ? 0 : SrcLen;
|
|
if ((DestReg>=16) AND (SrcLen!=-1) AND (SrcLen!=Rot)) WrError(1131);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=(AriOrders[z].Code << 13)+(SrcReg << 8)+(Rot << 5)+DestReg;
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("XEC"))
|
|
BEGIN
|
|
if ((ArgCnt!=1) AND (ArgCnt!=2)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
p=HasDisp(ArgStr[1]);
|
|
if (p==Nil) WrError(1350);
|
|
else
|
|
BEGIN
|
|
strcpy(tmp,p+1); tmp[strlen(tmp)-1]='\0';
|
|
if (DecodeReg(tmp,&SrcReg,&SrcLen))
|
|
BEGIN
|
|
*p='\0';
|
|
if (SrcReg<16)
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt8,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]+=0x8000+(SrcReg << 8);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
else
|
|
BEGIN
|
|
if (ArgCnt==1)
|
|
BEGIN
|
|
Rot=0xffff; OK=True;
|
|
END
|
|
else OK=GetLen(ArgStr[2],&Rot);
|
|
if (OK)
|
|
BEGIN
|
|
if (Rot==0xffff)
|
|
Rot=(SrcLen==-1) ? 0 : SrcLen;
|
|
if ((SrcLen!=-1) AND (Rot!=SrcLen)) WrError(1131);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt5,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]+=0x8000+(SrcReg << 8)+(Rot << 5);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Spruenge */
|
|
|
|
if (Memo("JMP"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=EvalIntExpression(ArgStr[1],UInt13,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]+=0xe000; CodeLen=1;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("NZT"))
|
|
BEGIN
|
|
if ((ArgCnt!=2) AND (ArgCnt!=3)) WrError(1110);
|
|
else if (DecodeReg(ArgStr[1],&SrcReg,&SrcLen))
|
|
if (SrcReg<16)
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
Adr=EvalIntExpression(ArgStr[2],UInt13,&OK);
|
|
if (OK)
|
|
if ((NOT SymbolQuestionable) AND ((Adr >> 8)!=(EProgCounter() >> 8))) WrError(1910);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0xa000+(SrcReg << 8)+(Adr & 0xff);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
else
|
|
BEGIN
|
|
if (ArgCnt==2)
|
|
BEGIN
|
|
Rot=0xffff; OK=True;
|
|
END
|
|
else OK=GetLen(ArgStr[2],&Rot);
|
|
if (OK)
|
|
BEGIN
|
|
if (Rot==0xffff)
|
|
Rot=(SrcLen==-1) ? 0 : SrcLen;
|
|
if ((SrcLen!=-1) AND (Rot!=SrcLen)) WrError(1131);
|
|
else
|
|
BEGIN
|
|
Adr=EvalIntExpression(ArgStr[ArgCnt],UInt13,&OK);
|
|
if (OK)
|
|
if ((NOT SymbolQuestionable) AND ((Adr >> 5)!=(EProgCounter() >> 5))) WrError(1910);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0xa000+(SrcReg << 8)+(Rot << 5)+(Adr & 0x1f);
|
|
CodeLen=1;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END;
|
|
|
|
WrXError(1200,OpPart);
|
|
END
|
|
|
|
static Boolean IsDef_8x30X(void)
|
|
BEGIN
|
|
return (Memo("LIV") OR Memo("RIV"));
|
|
END
|
|
|
|
static void SwitchFrom_8x30X()
|
|
BEGIN
|
|
DeinitFields();
|
|
END
|
|
|
|
static void SwitchTo_8x30X(void)
|
|
BEGIN
|
|
TurnWords=False; ConstMode=ConstModeMoto; SetIsOccupied=False;
|
|
|
|
PCSymbol="*"; HeaderID=0x3a; NOPCode=0x0000;
|
|
DivideChars=","; HasAttrs=False;
|
|
|
|
ValidSegs=1<<SegCode;
|
|
Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
|
|
SegLimits[SegCode] = 0x1fff;
|
|
|
|
MakeCode=MakeCode_8x30X; IsDef=IsDef_8x30X;
|
|
SwitchFrom=SwitchFrom_8x30X; InitFields();
|
|
END
|
|
|
|
void code8x30x_init(void)
|
|
BEGIN
|
|
CPU8x300=AddCPU("8x300",SwitchTo_8x30X);
|
|
CPU8x305=AddCPU("8x305",SwitchTo_8x30X);
|
|
END
|
|
|