2314 lines
64 KiB
C
2314 lines
64 KiB
C
/* code3206x.c */
|
|
/*****************************************************************************/
|
|
/* AS-Portierung */
|
|
/* */
|
|
/* Codegenerator TMS320C6x */
|
|
/* */
|
|
/* Historie: 24. 2.1997 Grundsteinlegung */
|
|
/* 22. 5.1998 Schoenheitsoperatioenen fuer K&R-Compiler */
|
|
/* 3. 1.1999 ChkPC-Anpassung */
|
|
/* 23. 1.1999 DecodeCtrlReg jetzt mit unsigned-Ergebnis */
|
|
/* 30. 1.1999 Formate maschinenunabhaengig gemacht */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#include "stdinc.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "strutil.h"
|
|
#include "bpemu.h"
|
|
#include "nls.h"
|
|
#include "asmdef.h"
|
|
#include "asmsub.h"
|
|
#include "asmpars.h"
|
|
#include "asmcode.h"
|
|
#include "codepseudo.h"
|
|
#include "asmitree.h"
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
typedef enum {NoUnit,L1,L2,S1,S2,M1,M2,D1,D2,LastUnit,UnitCnt} TUnit;
|
|
|
|
typedef struct
|
|
{
|
|
LongInt OpCode;
|
|
LongInt SrcMask,SrcMask2,DestMask;
|
|
Byte CrossUsed; /* Bit 0 -->X1 benutzt, Bit 1 -->X2 benutzt */
|
|
Byte AddrUsed; /* Bit 0 -->Addr1 benutzt, Bit 1 -->Addr2 benutzt
|
|
Bit 2 -->LdSt1 benutzt, Bit 3 -->LdSt2 benutzt */
|
|
Byte LongUsed; /* Bit 0 -->lange Quelle, Bit 1-->langes Ziel */
|
|
Boolean StoreUsed,LongSrc,LongDest;
|
|
TUnit U;
|
|
} InstrRec;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
LongInt Code;
|
|
} FixedOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
LongInt Code;
|
|
LongInt Scale;
|
|
} MemOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
LongInt Code;
|
|
Boolean DSign,SSign1,SSign2;
|
|
Boolean MayImm;
|
|
} MulOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
LongInt Code;
|
|
Boolean Rd,Wr;
|
|
} CtrlReg;
|
|
|
|
static char *UnitNames[UnitCnt]={" ","L1","L2","S1","S2","M1","M2","D1","D2"," "};
|
|
#define MaxParCnt 8
|
|
#define FirstUnit L1
|
|
|
|
#define LinAddCnt 6
|
|
#define CmpCnt 5
|
|
#define MemCnt 8
|
|
#define MulCnt 20
|
|
#define CtrlCnt 13
|
|
|
|
#define ModNone (-1)
|
|
#define ModReg 0
|
|
#define MModReg (1 << ModReg)
|
|
#define ModLReg 1
|
|
#define MModLReg (1 << ModLReg)
|
|
#define ModImm 2
|
|
#define MModImm (1 << ModImm)
|
|
|
|
static ShortInt AdrMode;
|
|
|
|
static CPUVar CPU32060;
|
|
|
|
static Boolean ThisPar,ThisCross,ThisStore;
|
|
static Byte ThisAddr,ThisLong;
|
|
static LongInt ThisSrc,ThisSrc2,ThisDest;
|
|
static LongInt Condition;
|
|
static TUnit ThisUnit;
|
|
static LongWord UnitFlag,ThisInst;
|
|
static Integer ParCnt;
|
|
static LongWord PacketAddr;
|
|
|
|
static InstrRec ParRecs[MaxParCnt];
|
|
|
|
FixedOrder *LinAddOrders;
|
|
FixedOrder *CmpOrders;
|
|
MemOrder *MemOrders;
|
|
MulOrder *MulOrders;
|
|
CtrlReg *CtrlRegs;
|
|
PInstTable InstTable;
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static Boolean CheckOpt(char *Asc)
|
|
BEGIN
|
|
Boolean Flag,erg=True;
|
|
int l=strlen(Asc);
|
|
|
|
if (strcmp(Asc,"||")==0) ThisPar=True;
|
|
else if ((*Asc=='[') AND (Asc[l-1]==']'))
|
|
BEGIN
|
|
Asc++; Asc[l-2]='\0'; l-=2;
|
|
if (*Asc=='!')
|
|
BEGIN
|
|
Asc++; l--; Condition=1;
|
|
END
|
|
else Condition=0;
|
|
Flag=True;
|
|
if (l!=2) Flag=False;
|
|
else if (toupper(*Asc)=='A')
|
|
if ((Asc[1]>='1') AND (Asc[1]<='2')) Condition+=(Asc[1]-'0'+3) << 1;
|
|
else Flag=False;
|
|
else if (toupper(*Asc)=='B')
|
|
if ((Asc[1]>='0') AND (Asc[1]<='2')) Condition+=(Asc[1]-'0'+1) << 1;
|
|
else Flag=False;
|
|
if (NOT Flag) WrXError(1445,Asc); erg=Flag;
|
|
END
|
|
else erg=False;
|
|
|
|
return erg;
|
|
END
|
|
|
|
static Boolean ReiterateOpPart(void)
|
|
BEGIN
|
|
char *p;
|
|
int z;
|
|
|
|
if (NOT CheckOpt(OpPart)) return False;
|
|
|
|
if (ArgCnt<1)
|
|
BEGIN
|
|
WrError(1210); return False;
|
|
END
|
|
p=FirstBlank(ArgStr[1]);
|
|
if (p==Nil)
|
|
BEGIN
|
|
strcpy(OpPart,ArgStr[1]);
|
|
for (z=2; z<=ArgCnt; z++) strcpy(ArgStr[z-1],ArgStr[z]);
|
|
ArgCnt--;
|
|
END
|
|
else
|
|
BEGIN
|
|
*p='\0'; strcpy(OpPart,ArgStr[1]); strcpy(ArgStr[1],p+1);
|
|
KillPrefBlanks(ArgStr[1]);
|
|
END
|
|
NLS_UpString(OpPart);
|
|
p=strchr(OpPart,'.');
|
|
if (p==Nil) *AttrPart='\0';
|
|
else
|
|
BEGIN
|
|
strcpy(AttrPart,p+1);
|
|
*p='\0';
|
|
END;
|
|
return True;
|
|
END
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static void AddSrc(LongWord Reg)
|
|
BEGIN
|
|
LongWord Mask=1 << Reg;
|
|
|
|
if ((ThisSrc & Mask)==0) ThisSrc|=Mask;
|
|
else ThisSrc2|=Mask;
|
|
END
|
|
|
|
static void AddLSrc(LongWord Reg)
|
|
BEGIN
|
|
AddSrc(Reg); AddSrc(Reg+1);
|
|
ThisLong|=1;
|
|
END
|
|
|
|
static void AddDest(LongWord Reg)
|
|
BEGIN
|
|
ThisDest|=(1 << Reg);
|
|
END
|
|
|
|
static void AddLDest(LongWord Reg)
|
|
BEGIN
|
|
ThisDest|=(3 << Reg);
|
|
ThisLong|=2;
|
|
END
|
|
|
|
static LongInt FindReg(LongInt Mask)
|
|
BEGIN
|
|
int z;
|
|
|
|
for (z=0; z<32; z++)
|
|
BEGIN
|
|
if ((Mask&1)!=0) break;
|
|
Mask=Mask >> 1;
|
|
END
|
|
return z;
|
|
END
|
|
|
|
static char *RegName(LongInt Num)
|
|
BEGIN
|
|
static char s[5];
|
|
|
|
Num&=31;
|
|
sprintf(s, "%c%ld", 'A' + (Num >> 4), (long) (Num & 15));
|
|
return s;
|
|
END
|
|
|
|
static Boolean DecodeSReg(char *Asc, LongWord *Reg, Boolean Quarrel)
|
|
BEGIN
|
|
char *end;
|
|
Byte RVal;
|
|
Boolean TFlag;
|
|
|
|
TFlag=True;
|
|
if (toupper(*Asc)=='A') *Reg=0;
|
|
else if (toupper(*Asc)=='B') *Reg=16;
|
|
else TFlag=False;
|
|
if (TFlag)
|
|
BEGIN
|
|
RVal=strtol(Asc+1,&end,10);
|
|
if (*end!='\0') TFlag=False;
|
|
else if (RVal>15) TFlag=False;
|
|
else *Reg+=RVal;
|
|
END
|
|
if ((NOT TFlag) AND (Quarrel)) WrXError(1445,Asc);
|
|
return TFlag;
|
|
END
|
|
|
|
static Boolean DecodeReg(char *Asc, LongWord *Reg, Boolean *PFlag, Boolean Quarrel)
|
|
BEGIN
|
|
char *p;
|
|
LongWord NextReg;
|
|
|
|
p=strchr(Asc,':');
|
|
if (p==0)
|
|
BEGIN
|
|
*PFlag=False; return DecodeSReg(Asc,Reg,Quarrel);
|
|
END
|
|
else
|
|
BEGIN
|
|
*PFlag=True; *p='\0';
|
|
if (NOT DecodeSReg(Asc,&NextReg,Quarrel)) return False;
|
|
else if (NOT DecodeSReg(p+1,Reg,Quarrel)) return False;
|
|
else if ((Odd(*Reg)) OR (NextReg!=(*Reg)+1) OR ((((*Reg) ^ NextReg) & 0x10)!=0))
|
|
BEGIN
|
|
if (Quarrel) WrXError(1760,Asc); return False;
|
|
END
|
|
else return True;
|
|
END
|
|
END
|
|
|
|
static Boolean DecodeCtrlReg(char *Asc, LongWord *Erg, Boolean Write)
|
|
BEGIN
|
|
int z;
|
|
|
|
for (z=0; z<CtrlCnt; z++)
|
|
if (strcasecmp(Asc,CtrlRegs[z].Name)==0)
|
|
BEGIN
|
|
*Erg=CtrlRegs[z].Code;
|
|
return (Write AND CtrlRegs[z].Wr) OR ((NOT Write) AND CtrlRegs[z].Rd);
|
|
END
|
|
return False;
|
|
END
|
|
|
|
/* Was bedeutet das r-Feld im Adressoperanden mit kurzem Offset ???
|
|
und wie ist das genau mit der Skalierung gemeint ??? */
|
|
|
|
static Boolean DecodeMem(char *Asc, LongWord *Erg, LongWord Scale)
|
|
BEGIN
|
|
String RegPart,DispPart;
|
|
LongInt DispAcc,Mode;
|
|
LongWord BaseReg,IndReg;
|
|
int l;
|
|
char Counter;
|
|
char *p;
|
|
Boolean OK;
|
|
|
|
/* das muss da sein */
|
|
|
|
if (*Asc!='*')
|
|
BEGIN
|
|
WrError(1350); return False;
|
|
END;
|
|
Asc++;
|
|
|
|
/* teilen */
|
|
|
|
p=strchr(Asc,'['); Counter=']';
|
|
if (p==Nil)
|
|
BEGIN
|
|
p=strchr(Asc,'('); Counter=')';
|
|
END
|
|
if (p!=Nil)
|
|
BEGIN
|
|
if (Asc[strlen(Asc)-1]!=Counter)
|
|
BEGIN
|
|
WrError(1350); return False;
|
|
END
|
|
Asc[strlen(Asc)-1]='\0'; *p='\0';
|
|
strmaxcpy(RegPart,Asc,255); strmaxcpy(DispPart,p+1,255);
|
|
END
|
|
else
|
|
BEGIN
|
|
strcpy(RegPart,Asc); *DispPart='\0';
|
|
END
|
|
|
|
/* Registerfeld entschluesseln */
|
|
|
|
l=strlen(RegPart);
|
|
Mode=1; /* Default ist *+R */
|
|
if (*RegPart=='+')
|
|
BEGIN
|
|
strcpy(RegPart,RegPart+1); Mode=1;
|
|
if (*RegPart=='+')
|
|
BEGIN
|
|
strcpy(RegPart,RegPart+1); Mode=9;
|
|
END
|
|
END
|
|
else if (*RegPart=='-')
|
|
BEGIN
|
|
strcpy(RegPart,RegPart+1); Mode=0;
|
|
if (*RegPart=='-')
|
|
BEGIN
|
|
strcpy(RegPart,RegPart+1); Mode=8;
|
|
END
|
|
END
|
|
else if (RegPart[l-1]=='+')
|
|
BEGIN
|
|
if (RegPart[l-2]!='+')
|
|
BEGIN
|
|
WrError(1350); return False;
|
|
END
|
|
RegPart[l-2]='\0'; Mode=11;
|
|
END
|
|
else if (RegPart[l-1]=='-')
|
|
BEGIN
|
|
if (RegPart[l-2]!='-')
|
|
BEGIN
|
|
WrError(1350); return False;
|
|
END
|
|
RegPart[l-2]='\0'; Mode=10;
|
|
END
|
|
if (NOT DecodeSReg(RegPart,&BaseReg,False))
|
|
BEGIN
|
|
WrXError(1445,RegPart); return False;
|
|
END
|
|
AddSrc(BaseReg);
|
|
|
|
/* kein Offsetfeld ? --> Skalierungsgroesse bei Autoinkrement/De-
|
|
krement, sonst 0 */
|
|
|
|
if (*DispPart=='\0')
|
|
DispAcc=(Mode<2) ? 0 : Scale;
|
|
|
|
/* Register als Offsetfeld? Dann Bit 2 in Modus setzen */
|
|
|
|
else if (DecodeSReg(DispPart,&IndReg,False))
|
|
BEGIN
|
|
if ((IndReg ^ BaseReg)>15)
|
|
BEGIN
|
|
WrError(1350); return False;
|
|
END
|
|
Mode+=4; AddSrc(DispAcc=IndReg);
|
|
END
|
|
|
|
/* ansonsten normaler Offset */
|
|
|
|
else
|
|
BEGIN
|
|
FirstPassUnknown=False;
|
|
DispAcc=EvalIntExpression(DispPart,UInt15,&OK);
|
|
if (NOT OK) return False;
|
|
if (FirstPassUnknown) DispAcc&=7;
|
|
if (Counter==']') DispAcc*=Scale;
|
|
END
|
|
|
|
/* Benutzung des Adressierers markieren */
|
|
|
|
ThisAddr|=(BaseReg>15) ? 2 : 1;
|
|
|
|
/* Wenn Offset>31, muessen wir Variante 2 benutzen */
|
|
|
|
if (((Mode & 4)==0) AND (DispAcc>31))
|
|
if ((BaseReg<0x1e) OR (Mode!=1)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
*Erg=((DispAcc & 0x7fff) << 8)+((BaseReg & 1) << 7)+12;
|
|
return True;
|
|
END
|
|
|
|
else
|
|
BEGIN
|
|
*Erg=(BaseReg << 18)+((DispAcc & 0x1f) << 13)+(Mode << 9)
|
|
+((BaseReg & 0x10) << 3)+4;
|
|
return True;
|
|
END
|
|
|
|
return False;
|
|
END
|
|
|
|
static Boolean DecodeAdr(char *Asc, Byte Mask, Boolean Signed, LongWord *AdrVal)
|
|
BEGIN
|
|
Boolean OK;
|
|
|
|
AdrMode=ModNone;
|
|
|
|
if (DecodeReg(Asc,AdrVal,&OK,False))
|
|
BEGIN
|
|
AdrMode=(OK) ? ModLReg : ModReg;
|
|
END
|
|
else
|
|
BEGIN
|
|
if (Signed) *AdrVal=EvalIntExpression(Asc,SInt5,&OK) & 0x1f;
|
|
else *AdrVal=EvalIntExpression(Asc,UInt5,&OK);
|
|
if (OK) AdrMode=ModImm;
|
|
END
|
|
|
|
if ((AdrMode!=ModNone) AND (((1 << AdrMode) AND Mask)==0))
|
|
BEGIN
|
|
WrError(1350); AdrMode=ModNone; return False;
|
|
END
|
|
else return True;
|
|
END
|
|
|
|
static Boolean ChkUnit(LongWord Reg, TUnit U1, TUnit U2)
|
|
BEGIN
|
|
UnitFlag=Ord(Reg>15);
|
|
if (ThisUnit==NoUnit)
|
|
BEGIN
|
|
ThisUnit=(Reg>15) ? U2 : U1;
|
|
return True;
|
|
END
|
|
else if (((ThisUnit==U1) AND (Reg<16)) OR ((ThisUnit==U2) AND (Reg>15))) return True;
|
|
else
|
|
BEGIN
|
|
WrError(1107); return False;
|
|
END
|
|
END
|
|
|
|
static TUnit UnitCode(char c)
|
|
BEGIN
|
|
switch (c)
|
|
BEGIN
|
|
case 'L': return L1;
|
|
case 'S': return S1;
|
|
case 'D': return D1;
|
|
case 'M': return M1;
|
|
default: return NoUnit;
|
|
END
|
|
END
|
|
|
|
static Boolean UnitUsed(TUnit TestUnit)
|
|
BEGIN
|
|
Integer z;
|
|
|
|
for (z=0; z<ParCnt; z++)
|
|
if (ParRecs[z].U==TestUnit) return True;
|
|
|
|
return False;
|
|
END
|
|
|
|
static Boolean IsCross(LongWord Reg)
|
|
BEGIN
|
|
return (Reg >> 4)!=UnitFlag;
|
|
END
|
|
|
|
static void SetCross(LongWord Reg)
|
|
BEGIN
|
|
ThisCross=((Reg >> 4)!=UnitFlag);
|
|
END
|
|
|
|
static Boolean DecideUnit(LongWord Reg, char *Units)
|
|
BEGIN
|
|
Integer z;
|
|
TUnit TestUnit;
|
|
|
|
if (ThisUnit==NoUnit)
|
|
BEGIN
|
|
z=0;
|
|
while ((Units[z]!='\0') AND (ThisUnit==NoUnit))
|
|
BEGIN
|
|
TestUnit=UnitCode(Units[z]);
|
|
if (Reg>=16) TestUnit++;
|
|
if (NOT UnitUsed(TestUnit)) ThisUnit=TestUnit;
|
|
z++;
|
|
END
|
|
if (ThisUnit==NoUnit)
|
|
BEGIN
|
|
ThisUnit=UnitCode(*Units);
|
|
if (Reg>16) TestUnit++;
|
|
END
|
|
END
|
|
UnitFlag=(ThisUnit-FirstUnit) & 1;
|
|
if (IsCross(Reg))
|
|
BEGIN
|
|
WrError(1107); return False;
|
|
END
|
|
else return True;
|
|
END
|
|
|
|
static void SwapReg(LongWord *r1, LongWord *r2)
|
|
BEGIN
|
|
LongWord tmp;
|
|
|
|
tmp=(*r1); *r1=(*r2); *r2=tmp;
|
|
END
|
|
|
|
static Boolean DecodePseudo(void)
|
|
BEGIN
|
|
return False;
|
|
END
|
|
|
|
|
|
static Boolean CodeL(LongWord OpCode,LongWord Dest,LongWord Src1,LongWord Src2)
|
|
BEGIN
|
|
ThisInst=0x18+(OpCode << 5)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
|
|
+(Dest << 23)+(Src2 << 18)+(Src1 << 13);
|
|
return True;
|
|
END
|
|
|
|
static Boolean CodeM(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
|
|
BEGIN
|
|
ThisInst=0x00+(OpCode << 7)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
|
|
+(Dest << 23)+(Src2 << 18)+(Src1 << 13);
|
|
return True;
|
|
END
|
|
|
|
static Boolean CodeS(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
|
|
BEGIN
|
|
ThisInst=0x20+(OpCode << 6)+(UnitFlag << 1)+(Ord(ThisCross) << 12)
|
|
+(Dest << 23)+(Src2 << 18)+(Src1 << 13);
|
|
return True;
|
|
END
|
|
|
|
static Boolean CodeD(LongWord OpCode, LongWord Dest, LongWord Src1, LongWord Src2)
|
|
BEGIN
|
|
ThisInst=0x40+(OpCode << 7)+(UnitFlag << 1)
|
|
+(Dest << 23)+(Src2 << 18)+(Src1 << 13);
|
|
return True;
|
|
END
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static Boolean __erg;
|
|
|
|
static void DecodeIDLE(Word Index)
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else if ((ThisCross) OR (ThisUnit!=NoUnit)) WrError(1107);
|
|
else
|
|
BEGIN
|
|
ThisInst=0x0001e000; __erg=True;
|
|
END
|
|
END
|
|
|
|
static void DecodeNOP(Word Index)
|
|
BEGIN
|
|
LongInt Count;
|
|
Boolean OK;
|
|
|
|
if ((ArgCnt!=0) AND (ArgCnt!=1)) WrError(1110);
|
|
else if ((ThisCross) OR (ThisUnit!=NoUnit)) WrError(1107);
|
|
else
|
|
BEGIN
|
|
if (ArgCnt==0)
|
|
BEGIN
|
|
OK=True; Count=0;
|
|
END
|
|
else
|
|
BEGIN
|
|
FirstPassUnknown=False;
|
|
Count=EvalIntExpression(ArgStr[1],UInt4,&OK);
|
|
if (FirstPassUnknown) Count=0; else Count--;
|
|
OK=ChkRange(Count,0,8);
|
|
END
|
|
if (OK)
|
|
BEGIN
|
|
ThisInst=Count << 13; __erg=True;
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeMul(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg,S2Reg;
|
|
MulOrder *POrder=MulOrders+Index;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,POrder->DSign,&DReg))
|
|
if (ChkUnit(DReg,M1,M2))
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,POrder->SSign2,&S2Reg))
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
DecodeAdr(ArgStr[1],(POrder->MayImm?MModImm:0)+MModReg,
|
|
POrder->SSign1,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg)) AND (NOT IsCross(S1Reg))) WrError(1350);
|
|
else if ((IsCross(S2Reg)) AND (IsCross(S1Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
|
|
SetCross(S2Reg);
|
|
AddSrc(S1Reg);
|
|
__erg=CodeM(POrder->Code,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if (Memo("MPY")) __erg=CodeM(POrder->Code-1,DReg,S1Reg,S2Reg);
|
|
else __erg=CodeM(POrder->Code+3,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeMemO(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg;
|
|
MemOrder *POrder=MemOrders+Index;
|
|
Boolean OK,IsStore;
|
|
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
IsStore=(*OpPart)=='S';
|
|
if (IsStore)
|
|
BEGIN
|
|
strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]);
|
|
strcpy(ArgStr[2],ArgStr[3]);
|
|
ThisStore=True;
|
|
END
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
|
|
BEGIN
|
|
if (IsStore) AddSrc(DReg);
|
|
ThisAddr|=(DReg>15) ? 8 : 4;
|
|
/* Zielregister 4 Takte verzoegert, nicht als Dest eintragen */
|
|
OK=DecodeMem(ArgStr[1],&S1Reg,POrder->Scale);
|
|
if (OK)
|
|
if ((S1Reg & 8)==0) OK=ChkUnit((S1Reg >> 18) & 31,D1,D2);
|
|
else OK=ChkUnit(0x1e,D1,D2);
|
|
if (OK)
|
|
BEGIN
|
|
ThisInst=S1Reg+(DReg << 23)+(POrder->Code << 4)
|
|
+((DReg & 16) >> 3);
|
|
__erg=True;
|
|
END
|
|
END;
|
|
END
|
|
END
|
|
|
|
static void DecodeSTP(Word Index)
|
|
BEGIN
|
|
LongWord S2Reg;
|
|
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (ChkUnit(0x10,S1,S2))
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[1],MModReg,False,&S2Reg))
|
|
if ((ThisCross) OR (S2Reg<16)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
__erg=CodeS(0x0c,0,0,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeABS(Word Index)
|
|
BEGIN
|
|
Boolean DPFlag,S1Flag;
|
|
LongWord DReg,S1Reg;
|
|
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (DecodeReg(ArgStr[2],&DReg,&DPFlag,True))
|
|
if (ChkUnit(DReg,L1,L2))
|
|
if (DecodeReg(ArgStr[1],&S1Reg,&S1Flag,True))
|
|
if (DPFlag!=S1Flag) WrError(1350);
|
|
else if ((ThisCross) AND ((S1Reg >> 4)==UnitFlag)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S1Reg);
|
|
if (DPFlag) __erg=CodeL(0x38,DReg,0,S1Reg);
|
|
else __erg=CodeL(0x1a,DReg,0,S1Reg);
|
|
if (DPFlag) AddLSrc(S1Reg); else AddSrc(S1Reg);
|
|
if (DPFlag) AddLDest(DReg); else AddDest(DReg);
|
|
END
|
|
END
|
|
|
|
static void DecodeADD(Word Index)
|
|
BEGIN
|
|
LongWord S1Reg,S2Reg,DReg;
|
|
Boolean OK;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
|
|
UnitFlag=DReg >> 4;
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModLReg: /* ADD ?,?,long */
|
|
AddLDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModLReg+MModImm,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADD int,?,long */
|
|
AddSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModLReg,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADD int,int,long */
|
|
if (ChkUnit(DReg,L1,L2))
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
|
|
SetCross(S2Reg);
|
|
__erg=CodeL(0x23,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModLReg:/* ADD int,long,long */
|
|
if (ChkUnit(DReg,L1,L2))
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
SetCross(S1Reg);
|
|
__erg=CodeL(0x21,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModLReg: /* ADD long,?,long */
|
|
AddLSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADD long,int,long */
|
|
if (ChkUnit(DReg,L1,L2))
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
SetCross(S2Reg);
|
|
__erg=CodeL(0x21,DReg,S2Reg,S1Reg);
|
|
END
|
|
break;
|
|
case ModImm: /* ADD long,imm,long */
|
|
if (ChkUnit(DReg,L1,L2))
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else if (ThisCross) WrError(1350);
|
|
else __erg=CodeL(0x20,DReg,S2Reg,S1Reg);
|
|
break;
|
|
END
|
|
break;
|
|
case ModImm: /* ADD imm,?,long */
|
|
if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
|
|
BEGIN /* ADD imm,long,long */
|
|
if (ChkUnit(DReg,L1,L2))
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else if (ThisCross) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
__erg=CodeL(0x20,DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModReg: /* ADD ?,?,int */
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADD int,?,int */
|
|
AddSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADD int,int,int */
|
|
AddSrc(S2Reg);
|
|
if (((DReg^S1Reg)>15) AND ((DReg^S2Reg)>15)) WrError(1350);
|
|
else if ((ThisCross) AND ((DReg^S1Reg)<16) AND ((DReg^S2Reg)<15)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
if ((S1Reg^DReg)>15) SwapReg(&S1Reg,&S2Reg);
|
|
OK=DecideUnit(DReg,((S2Reg^DReg)>15) ? "LS" : "LSD");
|
|
if (OK)
|
|
BEGIN
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case L2: __erg=CodeL(0x03,DReg,S1Reg,S2Reg); break; /* ADD.Lx int,int,int */
|
|
case S1: case S2: __erg=CodeS(0x07,DReg,S1Reg,S2Reg); break; /* ADD.Sx int,int,int */
|
|
case D1: case D2: __erg=CodeD(0x10,DReg,S1Reg,S2Reg); break; /* ADD.Dx int,int,int */
|
|
default: WrError(20000);
|
|
END
|
|
END
|
|
END
|
|
break;
|
|
case ModImm: /* ADD int,imm,int */
|
|
if ((ThisCross) AND ((S1Reg^DReg)<16)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S1Reg);
|
|
if (DecideUnit(DReg,"LS"))
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case L2: __erg=CodeL(0x02,DReg,S2Reg,S1Reg); break;
|
|
case S1: case S2: __erg=CodeS(0x06,DReg,S2Reg,S1Reg); break;
|
|
default: WrError(20000);
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModImm: /* ADD imm,?,int */
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S2Reg);
|
|
if (DecideUnit(DReg,"LS"))
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case L2: __erg=CodeL(0x02,DReg,S1Reg,S2Reg); break;
|
|
case S1: case S2: __erg=CodeS(0x06,DReg,S1Reg,S2Reg); break;
|
|
default: WrError(20000);
|
|
END
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeADDU(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg,S2Reg;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[3],MModReg+MModLReg,False,&DReg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADDU ?,?,int */
|
|
if (ChkUnit(DReg,D1,D2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModImm,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADDU int,?,int */
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModImm,False,&S2Reg))
|
|
__erg=CodeD(0x12,DReg,S2Reg,S1Reg);
|
|
END
|
|
break;
|
|
case ModImm: /* ADDU imm,?,int */
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
__erg=CodeD(0x12,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
case ModLReg: /* ADDU ?,?,long */
|
|
if (ChkUnit(DReg,L1,L2))
|
|
BEGIN
|
|
AddLDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModLReg,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADDU int,?,long */
|
|
AddSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModLReg,False,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg: /* ADDU int,int,long */
|
|
if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else if ((ThisCross) AND (((S1Reg^DReg)<16) AND ((S2Reg^DReg)<16))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
if ((S1Reg^DReg)>15) SwapReg(&S1Reg,&S2Reg);
|
|
SetCross(S2Reg);
|
|
__erg=CodeL(0x2b,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModLReg: /* ADDU int,long,long */
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else if ((ThisCross) AND ((S1Reg^DReg)<16)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
SetCross(S1Reg);
|
|
__erg=CodeL(0x29,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
|
|
if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
__erg=CodeL(0x29,DReg,S2Reg,S1Reg);
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeSUB(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg,S2Reg;
|
|
Boolean OK;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND ((S1Reg^DReg)<16) AND ((S2Reg^DReg)<16)) WrError(1350);
|
|
else if (((S1Reg^DReg)>15) AND ((S2Reg^DReg)>15)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
ThisCross=((S1Reg^DReg)>15) OR ((S2Reg^DReg)>15);
|
|
if ((S1Reg^DReg)>15) OK=DecideUnit(DReg,"L");
|
|
else if ((S2Reg^DReg)>15) OK=DecideUnit(DReg,"LS");
|
|
else OK=DecideUnit(DReg,"LSD");
|
|
if (OK)
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case L2:
|
|
if ((S1Reg^DReg)>15) __erg=CodeL(0x17,DReg,S1Reg,S2Reg);
|
|
else __erg=CodeL(0x07,DReg,S1Reg,S2Reg);
|
|
break;
|
|
case S1: case S2:
|
|
__erg=CodeS(0x17,DReg,S1Reg,S2Reg);
|
|
break;
|
|
case D1: case D2:
|
|
__erg=CodeD(0x11,DReg,S2Reg,S1Reg);
|
|
break;
|
|
default:
|
|
WrError(20000);
|
|
END
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if (ChkUnit(DReg,D1,D2))
|
|
if ((ThisCross) OR ((S1Reg^DReg)>15)) WrError(1350);
|
|
else __erg=CodeD(0x13,DReg,S2Reg,S1Reg);
|
|
break;
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND ((S2Reg^DReg)<16)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
if (DecideUnit(DReg,"LS"))
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case L2: __erg=CodeL(0x06,DReg,S1Reg,S2Reg); break;
|
|
case S1: case S2: __erg=CodeS(0x16,DReg,S1Reg,S2Reg); break;
|
|
default: WrError(20000);
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
AddLDest(DReg);
|
|
if (ChkUnit(DReg,L1,L2))
|
|
BEGIN
|
|
DecodeAdr(ArgStr[1],MModImm+MModReg,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModImm:
|
|
if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
|
|
if ((ThisCross) OR (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
__erg=CodeL(0x24,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
ThisCross=(IsCross(S1Reg)) OR (IsCross(S2Reg));
|
|
if (IsCross(S1Reg)) __erg=CodeL(0x37,DReg,S1Reg,S2Reg);
|
|
else __erg=CodeL(0x47,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeSUBU(Word Index)
|
|
BEGIN
|
|
LongWord S1Reg,S2Reg,DReg;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if ((DecodeAdr(ArgStr[3],MModLReg,False,&DReg)) AND (ChkUnit(DReg,L1,L2)))
|
|
BEGIN
|
|
AddLDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,False,&S1Reg))
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
ThisCross=IsCross(S1Reg) OR IsCross(S2Reg);
|
|
if (IsCross(S1Reg)) __erg=CodeL(0x3f,DReg,S1Reg,S2Reg);
|
|
else __erg=CodeL(0x2f,DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeSUBC(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg,S2Reg;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if ((DecodeAdr(ArgStr[3],MModReg,False,&DReg)) AND (ChkUnit(DReg,L1,L2)))
|
|
BEGIN
|
|
AddLDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,False,&S1Reg))
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
__erg=CodeL(0x4b,DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeLinAdd(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg,S2Reg;
|
|
FixedOrder *POrder=LinAddOrders+Index;
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else if (ThisCross) WrError(1350);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
|
|
if (ChkUnit(DReg,D1,D2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
__erg=CodeD(POrder->Code,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
__erg=CodeD(POrder->Code+2,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeADDK(Word Index)
|
|
BEGIN
|
|
LongInt Value;
|
|
LongWord DReg;
|
|
Boolean OK;
|
|
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
|
|
if (ChkUnit(DReg,S1,S2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
Value=EvalIntExpression(ArgStr[1],SInt16,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
ThisInst=0x50+(UnitFlag << 1)+((Value & 0xffff) << 7)+(DReg << 23);
|
|
__erg=True;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeADD2_SUB2(Word Index)
|
|
BEGIN
|
|
LongWord DReg,S1Reg,S2Reg;
|
|
Boolean OK;
|
|
|
|
Index=(Index<<5)+1;
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
|
|
if (ChkUnit(DReg,S1,S2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,True,&S1Reg))
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
OK=True; AddSrc(S2Reg);
|
|
if (IsCross(S1Reg))
|
|
if (Index>1)
|
|
BEGIN
|
|
WrError(1350); OK=False;
|
|
END
|
|
else SwapReg(&S1Reg,&S2Reg);
|
|
if (OK)
|
|
BEGIN
|
|
SetCross(S2Reg);
|
|
__erg=CodeS(Index,DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static void DecodeLogic(Word Index)
|
|
BEGIN
|
|
LongWord S1Reg,S2Reg,DReg;
|
|
LongWord Code1,Code2;
|
|
Boolean OK,WithImm;
|
|
|
|
Code1=Lo(Index); Code2=Hi(Index);
|
|
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModImm+MModReg,True,&S1Reg); WithImm=False;
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModImm:
|
|
OK=DecodeAdr(ArgStr[2],MModReg,True,&S2Reg);
|
|
if (OK) AddSrc(S2Reg);
|
|
WithImm=True;
|
|
break;
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
OK=DecodeAdr(ArgStr[2],MModImm+MModReg,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModImm:
|
|
SwapReg(&S1Reg,&S2Reg); WithImm=True;
|
|
break;
|
|
case ModReg:
|
|
AddSrc(S2Reg); WithImm=False;
|
|
break;
|
|
default:
|
|
OK=False;
|
|
END
|
|
break;
|
|
default:
|
|
OK=False;
|
|
END
|
|
if (OK)
|
|
if (DecideUnit(DReg,"LS"))
|
|
if ((NOT WithImm) AND (IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else if ((ThisCross) AND (NOT IsCross(S2Reg)) AND ((WithImm) OR (NOT IsCross(S1Reg)))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
if ((NOT WithImm) AND (IsCross(S1Reg))) SwapReg(&S1Reg,&S2Reg);
|
|
SetCross(S2Reg);
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case L2:
|
|
__erg=CodeL(Code1-Ord(WithImm),DReg,S1Reg,S2Reg); break;
|
|
case S1: case S2:
|
|
__erg=CodeS(Code1-Ord(WithImm),DReg,S1Reg,S2Reg); break;
|
|
default:
|
|
WrError(20000);
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
|
|
static Boolean DecodeInst(void)
|
|
BEGIN
|
|
Boolean OK,erg;
|
|
LongInt Dist;
|
|
int z;
|
|
LongWord DReg,S1Reg,S2Reg,HReg;
|
|
LongWord Code1;
|
|
Boolean WithImm,HasSign;
|
|
|
|
erg=__erg=False;
|
|
|
|
/* ueber Tabelle: */
|
|
|
|
if (LookupInstTable(InstTable,OpPart)) return __erg;
|
|
|
|
/* jetzt geht's los... */
|
|
|
|
if ((Memo("CLR") OR (Memo("EXT")) OR (Memo("EXTU")) OR (Memo("SET"))))
|
|
BEGIN
|
|
if ((ArgCnt!=3) AND (ArgCnt!=4)) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[ArgCnt],MModReg,Memo("EXT"),&DReg))
|
|
if (ChkUnit(DReg,S1,S2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,Memo("EXT"),&S2Reg))
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
if (ArgCnt==3)
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&S1Reg))
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S2Reg);
|
|
if (Memo("CLR")) erg=CodeS(0x3f,DReg,S1Reg,S2Reg);
|
|
else if (Memo("EXTU")) erg=CodeS(0x2b,DReg,S1Reg,S2Reg);
|
|
else if (Memo("SET")) erg=CodeS(0x3b,DReg,S1Reg,S2Reg);
|
|
else erg=CodeS(0x2f,DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
else if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
S1Reg=EvalIntExpression(ArgStr[2],UInt5,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
HReg=EvalIntExpression(ArgStr[3],UInt5,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
ThisInst=(DReg << 23)+(S2Reg << 18)+(S1Reg << 13)+
|
|
(HReg << 8)+(UnitFlag << 1);
|
|
if (Memo("CLR")) ThisInst+=0xc8;
|
|
else if (Memo("SET")) ThisInst+=0x88;
|
|
else if (Memo("EXT")) ThisInst+=0x48;
|
|
else ThisInst+=0x08;
|
|
erg=True;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
for (z=0; z<CmpCnt; z++)
|
|
if (Memo(CmpOrders[z].Name))
|
|
BEGIN
|
|
WithImm=OpPart[strlen(OpPart)-1]!='U';
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,False,&DReg))
|
|
if (ChkUnit(DReg,L1,L2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModImm,WithImm,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModLReg,WithImm,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
|
|
SetCross(S2Reg);
|
|
erg=CodeL(CmpOrders[z].Code+3,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg); SetCross(S1Reg);
|
|
erg=CodeL(CmpOrders[z].Code+1,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModImm:
|
|
DecodeAdr(ArgStr[2],MModReg+MModLReg,WithImm,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
erg=CodeL(CmpOrders[z].Code+2,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
erg=CodeL(CmpOrders[z].Code,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("LMBD"))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,False,&DReg))
|
|
if (ChkUnit(DReg,L1,L2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S2Reg);
|
|
if (DecodeAdr(ArgStr[1],MModImm+MModReg,False,&S1Reg))
|
|
BEGIN
|
|
if (AdrMode==ModReg) AddSrc(S1Reg);
|
|
erg=CodeL(0x6a+Ord(AdrMode==ModImm),DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("NORM"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,False,&DReg))
|
|
if (ChkUnit(DReg,L1,L2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModLReg,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S2Reg); AddSrc(S2Reg);
|
|
erg=CodeL(0x63,DReg,0,S2Reg);
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
erg=CodeL(0x60,DReg,0,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("SADD"))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if ((DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg)) AND (ChkUnit(DReg,L1,L2)))
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
if (IsCross(S1Reg)) SwapReg(&S1Reg,&S2Reg);
|
|
SetCross(S2Reg);
|
|
erg=CodeL(0x13,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S1Reg);
|
|
erg=CodeL(0x12,DReg,S2Reg,S1Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
SetCross(S2Reg);
|
|
erg=CodeL(0x12,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
AddLDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModLReg+MModImm,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg); SetCross(S1Reg);
|
|
erg=CodeL(0x31,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S1Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
erg=CodeL(0x31,DReg,S2Reg,S1Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeL(0x30,DReg,S2Reg,S1Reg);
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
|
|
if (IsCross(S2Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
erg=CodeL(0x30,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("SAT"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&DReg))
|
|
if (ChkUnit(DReg,L1,L2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModLReg,True,&S2Reg))
|
|
if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg); erg=CodeL(0x40,DReg,0,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("MVC"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if ((ThisUnit!=NoUnit) AND (ThisUnit!=S2)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
z=0; ThisUnit=S2; UnitFlag=1;
|
|
if (DecodeCtrlReg(ArgStr[1],&S2Reg,False)) z=2;
|
|
else if (DecodeCtrlReg(ArgStr[2],&DReg,True)) z=1;
|
|
else WrXError(1440,ArgStr[1]);
|
|
if (z>0)
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[z],MModReg,False,&S1Reg))
|
|
if ((ThisCross) AND ((z==2) OR (IsCross(S1Reg)))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
if (z==1)
|
|
BEGIN
|
|
S2Reg=S1Reg;
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
END
|
|
else
|
|
BEGIN
|
|
DReg=S1Reg; AddDest(DReg);
|
|
END
|
|
erg=CodeS(0x0d+z,DReg,0,S2Reg);
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if ((Memo("MVK")) OR (Memo("MVKH")) OR (Memo("MVKLH")))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&DReg))
|
|
if (ChkUnit(DReg,S1,S2))
|
|
BEGIN
|
|
S1Reg=EvalIntExpression(ArgStr[1],Memo("MVKLH")?Int16:Int32,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (Memo("MVKH")) S1Reg=S1Reg >> 16;
|
|
ThisInst=(DReg << 23)+((S1Reg & 0xffff) << 7)+(UnitFlag << 1);
|
|
ThisInst+=Memo("MVK") ? 0x28 : 0x68;
|
|
erg=True;
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if (Memo("SHL"))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
|
|
if ((AdrMode!=ModNone) AND (ChkUnit(DReg,S1,S2)))
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg);
|
|
SetCross(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
erg=CodeS(0x33,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeS(0x32,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
AddLDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModLReg,True,&S2Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModImm+MModReg,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
erg=CodeS(0x13,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeS(0x12,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModImm+MModReg,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
erg=CodeS(0x31,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeS(0x30,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if ((Memo("SHR")) OR (Memo("SHRU")))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
HasSign=Memo("SHR"); z=Ord(HasSign) << 4;
|
|
DecodeAdr(ArgStr[3],MModReg+MModLReg,HasSign,&DReg);
|
|
if ((AdrMode!=ModNone) AND (ChkUnit(DReg,S1,S2)))
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,HasSign,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
erg=CodeS(0x27+z,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeS(0x26+z,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
AddLDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModLReg,HasSign,&S2Reg))
|
|
if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
erg=CodeS(0x25+z,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeS(0x24+z,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("SSHL"))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[3],MModReg,True,&DReg))
|
|
if (ChkUnit(DReg,S1,S2))
|
|
BEGIN
|
|
AddDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
DecodeAdr(ArgStr[2],MModReg+MModImm,False,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
if (IsCross(S1Reg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S1Reg);
|
|
erg=CodeS(0x23,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
erg=CodeS(0x22,DReg,S1Reg,S2Reg);
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
if (Memo("SSUB"))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else
|
|
BEGIN
|
|
DecodeAdr(ArgStr[3],MModReg+MModLReg,True,&DReg);
|
|
if ((AdrMode!=ModNone) AND (ChkUnit(DReg,L1,L2)))
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddDest(DReg);
|
|
DecodeAdr(ArgStr[1],MModReg+MModImm,True,&S1Reg);
|
|
switch (AdrMode)
|
|
BEGIN
|
|
case ModReg:
|
|
AddSrc(S1Reg);
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S1Reg)) AND (NOT IsCross(S2Reg))) WrError(1350);
|
|
else if ((IsCross(S1Reg)) AND (IsCross(S2Reg))) WrError(1350);
|
|
else if (IsCross(S1Reg))
|
|
BEGIN
|
|
ThisCross=True;
|
|
erg=CodeL(0x1f,DReg,S1Reg,S2Reg);
|
|
END
|
|
else
|
|
BEGIN
|
|
SetCross(S2Reg);
|
|
erg=CodeL(0x0f,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
case ModImm:
|
|
if (DecodeAdr(ArgStr[2],MModReg,True,&S2Reg))
|
|
if ((ThisCross) AND (NOT IsCross(S2Reg)<16)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddSrc(S2Reg); SetCross(S2Reg);
|
|
erg=CodeL(0x0e,DReg,S1Reg,S2Reg);
|
|
END
|
|
break;
|
|
END
|
|
break;
|
|
case ModLReg:
|
|
AddLDest(DReg);
|
|
if (DecodeAdr(ArgStr[1],MModImm,True,&S1Reg))
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[2],MModLReg,True,&S2Reg))
|
|
if ((ThisCross) OR (IsCross(S2Reg))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AddLSrc(S2Reg);
|
|
erg=CodeL(0x2c,DReg,S1Reg,S2Reg);
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END;
|
|
return erg;
|
|
END
|
|
|
|
/* Spruenge */
|
|
|
|
/* Wie zum Henker unterscheiden sich B IRP und B NRP ???
|
|
Kann TI keine ordentlichen Handbuecher mehr schreiben ? */
|
|
|
|
if (Memo("B"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1350);
|
|
else if (ThisCross) WrError(1350);
|
|
else if ((ThisUnit!=NoUnit) AND (ThisUnit!=S1) AND (ThisUnit!=S2)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
OK=True; S2Reg=0; WithImm=False; Code1=0;
|
|
if (strcasecmp(ArgStr[1],"IRP")==0) Code1=0x03;
|
|
else if (strcasecmp(ArgStr[1],"NRP")==0) Code1=0x03; /* !!! */
|
|
else if (DecodeReg(ArgStr[1],&S2Reg,&OK,False))
|
|
BEGIN
|
|
if (OK) WrError(1350); OK=NOT OK;
|
|
Code1=0x0d;
|
|
END
|
|
else WithImm=True;
|
|
if (OK)
|
|
if (WithImm)
|
|
BEGIN
|
|
if (ThisUnit==NoUnit)
|
|
ThisUnit=(UnitUsed(S1)) ? S2 : S1;
|
|
UnitFlag=Ord(ThisUnit==S2);
|
|
Dist=EvalIntExpression(ArgStr[1],Int32,&OK)-PacketAddr;
|
|
if (OK)
|
|
if ((Dist & 3)!=0) WrError(1325);
|
|
else if ((NOT SymbolQuestionable) AND ((Dist>0x3fffff) OR (Dist<-0x400000))) WrError(1370);
|
|
else
|
|
BEGIN
|
|
ThisInst=0x50+((Dist & 0x007ffffc) << 5)+(UnitFlag << 1);
|
|
erg=True;
|
|
END
|
|
END
|
|
else
|
|
BEGIN
|
|
if (ChkUnit(0x10,S1,S2)) erg=CodeS(Code1,0,0,S2Reg);
|
|
END
|
|
END
|
|
return erg;
|
|
END
|
|
|
|
WrXError(1200,OpPart);
|
|
|
|
return erg;
|
|
END
|
|
|
|
static void ChkPacket(void)
|
|
BEGIN
|
|
LongWord EndAddr,Mask;
|
|
LongInt z,z1,z2;
|
|
Integer RegReads[32];
|
|
char TestUnit[4];
|
|
|
|
/* nicht ueber 8er-Grenze */
|
|
|
|
EndAddr=PacketAddr+((ParCnt << 2)-1);
|
|
if ((PacketAddr >> 5)!=(EndAddr >> 5)) WrError(2000);
|
|
|
|
/* doppelte Units,Crosspaths,Adressierer,Zielregister */
|
|
|
|
for (z1=0; z1<ParCnt; z1++)
|
|
for (z2=z1+1; z2<ParCnt; z2++)
|
|
if ((ParRecs[z1].OpCode >> 28)==(ParRecs[z2].OpCode >> 28))
|
|
BEGIN
|
|
/* doppelte Units */
|
|
if ((ParRecs[z1].U!=NoUnit) AND (ParRecs[z1].U==ParRecs[z2].U))
|
|
WrXError(2001,UnitNames[ParRecs[z1].U]);
|
|
|
|
/* Crosspaths */
|
|
z=ParRecs[z1].CrossUsed & ParRecs[z2].CrossUsed;
|
|
if (z!=0)
|
|
BEGIN
|
|
*TestUnit=z+'0'; TestUnit[1]='X'; TestUnit[2]='\0';
|
|
WrXError(2001,TestUnit);
|
|
END
|
|
|
|
z=ParRecs[z1].AddrUsed & ParRecs[z2].AddrUsed;
|
|
/* Adressgeneratoren */
|
|
if ((z & 1)==1) WrXError(2001,"Addr. A");
|
|
if ((z & 2)==2) WrXError(2001,"Addr. B");
|
|
/* Hauptspeicherpfade */
|
|
if ((z & 4)==4) WrXError(2001,"LdSt. A");
|
|
if ((z & 8)==8) WrXError(2001,"LdSt. B");
|
|
|
|
/* ueberlappende Zielregister */
|
|
z=ParRecs[z1].DestMask & ParRecs[z2].DestMask;
|
|
if (z!=0) WrXError(2006,RegName(FindReg(z)));
|
|
|
|
if ((ParRecs[z1].U & 1)==(ParRecs[z2].U & 1))
|
|
BEGIN
|
|
TestUnit[0]=ParRecs[z1].U-NoUnit-1+'A';
|
|
TestUnit[1]='\0';
|
|
|
|
/* mehrere Long-Reads */
|
|
if ((ParRecs[z1].LongSrc) AND (ParRecs[z2].LongSrc))
|
|
WrXError(2002,TestUnit);
|
|
|
|
/* mehrere Long-Writes */
|
|
if ((ParRecs[z1].LongDest) AND (ParRecs[z2].LongDest))
|
|
WrXError(2003,TestUnit);
|
|
|
|
/* Long-Read mit Store */
|
|
if ((ParRecs[z1].StoreUsed) AND (ParRecs[z2].LongSrc))
|
|
WrXError(2004,TestUnit);
|
|
if ((ParRecs[z2].StoreUsed) AND (ParRecs[z1].LongSrc))
|
|
WrXError(2004,TestUnit);
|
|
END
|
|
END
|
|
|
|
for (z2=0; z2<32; RegReads[z2++]=0);
|
|
for (z1=0; z1<ParCnt; z1++)
|
|
BEGIN
|
|
Mask=1;
|
|
for (z2=0; z2<32; z2++)
|
|
BEGIN
|
|
if ((ParRecs[z1].SrcMask & Mask)!=0) RegReads[z2]++;
|
|
if ((ParRecs[z1].SrcMask2 & Mask)!=0) RegReads[z2]++;
|
|
Mask=Mask << 1;
|
|
END
|
|
END
|
|
|
|
/* Register mehr als 4mal gelesen */
|
|
|
|
for (z1=0; z1<32; z1++)
|
|
if (RegReads[z1]>4) WrXError(2005,RegName(z1));
|
|
END
|
|
|
|
static void MakeCode_3206X(void)
|
|
BEGIN
|
|
CodeLen=0; DontPrint=False;
|
|
|
|
/* zu ignorierendes */
|
|
|
|
if ((*OpPart=='\0') AND (*LabPart=='\0')) return;
|
|
|
|
/* Pseudoanweisungen */
|
|
|
|
if (DecodePseudo()) return;
|
|
|
|
/* Flags zuruecksetzen */
|
|
|
|
ThisPar=False; Condition=0;
|
|
|
|
/* Optionen aus Label holen */
|
|
|
|
if (*LabPart!='\0')
|
|
if ((strcmp(LabPart,"||")==0) OR (*LabPart=='['))
|
|
if (NOT CheckOpt(LabPart)) return;
|
|
|
|
/* eventuell falsche Mnemonics verwerten */
|
|
|
|
if (strcmp(OpPart,"||")==0)
|
|
if (NOT ReiterateOpPart()) return;
|
|
if (*OpPart=='[')
|
|
if (NOT ReiterateOpPart()) return;
|
|
|
|
if (Memo("")) return;
|
|
|
|
/* Attribut auswerten */
|
|
|
|
ThisUnit=NoUnit; ThisCross=False;
|
|
if (*AttrPart!='\0')
|
|
BEGIN
|
|
if (toupper(AttrPart[strlen(AttrPart)-1])=='X')
|
|
BEGIN
|
|
ThisCross=True;
|
|
AttrPart[strlen(AttrPart)-1]='\0';
|
|
END
|
|
if (*AttrPart=='\0') ThisUnit=NoUnit;
|
|
else
|
|
for (; ThisUnit!=LastUnit; ThisUnit++)
|
|
if (strcasecmp(AttrPart,UnitNames[ThisUnit])==0) break;
|
|
if (ThisUnit==LastUnit)
|
|
BEGIN
|
|
WrError(1107); return;
|
|
END
|
|
if (((ThisUnit==D1) OR (ThisUnit==D2)) AND (ThisCross))
|
|
BEGIN
|
|
WrError(1350); return;
|
|
END
|
|
END
|
|
|
|
/* falls nicht parallel, vorherigen Stack durchpruefen und verwerfen */
|
|
|
|
if ((NOT ThisPar) AND (ParCnt>0))
|
|
BEGIN
|
|
ChkPacket();
|
|
ParCnt=0; PacketAddr=EProgCounter();
|
|
END
|
|
|
|
/* dekodieren */
|
|
|
|
ThisSrc=0; ThisSrc2=0; ThisDest=0;
|
|
ThisAddr=0; ThisStore=False; ThisLong=0;
|
|
if (NOT DecodeInst()) return;
|
|
|
|
/* einsortieren */
|
|
|
|
ParRecs[ParCnt].OpCode=(Condition << 28)+ThisInst;
|
|
ParRecs[ParCnt].U=ThisUnit;
|
|
if (ThisCross)
|
|
switch (ThisUnit)
|
|
BEGIN
|
|
case L1: case S1: case M1: case D1: ParRecs[ParCnt].CrossUsed=1; break;
|
|
default: ParRecs[ParCnt].CrossUsed=2;
|
|
END
|
|
else ParRecs[ParCnt].CrossUsed=0;
|
|
ParRecs[ParCnt].AddrUsed=ThisAddr;
|
|
ParRecs[ParCnt].SrcMask=ThisSrc;
|
|
ParRecs[ParCnt].SrcMask2=ThisSrc2;
|
|
ParRecs[ParCnt].DestMask=ThisDest;
|
|
ParRecs[ParCnt].LongSrc=(ThisLong & 1)==1;
|
|
ParRecs[ParCnt].LongDest=(ThisLong & 2)==2;
|
|
ParRecs[ParCnt].StoreUsed=ThisStore;
|
|
ParCnt++;
|
|
|
|
/* wenn mehr als eine Instruktion, Ressourcenkonflikte abklopfen und
|
|
vorherige Instruktion zuruecknehmen */
|
|
|
|
if (ParCnt>1)
|
|
BEGIN
|
|
RetractWords(4);
|
|
DAsmCode[CodeLen >> 2]=ParRecs[ParCnt-2].OpCode | 1;
|
|
CodeLen+=4;
|
|
END
|
|
|
|
/* aktuelle Instruktion auswerfen: fuer letzte kein Parallelflag setzen */
|
|
|
|
DAsmCode[CodeLen >> 2]=ParRecs[ParCnt-1].OpCode;
|
|
CodeLen+=4;
|
|
END
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static int InstrZ;
|
|
|
|
|
|
static void AddLinAdd(char *NName, LongInt NCode)
|
|
BEGIN
|
|
if (InstrZ>=LinAddCnt) exit(255);
|
|
LinAddOrders[InstrZ].Name=NName;
|
|
LinAddOrders[InstrZ].Code=NCode;
|
|
AddInstTable(InstTable,NName,InstrZ++,DecodeLinAdd);
|
|
END
|
|
|
|
static void AddCmp(char *NName, LongInt NCode)
|
|
BEGIN
|
|
if (InstrZ>=CmpCnt) exit(255);
|
|
CmpOrders[InstrZ].Name=NName;
|
|
CmpOrders[InstrZ++].Code=NCode;
|
|
END
|
|
|
|
static void AddMem(char *NName, LongInt NCode, LongInt NScale)
|
|
BEGIN
|
|
if (InstrZ>=MemCnt) exit(255);
|
|
MemOrders[InstrZ].Name=NName;
|
|
MemOrders[InstrZ].Code=NCode;
|
|
MemOrders[InstrZ].Scale=NScale;
|
|
AddInstTable(InstTable,NName,InstrZ++,DecodeMemO);
|
|
END
|
|
|
|
static void AddMul(char *NName, LongInt NCode,
|
|
Boolean NDSign,Boolean NSSign1,Boolean NSSign2, Boolean NMay)
|
|
BEGIN
|
|
if (InstrZ>=MulCnt) exit(255);
|
|
MulOrders[InstrZ].Name=NName;
|
|
MulOrders[InstrZ].Code=NCode;
|
|
MulOrders[InstrZ].DSign=NDSign;
|
|
MulOrders[InstrZ].SSign1=NSSign1;
|
|
MulOrders[InstrZ].SSign2=NSSign2;
|
|
MulOrders[InstrZ].MayImm=NMay;
|
|
AddInstTable(InstTable,NName,InstrZ++,DecodeMul);
|
|
END
|
|
|
|
static void AddCtrl(char *NName, LongInt NCode,
|
|
Boolean NWr, Boolean NRd)
|
|
BEGIN
|
|
if (InstrZ>=CtrlCnt) exit(255);
|
|
CtrlRegs[InstrZ].Name=NName;
|
|
CtrlRegs[InstrZ].Code=NCode;
|
|
CtrlRegs[InstrZ].Wr=NWr;
|
|
CtrlRegs[InstrZ++].Rd=NRd;
|
|
END
|
|
|
|
static void InitFields(void)
|
|
BEGIN
|
|
InstTable=CreateInstTable(203);
|
|
|
|
AddInstTable(InstTable,"IDLE",0,DecodeIDLE);
|
|
AddInstTable(InstTable,"NOP",0,DecodeNOP);
|
|
AddInstTable(InstTable,"STP",0,DecodeSTP);
|
|
AddInstTable(InstTable,"ABS",0,DecodeABS);
|
|
AddInstTable(InstTable,"ADD",0,DecodeADD);
|
|
AddInstTable(InstTable,"ADDU",0,DecodeADDU);
|
|
AddInstTable(InstTable,"SUB",0,DecodeSUB);
|
|
AddInstTable(InstTable,"SUBU",0,DecodeSUBU);
|
|
AddInstTable(InstTable,"SUBC",0,DecodeSUBC);
|
|
AddInstTable(InstTable,"ADDK",0,DecodeADDK);
|
|
AddInstTable(InstTable,"ADD2",0,DecodeADD2_SUB2);
|
|
AddInstTable(InstTable,"SUB2",1,DecodeADD2_SUB2);
|
|
AddInstTable(InstTable,"AND",0x1f79,DecodeLogic);
|
|
AddInstTable(InstTable,"OR",0x1b7f,DecodeLogic);
|
|
AddInstTable(InstTable,"XOR",0x0b6f,DecodeLogic);
|
|
|
|
LinAddOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*LinAddCnt); InstrZ=0;
|
|
AddLinAdd("ADDAB",0x30); AddLinAdd("ADDAH",0x34); AddLinAdd("ADDAW",0x38);
|
|
AddLinAdd("SUBAB",0x31); AddLinAdd("SUBAH",0x35); AddLinAdd("SUBAW",0x39);
|
|
|
|
CmpOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*CmpCnt); InstrZ=0;
|
|
AddCmp("CMPEQ",0x50); AddCmp("CMPGT",0x44); AddCmp("CMPGTU",0x4c);
|
|
AddCmp("CMPLT",0x54); AddCmp("CMPLTU",0x5c);
|
|
|
|
MemOrders=(MemOrder *) malloc(sizeof(MemOrder)*MemCnt); InstrZ=0;
|
|
AddMem("LDB",2,1); AddMem("LDH",4,2); AddMem("LDW",6,4);
|
|
AddMem("LDBU",1,1); AddMem("LDHU",0,2); AddMem("STB",3,1);
|
|
AddMem("STH",5,2); AddMem("STW",7,4);
|
|
|
|
MulOrders=(MulOrder *) malloc(sizeof(MulOrder)*MulCnt); InstrZ=0;
|
|
AddMul("MPY" ,0x19,True ,True ,True ,True );
|
|
AddMul("MPYU" ,0x1f,False,False,False,False);
|
|
AddMul("MPYUS" ,0x1d,True ,False,True ,False);
|
|
AddMul("MPYSU" ,0x1b,True ,True ,False,True );
|
|
AddMul("MPYH" ,0x01,True ,True ,True ,False);
|
|
AddMul("MPYHU" ,0x07,False,False,False,False);
|
|
AddMul("MPYHUS" ,0x05,True ,False,True ,False);
|
|
AddMul("MPYHSU" ,0x03,True ,True ,False,False);
|
|
AddMul("MPYHL" ,0x09,True ,True ,True ,False);
|
|
AddMul("MPYHLU" ,0x0f,False,False,False,False);
|
|
AddMul("MPYHULS",0x0d,True ,False,True ,False);
|
|
AddMul("MPYHSLU",0x0b,True ,True ,False,False);
|
|
AddMul("MPYLH" ,0x11,True ,True ,True ,False);
|
|
AddMul("MPYLHU" ,0x17,False,False,False,False);
|
|
AddMul("MPYLUHS",0x15,True ,False,True ,False);
|
|
AddMul("MPYLSHU",0x13,True ,True ,False,False);
|
|
AddMul("SMPY" ,0x1a,True ,True ,True ,False);
|
|
AddMul("SMPYHL" ,0x0a,True ,True ,True ,False);
|
|
AddMul("SMPYLH" ,0x12,True ,True ,True ,False);
|
|
AddMul("SMPYH" ,0x02,True ,True ,True ,False);
|
|
|
|
CtrlRegs=(CtrlReg *) malloc(sizeof(CtrlReg)*CtrlCnt); InstrZ=0;
|
|
AddCtrl("AMR" , 0,True ,True );
|
|
AddCtrl("CSR" , 1,True ,True );
|
|
AddCtrl("IFR" , 2,False,True );
|
|
AddCtrl("ISR" , 2,True ,False);
|
|
AddCtrl("ICR" , 3,True ,False);
|
|
AddCtrl("IER" , 4,True ,True );
|
|
AddCtrl("ISTP" , 5,True ,True );
|
|
AddCtrl("IRP" , 6,True ,True );
|
|
AddCtrl("NRP" , 7,True ,True );
|
|
AddCtrl("IN" , 8,False,True );
|
|
AddCtrl("OUT" , 9,True ,True );
|
|
AddCtrl("PCE1" ,16,False,True );
|
|
AddCtrl("PDATA_O",15,True ,True );
|
|
END
|
|
|
|
static void DeinitFields(void)
|
|
BEGIN
|
|
DestroyInstTable(InstTable);
|
|
free(LinAddOrders);
|
|
free(CmpOrders);
|
|
free(MemOrders);
|
|
free(MulOrders);
|
|
free(CtrlRegs);
|
|
END
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
static Boolean IsDef_3206X(void)
|
|
BEGIN
|
|
return (strcmp(LabPart,"||")==0) OR (*LabPart=='[');
|
|
END
|
|
|
|
static void SwitchFrom_3206X(void)
|
|
BEGIN
|
|
if (ParCnt>1) ChkPacket();
|
|
DeinitFields();
|
|
END
|
|
|
|
static void SwitchTo_3206X(void)
|
|
BEGIN
|
|
TurnWords=False; ConstMode=ConstModeIntel; SetIsOccupied=False;
|
|
|
|
PCSymbol="$"; HeaderID=0x47; NOPCode=0x00000000;
|
|
DivideChars=","; HasAttrs=True; AttrChars=".";
|
|
SetIsOccupied=True;
|
|
|
|
ValidSegs=1<<SegCode;
|
|
Grans[SegCode]=1; ListGrans[SegCode]=4; SegInits[SegCode]=0;
|
|
#ifdef __STDC__
|
|
SegLimits[SegCode] = 0xfffffffful;
|
|
#else
|
|
SegLimits[SegCode] = 0xffffffffl;
|
|
#endif
|
|
|
|
MakeCode=MakeCode_3206X; IsDef=IsDef_3206X;
|
|
SwitchFrom=SwitchFrom_3206X; InitFields();
|
|
|
|
ParCnt=0; PacketAddr=0;
|
|
END
|
|
|
|
void code3206x_init(void)
|
|
BEGIN
|
|
CPU32060=AddCPU("32060",SwitchTo_3206X);
|
|
END
|