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/code9900.c

686 lines
17 KiB
C

/* code9900.h */
/*****************************************************************************/
/* AS-Portierung */
/* */
/* Codegenerator TMS99xx */
/* */
/* Historie: 9. 3.1997 Grundsteinlegung */
/* 18. 8.1998 BookKeeping-Aufruf bei BSS */
/* 2. 1.1999 ChkPC angepasst */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "strutil.h"
#include "endian.h"
#include "bpemu.h"
#include "nls.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "codepseudo.h"
#include "codevars.h"
#define TwoOrderCount 6
#define OneOrderCount 6
#define SingOrderCount 16
#define SBitOrderCount 3
#define JmpOrderCount 13
#define ShiftOrderCount 4
#define ImmOrderCount 5
#define RegOrderCount 4
#define FixedOrderCount 6
typedef struct
{
char *Name;
int NameLen;
Word Code;
} FixedOrder;
typedef struct
{
char *Name;
int NameLen;
Word Code;
Boolean MustSup;
} SupOrder;
static CPUVar CPU9900;
static Boolean IsWord;
static Word AdrVal,AdrPart;
static FixedOrder *TwoOrders;
static FixedOrder *OneOrders;
static SupOrder *SingOrders;
static FixedOrder *SBitOrders;
static FixedOrder *JmpOrders;
static FixedOrder *ShiftOrders;
static FixedOrder *ImmOrders;
static FixedOrder *RegOrders;
static SupOrder *FixedOrders;
/*-------------------------------------------------------------------------*/
/* dynamische Belegung/Freigabe Codetabellen */
static void AddTwo(char *NName, Word NCode)
BEGIN
if (InstrZ>=TwoOrderCount) exit(255);
TwoOrders[InstrZ].Name=NName;
TwoOrders[InstrZ].Code=NCode;
TwoOrders[InstrZ++].NameLen=strlen(NName);
END
static void AddOne(char *NName, Word NCode)
BEGIN
if (InstrZ>=OneOrderCount) exit(255);
OneOrders[InstrZ].Name=NName;
OneOrders[InstrZ++].Code=NCode;
END
static void AddSing(char *NName, Word NCode,Boolean NSup)
BEGIN
if (InstrZ>=SingOrderCount) exit(255);
SingOrders[InstrZ].Name=NName;
SingOrders[InstrZ].MustSup=NSup;
SingOrders[InstrZ++].Code=NCode;
END
static void AddSBit(char *NName, Word NCode)
BEGIN
if (InstrZ>=SBitOrderCount) exit(255);
SBitOrders[InstrZ].Name=NName;
SBitOrders[InstrZ++].Code=NCode;
END
static void AddJmp(char *NName, Word NCode)
BEGIN
if (InstrZ>=JmpOrderCount) exit(255);
JmpOrders[InstrZ].Name=NName;
JmpOrders[InstrZ++].Code=NCode;
END
static void AddShift(char *NName, Word NCode)
BEGIN
if (InstrZ>=ShiftOrderCount) exit(255);
ShiftOrders[InstrZ].Name=NName;
ShiftOrders[InstrZ++].Code=NCode;
END
static void AddImm(char *NName, Word NCode)
BEGIN
if (InstrZ>=ImmOrderCount) exit(255);
ImmOrders[InstrZ].Name=NName;
ImmOrders[InstrZ++].Code=NCode;
END
static void AddReg(char *NName, Word NCode)
BEGIN
if (InstrZ>=RegOrderCount) exit(255);
RegOrders[InstrZ].Name=NName;
RegOrders[InstrZ++].Code=NCode;
END
static void AddFixed(char *NName, Word NCode, Boolean NSup)
BEGIN
if (InstrZ>=FixedOrderCount) exit(255);
FixedOrders[InstrZ].Name=NName;
FixedOrders[InstrZ].MustSup=NSup;
FixedOrders[InstrZ++].Code=NCode;
END
static void InitFields(void)
BEGIN
TwoOrders=(FixedOrder *) malloc(TwoOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddTwo("A" ,5); AddTwo("C" ,4); AddTwo("S" ,3);
AddTwo("SOC" ,7); AddTwo("SZC" ,2); AddTwo("MOV" ,6);
OneOrders=(FixedOrder *) malloc(OneOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddOne("COC" ,0x08); AddOne("CZC" ,0x09); AddOne("XOR" ,0x0a);
AddOne("MPY" ,0x0e); AddOne("DIV" ,0x0f); AddOne("XOP" ,0x0b);
SingOrders=(SupOrder *) malloc(SingOrderCount*sizeof(SupOrder)); InstrZ=0;
AddSing("B" ,0x0440,False); AddSing("BL" ,0x0680,False); AddSing("BLWP",0x0400,False);
AddSing("CLR" ,0x04c0,False); AddSing("SETO",0x0700,False); AddSing("INV" ,0x0540,False);
AddSing("NEG" ,0x0500,False); AddSing("ABS" ,0x0740,False); AddSing("SWPB",0x06c0,False);
AddSing("INC" ,0x0580,False); AddSing("INCT",0x05c0,False); AddSing("DEC" ,0x0600,False);
AddSing("DECT",0x0640,True ); AddSing("X" ,0x0480,False); AddSing("LDS" ,0x0780,True );
AddSing("LDD" ,0x07c0,True );
SBitOrders=(FixedOrder *) malloc(SBitOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddSBit("SBO" ,0x1d); AddSBit("SBZ",0x1e); AddSBit("TB" ,0x1f);
JmpOrders=(FixedOrder *) malloc(JmpOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddJmp("JEQ",0x13); AddJmp("JGT",0x15); AddJmp("JH" ,0x1b);
AddJmp("JHE",0x14); AddJmp("JL" ,0x1a); AddJmp("JLE",0x12);
AddJmp("JLT",0x11); AddJmp("JMP",0x10); AddJmp("JNC",0x17);
AddJmp("JNE",0x16); AddJmp("JNO",0x19); AddJmp("JOC",0x18);
AddJmp("JOP",0x1c);
ShiftOrders=(FixedOrder *) malloc(ShiftOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddShift("SLA",0x0a); AddShift("SRA",0x08);
AddShift("SRC",0x0b); AddShift("SRL",0x09);
ImmOrders=(FixedOrder *) malloc(ImmOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddImm("AI" ,0x011); AddImm("ANDI",0x012); AddImm("CI" ,0x014);
AddImm("LI" ,0x010); AddImm("ORI" ,0x013);
RegOrders=(FixedOrder *) malloc(RegOrderCount*sizeof(FixedOrder)); InstrZ=0;
AddReg("STST",0x02c); AddReg("LST",0x008);
AddReg("STWP",0x02a); AddReg("LWP",0x009);
FixedOrders=(SupOrder *) malloc(FixedOrderCount*sizeof(SupOrder)); InstrZ=0;
AddFixed("RTWP",0x0380,False); AddFixed("IDLE",0x0340,True );
AddFixed("RSET",0x0360,True ); AddFixed("CKOF",0x03c0,True );
AddFixed("CKON",0x03a0,True ); AddFixed("LREX",0x03e0,True );
END
static void DeinitFields(void)
BEGIN
free(TwoOrders);
free(OneOrders);
free(SingOrders);
free(SBitOrders);
free(JmpOrders);
free(ShiftOrders);
free(ImmOrders);
free(RegOrders);
free(FixedOrders);
END
/*-------------------------------------------------------------------------*/
/* Adressparser */
static Boolean DecodeReg(char *Asc, Word *Erg)
BEGIN
Boolean OK;
*Erg=EvalIntExpression(Asc,UInt4,&OK); return OK;
END
static char *HasDisp(char *Asc)
BEGIN
char *p;
int Lev;
if (Asc[strlen(Asc)-1]==')')
BEGIN
p=Asc+strlen(Asc)-2; Lev=0;
while ((p>=Asc) AND (Lev!=-1))
BEGIN
switch (*p)
BEGIN
case '(': Lev--; break;
case ')': Lev++; break;
END
if (Lev!=-1) p--;
END
if (Lev!=-1)
BEGIN
WrError(1300); p=Nil;
END
END
else p=Nil;
return p;
END
static Boolean DecodeAdr(char *Asc)
BEGIN
Boolean IncFlag;
String Reg;
Boolean OK;
char *p;
AdrCnt=0;
if (*Asc=='*')
BEGIN
Asc++;
if (Asc[strlen(Asc)-1]=='+')
BEGIN
IncFlag=True; Asc[strlen(Asc)-1]='\0';
END
else IncFlag=False;
if (DecodeReg(Asc,&AdrPart))
BEGIN
AdrPart+=0x10+(Ord(IncFlag) << 5);
return True;
END
return False;
END
if (*Asc=='@')
BEGIN
Asc++; p=HasDisp(Asc);
if (p==Nil)
BEGIN
FirstPassUnknown=False;
AdrVal=EvalIntExpression(Asc,UInt16,&OK);
if (OK)
BEGIN
AdrPart=0x20; AdrCnt=1;
if ((NOT FirstPassUnknown) AND (IsWord) AND (Odd(AdrVal))) WrError(180);
return True;
END
END
else
BEGIN
strmaxcpy(Reg,p+1,255); Reg[strlen(Reg)-1]='\0';
if (DecodeReg(Reg,&AdrPart))
if (AdrPart==0) WrXError(1445,Reg);
else
BEGIN
*p='\0';
AdrVal=EvalIntExpression(Asc,Int16,&OK);
if (OK)
BEGIN
AdrPart+=0x20; AdrCnt=1; return True;
END
END
END
return False;
END
if (DecodeReg(Asc,&AdrPart)) return True;
else
BEGIN
WrError(1350); return False;
END
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
int z;
char *p;
Boolean OK;
TempResult t;
Word HVal16;
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 ((DoPadding) AND (Odd(HVal16))) HVal16++;
DontPrint=True; CodeLen=HVal16;
BookKeeping();
END
END
return True;
END
return False;
END
static void MakeCode_9900(void)
BEGIN
Word HPart;
Integer AdrInt;
int z;
Boolean OK;
CodeLen=0; DontPrint=False; IsWord=False;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodePseudo()) return;
/* zwei Operanden */
for (z=0; z<TwoOrderCount; z++)
if ((strncmp(OpPart,TwoOrders[z].Name,TwoOrders[z].NameLen)==0) AND (((OpPart[TwoOrders[z].NameLen]=='B') AND (OpPart[TwoOrders[z].NameLen+1]=='\0')) OR (OpPart[TwoOrders[z].NameLen]=='\0')))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (DecodeAdr(ArgStr[1]))
BEGIN
WAsmCode[0]=AdrPart; WAsmCode[1]=AdrVal;
HPart=AdrCnt;
if (DecodeAdr(ArgStr[2]))
BEGIN
WAsmCode[0]+=AdrPart << 6; WAsmCode[1+HPart]=AdrVal;
CodeLen=(1+HPart+AdrCnt) << 1;
if (OpPart[strlen(OpPart)-1]=='B') WAsmCode[0]+=0x1000;
WAsmCode[0]+=TwoOrders[z].Code << 13;
END
END
return;
END
for (z=0; z<OneOrderCount; z++)
if (Memo(OneOrders[z].Name))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (DecodeAdr(ArgStr[1]))
BEGIN
WAsmCode[0]=AdrPart; WAsmCode[1]=AdrVal;
if (DecodeReg(ArgStr[2],&HPart))
BEGIN
WAsmCode[0]+=(HPart << 6)+(OneOrders[z].Code << 10);
CodeLen=(1+AdrCnt) << 1;
END
END
return;
END
if ((Memo("LDCR")) OR (Memo("STCR")))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (DecodeAdr(ArgStr[1]))
BEGIN
WAsmCode[0]=0x3000+(Ord(Memo("STCR")) << 10)+AdrPart;
WAsmCode[1]=AdrVal;
FirstPassUnknown=False;
HPart=EvalIntExpression(ArgStr[2],UInt5,&OK);
if (FirstPassUnknown) HPart=1;
if (OK)
if (ChkRange(HPart,1,16))
BEGIN
WAsmCode[0]+=(HPart & 15) << 6;
CodeLen=(1+AdrCnt) << 1;
END
END
return;
END
for (z=0; z<ShiftOrderCount; z++)
if (Memo(ShiftOrders[z].Name))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (DecodeReg(ArgStr[1],WAsmCode+0))
BEGIN
if (DecodeReg(ArgStr[2],&HPart))
BEGIN
WAsmCode[0]+=(HPart << 4)+(ShiftOrders[z].Code << 8);
CodeLen=2;
END
END
return;
END
for (z=0; z<ImmOrderCount; z++)
if (Memo(ImmOrders[z].Name))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (DecodeReg(ArgStr[1],WAsmCode+0))
BEGIN
WAsmCode[1]=EvalIntExpression(ArgStr[2],Int16,&OK);
if (OK)
BEGIN
WAsmCode[0]+=(ImmOrders[z].Code << 5); CodeLen=4;
END
END
return;
END
for (z=0; z<RegOrderCount; z++)
if (Memo(RegOrders[z].Name))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (DecodeReg(ArgStr[1],WAsmCode+0))
BEGIN
WAsmCode[0]+=RegOrders[z].Code << 4; CodeLen=2;
END
return;
END;
if (Memo("LMF"))
BEGIN
if (ArgCnt!=2) WrError(1110);
else if (DecodeReg(ArgStr[1],WAsmCode+0))
BEGIN
WAsmCode[0]+=0x320+(EvalIntExpression(ArgStr[2],UInt1,&OK) << 4);
if (OK) CodeLen=2;
if (NOT SupAllowed) WrError(50);
END
return;
END
/* ein Operand */
if ((Memo("MPYS")) OR (Memo("DIVS")))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (DecodeAdr(ArgStr[1]))
BEGIN
WAsmCode[0]=0x0180+(Ord(Memo("MPYS")) << 6)+AdrPart;
WAsmCode[1]=AdrVal;
CodeLen=(1+AdrCnt) << 1;
END
return;
END
for (z=0; z<SingOrderCount; z++)
if (Memo(SingOrders[z].Name))
BEGIN
if (ArgCnt!=1) WrError(1110);
else if (DecodeAdr(ArgStr[1]))
BEGIN
WAsmCode[0]=SingOrders[z].Code+AdrPart;
WAsmCode[1]=AdrVal;
CodeLen=(1+AdrCnt) << 1;
if ((SingOrders[z].MustSup) AND (NOT SupAllowed)) WrError(50);
END
return;
END
for (z=0; z<SBitOrderCount; z++)
if (Memo(SBitOrders[z].Name))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
WAsmCode[0]=EvalIntExpression(ArgStr[1],SInt8,&OK);
if (OK)
BEGIN
WAsmCode[0]=(WAsmCode[0] & 0xff) | (SBitOrders[z].Code << 8);
CodeLen=2;
END
END
return;
END
for (z=0; z<JmpOrderCount; z++)
if (Memo(JmpOrders[z].Name))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
AdrInt=EvalIntExpression(ArgStr[1],UInt16,&OK)-(EProgCounter()+2);
if (OK)
if (Odd(AdrInt)) WrError(1375);
else if ((NOT SymbolQuestionable) AND ((AdrInt<-256) OR (AdrInt>254))) WrError(1370);
else
BEGIN
WAsmCode[0]=((AdrInt>>1) & 0xff) | (JmpOrders[z].Code << 8);
CodeLen=2;
END
END;
return;
END
if ((Memo("LWPI")) OR (Memo("LIMI")))
BEGIN
if (ArgCnt!=1) WrError(1110);
else
BEGIN
WAsmCode[1]=EvalIntExpression(ArgStr[1],UInt16,&OK);
if (OK)
BEGIN
WAsmCode[0]=(0x017+Ord(Memo("LIMI"))) << 5;
CodeLen=4;
END
END
return;
END
/* kein Operand */
for (z=0; z<FixedOrderCount; z++)
if (Memo(FixedOrders[z].Name))
BEGIN
if (ArgCnt!=0) WrError(1110);
else
BEGIN
WAsmCode[0]=FixedOrders[z].Code; CodeLen=2;
if ((FixedOrders[z].MustSup) AND (NOT SupAllowed)) WrError(50);
END
return;
END
WrXError(1200,OpPart);
END
static Boolean IsDef_9900(void)
BEGIN
return False;
END
static void SwitchFrom_9900(void)
BEGIN
DeinitFields(); ClearONOFF();
END
static void InternSymbol_9900(char *Asc, TempResult*Erg)
BEGIN
Boolean err;
char *h=Asc;
Erg->Typ=TempNone;
if ((strlen(Asc)>=2) AND (toupper(*Asc)=='R')) h=Asc+1;
else if ((strlen(Asc)>=3) AND (toupper(*Asc)=='W') AND (toupper(Asc[1])=='R')) h=Asc+2;
Erg->Contents.Int=ConstLongInt(h,&err);
if ((NOT err) OR (Erg->Contents.Int<0) OR (Erg->Contents.Int>15)) return;
Erg->Typ=TempInt;
END
static void SwitchTo_9900()
BEGIN
TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False;
PCSymbol="$"; HeaderID=0x48; NOPCode=0x0000;
DivideChars=","; HasAttrs=False;
ValidSegs=1<<SegCode;
Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
SegLimits[SegCode] = 0xffff;
MakeCode=MakeCode_9900; IsDef=IsDef_9900;
SwitchFrom=SwitchFrom_9900; InternSymbol=InternSymbol_9900;
AddONOFF("PADDING", &DoPadding , DoPaddingName ,False);
AddONOFF("SUPMODE", &SupAllowed, SupAllowedName,False);
InitFields();
END
void code9900_init(void)
BEGIN
CPU9900=AddCPU("TMS9900",SwitchTo_9900);
END