554 lines
14 KiB
C
554 lines
14 KiB
C
/* code3201x.c */
|
|
/*****************************************************************************/
|
|
/* AS-Portierung */
|
|
/* */
|
|
/* Codegenerator TMS3201x-Familie */
|
|
/* */
|
|
/* Historie: 28.11.1996 Grundsteinlegung */
|
|
/* 7. 7.1998 Fix Zugriffe auf CharTransTable wg. signed chars */
|
|
/* 18. 8.1992 BookKeeping-Aufruf in RES */
|
|
/* 2. 1.1999 ChkPC-Anpassung */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#include "stdinc.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "bpemu.h"
|
|
#include "strutil.h"
|
|
#include "chunks.h"
|
|
#include "asmdef.h"
|
|
#include "asmsub.h"
|
|
#include "asmpars.h"
|
|
#include "codepseudo.h"
|
|
#include "codevars.h"
|
|
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Code;
|
|
} FixedOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Code;
|
|
Boolean Must1;
|
|
} AdrOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Code;
|
|
Word AllowShifts;
|
|
} AdrShiftOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Code;
|
|
Integer Min,Max;
|
|
Word Mask;
|
|
} ImmOrder;
|
|
|
|
|
|
#define FixedOrderCnt 14
|
|
#define JmpOrderCnt 11
|
|
#define AdrOrderCnt 21
|
|
#define AdrShiftOrderCnt 5
|
|
#define ImmOrderCnt 3
|
|
|
|
|
|
static Word AdrMode;
|
|
static Boolean AdrOK;
|
|
|
|
static CPUVar CPU32010,CPU32015;
|
|
|
|
static FixedOrder *FixedOrders;
|
|
static FixedOrder *JmpOrders;
|
|
static AdrOrder *AdrOrders;
|
|
static AdrShiftOrder *AdrShiftOrders;
|
|
static ImmOrder *ImmOrders;
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
static void AddFixed(char *NName, Word NCode)
|
|
BEGIN
|
|
if (InstrZ>=FixedOrderCnt) exit(255);
|
|
FixedOrders[InstrZ].Name=NName;
|
|
FixedOrders[InstrZ++].Code=NCode;
|
|
END
|
|
|
|
static void AddJmp(char *NName, Word NCode)
|
|
BEGIN
|
|
if (InstrZ>=JmpOrderCnt) exit(255);
|
|
JmpOrders[InstrZ].Name=NName;
|
|
JmpOrders[InstrZ++].Code=NCode;
|
|
END
|
|
|
|
static void AddAdr(char *NName, Word NCode, Word NMust1)
|
|
BEGIN
|
|
if (InstrZ>=AdrOrderCnt) exit(255);
|
|
AdrOrders[InstrZ].Name=NName;
|
|
AdrOrders[InstrZ].Code=NCode;
|
|
AdrOrders[InstrZ++].Must1=NMust1;
|
|
END
|
|
|
|
static void AddAdrShift(char *NName, Word NCode, Word NAllow)
|
|
BEGIN
|
|
if (InstrZ>=AdrShiftOrderCnt) exit(255);
|
|
AdrShiftOrders[InstrZ].Name=NName;
|
|
AdrShiftOrders[InstrZ].Code=NCode;
|
|
AdrShiftOrders[InstrZ++].AllowShifts=NAllow;
|
|
END
|
|
|
|
static void AddImm(char *NName, Word NCode, Integer NMin, Integer NMax, Word NMask)
|
|
BEGIN
|
|
if (InstrZ>=ImmOrderCnt) exit(255);
|
|
ImmOrders[InstrZ].Name=NName;
|
|
ImmOrders[InstrZ].Code=NCode;
|
|
ImmOrders[InstrZ].Min=NMin;
|
|
ImmOrders[InstrZ].Max=NMax;
|
|
ImmOrders[InstrZ++].Mask=NMask;
|
|
END
|
|
|
|
static void InitFields(void)
|
|
BEGIN
|
|
FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ=0;
|
|
AddFixed("ABS" , 0x7f88); AddFixed("APAC" , 0x7f8f);
|
|
AddFixed("CALA" , 0x7f8c); AddFixed("DINT" , 0x7f81);
|
|
AddFixed("EINT" , 0x7f82); AddFixed("NOP" , 0x7f80);
|
|
AddFixed("PAC" , 0x7f8e); AddFixed("POP" , 0x7f9d);
|
|
AddFixed("PUSH" , 0x7f9c); AddFixed("RET" , 0x7f8d);
|
|
AddFixed("ROVM" , 0x7f8a); AddFixed("SOVM" , 0x7f8b);
|
|
AddFixed("SPAC" , 0x7f90); AddFixed("ZAC" , 0x7f89);
|
|
|
|
JmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*JmpOrderCnt); InstrZ=0;
|
|
AddJmp("B" , 0xf900); AddJmp("BANZ" , 0xf400);
|
|
AddJmp("BGEZ" , 0xfd00); AddJmp("BGZ" , 0xfc00);
|
|
AddJmp("BIOZ" , 0xf600); AddJmp("BLEZ" , 0xfb00);
|
|
AddJmp("BLZ" , 0xfa00); AddJmp("BNZ" , 0xfe00);
|
|
AddJmp("BV" , 0xf500); AddJmp("BZ" , 0xff00);
|
|
AddJmp("CALL" , 0xf800);
|
|
|
|
AdrOrders=(AdrOrder *) malloc(sizeof(AdrOrder)*AdrOrderCnt); InstrZ=0;
|
|
AddAdr("ADDH" , 0x6000, False); AddAdr("ADDS" , 0x6100, False);
|
|
AddAdr("AND" , 0x7900, False); AddAdr("DMOV" , 0x6900, False);
|
|
AddAdr("LDP" , 0x6f00, False); AddAdr("LST" , 0x7b00, False);
|
|
AddAdr("LT" , 0x6a00, False); AddAdr("LTA" , 0x6c00, False);
|
|
AddAdr("LTD" , 0x6b00, False); AddAdr("MAR" , 0x6800, False);
|
|
AddAdr("MPY" , 0x6d00, False); AddAdr("OR" , 0x7a00, False);
|
|
AddAdr("SST" , 0x7c00, True ); AddAdr("SUBC" , 0x6400, False);
|
|
AddAdr("SUBH" , 0x6200, False); AddAdr("SUBS" , 0x6300, False);
|
|
AddAdr("TBLR" , 0x6700, False); AddAdr("TBLW" , 0x7d00, False);
|
|
AddAdr("XOR" , 0x7800, False); AddAdr("ZALH" , 0x6500, False);
|
|
AddAdr("ZALS" , 0x6600, False);
|
|
|
|
AdrShiftOrders=(AdrShiftOrder *) malloc(sizeof(AdrShiftOrder)*AdrShiftOrderCnt); InstrZ=0;
|
|
AddAdrShift("ADD" , 0x0000, 0xffff);
|
|
AddAdrShift("LAC" , 0x2000, 0xffff);
|
|
AddAdrShift("SACH" , 0x5800, 0x0013);
|
|
AddAdrShift("SACL" , 0x5000, 0x0001);
|
|
AddAdrShift("SUB" , 0x1000, 0xffff);
|
|
|
|
ImmOrders=(ImmOrder *) malloc(sizeof(ImmOrder)*ImmOrderCnt); InstrZ=0;
|
|
AddImm("LACK", 0x7e00, 0, 255, 0xff);
|
|
AddImm("LDPK", 0x6e00, 0, 1, 0x1);
|
|
AddImm("MPYK", 0x8000, -4096, 4095, 0x1fff);
|
|
END
|
|
|
|
static void DeinitFields(void)
|
|
BEGIN
|
|
free(FixedOrders);
|
|
free(JmpOrders);
|
|
free(AdrOrders);
|
|
free(AdrShiftOrders);
|
|
free(ImmOrders);
|
|
END
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
static Word EvalARExpression(char *Asc, Boolean *OK)
|
|
BEGIN
|
|
*OK=True;
|
|
if (strcasecmp(Asc,"AR0")==0) return 0;
|
|
if (strcasecmp(Asc,"AR1")==0) return 1;
|
|
return EvalIntExpression(Asc,UInt1,OK);
|
|
END
|
|
|
|
static void DecodeAdr(char *Arg, int Aux, Boolean Must1)
|
|
BEGIN
|
|
Byte h;
|
|
char *p;
|
|
|
|
AdrOK=False;
|
|
|
|
if ((strcmp(Arg,"*")==0) OR (strcmp(Arg,"*-")==0) OR (strcmp(Arg,"*+")==0))
|
|
BEGIN
|
|
AdrMode=0x88;
|
|
if (strlen(Arg)==2)
|
|
AdrMode+=(Arg[1]=='+') ? 0x20 : 0x10;
|
|
if (Aux<=ArgCnt)
|
|
BEGIN
|
|
h=EvalARExpression(ArgStr[Aux],&AdrOK);
|
|
if (AdrOK)
|
|
BEGIN
|
|
AdrMode&=0xf7; AdrMode+=h;
|
|
END
|
|
END
|
|
else AdrOK=True;
|
|
END
|
|
else if (Aux<=ArgCnt) WrError(1110);
|
|
else
|
|
BEGIN
|
|
h=0;
|
|
if ((strlen(Arg)>3) AND (strncasecmp(Arg,"DAT",3)==0))
|
|
BEGIN
|
|
AdrOK=True;
|
|
for (p=Arg+3; *p!='\0'; p++)
|
|
if ((*p>'9') OR (*p<'0')) AdrOK=False;
|
|
if (AdrOK) h=EvalIntExpression(Arg+3,UInt8,&AdrOK);
|
|
END
|
|
if (NOT AdrOK) h=EvalIntExpression(Arg,Int8,&AdrOK);
|
|
if (AdrOK)
|
|
if ((Must1) AND (h<0x80) AND (NOT FirstPassUnknown))
|
|
BEGIN
|
|
WrError(1315); AdrOK=False;
|
|
END
|
|
else
|
|
BEGIN
|
|
AdrMode=h & 0x7f; ChkSpace(SegData);
|
|
END
|
|
END
|
|
END
|
|
|
|
static Boolean DecodePseudo(void)
|
|
BEGIN
|
|
Word Size;
|
|
int z,z2;
|
|
char *p;
|
|
TempResult t;
|
|
Boolean OK;
|
|
|
|
if (Memo("PORT"))
|
|
BEGIN
|
|
CodeEquate(SegIO,0,7);
|
|
return True;
|
|
END
|
|
|
|
if (Memo("RES"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
FirstPassUnknown=False;
|
|
Size=EvalIntExpression(ArgStr[1],Int16,&OK);
|
|
if (FirstPassUnknown) WrError(1820);
|
|
if ((OK) AND (NOT FirstPassUnknown))
|
|
BEGIN
|
|
DontPrint=True;
|
|
CodeLen=Size;
|
|
BookKeeping();
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if (Memo("DATA"))
|
|
BEGIN
|
|
if (ArgCnt==0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
OK=True;
|
|
for (z=1; z<=ArgCnt; z++)
|
|
if (OK)
|
|
BEGIN
|
|
EvalExpression(ArgStr[z],&t);
|
|
switch (t.Typ)
|
|
BEGIN
|
|
case TempInt:
|
|
if ((t.Contents.Int<-32768) OR (t.Contents.Int>0xffff))
|
|
BEGIN
|
|
WrError(1320); OK=False;
|
|
END
|
|
else WAsmCode[CodeLen++]=t.Contents.Int;
|
|
break;
|
|
case TempFloat:
|
|
WrError(1135); OK=False;
|
|
break;
|
|
case TempString:
|
|
for (p=t.Contents.Ascii,z2=0; *p!='\0'; p++,z2++)
|
|
BEGIN
|
|
if ((z2&1)==0)
|
|
WAsmCode[CodeLen]=CharTransTable[((usint)*p)&0xff];
|
|
else
|
|
WAsmCode[CodeLen++]+=((Word) CharTransTable[((usint)*p)&0xff]) << 8;
|
|
END
|
|
if ((z2&1)==0) CodeLen++;
|
|
break;
|
|
default:
|
|
OK=False;
|
|
END
|
|
END
|
|
if (NOT OK) CodeLen=0;
|
|
END
|
|
return True;
|
|
END
|
|
|
|
return False;
|
|
END
|
|
|
|
static void MakeCode_3201X(void)
|
|
BEGIN
|
|
Boolean OK,HasSh;
|
|
Word AdrWord;
|
|
LongInt AdrLong;
|
|
int z,Cnt;
|
|
|
|
CodeLen=0; DontPrint=False;
|
|
|
|
/* zu ignorierendes */
|
|
|
|
if (Memo("")) return;
|
|
|
|
/* Pseudoanweisungen */
|
|
|
|
if (DecodePseudo()) return;
|
|
|
|
/* kein Argument */
|
|
|
|
for (z=0; z<FixedOrderCnt; z++)
|
|
if (Memo(FixedOrders[z].Name))
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
CodeLen=1; WAsmCode[0]=FixedOrders[z].Code;
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Spruenge */
|
|
|
|
for (z=0; z<JmpOrderCnt; z++)
|
|
if (Memo(JmpOrders[z].Name))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
WAsmCode[1]=EvalIntExpression(ArgStr[1],UInt12,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
CodeLen=2; WAsmCode[0]=JmpOrders[z].Code;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* nur Adresse */
|
|
|
|
for (z=0; z<AdrOrderCnt; z++)
|
|
if (Memo(AdrOrders[z].Name))
|
|
BEGIN
|
|
if ((ArgCnt<1) OR (ArgCnt>2)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[1],2,AdrOrders[z].Must1);
|
|
if (AdrOK)
|
|
BEGIN
|
|
CodeLen=1; WAsmCode[0]=AdrOrders[z].Code+AdrMode;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Adresse & schieben */
|
|
|
|
for (z=0; z<AdrShiftOrderCnt; z++)
|
|
if (Memo(AdrShiftOrders[z].Name))
|
|
BEGIN
|
|
if ((ArgCnt<1) OR (ArgCnt>3)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (*ArgStr[1]=='*')
|
|
if (ArgCnt==2)
|
|
if (strncasecmp(ArgStr[2],"AR",2)==0)
|
|
BEGIN
|
|
HasSh=False; Cnt=2;
|
|
END
|
|
else
|
|
BEGIN
|
|
HasSh=True; Cnt=3;
|
|
END
|
|
else
|
|
BEGIN
|
|
HasSh=True; Cnt=3;
|
|
END
|
|
else
|
|
BEGIN
|
|
Cnt=3; HasSh=(ArgCnt==2);
|
|
END
|
|
DecodeAdr(ArgStr[1],Cnt,False);
|
|
if (AdrOK)
|
|
BEGIN
|
|
if (NOT HasSh)
|
|
BEGIN
|
|
OK=True; AdrWord=0;
|
|
END
|
|
else
|
|
BEGIN
|
|
AdrWord=EvalIntExpression(ArgStr[2],Int4,&OK);
|
|
if ((OK) AND (FirstPassUnknown)) AdrWord=0;
|
|
END
|
|
if (OK)
|
|
if ((AdrShiftOrders[z].AllowShifts & (1 << AdrWord))==0) WrError(1380);
|
|
else
|
|
BEGIN
|
|
CodeLen=1; WAsmCode[0]=AdrShiftOrders[z].Code+AdrMode+(AdrWord << 8);
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Ein/Ausgabe */
|
|
|
|
if ((Memo("IN")) OR (Memo("OUT")))
|
|
BEGIN
|
|
if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[1],3,False);
|
|
if (AdrOK)
|
|
BEGIN
|
|
AdrWord=EvalIntExpression(ArgStr[2],UInt3,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
ChkSpace(SegIO);
|
|
CodeLen=1;
|
|
WAsmCode[0]=0x4000+AdrMode+(AdrWord << 8);
|
|
if (Memo("OUT")) WAsmCode[0]+=0x800;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* konstantes Argument */
|
|
|
|
for (z=0; z<ImmOrderCnt; z++)
|
|
if (Memo(ImmOrders[z].Name))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
if (FirstPassUnknown) AdrLong&=ImmOrders[z].Mask;
|
|
if (AdrLong<ImmOrders[z].Min) WrError(1315);
|
|
else if (AdrLong>ImmOrders[z].Max) WrError(1320);
|
|
else
|
|
BEGIN
|
|
CodeLen=1; WAsmCode[0]=ImmOrders[z].Code+(AdrLong & ImmOrders[z].Mask);
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* mit Hilfsregistern */
|
|
|
|
if (Memo("LARP"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
BEGIN
|
|
AdrWord=EvalARExpression(ArgStr[1],&OK);
|
|
if (OK)
|
|
BEGIN
|
|
CodeLen=1; WAsmCode[0]=0x6880+AdrWord;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("LAR")) OR (Memo("SAR")))
|
|
BEGIN
|
|
if ((ArgCnt<2) OR (ArgCnt>3)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
AdrWord=EvalARExpression(ArgStr[1],&OK);
|
|
if (OK)
|
|
BEGIN
|
|
DecodeAdr(ArgStr[2],3,False);
|
|
if (AdrOK)
|
|
BEGIN
|
|
CodeLen=1;
|
|
WAsmCode[0]=0x3000+AdrMode+(AdrWord << 8);
|
|
if (Memo("LAR")) WAsmCode[0]+=0x800;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("LARK"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
AdrWord=EvalARExpression(ArgStr[1],&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]=EvalIntExpression(ArgStr[2],Int8,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
CodeLen=1;
|
|
WAsmCode[0]=Lo(WAsmCode[0])+0x7000+(AdrWord << 8);
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
WrXError(1200,OpPart);
|
|
END
|
|
|
|
static Boolean IsDef_3201X(void)
|
|
BEGIN
|
|
return (Memo("PORT"));
|
|
END
|
|
|
|
static void SwitchFrom_3201X(void)
|
|
BEGIN
|
|
DeinitFields();
|
|
END
|
|
|
|
static void SwitchTo_3201X(void)
|
|
BEGIN
|
|
TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
|
|
|
|
PCSymbol="$"; HeaderID=0x74; NOPCode=0x7f80;
|
|
DivideChars=","; HasAttrs=False;
|
|
|
|
ValidSegs=(1<<SegCode)|(1<<SegData)|(1<<SegIO);
|
|
Grans[SegCode]=2; ListGrans[SegCode]=2; SegInits[SegCode]=0;
|
|
SegLimits[SegCode] = 0xfff;
|
|
Grans[SegData]=2; ListGrans[SegData]=2; SegInits[SegData]=0;
|
|
SegLimits[SegData] = (MomCPU==CPU32010) ? 0x8f : 0xff;
|
|
Grans[SegIO ]=2; ListGrans[SegIO ]=2; SegInits[SegIO ]=0;
|
|
SegLimits[SegIO ] = 7;
|
|
|
|
MakeCode=MakeCode_3201X; IsDef=IsDef_3201X;
|
|
SwitchFrom=SwitchFrom_3201X; InitFields();
|
|
END
|
|
|
|
void code3201x_init(void)
|
|
BEGIN
|
|
CPU32010=AddCPU("32010",SwitchTo_3201X);
|
|
CPU32015=AddCPU("32015",SwitchTo_3201X);
|
|
END
|