2820 lines
84 KiB
C
2820 lines
84 KiB
C
/* codem16.c */
|
|
/*****************************************************************************/
|
|
/* AS-Portierung */
|
|
/* */
|
|
/* Codegenerator Mitsubishi M16 */
|
|
/* */
|
|
/* Historie: 27.12.1996 Grundsteinlegung */
|
|
/* 3. 1.1999 ChkPC-Anpassung */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#include "stdinc.h"
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "bpemu.h"
|
|
#include "nls.h"
|
|
#include "strutil.h"
|
|
#include "asmdef.h"
|
|
#include "asmsub.h"
|
|
#include "asmpars.h"
|
|
#include "codepseudo.h"
|
|
#include "codevars.h"
|
|
|
|
#define ModNone (-1)
|
|
#define ModReg 0
|
|
#define MModReg (1 << ModReg)
|
|
#define ModIReg 1
|
|
#define MModIReg (1 << ModIReg)
|
|
#define ModDisp16 2
|
|
#define MModDisp16 (1 << ModDisp16)
|
|
#define ModDisp32 3
|
|
#define MModDisp32 (1 << ModDisp32)
|
|
#define ModImm 4
|
|
#define MModImm (1 << ModImm)
|
|
#define ModAbs16 5
|
|
#define MModAbs16 (1 << ModAbs16)
|
|
#define ModAbs32 6
|
|
#define MModAbs32 (1 << ModAbs32)
|
|
#define ModPCRel16 7
|
|
#define MModPCRel16 (1 << ModPCRel16)
|
|
#define ModPCRel32 8
|
|
#define MModPCRel32 (1 << ModPCRel32)
|
|
#define ModPop 9
|
|
#define MModPop (1 << ModPop)
|
|
#define ModPush 10
|
|
#define MModPush (1 << ModPush)
|
|
#define ModRegChain 11
|
|
#define MModRegChain (1 << ModRegChain)
|
|
#define ModPCChain 12
|
|
#define MModPCChain (1 << ModPCChain)
|
|
#define ModAbsChain 13
|
|
#define MModAbsChain (1 << ModAbsChain)
|
|
|
|
#define Mask_RegOnly (MModReg)
|
|
#define Mask_AllShort (MModReg+MModIReg+MModDisp16+MModImm+MModAbs16+MModAbs32+MModPCRel16+MModPCRel32+MModPop+MModPush+MModPCChain+MModAbsChain)
|
|
#define Mask_AllGen (Mask_AllShort+MModDisp32+MModRegChain)
|
|
#define Mask_NoImmShort (Mask_AllShort-MModImm)
|
|
#define Mask_NoImmGen (Mask_AllGen-MModImm)
|
|
#define Mask_MemShort (Mask_NoImmShort-MModReg)
|
|
#define Mask_MemGen (Mask_NoImmGen-MModReg)
|
|
|
|
#define Mask_Source (Mask_AllGen-MModPush)
|
|
#define Mask_Dest (Mask_NoImmGen-MModPop)
|
|
#define Mask_PureDest (Mask_NoImmGen-MModPush-MModPop)
|
|
#define Mask_PureMem (Mask_MemGen-MModPush-MModPop)
|
|
|
|
#define FixedOrderCount 7
|
|
#define OneOrderCount 13
|
|
#define GE2OrderCount 11
|
|
#define BitOrderCount 6
|
|
#define GetPutOrderCount 8
|
|
#define BFieldOrderCount 4
|
|
#define MulOrderCount 4
|
|
#define ConditionCount 14
|
|
#define LogOrderCount 3
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Code;
|
|
} FixedOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Mask;
|
|
Byte OpMask;
|
|
Word Code;
|
|
} OneOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Word Mask1,Mask2;
|
|
Word SMask1,SMask2;
|
|
Word Code;
|
|
Boolean Signed;
|
|
} GE2Order;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
Boolean MustByte;
|
|
Word Code1,Code2;
|
|
} BitOrder;
|
|
|
|
typedef struct
|
|
{
|
|
char *Name;
|
|
ShortInt Size;
|
|
Word Code;
|
|
Boolean Turn;
|
|
} GetPutOrder;
|
|
|
|
|
|
static CPUVar CPUM16;
|
|
|
|
static String Format;
|
|
static Byte FormatCode;
|
|
static ShortInt DOpSize,OpSize[5];
|
|
static Word AdrMode[5];
|
|
static ShortInt AdrType[5];
|
|
static Byte AdrCnt1[5],AdrCnt2[5];
|
|
static Word AdrVals[5][8];
|
|
|
|
static Byte OptionCnt;
|
|
static char Options[2][5];
|
|
|
|
static FixedOrder *FixedOrders;
|
|
static OneOrder *OneOrders;
|
|
static GE2Order *GE2Orders;
|
|
static BitOrder *BitOrders;
|
|
static GetPutOrder *GetPutOrders;
|
|
static char **BFieldOrders;
|
|
static char **MulOrders;
|
|
static char **Conditions;
|
|
static char **LogOrders;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
static void AddFixed(char *NName, Word NCode)
|
|
BEGIN
|
|
if (InstrZ>=FixedOrderCount) exit(255);
|
|
FixedOrders[InstrZ].Name=NName;
|
|
FixedOrders[InstrZ++].Code=NCode;
|
|
END
|
|
|
|
static void AddOne(char *NName, Byte NOpMask, Word NMask, Word NCode)
|
|
BEGIN
|
|
if (InstrZ>=OneOrderCount) exit(255);
|
|
OneOrders[InstrZ].Name=NName;
|
|
OneOrders[InstrZ].Code=NCode;
|
|
OneOrders[InstrZ].Mask=NMask;
|
|
OneOrders[InstrZ++].OpMask=NOpMask;
|
|
END
|
|
|
|
static void AddGE2(char *NName, Word NMask1, Word NMask2,
|
|
Byte NSMask1, Byte NSMask2, Word NCode,
|
|
Boolean NSigned)
|
|
BEGIN
|
|
if (InstrZ>=GE2OrderCount) exit(255);
|
|
GE2Orders[InstrZ].Name=NName;
|
|
GE2Orders[InstrZ].Mask1=NMask1;
|
|
GE2Orders[InstrZ].Mask2=NMask2;
|
|
GE2Orders[InstrZ].SMask1=NSMask1;
|
|
GE2Orders[InstrZ].SMask2=NSMask2;
|
|
GE2Orders[InstrZ].Code=NCode;
|
|
GE2Orders[InstrZ++].Signed=NSigned;
|
|
END
|
|
|
|
static void AddBit(char *NName, Boolean NMust, Word NCode1, Word NCode2)
|
|
BEGIN
|
|
if (InstrZ>=BitOrderCount) exit(255);
|
|
BitOrders[InstrZ].Name=NName;
|
|
BitOrders[InstrZ].Code1=NCode1;
|
|
BitOrders[InstrZ].Code2=NCode2;
|
|
BitOrders[InstrZ++].MustByte=NMust;
|
|
END
|
|
|
|
static void AddGetPut(char *NName, Byte NSize, Word NCode, Boolean NTurn)
|
|
BEGIN
|
|
if (InstrZ>=GetPutOrderCount) exit(255);
|
|
GetPutOrders[InstrZ].Name=NName;
|
|
GetPutOrders[InstrZ].Code=NCode;
|
|
GetPutOrders[InstrZ].Turn=NTurn;
|
|
GetPutOrders[InstrZ++].Size=NSize;
|
|
END
|
|
|
|
static void InitFields(void)
|
|
BEGIN
|
|
FixedOrders=(FixedOrder *) malloc(sizeof(FixedOrder)*FixedOrderCount); InstrZ=0;
|
|
AddFixed("NOP" ,0x1bd6); AddFixed("PIB" ,0x0bd6);
|
|
AddFixed("RIE" ,0x08f7); AddFixed("RRNG" ,0x3bd6);
|
|
AddFixed("RTS" ,0x2bd6); AddFixed("STCTX",0x07d6);
|
|
AddFixed("REIT" ,0x2fd6);
|
|
|
|
OneOrders=(OneOrder *) malloc(sizeof(OneOrder)*OneOrderCount); InstrZ=0;
|
|
AddOne("ACS" ,0x00,Mask_PureMem, 0x8300);
|
|
AddOne("NEG" ,0x07,Mask_PureDest, 0xc800);
|
|
AddOne("NOT" ,0x07,Mask_PureDest, 0xcc00);
|
|
AddOne("JMP" ,0x00,Mask_PureMem, 0x8200);
|
|
AddOne("JSR" ,0x00,Mask_PureMem, 0xaa00);
|
|
AddOne("LDCTX" ,0x00,MModIReg+MModDisp16+MModDisp32+
|
|
MModAbs16+MModAbs32+MModPCRel16+MModPCRel32, 0x8600);
|
|
AddOne("LDPSB" ,0x02,Mask_Source, 0xdb00);
|
|
AddOne("LDPSM" ,0x02,Mask_Source, 0xdc00);
|
|
AddOne("POP" ,0x04,Mask_PureDest, 0x9000);
|
|
AddOne("PUSH" ,0x04,Mask_Source-MModPop, 0xb000);
|
|
AddOne("PUSHA" ,0x00,Mask_PureMem, 0xa200);
|
|
AddOne("STPSB" ,0x02,Mask_Dest, 0xdd00);
|
|
AddOne("STPSM" ,0x02,Mask_Dest, 0xde00);
|
|
|
|
GE2Orders=(GE2Order *) malloc(sizeof(GE2Order)*GE2OrderCount); InstrZ=0;
|
|
AddGE2("ADDU" ,Mask_Source,Mask_PureDest,7,7,0x0400,False);
|
|
AddGE2("ADDX" ,Mask_Source,Mask_PureDest,7,7,0x1000,True );
|
|
AddGE2("SUBU" ,Mask_Source,Mask_PureDest,7,7,0x0c00,False);
|
|
AddGE2("SUBX" ,Mask_Source,Mask_PureDest,7,7,0x1800,True );
|
|
AddGE2("CMPU" ,Mask_Source,Mask_PureDest,7,7,0x8400,False);
|
|
AddGE2("LDC" ,Mask_Source,Mask_PureDest,7,4,0x9800,True );
|
|
AddGE2("LDP" ,Mask_Source,Mask_PureMem ,7,7,0x9c00,True );
|
|
AddGE2("MOVU" ,Mask_Source,Mask_Dest ,7,7,0x8c00,True );
|
|
AddGE2("REM" ,Mask_Source,Mask_PureDest,7,7,0x5800,True );
|
|
AddGE2("REMU" ,Mask_Source,Mask_PureDest,7,7,0x5c00,True );
|
|
AddGE2("ROT" ,Mask_Source,Mask_PureDest,1,7,0x3800,True );
|
|
|
|
BitOrders=(BitOrder *) malloc(sizeof(BitOrder)*BitOrderCount); InstrZ=0;
|
|
AddBit("BCLR" ,False,0xb400,0xa180);
|
|
AddBit("BCLRI",True ,0xa400,0x0000);
|
|
AddBit("BNOT" ,False,0xb800,0x0000);
|
|
AddBit("BSET" ,False,0xb000,0x8180);
|
|
AddBit("BSETI",True ,0xa000,0x81c0);
|
|
AddBit("BTST" ,False,0xbc00,0xa1c0);
|
|
|
|
GetPutOrders=(GetPutOrder *) malloc(sizeof(GetPutOrder)*GetPutOrderCount); InstrZ=0;
|
|
AddGetPut("GETB0",0,0xc000,False);
|
|
AddGetPut("GETB1",0,0xc400,False);
|
|
AddGetPut("GETB2",0,0xc800,False);
|
|
AddGetPut("GETH0",1,0xcc00,False);
|
|
AddGetPut("PUTB0",0,0xd000,True );
|
|
AddGetPut("PUTB1",0,0xd400,True );
|
|
AddGetPut("PUTB2",0,0xd800,True );
|
|
AddGetPut("PUTH0",1,0xdc00,True );
|
|
|
|
BFieldOrders=(char **) malloc(sizeof(char *)*BFieldOrderCount); InstrZ=0;
|
|
BFieldOrders[InstrZ++]="BFCMP"; BFieldOrders[InstrZ++]="BFCMPU";
|
|
BFieldOrders[InstrZ++]="BFINS"; BFieldOrders[InstrZ++]="BFINSU";
|
|
|
|
MulOrders=(char **) malloc(sizeof(char *)*MulOrderCount); InstrZ=0;
|
|
MulOrders[InstrZ++]="MUL"; MulOrders[InstrZ++]="MULU";
|
|
MulOrders[InstrZ++]="DIV"; MulOrders[InstrZ++]="DIVU";
|
|
|
|
Conditions=(char **) malloc(sizeof(char *)*ConditionCount); InstrZ=0;
|
|
Conditions[InstrZ++]="XS"; Conditions[InstrZ++]="XC";
|
|
Conditions[InstrZ++]="EQ"; Conditions[InstrZ++]="NE";
|
|
Conditions[InstrZ++]="LT"; Conditions[InstrZ++]="GE";
|
|
Conditions[InstrZ++]="LE"; Conditions[InstrZ++]="GT";
|
|
Conditions[InstrZ++]="VS"; Conditions[InstrZ++]="VC";
|
|
Conditions[InstrZ++]="MS"; Conditions[InstrZ++]="MC";
|
|
Conditions[InstrZ++]="FS"; Conditions[InstrZ++]="FC";
|
|
|
|
LogOrders=(char **) malloc(sizeof(char *)*LogOrderCount); InstrZ=0;
|
|
LogOrders[InstrZ++]="AND"; LogOrders[InstrZ]="OR"; LogOrders[InstrZ++]="XOR";
|
|
END
|
|
|
|
static void DeinitFields(void)
|
|
BEGIN
|
|
free(FixedOrders);
|
|
free(OneOrders);
|
|
free(GE2Orders);
|
|
free(BitOrders);
|
|
free(GetPutOrders);
|
|
free(BFieldOrders);
|
|
free(MulOrders);
|
|
free(Conditions);
|
|
free(LogOrders);
|
|
END
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
typedef enum {DispSizeNone,DispSize4,DispSize4Eps,DispSize16,DispSize32} DispSize;
|
|
typedef struct _TChainRec
|
|
{
|
|
struct _TChainRec *Next;
|
|
Byte RegCnt;
|
|
Word Regs[5],Scales[5];
|
|
LongInt DispAcc;
|
|
Boolean HasDisp;
|
|
DispSize DSize;
|
|
} *PChainRec,TChainRec;
|
|
static Boolean ErrFlag;
|
|
|
|
|
|
static Boolean IsD4(LongInt inp)
|
|
BEGIN
|
|
return ((inp>=-32) AND (inp<=28));
|
|
END
|
|
|
|
static Boolean IsD16(LongInt inp)
|
|
BEGIN
|
|
return ((inp>=-0x8000) AND (inp<=0x7fff));
|
|
END
|
|
|
|
static Boolean DecodeReg(char *Asc, Word *Erg)
|
|
BEGIN
|
|
Boolean IO;
|
|
|
|
if (strcasecmp(Asc,"SP")==0) *Erg=15;
|
|
else if (strcasecmp(Asc,"FP")==0) *Erg=14;
|
|
else if ((strlen(Asc)>1) AND (toupper(*Asc)=='R'))
|
|
BEGIN
|
|
*Erg=ConstLongInt(Asc+1,&IO);
|
|
return ((IO) AND (*Erg<=15));
|
|
END
|
|
else return False;
|
|
return True;
|
|
END
|
|
|
|
static void SplitSize(char *s, DispSize *Erg)
|
|
BEGIN
|
|
int l=strlen(s);
|
|
|
|
if ((l>2) AND (s[l-1]=='4') AND (s[l-2]==':'))
|
|
BEGIN
|
|
*Erg=DispSize4;
|
|
s[l-2]='\0';
|
|
END
|
|
else if ((l>3) AND (s[l-1]=='6') AND (s[l-2]=='1') AND (s[l-3]==':'))
|
|
BEGIN
|
|
*Erg=DispSize16;
|
|
s[l-3]='\0';
|
|
END
|
|
else if ((l>3) AND (s[l-1]=='2') AND (s[l-2]=='3') AND (s[l-3]==':'))
|
|
BEGIN
|
|
*Erg=DispSize32;
|
|
s[l-3]='\0';
|
|
END
|
|
END
|
|
|
|
static void DecideAbs(LongInt Disp, DispSize Size, Word Mask, int Index)
|
|
BEGIN
|
|
switch (Size)
|
|
BEGIN
|
|
case DispSize4:
|
|
Size=DispSize16; break;
|
|
case DispSizeNone:
|
|
if ((IsD16(Disp)) AND ((Mask & MModAbs16)!=0)) Size=DispSize16;
|
|
else Size=DispSize32;
|
|
break;
|
|
default:
|
|
break;
|
|
END
|
|
|
|
switch (Size)
|
|
BEGIN
|
|
case DispSize16:
|
|
if (ChkRange(Disp,-0x8000,0x7fff))
|
|
BEGIN
|
|
AdrType[Index]=ModAbs16; AdrMode[Index]=0x09;
|
|
AdrVals[Index][0]=Disp & 0xffff; AdrCnt1[Index]=2;
|
|
END
|
|
break;
|
|
case DispSize32:
|
|
AdrType[Index]=ModAbs32; AdrMode[Index]=0x0a;
|
|
AdrVals[Index][0]=Disp >> 16;
|
|
AdrVals[Index][1]=Disp & 0xffff; AdrCnt1[Index]=4;
|
|
break;
|
|
default:
|
|
WrError(10000);
|
|
END
|
|
END
|
|
|
|
static void SetError(Word Code)
|
|
BEGIN
|
|
WrError(Code); ErrFlag=True;
|
|
END
|
|
|
|
static PChainRec DecodeChain(char *Asc)
|
|
BEGIN
|
|
PChainRec Rec;
|
|
String Part,SReg;
|
|
int z;
|
|
char *p;
|
|
Boolean OK;
|
|
Byte Scale;
|
|
|
|
ChkStack();
|
|
Rec=(PChainRec) malloc(sizeof(TChainRec));
|
|
Rec->Next=Nil; Rec->RegCnt=0; Rec->DispAcc=0; Rec->HasDisp=False;
|
|
Rec->DSize=DispSizeNone;
|
|
|
|
while ((*Asc!='\0') AND (NOT ErrFlag))
|
|
BEGIN
|
|
|
|
/* eine Komponente abspalten */
|
|
|
|
p=QuotPos(Asc,',');
|
|
if (p==Nil)
|
|
BEGIN
|
|
strmaxcpy(Part,Asc,255); *Asc='\0';
|
|
END
|
|
else
|
|
BEGIN
|
|
*p='\0'; strmaxcpy(Part,Asc,255); strcpy(Asc,p+1);
|
|
END
|
|
|
|
strcpy(SReg,Part); p=QuotPos(SReg,'*'); if (p!=Nil) *p='\0';
|
|
|
|
/* weitere Indirektion ? */
|
|
|
|
if (*Part=='@')
|
|
if (Rec->Next!=Nil) SetError(1350);
|
|
else
|
|
BEGIN
|
|
strcpy(Part,Part+1);
|
|
if (IsIndirect(Part))
|
|
BEGIN
|
|
strcpy(Part,Part+1); Part[strlen(Part)-1]='\0';
|
|
END
|
|
Rec->Next=DecodeChain(Part);
|
|
END
|
|
|
|
/* Register, mit Skalierungsfaktor ? */
|
|
|
|
else if (DecodeReg(SReg,Rec->Regs+Rec->RegCnt))
|
|
BEGIN
|
|
if (Rec->RegCnt>=5) SetError(1350);
|
|
else
|
|
BEGIN
|
|
FirstPassUnknown=False;
|
|
if (p==Nil)
|
|
BEGIN
|
|
OK=True; Scale=1;
|
|
END
|
|
else Scale=EvalIntExpression(p+1,UInt4,&OK);
|
|
if (FirstPassUnknown) Scale=1;
|
|
if (NOT OK) ErrFlag=True;
|
|
else if ((Scale!=1) AND (Scale!=2) AND (Scale!=4) AND (Scale!=8)) SetError(1350);
|
|
else
|
|
BEGIN
|
|
Rec->Scales[Rec->RegCnt]=0;
|
|
while (Scale>1)
|
|
BEGIN
|
|
Rec->Scales[Rec->RegCnt]++; Scale=Scale >> 1;
|
|
END
|
|
Rec->RegCnt++;
|
|
END
|
|
END
|
|
END
|
|
|
|
/* PC, mit Skalierungsfaktor ? */
|
|
|
|
else if (strcasecmp(SReg,"PC")==0)
|
|
BEGIN
|
|
if (Rec->RegCnt>=5) SetError(1350);
|
|
else
|
|
BEGIN
|
|
FirstPassUnknown=False;
|
|
if (p==Nil)
|
|
BEGIN
|
|
OK=True; Scale=1;
|
|
END
|
|
else Scale=EvalIntExpression(p+1,UInt4,&OK);
|
|
if (FirstPassUnknown) Scale=1;
|
|
if (NOT OK) ErrFlag=True;
|
|
else if ((Scale!=1) AND (Scale!=2) AND (Scale!=4) AND (Scale!=8)) SetError(1350);
|
|
else
|
|
BEGIN
|
|
for (z=Rec->RegCnt-1; z>=0; z--)
|
|
BEGIN
|
|
Rec->Regs[z+1]=Rec->Regs[z];
|
|
Rec->Scales[z+1]=Rec->Scales[z];
|
|
END
|
|
Rec->Scales[0]=0;
|
|
while (Scale>1)
|
|
BEGIN
|
|
Rec->Scales[0]++; Scale=Scale >> 1;
|
|
END
|
|
Rec->Regs[0]=16;
|
|
Rec->RegCnt++;
|
|
END
|
|
END
|
|
END
|
|
|
|
/* ansonsten Displacement */
|
|
|
|
else
|
|
BEGIN
|
|
SplitSize(Part,&(Rec->DSize));
|
|
Rec->DispAcc+=EvalIntExpression(Part,Int32,&OK);
|
|
if (NOT OK) ErrFlag=True;
|
|
Rec->HasDisp=True;
|
|
END
|
|
END
|
|
|
|
if (ErrFlag)
|
|
BEGIN
|
|
free(Rec); return Nil;
|
|
END
|
|
else return Rec;
|
|
END
|
|
|
|
static Boolean ChkAdr(Word Mask, int Index)
|
|
BEGIN
|
|
AdrCnt2[Index]=AdrCnt1[Index] >> 1;
|
|
if ((AdrType[Index]!=-1) AND ((Mask & (1 << AdrType[Index]))==0))
|
|
BEGIN
|
|
AdrCnt1[Index]=AdrCnt2[Index]=0;
|
|
AdrType[Index]=ModNone;
|
|
WrError(1350);
|
|
return False;
|
|
END
|
|
else return (AdrType[Index]!=ModNone);
|
|
END
|
|
|
|
static Boolean DecodeAdr(char *Asc, int Index, Word Mask)
|
|
BEGIN
|
|
LongInt AdrLong,MinReserve,MaxReserve;
|
|
int z,z2,LastChain;
|
|
Boolean OK;
|
|
PChainRec RootChain,RunChain,PrevChain;
|
|
DispSize DSize;
|
|
|
|
AdrCnt1[Index]=0; AdrType[Index]=ModNone;
|
|
|
|
/* Register ? */
|
|
|
|
if (DecodeReg(Asc,AdrMode+Index))
|
|
BEGIN
|
|
AdrType[Index]=ModReg; AdrMode[Index]+=0x10; return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
/* immediate ? */
|
|
|
|
if (*Asc=='#')
|
|
BEGIN
|
|
switch (OpSize[Index])
|
|
BEGIN
|
|
case -1:
|
|
WrError(1132); OK=False;
|
|
break;
|
|
case 0:
|
|
AdrVals[Index][0]=EvalIntExpression(Asc+1,Int8,&OK) & 0xff;
|
|
if (OK) AdrCnt1[Index]=2;
|
|
break;
|
|
case 1:
|
|
AdrVals[Index][0]=EvalIntExpression(Asc+1,Int16,&OK);
|
|
if (OK) AdrCnt1[Index]=2;
|
|
break;
|
|
case 2:
|
|
AdrLong=EvalIntExpression(Asc+1,Int32,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
AdrVals[Index][0]=AdrLong >> 16;
|
|
AdrVals[Index][1]=AdrLong & 0xffff;
|
|
AdrCnt1[Index]=4;
|
|
END
|
|
break;
|
|
END
|
|
if (OK)
|
|
BEGIN
|
|
AdrType[Index]=ModImm; AdrMode[Index]=0x0c;
|
|
END
|
|
return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
/* indirekt ? */
|
|
|
|
if (*Asc=='@')
|
|
BEGIN
|
|
strcpy(Asc,Asc+1);
|
|
if (IsIndirect(Asc))
|
|
BEGIN
|
|
strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
|
|
END
|
|
|
|
/* Stack Push ? */
|
|
|
|
if ((strcasecmp(Asc,"-R15")==0) OR (strcasecmp(Asc,"-SP")==0))
|
|
BEGIN
|
|
AdrType[Index]=ModPush; AdrMode[Index]=0x05;
|
|
return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
/* Stack Pop ? */
|
|
|
|
if ((strcasecmp(Asc,"R15+")==0) OR (strcasecmp(Asc,"SP+")==0))
|
|
BEGIN
|
|
AdrType[Index]=ModPop; AdrMode[Index]=0x04;
|
|
return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
/* Register einfach indirekt ? */
|
|
|
|
if (DecodeReg(Asc,AdrMode+Index))
|
|
BEGIN
|
|
AdrType[Index]=ModIReg; AdrMode[Index]+=0x30;
|
|
return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
/* zusammengesetzt indirekt ? */
|
|
|
|
ErrFlag=False;
|
|
RootChain=DecodeChain(Asc);
|
|
|
|
if (ErrFlag);
|
|
|
|
else if (RootChain==Nil);
|
|
|
|
/* absolut ? */
|
|
|
|
else if ((RootChain->Next==Nil) AND (RootChain->RegCnt==0))
|
|
BEGIN
|
|
if (NOT RootChain->HasDisp) RootChain->DispAcc=0;
|
|
DecideAbs(RootChain->DispAcc,RootChain->DSize,Mask,Index);
|
|
free(RootChain);
|
|
END
|
|
|
|
/* einfaches Register/PC mit Displacement ? */
|
|
|
|
else if ((RootChain->Next==Nil) AND (RootChain->RegCnt==1) AND (RootChain->Scales[0]==0))
|
|
BEGIN
|
|
if (RootChain->Regs[0]==16) RootChain->DispAcc-=EProgCounter();
|
|
|
|
/* Displacement-Groesse entscheiden */
|
|
|
|
if (RootChain->DSize==DispSizeNone)
|
|
if ((RootChain->DispAcc==0) AND (RootChain->Regs[0]<16));
|
|
else if (IsD16(RootChain->DispAcc))
|
|
RootChain->DSize=DispSize16;
|
|
else RootChain->DSize=DispSize32;
|
|
|
|
switch (RootChain->DSize)
|
|
BEGIN
|
|
|
|
/* kein Displacement mit Register */
|
|
|
|
case DispSizeNone:
|
|
if (ChkRange(RootChain->DispAcc,0,0))
|
|
if (RootChain->Regs[0]>=16) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AdrType[Index]=ModIReg;
|
|
AdrMode[Index]=0x30+RootChain->Regs[0];
|
|
END
|
|
break;
|
|
|
|
/* 16-Bit-Displacement */
|
|
|
|
case DispSize4:
|
|
case DispSize16:
|
|
if (ChkRange(RootChain->DispAcc,-0x8000,0x7fff))
|
|
BEGIN
|
|
AdrVals[Index][0]=RootChain->DispAcc & 0xffff; AdrCnt1[Index]=2;
|
|
if (RootChain->Regs[0]==16)
|
|
BEGIN
|
|
AdrType[Index]=ModPCRel16; AdrMode[Index]=0x0d;
|
|
END
|
|
else
|
|
BEGIN
|
|
AdrType[Index]=ModDisp16; AdrMode[Index]=0x20+RootChain->Regs[0];
|
|
END
|
|
END
|
|
break;
|
|
|
|
/* 32-Bit-Displacement */
|
|
|
|
default:
|
|
AdrVals[Index][1]=RootChain->DispAcc & 0xffff;
|
|
AdrVals[Index][0]=RootChain->DispAcc >> 16; AdrCnt1[Index]=4;
|
|
if (RootChain->Regs[0]==16)
|
|
BEGIN
|
|
AdrType[Index]=ModPCRel32; AdrMode[Index]=0x0e;
|
|
END
|
|
else
|
|
BEGIN
|
|
AdrType[Index]=ModDisp32; AdrMode[Index]=0x40+RootChain->Regs[0];
|
|
END
|
|
END
|
|
|
|
free(RootChain);
|
|
END
|
|
|
|
/* komplex: dann chained iterieren */
|
|
|
|
else
|
|
BEGIN
|
|
/* bis zum innersten Element der Indirektion als Basis laufen */
|
|
|
|
RunChain=RootChain;
|
|
while (RunChain->Next!=Nil) RunChain=RunChain->Next;
|
|
|
|
/* Entscheidung des Basismodus: die Basis darf nicht skaliert
|
|
sein, und wenn ein Modus nicht erlaubt ist, muessen wir mit
|
|
Base-none anfangen... */
|
|
|
|
z=0; while ((z<RunChain->RegCnt) AND (RunChain->Scales[z]!=0)) z++;
|
|
if (z>=RunChain->RegCnt)
|
|
BEGIN
|
|
AdrType[Index]=ModAbsChain; AdrMode[Index]=0x0b;
|
|
END
|
|
else
|
|
BEGIN
|
|
if (RunChain->Regs[z]==16)
|
|
BEGIN
|
|
AdrType[Index]=ModPCChain; AdrMode[Index]=0x0f;
|
|
RunChain->DispAcc-=EProgCounter();
|
|
END
|
|
else
|
|
BEGIN
|
|
AdrType[Index]=ModRegChain;
|
|
AdrMode[Index]=0x60+RunChain->Regs[z];
|
|
END
|
|
for (z2=z; z2<=RunChain->RegCnt-2; z2++)
|
|
BEGIN
|
|
RunChain->Regs[z2]=RunChain->Regs[z2+1];
|
|
RunChain->Scales[z2]=RunChain->Scales[z2+1];
|
|
END
|
|
RunChain->RegCnt--;
|
|
END;
|
|
|
|
/* Jetzt ueber die einzelnen Komponenten iterieren */
|
|
|
|
LastChain=0;
|
|
while (RootChain!=Nil)
|
|
BEGIN
|
|
RunChain=RootChain; PrevChain=Nil;
|
|
while (RunChain->Next!=Nil)
|
|
BEGIN
|
|
PrevChain=RunChain;
|
|
RunChain=RunChain->Next;
|
|
END;
|
|
|
|
/* noch etwas abzulegen ? */
|
|
|
|
if ((RunChain->RegCnt!=0) OR (RunChain->HasDisp))
|
|
BEGIN
|
|
LastChain=AdrCnt1[Index] >> 1;
|
|
|
|
/* Register ablegen */
|
|
|
|
if (RunChain->RegCnt!=0)
|
|
BEGIN
|
|
if (RunChain->Regs[0]==16) AdrVals[Index][LastChain]=0x0600;
|
|
else AdrVals[Index][LastChain]=RunChain->Regs[0] << 10;
|
|
AdrVals[Index][LastChain]+=RunChain->Scales[0] << 5;
|
|
for (z2=0; z2<=RunChain->RegCnt-2; z2++)
|
|
BEGIN
|
|
RunChain->Regs[z2]=RunChain->Regs[z2+1];
|
|
RunChain->Scales[z2]=RunChain->Scales[z2+1];
|
|
END
|
|
RunChain->RegCnt--;
|
|
END
|
|
else AdrVals[Index][LastChain]=0x0200;
|
|
AdrCnt1[Index]+=2;
|
|
|
|
/* Displacement ablegen */
|
|
|
|
if (RunChain->HasDisp)
|
|
BEGIN
|
|
if ((AdrVals[Index][LastChain] & 0x3e00)==0x0600)
|
|
RunChain->DispAcc-=EProgCounter();
|
|
|
|
if (RunChain->DSize==DispSizeNone)
|
|
BEGIN
|
|
MinReserve=32*RunChain->RegCnt; MaxReserve=28*RunChain->RegCnt;
|
|
if (IsD4(RunChain->DispAcc))
|
|
if ((RunChain->DispAcc & 3)==0) DSize=DispSize4;
|
|
else DSize=DispSize16;
|
|
else if ((RunChain->DispAcc>=-32-MinReserve) AND
|
|
(RunChain->DispAcc<=28+MaxReserve)) DSize=DispSize4Eps;
|
|
else if (IsD16(RunChain->DispAcc)) DSize=DispSize16;
|
|
else if ((RunChain->DispAcc>=-0x8000-MinReserve) AND
|
|
(RunChain->DispAcc<=0x7fff+MaxReserve)) DSize=DispSize4Eps;
|
|
else DSize=DispSize32;
|
|
END
|
|
else DSize=RunChain->DSize;
|
|
RunChain->DSize=DispSizeNone;
|
|
|
|
switch (DSize)
|
|
BEGIN
|
|
|
|
/* Fall 1: passt komplett in 4er-Displacement */
|
|
|
|
case DispSize4:
|
|
if (ChkRange(RunChain->DispAcc,-32,28))
|
|
if ((RunChain->DispAcc & 3)!=0) WrError(1325);
|
|
else
|
|
BEGIN
|
|
AdrVals[Index][LastChain]+=(RunChain->DispAcc >> 2) & 0x000f;
|
|
RunChain->HasDisp=False;
|
|
END
|
|
break;
|
|
|
|
/* Fall 2: passt nicht mehr in naechstkleineres Displacement, aber wir
|
|
koennen hier schon einen Teil ablegen, um im naechsten Iterations-
|
|
schritt ein kuerzeres Displacement zu bekommen */
|
|
|
|
case DispSize4Eps:
|
|
if (RunChain->DispAcc>0)
|
|
BEGIN
|
|
AdrVals[Index][LastChain]+=0x0007;
|
|
RunChain->DispAcc-=28;
|
|
END
|
|
else
|
|
BEGIN
|
|
AdrVals[Index][LastChain]+=0x0008;
|
|
RunChain->DispAcc+=32;
|
|
END
|
|
break;
|
|
|
|
/* Fall 3: 16 Bit */
|
|
|
|
case DispSize16:
|
|
if (ChkRange(RunChain->DispAcc,-0x8000,0x7fff))
|
|
BEGIN
|
|
AdrVals[Index][LastChain]+=0x0011;
|
|
AdrVals[Index][LastChain+1]=RunChain->DispAcc & 0xffff;
|
|
AdrCnt1[Index]+=2;
|
|
RunChain->HasDisp=False;
|
|
END
|
|
break;
|
|
|
|
/* Fall 4: 32 Bit */
|
|
|
|
case DispSize32:
|
|
AdrVals[Index][LastChain]+=0x0012;
|
|
AdrVals[Index][LastChain+1]=RunChain->DispAcc >> 16;
|
|
AdrVals[Index][LastChain+2]=RunChain->DispAcc & 0xffff;
|
|
AdrCnt1[Index]+=4;
|
|
RunChain->HasDisp=False;
|
|
break;
|
|
|
|
default:
|
|
WrError(10000);
|
|
END
|
|
END
|
|
END
|
|
|
|
/* nichts mehr drin: dann ein leeres Steuerwort erzeugen. Tritt
|
|
auf, falls alles schon im Basisadressierungsbyte verschwunden */
|
|
|
|
else if (RunChain!=RootChain)
|
|
BEGIN
|
|
LastChain=AdrCnt1[Index] >> 1;
|
|
AdrVals[Index][LastChain]=0x0200; AdrCnt1[Index]+=2;
|
|
END
|
|
|
|
/* nichts mehr drin: wegwerfen
|
|
wenn wir noch nicht ganz vorne angekommen sind, dann ein
|
|
Indirektionsflag setzen */
|
|
|
|
if ((RunChain->RegCnt==0) AND (NOT RunChain->HasDisp))
|
|
BEGIN
|
|
if (RunChain!=RootChain) AdrVals[Index][LastChain]+=0x4000;
|
|
if (PrevChain==Nil) RootChain=Nil; else PrevChain->Next=Nil;
|
|
free(RunChain);
|
|
END
|
|
END
|
|
|
|
/* Ende-Kennung fuer letztes Glied */
|
|
|
|
AdrVals[Index][LastChain]+=0x8000;
|
|
END
|
|
|
|
return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
/* ansonsten absolut */
|
|
|
|
DSize=DispSizeNone;
|
|
SplitSize(Asc,&DSize);
|
|
AdrLong=EvalIntExpression(Asc,Int32,&OK);
|
|
if (OK) DecideAbs(AdrLong,DSize,Mask,Index);
|
|
|
|
return ChkAdr(Mask,Index);
|
|
END
|
|
|
|
static LongInt ImmVal(int Index)
|
|
BEGIN
|
|
switch (OpSize[Index])
|
|
BEGIN
|
|
case 0: return (ShortInt) (AdrVals[Index][0] & 0xff);
|
|
case 1: return (Integer) (AdrVals[Index][0]);
|
|
case 2: return (((LongInt)AdrVals[Index][0]) << 16)+((Integer)AdrVals[Index][1]);
|
|
default: WrError(10000); return 0;
|
|
END
|
|
END
|
|
|
|
static Boolean IsShort(int Index)
|
|
BEGIN
|
|
return ((AdrMode[Index] & 0xc0)==0);
|
|
END
|
|
|
|
static void AdaptImm(int Index, Byte NSize, Boolean Signed)
|
|
BEGIN
|
|
switch (OpSize[Index])
|
|
BEGIN
|
|
case 0:
|
|
if (NSize!=0)
|
|
BEGIN
|
|
if (((AdrVals[Index][0] & 0x80)==0x80) AND (Signed))
|
|
AdrVals[Index][0]|=0xff00;
|
|
else AdrVals[Index][0]&=0xff;
|
|
if (NSize==2)
|
|
BEGIN
|
|
if (((AdrVals[Index][0] & 0x8000)==0x8000) AND (Signed))
|
|
AdrVals[Index][1]=0xffff;
|
|
else AdrVals[Index][1]=0;
|
|
AdrCnt1[Index]+=2; AdrCnt2[Index]++;
|
|
END
|
|
END
|
|
break;
|
|
case 1:
|
|
if (NSize==0) AdrVals[Index][0]&=0xff;
|
|
else if (NSize==2)
|
|
BEGIN
|
|
if (((AdrVals[Index][0] & 0x8000)==0x8000) AND (Signed))
|
|
AdrVals[Index][1]=0xffff;
|
|
else AdrVals[Index][1]=0;
|
|
AdrCnt1[Index]+=2; AdrCnt2[Index]++;
|
|
END
|
|
break;
|
|
case 2:
|
|
if (NSize!=2)
|
|
BEGIN
|
|
AdrCnt1[Index]-=2; AdrCnt2[Index]--;
|
|
if (NSize==0) AdrVals[Index][0]&=0xff;
|
|
END
|
|
break;
|
|
END
|
|
OpSize[Index]=NSize;
|
|
END
|
|
|
|
static ShortInt DefSize(Byte Mask)
|
|
BEGIN
|
|
ShortInt z;
|
|
|
|
z=2;
|
|
while ((z>=0) AND ((Mask & 4)==0))
|
|
BEGIN
|
|
Mask=(Mask << 1) & 7; z--;
|
|
END
|
|
return z;
|
|
END
|
|
|
|
static Word RMask(Word No, Boolean Turn)
|
|
BEGIN
|
|
return (Turn) ? (0x8000 >> No) : (1 << No);
|
|
END
|
|
|
|
static Boolean DecodeRegList(char *Asc, Word *Erg, Boolean Turn)
|
|
BEGIN
|
|
char Part[11];
|
|
char *p,*p1,*p2;
|
|
Word r1,r2,z;
|
|
|
|
if (IsIndirect(Asc))
|
|
BEGIN
|
|
strcpy(Asc,Asc+1); Asc[strlen(Asc)-1]='\0';
|
|
END
|
|
*Erg=0;
|
|
while (*Asc!='\0')
|
|
BEGIN
|
|
p1=strchr(Asc,','); p2=strchr(Asc,'/');
|
|
if ((p1!=Nil) AND (p1<p2)) p=p1; else p=p2;
|
|
if (p==Nil)
|
|
BEGIN
|
|
strmaxcpy(Part,Asc,11); *Asc='\0';
|
|
END
|
|
else
|
|
BEGIN
|
|
*p='\0'; strmaxcpy(Part,Asc,11); strcpy(Asc,p+1);
|
|
END
|
|
p=strchr(Part,'-');
|
|
if (p==Nil)
|
|
BEGIN
|
|
if (NOT DecodeReg(Part,&r1))
|
|
BEGIN
|
|
WrXError(1410,Part); return False;
|
|
END
|
|
*Erg|=RMask(r1,Turn);
|
|
END
|
|
else
|
|
BEGIN
|
|
*p='\0';
|
|
if (NOT DecodeReg(Part,&r1))
|
|
BEGIN
|
|
WrXError(1410,Part); return False;
|
|
END;
|
|
if (NOT DecodeReg(p+1,&r2))
|
|
BEGIN
|
|
WrXError(1410,p+1); return False;
|
|
END
|
|
if (r1<=r2)
|
|
for (z=r1; z<=r2; z++) *Erg|=RMask(z,Turn);
|
|
else
|
|
BEGIN
|
|
for (z=r2; z<=15; z++) *Erg|=RMask(z,Turn);
|
|
for (z=0; z<=r1; z++) *Erg|=RMask(z,Turn);
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
static Boolean DecodeCondition(char *Asc, Word *Erg)
|
|
BEGIN
|
|
int z;
|
|
String Asc_N;
|
|
|
|
strmaxcpy(Asc_N,Asc,255); NLS_UpString(Asc_N); Asc=Asc_N;
|
|
|
|
for (z=0; z<ConditionCount; z++)
|
|
if (strcmp(Asc,Conditions[z])==0) break;
|
|
*Erg=z; return (z<ConditionCount);
|
|
END
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
static Boolean CheckFormat(char *FSet)
|
|
BEGIN
|
|
char *p;
|
|
|
|
if (strcmp(Format," ")==0) FormatCode=0;
|
|
else
|
|
BEGIN
|
|
p=strchr(FSet,*Format);
|
|
if (p!=Nil) FormatCode=p-FSet+1;
|
|
else WrError(1090);
|
|
return (p!=Nil);
|
|
END;
|
|
return True;
|
|
END
|
|
|
|
static Boolean CheckBFieldFormat(void)
|
|
BEGIN
|
|
if ((strcmp(Format,"G:R")==0) OR (strcmp(Format,"R:G")==0)) FormatCode=1;
|
|
else if ((strcmp(Format,"G:I")==0) OR (strcmp(Format,"I:G")==0)) FormatCode=2;
|
|
else if ((strcmp(Format,"E:R")==0) OR (strcmp(Format,"R:E")==0)) FormatCode=3;
|
|
else if ((strcmp(Format,"E:I")==0) OR (strcmp(Format,"I:E")==0)) FormatCode=4;
|
|
else
|
|
BEGIN
|
|
WrError(1090); return False;
|
|
END
|
|
return True;
|
|
END
|
|
|
|
static Boolean GetOpSize(char *Asc, Byte Index)
|
|
BEGIN
|
|
char *p;
|
|
int l=strlen(Asc);
|
|
|
|
p=RQuotPos(Asc,'.');
|
|
if (p==Nil)
|
|
BEGIN
|
|
OpSize[Index]=DOpSize; return True;
|
|
END
|
|
else if (p==Asc+l-2)
|
|
BEGIN
|
|
switch (p[1])
|
|
BEGIN
|
|
case 'B': OpSize[Index]=0; break;
|
|
case 'H': OpSize[Index]=1; break;
|
|
case 'W': OpSize[Index]=2; break;
|
|
default:
|
|
WrError(1107); return False;
|
|
END
|
|
*p='\0';
|
|
return True;
|
|
END
|
|
else
|
|
BEGIN
|
|
WrError(1107); return False;
|
|
END
|
|
END
|
|
|
|
static void SplitOptions(void)
|
|
BEGIN
|
|
char *p;
|
|
int z;
|
|
|
|
OptionCnt=0; *Options[0]='\0'; *Options[1]='\0';
|
|
do
|
|
BEGIN
|
|
p=RQuotPos(OpPart,'/');
|
|
if (p!=Nil)
|
|
BEGIN
|
|
if (OptionCnt<2)
|
|
BEGIN
|
|
for (z=OptionCnt-1; z>=0; z--) strcpy(Options[z+1],Options[z]);
|
|
OptionCnt++; strmaxcpy(Options[0],p+1,255);
|
|
END
|
|
*p='\0';
|
|
END
|
|
END
|
|
while (p!=Nil);
|
|
END
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
static Boolean DecodePseudo(void)
|
|
BEGIN
|
|
return False;
|
|
END
|
|
|
|
static void DecideBranch(LongInt Adr, Byte Index)
|
|
BEGIN
|
|
LongInt Dist=Adr-EProgCounter();
|
|
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
/* Groessenangabe erzwingt G-Format */
|
|
if (OpSize[Index]!=-1) FormatCode=1;
|
|
/* gerade 9-Bit-Zahl kurz darstellbar */
|
|
else if (((Dist & 1)==0) AND (Dist<=254) AND (Dist>=-256)) FormatCode=2;
|
|
/* ansonsten allgemein */
|
|
else FormatCode=1;
|
|
END
|
|
if ((FormatCode==1) AND (OpSize[Index]==-1))
|
|
if ((Dist<=127) AND (Dist>=-128)) OpSize[Index]=0;
|
|
else if ((Dist<=32767) AND (Dist>=-32768)) OpSize[Index]=1;
|
|
else OpSize[Index]=2;
|
|
END
|
|
|
|
static Boolean DecideBranchLength(LongInt *Addr, int Index)
|
|
BEGIN
|
|
*Addr-=EProgCounter();
|
|
if (OpSize[Index]==-1)
|
|
BEGIN
|
|
if ((*Addr>=-128) AND (*Addr<=127)) OpSize[Index]=0;
|
|
else if ((*Addr>=-32768) AND (*Addr<=32767)) OpSize[Index]=1;
|
|
else OpSize[Index]=2;
|
|
END
|
|
|
|
if ((NOT SymbolQuestionable) AND
|
|
(((OpSize[Index]==0) AND ((*Addr<-128) OR (*Addr>127)))
|
|
OR ((OpSize[Index]==1) AND ((*Addr<-32768) OR (*Addr>32767)))))
|
|
BEGIN
|
|
WrError(1370); return False;
|
|
END
|
|
else return True;
|
|
END
|
|
|
|
static void Make_G(Word Code)
|
|
BEGIN
|
|
WAsmCode[0]=0xd000+(OpSize[1] << 8)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
WAsmCode[1+AdrCnt2[1]]=Code+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=4+AdrCnt1[1]+AdrCnt1[2];
|
|
END
|
|
|
|
static void Make_E(Word Code, Boolean Signed)
|
|
BEGIN
|
|
LongInt HVal,Min,Max;
|
|
|
|
Min=128*(-Ord(Signed)); Max=Min+255;
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,Min,Max))
|
|
BEGIN
|
|
WAsmCode[0]=0xbf00+(HVal & 0xff);
|
|
WAsmCode[1]=Code+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+2,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=4+AdrCnt1[2];
|
|
END
|
|
END
|
|
END
|
|
|
|
static void Make_I(Word Code, Boolean Signed)
|
|
BEGIN
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AdaptImm(1,OpSize[2],Signed);
|
|
WAsmCode[0]=Code+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
memcpy(WAsmCode+1+AdrCnt2[2],AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1]+AdrCnt1[2];
|
|
END
|
|
END
|
|
|
|
static Boolean CodeAri(void)
|
|
BEGIN
|
|
int z;
|
|
Word AdrWord,Mask,Mask2;
|
|
char Form[6];
|
|
LongInt HVal;
|
|
|
|
if ((Memo("ADD")) OR (Memo("SUB")))
|
|
BEGIN
|
|
z=Ord(Memo("SUB"));
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GELQI"))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (IsShort(2))
|
|
if ((HVal>=1) AND (HVal<=8)) FormatCode=4;
|
|
else FormatCode=5;
|
|
else if ((HVal>=-128) AND (HVal<127)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else if (IsShort(1) AND (AdrType[2]==ModReg) AND (OpSize[1]==2) AND (OpSize[2]==2)) FormatCode=3;
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(z << 11);
|
|
break;
|
|
case 2:
|
|
Make_E(z << 11,True);
|
|
break;
|
|
case 3:
|
|
if ((NOT IsShort(1)) OR (AdrType[2]!=ModReg)) WrError(1350);
|
|
else if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x8100+(z << 6)+((AdrMode[2] & 15) << 10)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1];
|
|
if ((AdrMode[1]==0x04) & (AdrMode[2]==15)) WrError(140);
|
|
END
|
|
break;
|
|
case 4:
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,1,8))
|
|
BEGIN
|
|
WAsmCode[0]=0x4040+(z << 13)+((HVal & 7) << 10)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
case 5:
|
|
Make_I(0x44c0+(z << 11),True);
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if (Memo("CMP"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GELZQI"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_NoImmGen-MModPush))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (HVal==0) FormatCode=4;
|
|
else if ((HVal>=1) AND (HVal<=8) AND (IsShort(2))) FormatCode=5;
|
|
else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
|
|
else if (AdrType[2]==ModReg) FormatCode=3;
|
|
else if (IsShort(2)) FormatCode=5;
|
|
else FormatCode=1;
|
|
END
|
|
else if ((IsShort(1)) AND (AdrType[2]==ModReg)) FormatCode=3;
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(0x8000);
|
|
break;
|
|
case 2:
|
|
Make_E(0x8000,True);
|
|
break;
|
|
case 3:
|
|
if ((NOT IsShort(1)) OR (AdrType[2]!=ModReg)) WrError(1350);
|
|
else if (OpSize[1]!=2) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=((AdrMode[2] & 15) << 10)+(OpSize[2] << 8)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1];
|
|
END
|
|
break;
|
|
case 4:
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,0,0))
|
|
BEGIN
|
|
WAsmCode[0]=0xc000+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
case 5:
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,1,8))
|
|
BEGIN
|
|
WAsmCode[0]=0x4000+(OpSize[2] << 8)+AdrMode[2]+((HVal & 7) << 10);
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
case 6:
|
|
Make_I(0x40c0,True);
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
for (z=0; z<GE2OrderCount; z++)
|
|
if (Memo(GE2Orders[z].Name))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GE"))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=DefSize(GE2Orders[z].SMask2);
|
|
if (OpSize[1]==-1) OpSize[1]=DefSize(GE2Orders[z].SMask1);
|
|
if (((GE2Orders[z].SMask1 & (1 << OpSize[1]))==0) OR ((GE2Orders[z].SMask2 & (1 << OpSize[2]))==0)) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,GE2Orders[z].Mask1))
|
|
if (DecodeAdr(ArgStr[2],2,GE2Orders[z].Mask2))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((GE2Orders[z].Signed) AND (HVal>=-128) AND (HVal<=127)) FormatCode=2;
|
|
else if ((NOT GE2Orders[z].Signed) AND (HVal>=0) AND (HVal<=255)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(GE2Orders[z].Code); break;
|
|
case 2:
|
|
Make_E(GE2Orders[z].Code,GE2Orders[z].Signed); break;
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
for (z=0; z<LogOrderCount; z++)
|
|
if (Memo(LogOrders[z]))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GERI"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_Dest-MModPush))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((HVal>=0) AND (HVal<=255)) FormatCode=2;
|
|
else if (IsShort(2)) FormatCode=4;
|
|
else FormatCode=1;
|
|
END
|
|
else if ((AdrType[1]==ModReg) AND (AdrType[2]==ModReg) AND (OpSize[1]==2) AND (OpSize[2]==2))
|
|
FormatCode=3;
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(0x2000+(z << 10));
|
|
break;
|
|
case 2:
|
|
Make_E(0x2000+(z << 10),False);
|
|
break;
|
|
case 3:
|
|
if ((AdrType[1]!=ModReg) OR (AdrType[2]!=ModReg)) WrError(1350);
|
|
else if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x00c0+(z << 8)+(AdrMode[1] & 15)+((AdrMode[2] & 15) << 10);
|
|
CodeLen=2;
|
|
END
|
|
break;
|
|
case 4:
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x50c0+(OpSize[2] << 8)+(z << 10)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
AdaptImm(1,OpSize[2],False);
|
|
memcpy(WAsmCode+1+AdrCnt2[2],AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1]+AdrCnt1[2];
|
|
END
|
|
break;
|
|
END
|
|
if (OpSize[1]>OpSize[2]) WrError(140);
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
for (z=0; z<MulOrderCount; z++)
|
|
if (Memo(MulOrders[z]))
|
|
BEGIN
|
|
strcpy(Form,(Odd(z)) ? "GE" : "GER");
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat(Form))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((HVal>=-128+(Ord(Odd(z)) << 7)) AND
|
|
(HVal<=127+(Ord(Odd(z)) << 7))) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else if ((NOT Odd(z)) AND (AdrType[1]==ModReg) AND (OpSize[1]==2)
|
|
AND (AdrType[2]==ModReg) AND (OpSize[2]==2)) FormatCode=3;
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(0x4000+(z << 10)); break;
|
|
case 2:
|
|
Make_E(0x4000+(z << 10),NOT Odd(z)); break;
|
|
case 3:
|
|
if ((AdrType[1]!=ModReg) OR (AdrType[2]!=ModReg)) WrError(1350);
|
|
else if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x00d0+((AdrMode[2] & 15) << 10)+(z << 7)+
|
|
(AdrMode[1] & 15);
|
|
CodeLen=2;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
for (z=0; z<GetPutOrderCount; z++)
|
|
if (Memo(GetPutOrders[z].Name))
|
|
BEGIN
|
|
if (GetPutOrders[z].Turn)
|
|
BEGIN
|
|
Mask=Mask_Source; Mask2=MModReg; AdrWord=1;
|
|
END
|
|
else
|
|
BEGIN
|
|
Mask=MModReg; Mask2=Mask_Dest; AdrWord=2;
|
|
END;
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[AdrWord]==-1) OpSize[AdrWord]=GetPutOrders[z].Size;
|
|
if (OpSize[3-AdrWord]==-1) OpSize[3-AdrWord]=2;
|
|
if ((OpSize[AdrWord]!=GetPutOrders[z].Size) OR (OpSize[3-AdrWord]!=2)) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask))
|
|
if (DecodeAdr(ArgStr[2],2,Mask2))
|
|
BEGIN
|
|
Make_G(GetPutOrders[z].Code); WAsmCode[0]+=0x0400;
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if (Memo("MOVA"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GR"))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
OpSize[1]=0;
|
|
if (OpSize[2]!=2) WrError(1110);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask_PureMem))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_Dest))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
if ((AdrType[1]==ModDisp16) AND (AdrType[2]==ModReg)) FormatCode=2;
|
|
else FormatCode=1;
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(0xb400); WAsmCode[0]+=0x800;
|
|
break;
|
|
case 2:
|
|
if ((AdrType[1]!=ModDisp16) OR (AdrType[2]!=ModReg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x03c0+((AdrMode[2] & 15) << 10)+(AdrMode[1] & 15);
|
|
WAsmCode[1]=AdrVals[1][0];
|
|
CodeLen=4;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if ((Memo("QINS")) OR (Memo("QDEL")))
|
|
BEGIN
|
|
z=Ord(Memo("QINS")) << 11;
|
|
Mask=Mask_PureMem;
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if ((Memo("QINS")) OR (GetOpSize(ArgStr[2],2)))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
OpSize[1]=0;
|
|
if (OpSize[2]!=2) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask))
|
|
if (DecodeAdr(ArgStr[2],2,Mask+(Ord(Memo("QDEL"))*MModReg)))
|
|
BEGIN
|
|
Make_G(0xb000+z); WAsmCode[0]+=0x800;
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if (Memo("RVBY"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_Dest))
|
|
BEGIN
|
|
Make_G(0x4000); WAsmCode[0]+=0x400;
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if ((Memo("SHL")) OR (Memo("SHA")))
|
|
BEGIN
|
|
z=Ord(Memo("SHA"));
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GEQ"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=0;
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]!=0) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((IsShort(2)) AND (abs(HVal)>=1) AND (abs(HVal)<=8) AND ((z==0) OR (HVal<0))) FormatCode=3;
|
|
else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(0x3000+(z << 10)); break;
|
|
case 2:
|
|
Make_E(0x3000+(z << 10),True); break;
|
|
case 3:
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,-8,(1-z) << 3))
|
|
if (HVal==0) WrError(1135);
|
|
else
|
|
BEGIN
|
|
if (HVal<0) HVal+=16;
|
|
else HVal&=7;
|
|
WAsmCode[0]=0x4080+(HVal << 10)+(z << 6)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if ((Memo("SHXL")) OR (Memo("SHXR")))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (OpSize[1]!=2) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask_PureDest))
|
|
BEGIN
|
|
WAsmCode[0]=0x02f7;
|
|
WAsmCode[1]=0x8a00+(Ord(Memo("SHXR")) << 12)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals,AdrCnt1[1]);
|
|
CodeLen=4+AdrCnt1[1];
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
return False;
|
|
END
|
|
|
|
static Boolean CodeBits(void)
|
|
BEGIN
|
|
int z;
|
|
char Form[6];
|
|
LongInt HVal,AdrLong;
|
|
Word Mask;
|
|
|
|
for (z=0; z<BitOrderCount; z++)
|
|
if (Memo(BitOrders[z].Name))
|
|
BEGIN
|
|
strcpy(Form,(BitOrders[z].Code2!=0) ? "GER" : "GE");
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat(Form))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
|
|
BEGIN
|
|
if (OpSize[2]==-1)
|
|
if ((AdrType[2]==ModReg) AND (NOT BitOrders[z].MustByte)) OpSize[2]=2;
|
|
else OpSize[2]=0;
|
|
if (((AdrType[2]!=ModReg) OR (BitOrders[z].MustByte)) AND (OpSize[2]!=0)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((HVal>=0) AND (HVal<=7) AND (IsShort(2)) AND (BitOrders[z].Code2!=0) AND (OpSize[2]==0)) FormatCode=3;
|
|
else if ((HVal>=-128) AND (HVal<127)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else FormatCode=1;
|
|
END;
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(BitOrders[z].Code1); break;
|
|
case 2:
|
|
Make_E(BitOrders[z].Code1,True); break;
|
|
case 3:
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else if (OpSize[2]!=0) WrError(1130);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,0,7))
|
|
BEGIN
|
|
WAsmCode[0]=BitOrders[z].Code2+((HVal & 7) << 10)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
for (z=0; z<BFieldOrderCount; z++)
|
|
if (Memo(BFieldOrders[z]))
|
|
BEGIN
|
|
if (ArgCnt!=4) WrError(1110);
|
|
else if (CheckBFieldFormat())
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
if (GetOpSize(ArgStr[3],3))
|
|
if (GetOpSize(ArgStr[4],4))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[3]==-1) OpSize[3]=2;
|
|
if (OpSize[4]==-1) OpSize[4]=2;
|
|
if (DecodeAdr(ArgStr[1],1,MModReg+MModImm))
|
|
if (DecodeAdr(ArgStr[3],3,MModReg+MModImm))
|
|
BEGIN
|
|
Mask=(AdrType[3]==ModReg) ? Mask_Source : MModImm;
|
|
if (DecodeAdr(ArgStr[2],2,Mask))
|
|
if (DecodeAdr(ArgStr[4],4,Mask_PureMem))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[3]==ModReg)
|
|
if (AdrType[1]==ModReg) FormatCode=1; else FormatCode=2;
|
|
else
|
|
if (AdrType[1]==ModReg) FormatCode=3; else FormatCode=4;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
if ((AdrType[1]!=ModReg) OR (AdrType[3]!=ModReg)) WrError(1350);
|
|
else if ((OpSize[1]!=2) OR (OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0xd000+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
WAsmCode[1+AdrCnt2[2]]=0xc200+(z << 10)+AdrMode[4];
|
|
memcpy(WAsmCode+2+AdrCnt2[2],AdrVals[4],AdrCnt1[4]);
|
|
WAsmCode[2+AdrCnt2[2]+AdrCnt2[4]]=((AdrMode[3] & 15) << 10)+(AdrMode[1] & 15);
|
|
CodeLen=6+AdrCnt1[2]+AdrCnt1[4];
|
|
END
|
|
break;
|
|
case 2:
|
|
if ((AdrType[1]!=ModImm) OR (AdrType[3]!=ModReg)) WrError(1350);
|
|
else if ((OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0xd000+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
WAsmCode[1+AdrCnt2[2]]=0xd200+(z << 10)+AdrMode[4];
|
|
memcpy(WAsmCode+2+AdrCnt2[2],AdrVals[4],AdrCnt1[4]);
|
|
WAsmCode[2+AdrCnt2[2]+AdrCnt2[4]]=((AdrMode[3] & 15) << 10)+(OpSize[1] << 8);
|
|
CodeLen=6+AdrCnt1[2]+AdrCnt1[4];
|
|
if (OpSize[1]==0) WAsmCode[(CodeLen-2) >> 1]+=AdrVals[1][0] & 0xff;
|
|
else
|
|
BEGIN
|
|
memcpy(WAsmCode+(CodeLen >> 1),AdrVals[1],AdrCnt1[1]);
|
|
CodeLen+=AdrCnt1[1];
|
|
END
|
|
END
|
|
break;
|
|
case 3:
|
|
if ((AdrType[1]!=ModReg) OR (AdrType[2]!=ModImm) OR (AdrType[3]!=ModImm)) WrError(1350);
|
|
else if ((OpSize[1]!=2) OR (OpSize[4]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(2);
|
|
if (ChkRange(HVal,-128,-127))
|
|
BEGIN
|
|
AdrLong=ImmVal(3);
|
|
if (ChkRange(AdrLong,1,32))
|
|
BEGIN
|
|
WAsmCode[0]=0xbf00+(HVal & 0xff);
|
|
WAsmCode[1]=0xc200+(z << 10)+AdrMode[4];
|
|
memcpy(WAsmCode+2,AdrVals[4],AdrCnt1[4]);
|
|
WAsmCode[2+AdrCnt2[4]]=((AdrLong & 31) << 10)+(AdrMode[1] & 15);
|
|
CodeLen=6+AdrCnt1[4];
|
|
END
|
|
END
|
|
END
|
|
break;
|
|
case 4:
|
|
if ((AdrType[1]!=ModImm) OR (AdrType[2]!=ModImm) OR (AdrType[3]!=ModImm)) WrError(1350);
|
|
else if (OpSize[4]!=2) WrError(1130);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(2);
|
|
if (ChkRange(HVal,-128,-127))
|
|
BEGIN
|
|
AdrLong=ImmVal(3);
|
|
if (ChkRange(AdrLong,1,32))
|
|
BEGIN
|
|
WAsmCode[0]=0xbf00+(HVal & 0xff);
|
|
WAsmCode[1]=0xd200+(z << 10)+AdrMode[4];
|
|
memcpy(WAsmCode+2,AdrVals[4],AdrCnt1[4]);
|
|
WAsmCode[2+AdrCnt2[4]]=((AdrLong & 31) << 10)+(OpSize[1] << 8);
|
|
CodeLen=6+AdrCnt1[4];
|
|
if (OpSize[1]==0) WAsmCode[(CodeLen-1) >> 1]+=AdrVals[1][0] & 0xff;
|
|
else
|
|
BEGIN
|
|
memcpy(WAsmCode+(CodeLen >> 1),AdrVals[1],AdrCnt1[1]);
|
|
CodeLen+=AdrCnt1[1];
|
|
END
|
|
END
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if ((Memo("BFEXT")) OR (Memo("BFEXTU")))
|
|
BEGIN
|
|
z=Ord(Memo("BFEXTU"));
|
|
if (ArgCnt!=4) WrError(1110);
|
|
else if (CheckFormat("GE"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
if (GetOpSize(ArgStr[3],3))
|
|
if (GetOpSize(ArgStr[4],4))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[3]==-1) OpSize[3]=2;
|
|
if (OpSize[4]==-1) OpSize[4]=2;
|
|
if (DecodeAdr(ArgStr[4],4,MModReg))
|
|
if (DecodeAdr(ArgStr[3],3,Mask_MemGen-MModPop-MModPush))
|
|
if (DecodeAdr(ArgStr[2],2,MModReg+MModImm))
|
|
BEGIN
|
|
if (AdrType[2]==ModReg) Mask=Mask_Source; else Mask=MModImm;
|
|
if (DecodeAdr(ArgStr[1],1,Mask))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[2]==ModReg) FormatCode=1; else FormatCode=2;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
if ((OpSize[2]!=2) OR (OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0xd000+(OpSize[1] << 8)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
WAsmCode[1+AdrCnt2[1]]=0xea00+(z << 10)+AdrMode[3];
|
|
memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[3],AdrCnt1[3]);
|
|
WAsmCode[2+AdrCnt2[1]+AdrCnt2[3]]=((AdrMode[2] & 15) << 10)+(AdrMode[4] & 15);
|
|
CodeLen=6+AdrCnt1[1]+AdrCnt1[3];
|
|
END
|
|
break;
|
|
case 2:
|
|
if ((AdrType[1]!=ModImm) OR (AdrType[2]!=ModImm)) WrError(1350);
|
|
else if ((OpSize[3]!=2) OR (OpSize[4]!=2)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,-128,127))
|
|
BEGIN
|
|
AdrLong=ImmVal(2);
|
|
if (ChkRange(AdrLong,1,32))
|
|
BEGIN
|
|
WAsmCode[0]=0xbf00+(HVal & 0xff);
|
|
WAsmCode[1]=0xea00+(z << 10)+AdrMode[3];
|
|
memcpy(WAsmCode+2,AdrVals[3],AdrCnt1[3]);
|
|
WAsmCode[2+AdrCnt2[3]]=((AdrLong & 31) << 10)+(AdrMode[4] & 15);
|
|
CodeLen=6+AdrCnt1[3];
|
|
END
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
if ((Memo("BSCH/0")) OR (Memo("BSCH/1")))
|
|
BEGIN
|
|
z=OpPart[5]-'0';
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]!=2) WrError(1130);
|
|
else
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
|
|
BEGIN
|
|
/* immer G-Format */
|
|
WAsmCode[0]=0xd600+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
WAsmCode[1+AdrCnt2[1]]=0x5000+(z << 10)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=4+AdrCnt1[1]+AdrCnt1[2];
|
|
END
|
|
END
|
|
return True;
|
|
END
|
|
|
|
return False;
|
|
END
|
|
|
|
static void MakeCode_M16(void)
|
|
BEGIN
|
|
int z;
|
|
char *p;
|
|
Word AdrWord,HReg,Mask;
|
|
LongInt AdrLong,HVal;
|
|
Boolean OK;
|
|
|
|
DOpSize=(-1); for (z=1; z<=ArgCnt; OpSize[z++]=(-1));
|
|
|
|
/* zu ignorierendes */
|
|
|
|
if (Memo("")) return;
|
|
|
|
/* Formatangabe abspalten */
|
|
|
|
switch (AttrSplit)
|
|
BEGIN
|
|
case '.':
|
|
p=strchr(AttrPart,':');
|
|
if (p!=Nil)
|
|
BEGIN
|
|
if (p<AttrPart+strlen(AttrPart)-1) strmaxcpy(Format,p+1,255);
|
|
else strcpy(Format," ");
|
|
*p='\0';
|
|
END
|
|
else strcpy(Format," ");
|
|
break;
|
|
case ':':
|
|
p=strchr(AttrPart,'.');
|
|
if (p==Nil)
|
|
BEGIN
|
|
strmaxcpy(Format,AttrPart,255); *AttrPart='\0';
|
|
END
|
|
else
|
|
BEGIN
|
|
*p='\0';
|
|
if (p==AttrPart) strcpy(Format," "); else strmaxcpy(Format,AttrPart,255);
|
|
END
|
|
break;
|
|
default:
|
|
strcpy(Format," ");
|
|
END
|
|
NLS_UpString(Format);
|
|
|
|
/* Attribut abarbeiten */
|
|
|
|
if (*AttrPart=='\0') DOpSize=(-1);
|
|
else
|
|
switch (toupper(*AttrPart))
|
|
BEGIN
|
|
case 'B': DOpSize=0; break;
|
|
case 'H': DOpSize=1; break;
|
|
case 'W': DOpSize=2; break;
|
|
default:
|
|
WrError(1107); return;
|
|
END
|
|
|
|
/* Pseudoanweisungen */
|
|
|
|
if (DecodePseudo()) return;
|
|
|
|
if (DecodeIntelPseudo(False)) return;
|
|
|
|
/* ohne Argument */
|
|
|
|
for (z=0; z<FixedOrderCount; z++)
|
|
if (Memo(FixedOrders[z].Name))
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else if (*AttrPart!='\0') WrError(1100);
|
|
else if (strcmp(Format," ")!=0) WrError(1090);
|
|
else
|
|
BEGIN
|
|
CodeLen=2; WAsmCode[0]=FixedOrders[z].Code;
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("STOP")) OR (Memo("SLEEP")))
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else if (*AttrPart!='\0') WrError(1100);
|
|
else if (strcmp(Format," ")!=0) WrError(1090);
|
|
else
|
|
BEGIN
|
|
CodeLen=10;
|
|
WAsmCode[0]=0xd20c;
|
|
if (Memo("STOP"))
|
|
BEGIN
|
|
WAsmCode[1]=0x5374;
|
|
WAsmCode[2]=0x6f70;
|
|
END
|
|
else
|
|
BEGIN
|
|
WAsmCode[1]=0x5761;
|
|
WAsmCode[2]=0x6974;
|
|
END;
|
|
WAsmCode[3]=0x9e09;
|
|
WAsmCode[4]=0x0700;
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Datentransfer */
|
|
|
|
if (Memo("MOV"))
|
|
BEGIN
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GELSZQI"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_AllGen-MModPop))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (HVal==0) FormatCode=5;
|
|
else if ((HVal>=1) AND (HVal<=8) AND (IsShort(2))) FormatCode=6;
|
|
else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
|
|
else if (IsShort(2)) FormatCode=7;
|
|
else FormatCode=1;
|
|
END
|
|
else if ((AdrType[1]==ModReg) AND (OpSize[1]==2) AND (IsShort(2))) FormatCode=4;
|
|
else if ((AdrType[2]==ModReg) AND (OpSize[2]==2) AND (IsShort(1))) FormatCode=3;
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
Make_G(0x8800);
|
|
break;
|
|
case 2:
|
|
Make_E(0x8800,True);
|
|
break;
|
|
case 3:
|
|
if ((NOT IsShort(1)) OR (AdrType[2]!=ModReg)) WrError(1350);
|
|
else if (OpSize[2]!=2) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x0040+((AdrMode[2] & 15) << 10)+(OpSize[1] << 8)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1];
|
|
END
|
|
break;
|
|
case 4:
|
|
if ((NOT IsShort(2)) OR (AdrType[1]!=ModReg)) WrError(1350);
|
|
else if (OpSize[1]!=2) WrError(1130);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x0080+((AdrMode[1] & 15) << 10)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
break;
|
|
case 5:
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,0,0))
|
|
BEGIN
|
|
WAsmCode[0]=0xc400+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
case 6:
|
|
if ((AdrType[1]!=ModImm) OR (NOT IsShort(2))) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,1,8))
|
|
BEGIN
|
|
WAsmCode[0]=0x6000+((HVal & 7) << 10)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
CodeLen=2+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
case 7:
|
|
Make_I(0x48c0,True);
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* ein Operand */
|
|
|
|
for (z=0; z<OneOrderCount; z++)
|
|
if (Memo(OneOrders[z].Name))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
if ((OpSize[1]==-1) AND (OneOrders[z].OpMask!=0)) OpSize[1]=DefSize(OneOrders[z].OpMask);
|
|
if ((OpSize[1]!=-1) AND (((1 << OpSize[1]) & OneOrders[z].OpMask)==0)) WrError(1130);
|
|
else
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[1],1,OneOrders[z].Mask))
|
|
BEGIN
|
|
/* da nur G, Format ignorieren */
|
|
WAsmCode[0]=OneOrders[z].Code+AdrMode[1];
|
|
if (OneOrders[z].OpMask!=0) WAsmCode[0]+=OpSize[1] << 8;
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1];
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* zwei Operanden */
|
|
|
|
if (CodeAri()) return;
|
|
|
|
/* drei Operanden */
|
|
|
|
if ((Memo("CHK/N")) OR (Memo("CHK/S")) OR (Memo("CHK")))
|
|
BEGIN
|
|
z=Ord(OpPart[strlen(OpPart)-1]=='S');
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],2))
|
|
if (GetOpSize(ArgStr[2],1))
|
|
if (GetOpSize(ArgStr[3],3))
|
|
BEGIN
|
|
if (OpSize[3]==-1) OpSize[3]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=OpSize[3];
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[3];
|
|
if ((OpSize[1]!=OpSize[2]) OR (OpSize[2]!=OpSize[3])) WrError(1131);
|
|
else
|
|
if (DecodeAdr(ArgStr[1],2,Mask_MemGen-MModPop-MModPush))
|
|
if (DecodeAdr(ArgStr[2],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[3],3,MModReg))
|
|
BEGIN
|
|
OpSize[2]=2+z;
|
|
Make_G((AdrMode[3] & 15) << 10);
|
|
WAsmCode[0]+=0x400;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("CSI"))
|
|
BEGIN
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],3))
|
|
if (GetOpSize(ArgStr[2],1))
|
|
if (GetOpSize(ArgStr[3],2))
|
|
BEGIN
|
|
if (OpSize[3]==-1) OpSize[3]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=OpSize[3];
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if ((OpSize[1]!=OpSize[2]) OR (OpSize[2]!=OpSize[3])) WrError(1131);
|
|
else if (DecodeAdr(ArgStr[1],3,MModReg))
|
|
if (DecodeAdr(ArgStr[2],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[3],2,Mask_PureMem))
|
|
BEGIN
|
|
OpSize[2]=0;
|
|
Make_G((AdrMode[3] & 15) << 10);
|
|
WAsmCode[0]+=0x400;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("DIVX")) OR (Memo("MULX")))
|
|
BEGIN
|
|
z=Ord(Memo("DIVX"));
|
|
if (ArgCnt!=3) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
if (GetOpSize(ArgStr[3],3))
|
|
BEGIN
|
|
if (OpSize[3]==-1) OpSize[3]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=OpSize[3];
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if ((OpSize[1]!=2) OR (OpSize[2]!=2) OR (OpSize[3]!=2)) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_PureDest))
|
|
if (DecodeAdr(ArgStr[3],3,MModReg))
|
|
BEGIN
|
|
OpSize[2]=0;
|
|
Make_G(0x8200+((AdrMode[3] & 15) << 10)+(z << 8));
|
|
WAsmCode[0]+=0x400;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Bitoperationen */
|
|
|
|
if (CodeBits()) return;
|
|
|
|
/* Spruenge */
|
|
|
|
if ((Memo("BSR")) OR (Memo("BRA")))
|
|
BEGIN
|
|
z=Ord(Memo("BSR"));
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
if (CheckFormat("GD"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
DecideBranch(AdrLong,1);
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 2:
|
|
if (OpSize[1]!=-1) WrError(1100);
|
|
else
|
|
BEGIN
|
|
AdrLong-=EProgCounter();
|
|
if ((NOT SymbolQuestionable) AND ((AdrLong<-256) OR (AdrLong>254))) WrError(1370);
|
|
else if (Odd(AdrLong)) WrError(1375);
|
|
else
|
|
BEGIN
|
|
CodeLen=2;
|
|
WAsmCode[0]=0xae00+(z << 8)+Lo(AdrLong >> 1);
|
|
END
|
|
END
|
|
break;
|
|
case 1:
|
|
WAsmCode[0]=0x20f7+(z << 11)+(((Word)OpSize[1]) << 8);
|
|
AdrLong-=EProgCounter();
|
|
switch (OpSize[1])
|
|
BEGIN
|
|
case 0:
|
|
if ((NOT SymbolQuestionable) AND ((AdrLong<-128) OR (AdrLong>127))) WrError(1370);
|
|
else
|
|
BEGIN
|
|
CodeLen=4; WAsmCode[1]=Lo(AdrLong);
|
|
END
|
|
break;
|
|
case 1:
|
|
if ((NOT SymbolQuestionable) AND ((AdrLong<-32768) OR (AdrLong>32767))) WrError(1370);
|
|
else
|
|
BEGIN
|
|
CodeLen=4; WAsmCode[1]=AdrLong & 0xffff;
|
|
END
|
|
break;
|
|
case 2:
|
|
CodeLen=6; WAsmCode[1]=AdrLong >> 16;
|
|
WAsmCode[2]=AdrLong & 0xffff;
|
|
break;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (*OpPart=='B')
|
|
for (z=0; z<ConditionCount; z++)
|
|
if (strcmp(OpPart+1,Conditions[z])==0)
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else
|
|
if (CheckFormat("GD"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
AdrLong=EvalIntExpression(ArgStr[1],Int32,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
DecideBranch(AdrLong,1);
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 2:
|
|
if (OpSize[1]!=-1) WrError(1100);
|
|
else
|
|
BEGIN
|
|
AdrLong-=EProgCounter();
|
|
if ((NOT SymbolQuestionable) AND ((AdrLong<-256) OR (AdrLong>254))) WrError(1370);
|
|
else if (Odd(AdrLong)) WrError(1375);
|
|
else
|
|
BEGIN
|
|
CodeLen=2;
|
|
WAsmCode[0]=0x8000+(z << 10)+Lo(AdrLong >> 1);
|
|
END
|
|
END
|
|
break;
|
|
case 1:
|
|
WAsmCode[0]=0x00f6+(z << 10)+(((Word)OpSize[1]) << 8);
|
|
AdrLong-=EProgCounter();
|
|
switch (OpSize[1])
|
|
BEGIN
|
|
case 0:
|
|
if ((AdrLong<-128) OR (AdrLong>127)) WrError(1370);
|
|
else
|
|
BEGIN
|
|
CodeLen=4; WAsmCode[1]=Lo(AdrLong);
|
|
END
|
|
break;
|
|
case 1:
|
|
if ((AdrLong<-32768) OR (AdrLong>32767)) WrError(1370);
|
|
else
|
|
BEGIN
|
|
CodeLen=4; WAsmCode[1]=AdrLong & 0xffff;
|
|
END
|
|
break;
|
|
case 2:
|
|
CodeLen=6; WAsmCode[1]=AdrLong >> 16;
|
|
WAsmCode[2]=AdrLong & 0xffff;
|
|
break;
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("ACB")) OR (Memo("SCB")))
|
|
BEGIN
|
|
AdrWord=Ord(Memo("SCB"));
|
|
if (ArgCnt!=4) WrError(1110);
|
|
else if (CheckFormat("GEQR"))
|
|
if (GetOpSize(ArgStr[2],3))
|
|
if (GetOpSize(ArgStr[4],4))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[3],2))
|
|
BEGIN
|
|
if ((OpSize[3]==-1) AND (OpSize[2]==-1)) OpSize[3]=2;
|
|
if ((OpSize[3]==-1) AND (OpSize[2]!=-1)) OpSize[3]=OpSize[2];
|
|
else if ((OpSize[3]!=-1) AND (OpSize[2]==-1)) OpSize[2]=OpSize[3];
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[2];
|
|
if (OpSize[3]!=OpSize[2]) WrError(1131);
|
|
else if (NOT DecodeReg(ArgStr[2],&HReg)) WrError(1350);
|
|
else
|
|
BEGIN
|
|
AdrLong=EvalIntExpression(ArgStr[4],Int32,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
if (DecodeAdr(ArgStr[1],1,Mask_Source))
|
|
if (DecodeAdr(ArgStr[3],2,Mask_Source))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]!=ModImm) FormatCode=1;
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((HVal==1) AND (AdrType[2]==ModReg)) FormatCode=4;
|
|
else if ((HVal==1) AND (AdrType[2]==ModImm))
|
|
BEGIN
|
|
HVal=ImmVal(2);
|
|
if ((HVal>=1-AdrWord) AND (HVal<=64-AdrWord)) FormatCode=3;
|
|
else FormatCode=2;
|
|
END
|
|
else if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
if (DecideBranchLength(&AdrLong,4)) /* ??? */
|
|
BEGIN
|
|
WAsmCode[0]=0xd000+(OpSize[1] << 8)+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
WAsmCode[1+AdrCnt2[1]]=0xf000+(AdrWord << 11)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+2+AdrCnt2[1],AdrVals[2],AdrCnt1[2]);
|
|
WAsmCode[2+AdrCnt2[1]+AdrCnt2[2]]=(HReg << 10)+(OpSize[4] << 8);
|
|
CodeLen=6+AdrCnt1[1]+AdrCnt1[2];
|
|
END
|
|
break;
|
|
case 2:
|
|
if (DecideBranchLength(&AdrLong,4)) /* ??? */
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,-128,127))
|
|
BEGIN
|
|
WAsmCode[0]=0xbf00+(HVal & 0xff);
|
|
WAsmCode[1]=0xf000+(AdrWord << 11)+(OpSize[2] << 8)+AdrMode[2];
|
|
memcpy(WAsmCode+2,AdrVals[2],AdrCnt1[2]);
|
|
WAsmCode[2+AdrCnt2[2]]=(HReg << 10)+(OpSize[4] << 8);
|
|
CodeLen=6+AdrCnt1[2];
|
|
END
|
|
END
|
|
break;
|
|
case 3:
|
|
if (DecideBranchLength(&AdrLong,4)) /* ??? */
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else if (ImmVal(1)!=1) WrError(1135);
|
|
else if (AdrType[2]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(2);
|
|
if (ChkRange(HVal,1-AdrWord,64-AdrWord))
|
|
BEGIN
|
|
WAsmCode[0]=0x03d1+(HReg << 10)+(AdrWord << 1);
|
|
WAsmCode[1]=((HVal & 0x3f) << 10)+(OpSize[4] << 8);
|
|
CodeLen=4;
|
|
END
|
|
END
|
|
break;
|
|
case 4:
|
|
if (DecideBranchLength(&AdrLong,4)) /* ??? */
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else if (ImmVal(1)!=1) WrError(1135);
|
|
else if (OpSize[2]!=2) WrError(1130);
|
|
else if (AdrType[2]!=ModReg) WrError(1350);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x03d0+(HReg << 10)+(AdrWord << 1);
|
|
WAsmCode[1]=((AdrMode[2] & 15) << 10)+(OpSize[4] << 8);
|
|
CodeLen=4;
|
|
END
|
|
break;
|
|
END
|
|
if (CodeLen>0)
|
|
switch (OpSize[4])
|
|
BEGIN
|
|
case 0:
|
|
WAsmCode[(CodeLen >> 1)-1]+=AdrLong & 0xff;
|
|
break;
|
|
case 1:
|
|
WAsmCode[CodeLen >> 1]=AdrLong & 0xffff;
|
|
CodeLen+=2;
|
|
break;
|
|
case 2:
|
|
WAsmCode[ CodeLen >> 1 ]=AdrLong >> 16;
|
|
WAsmCode[(CodeLen >> 1)+1]=AdrLong & 0xffff;
|
|
CodeLen+=4;
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("TRAPA"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (*AttrPart!='\0') WrError(1100);
|
|
else if (strcmp(Format," ")!=0) WrError(1090);
|
|
else if (*ArgStr[1]!='#') WrError(1350);
|
|
else
|
|
BEGIN
|
|
AdrWord=EvalIntExpression(ArgStr[1]+1,UInt4,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
CodeLen=2; WAsmCode[0]=0x03d5+(AdrWord << 10);
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (strncmp(OpPart,"TRAP",4)==0)
|
|
BEGIN
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else if (*AttrPart!='\0') WrError(1100);
|
|
else if (strcmp(Format," ")!=0) WrError(1090);
|
|
else
|
|
BEGIN
|
|
SplitOptions();
|
|
if (OptionCnt!=1) WrError(1115);
|
|
else if (NOT DecodeCondition(Options[0],&AdrWord)) WrError(1360);
|
|
else
|
|
BEGIN
|
|
CodeLen=2; WAsmCode[0]=0x03d4+(AdrWord << 10);
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
/* Specials */
|
|
|
|
if ((Memo("ENTER")) OR (Memo("EXITD")))
|
|
BEGIN
|
|
if (Memo("EXITD"))
|
|
BEGIN
|
|
z=1; strcpy(ArgStr[3],ArgStr[1]);
|
|
strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
|
|
END
|
|
else z=0;
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("GE"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[2]!=2) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,MModReg+MModImm))
|
|
if (DecodeRegList(ArgStr[2],&AdrWord,z==1))
|
|
if ((z & 0xc000)!=0) WrXError(1410,"SP/FP");
|
|
else
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((HVal>=-128) AND (HVal<=127)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
WAsmCode[0]=0x02f7;
|
|
WAsmCode[1]=0x8c00+(z << 12)+(OpSize[1] << 8)+AdrMode[1];
|
|
memcpy(WAsmCode+2,AdrVals[1],AdrCnt1[1]);
|
|
WAsmCode[2+AdrCnt2[1]]=AdrWord;
|
|
CodeLen=6+AdrCnt1[1];
|
|
break;
|
|
case 2:
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,-128,127))
|
|
BEGIN
|
|
WAsmCode[0]=0x8e00+(z << 12)+(HVal & 0xff);
|
|
WAsmCode[1]=AdrWord;
|
|
CodeLen=4;
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (strncmp(OpPart,"SCMP",4)==0)
|
|
BEGIN
|
|
if (DOpSize==-1) DOpSize=2;
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
SplitOptions();
|
|
if (OptionCnt>1) WrError(1115);
|
|
else
|
|
BEGIN
|
|
OK=True;
|
|
if (OptionCnt==0) AdrWord=6;
|
|
else if (strcasecmp(Options[0],"LTU")==0) AdrWord=0;
|
|
else if (strcasecmp(Options[0],"GEU")==0) AdrWord=1;
|
|
else OK=(DecodeCondition(Options[0],&AdrWord) AND (AdrWord>1) AND (AdrWord<6));
|
|
if (NOT OK) WrXError(1360,Options[0]);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x00e0+(DOpSize << 8)+(AdrWord << 10);
|
|
CodeLen=2;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((strncmp(OpPart,"SMOV",4)==0) OR (strncmp(OpPart,"SSCH",4)==0))
|
|
BEGIN
|
|
if (DOpSize==-1) DOpSize=2;
|
|
z=Ord(OpPart[1]=='S') << 4;
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
SplitOptions();
|
|
if (strcasecmp(Options[0],"F")==0)
|
|
BEGIN
|
|
Mask=0; strcpy(Options[0],Options[1]); OptionCnt--;
|
|
END
|
|
else if (strcasecmp(Options[0],"B")==0)
|
|
BEGIN
|
|
Mask=1; strcpy(Options[0],Options[1]); OptionCnt--;
|
|
END
|
|
else if (strcasecmp(Options[1],"F")==0)
|
|
BEGIN
|
|
Mask=0; OptionCnt--;
|
|
END
|
|
else if (strcasecmp(Options[1],"B")==0)
|
|
BEGIN
|
|
Mask=1; OptionCnt--;
|
|
END
|
|
else Mask=0;
|
|
if (OptionCnt>1) WrError(1115);
|
|
else
|
|
BEGIN
|
|
OK=True;
|
|
if (OptionCnt==0) AdrWord=6;
|
|
else if (strcasecmp(Options[0],"LTU")==0) AdrWord=0;
|
|
else if (strcasecmp(Options[0],"GEU")==0) AdrWord=1;
|
|
else OK=(DecodeCondition(Options[0],&AdrWord)) AND (AdrWord>1) AND (AdrWord<6);
|
|
if (NOT OK) WrXError(1360,Options[0]);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x00e4+(DOpSize << 8)+(AdrWord << 10)+Mask+z;
|
|
CodeLen=2;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("SSTR"))
|
|
BEGIN
|
|
if (DOpSize==-1) DOpSize=2;
|
|
if (ArgCnt!=0) WrError(1110);
|
|
else
|
|
BEGIN
|
|
WAsmCode[0]=0x24f7+(DOpSize << 8); CodeLen=2;
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("LDM")) OR (Memo("STM")))
|
|
BEGIN
|
|
Mask=MModIReg+MModDisp16+MModDisp32+MModAbs16+MModAbs32+MModPCRel16+MModPCRel32;
|
|
if (Memo("LDM"))
|
|
BEGIN
|
|
z=0x1000; Mask+=MModPop;
|
|
strcpy(ArgStr[3],ArgStr[1]); strcpy(ArgStr[1],ArgStr[2]); strcpy(ArgStr[2],ArgStr[3]);
|
|
END
|
|
else
|
|
BEGIN
|
|
z=0; Mask+=MModPush;
|
|
END
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=2;
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if ((OpSize[1]!=2) OR (OpSize[2]!=2)) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[2],2,Mask))
|
|
if (DecodeRegList(ArgStr[1],&AdrWord,AdrType[2]!=ModPush))
|
|
BEGIN
|
|
WAsmCode[0]=0x8a00+z+AdrMode[2];
|
|
memcpy(WAsmCode+1,AdrVals[2],AdrCnt1[2]);
|
|
WAsmCode[1+AdrCnt2[2]]=AdrWord;
|
|
CodeLen=4+AdrCnt1[2];
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if ((Memo("STC")) OR (Memo("STP")))
|
|
BEGIN
|
|
z=Ord(Memo("STP")) << 10;
|
|
if (ArgCnt!=2) WrError(1110);
|
|
else if (CheckFormat("G"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
if (GetOpSize(ArgStr[2],2))
|
|
BEGIN
|
|
if (OpSize[2]==-1) OpSize[2]=2;
|
|
if (OpSize[1]==-1) OpSize[1]=OpSize[1];
|
|
if (OpSize[1]!=OpSize[2]) WrError(1132);
|
|
else if ((z==0) AND (OpSize[2]!=2)) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,Mask_PureMem))
|
|
if (DecodeAdr(ArgStr[2],2,Mask_Dest))
|
|
BEGIN
|
|
OpSize[1]=0;
|
|
Make_G(0xa800+z);
|
|
WAsmCode[0]+=0x800;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("WAIT"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (*AttrPart!='\0') WrError(1100);
|
|
else if (strcmp(Format," ")!=0) WrError(1090);
|
|
else if (*ArgStr[1]!='#') WrError(1350);
|
|
else
|
|
BEGIN
|
|
WAsmCode[1]=EvalIntExpression(ArgStr[1]+1,UInt3,&OK);
|
|
if (OK)
|
|
BEGIN
|
|
WAsmCode[0]=0x0fd6; CodeLen=4;
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
if (Memo("JRNG"))
|
|
BEGIN
|
|
if (ArgCnt!=1) WrError(1110);
|
|
else if (CheckFormat("GE"))
|
|
if (GetOpSize(ArgStr[1],1))
|
|
BEGIN
|
|
if (OpSize[1]==-1) OpSize[1]=1;
|
|
if (OpSize[1]!=1) WrError(1130);
|
|
else if (DecodeAdr(ArgStr[1],1,MModReg+MModImm))
|
|
BEGIN
|
|
if (FormatCode==0)
|
|
BEGIN
|
|
if (AdrType[1]==ModImm)
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if ((HVal>=0) AND (HVal<=255)) FormatCode=2;
|
|
else FormatCode=1;
|
|
END
|
|
else FormatCode=1;
|
|
END
|
|
switch (FormatCode)
|
|
BEGIN
|
|
case 1:
|
|
WAsmCode[0]=0xba00+AdrMode[1];
|
|
memcpy(WAsmCode+1,AdrVals[1],AdrCnt1[1]);
|
|
CodeLen=2+AdrCnt1[1];
|
|
break;
|
|
case 2:
|
|
if (AdrType[1]!=ModImm) WrError(1350);
|
|
else
|
|
BEGIN
|
|
HVal=ImmVal(1);
|
|
if (ChkRange(HVal,0,255))
|
|
BEGIN
|
|
WAsmCode[0]=0xbe00+(HVal & 0xff); CodeLen=2;
|
|
END
|
|
END
|
|
break;
|
|
END
|
|
END
|
|
END
|
|
return;
|
|
END
|
|
|
|
WrXError(1200,OpPart);
|
|
END
|
|
|
|
static Boolean IsDef_M16(void)
|
|
BEGIN
|
|
return False;
|
|
END
|
|
|
|
static void SwitchFrom_M16(void)
|
|
BEGIN
|
|
DeinitFields();
|
|
END
|
|
|
|
static void SwitchTo_M16(void)
|
|
BEGIN
|
|
TurnWords=True; ConstMode=ConstModeIntel; SetIsOccupied=False;
|
|
|
|
PCSymbol="$"; HeaderID=0x13; NOPCode=0x1bd6;
|
|
DivideChars=","; HasAttrs=True; AttrChars=".:";
|
|
|
|
ValidSegs=1<<SegCode;
|
|
Grans[SegCode]=1; ListGrans[SegCode]=2; SegInits[SegCode]=0;
|
|
#ifdef __STDC__
|
|
SegLimits[SegCode] = 0xfffffffful;
|
|
#else
|
|
SegLimits[SegCode] = 0xffffffffl;
|
|
#endif
|
|
|
|
MakeCode=MakeCode_M16; IsDef=IsDef_M16;
|
|
SwitchFrom=SwitchFrom_M16; InitFields();
|
|
END
|
|
|
|
void codem16_init(void)
|
|
BEGIN
|
|
CPUM16=AddCPU("M16",SwitchTo_M16);
|
|
END
|
|
|