/* codem16.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator Mitsubishi M16 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "nls.h"
#include "strutil.h"
#include "errmsg.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "asmallg.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#define REG_SP 15
#define REG_FP 14
#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))
typedef struct
{
Word Mask;
Byte OpMask;
Word Code;
} OneOrder;
typedef struct
{
Word Mask1,Mask2;
Word SMask1,SMask2;
Word Code;
Boolean Signed;
} GE2Order;
typedef struct
{
char *Name;
Boolean MustByte;
Word Code1,Code2;
} BitOrder;
typedef struct
{
const char *p_name;
} condition_t;
static CPUVar CPUM16;
static char *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][10];
static BitOrder *FixedLongOrders;
static OneOrder *OneOrders;
static GE2Order *GE2Orders;
static BitOrder *BitOrders;
static condition_t *Conditions;
/*------------------------------------------------------------------------*/
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)
{
return ((inp >= -32) && (inp <= 28));
}
static Boolean IsD16(LongInt inp)
{
return ((inp >= -32768) && (inp <= 32767));
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, Word *pResult)
* \brief check whether argument is a CPU register
* \param pArg argument to check
* \param pResult numeric register value if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore(const char *pArg, Word *pResult)
{
if (!as_strcasecmp(pArg, "SP"))
*pResult = REG_SP | REGSYM_FLAG_ALIAS;
else if (!as_strcasecmp(pArg, "FP"))
*pResult = REG_FP | REGSYM_FLAG_ALIAS;
else if ((strlen(pArg
) > 1) && (as_toupper
(*pArg
) == 'R'))
{
Boolean OK;
*pResult = ConstLongInt(pArg + 1, &OK, 10);
return OK && (*pResult <= 15);
}
else
return False;
return True;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_M16(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - M16 variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_M16(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
{
if (InpSize == eSymbolSize32Bit)
{
switch (Value)
{
case REGSYM_FLAG_ALIAS | REG_SP:
as_snprintf(pDest, DestSize, "SP");
break;
case REGSYM_FLAG_ALIAS | REG_FP:
as_snprintf(pDest, DestSize, "FP");
break;
default:
as_snprintf(pDest, DestSize, "R%u", (unsigned)(Value & 15));
}
}
else
as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
* \brief parse for register, including register aliases
* \param pArg source argument
* \param pResult result buffer
* \param MustBeReg True if register is expected
* \return tRegEvalResult
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
if (DecodeRegCore(pArg->str.p_str, pResult))
{
*pResult &= ~REGSYM_FLAG_ALIAS;
return eIsReg;
}
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
*pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
return RegEvalResult;
}
static void SplitSize(tStrComp *pArg, DispSize *Erg)
{
int ArgLen
= strlen(pArg
->str.
p_str);
if ((ArgLen
> 2) && (!strcmp(pArg
->str.
p_str + (ArgLen
- 2), ":4")))
{
*Erg = DispSize4;
StrCompShorten(pArg, 2);
}
else if ((ArgLen
> 3) && (!strcmp(pArg
->str.
p_str + (ArgLen
- 3), ":16")))
{
*Erg = DispSize16;
StrCompShorten(pArg, 3);
}
else if ((ArgLen
> 3) && (!strcmp(pArg
->str.
p_str + (ArgLen
- 3), ":32")))
{
*Erg = DispSize32;
StrCompShorten(pArg, 3);
}
}
static void DecideAbs(LongInt Disp, DispSize Size, Word Mask, int Index)
{
switch (Size)
{
case DispSize4:
Size = DispSize16;
break;
case DispSizeNone:
Size = ((IsD16(Disp)) && (Mask & MModAbs16)) ? DispSize16 : DispSize32;
break;
default:
break;
}
switch (Size)
{
case DispSize16:
if (ChkRange(Disp, -32768, 32767))
{
AdrType[Index] = ModAbs16;
AdrMode[Index] = 0x09;
AdrVals[Index][0] = Disp & 0xffff;
AdrCnt1[Index] = 2;
}
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(ErrNum_InternalError);
}
}
static void SetError(tErrorNum Code)
{
WrError(Code);
ErrFlag = True;
}
static PChainRec DecodeChain(tStrComp *pArg)
{
PChainRec Rec;
int z;
char *pCompSplit, *pScaleSplit;
String SRegStr;
tStrComp Arg, Remainder, ScaleArg, SReg;
Boolean OK;
Byte Scale;
tRegEvalResult RegEvalResult;
ChkStack();
Rec
= (PChainRec
) malloc(sizeof(TChainRec
));
Rec->Next = NULL;
Rec->RegCnt = 0;
Rec->DispAcc = 0;
Rec->HasDisp = False;
Rec->DSize = DispSizeNone;
StrCompMkTemp(&SReg, SRegStr, sizeof(SRegStr));
Arg = *pArg;
do
{
/* eine Komponente abspalten */
pCompSplit = QuotPos(Arg.str.p_str, ',');
if (pCompSplit)
StrCompSplitRef(&Arg, &Remainder, &Arg, pCompSplit);
StrCompCopy(&SReg, &Arg);
pScaleSplit = RQuotPos(SReg.str.p_str, '*');
if (pScaleSplit)
StrCompSplitRef(&SReg, &ScaleArg, &SReg, pScaleSplit);
/* weitere Indirektion ? */
if (*Arg.str.p_str == '@')
{
if (Rec->Next) SetError(ErrNum_InvAddrMode);
else
{
StrCompIncRefLeft(&Arg, 1);
if (IsIndirect(Arg.str.p_str))
{
StrCompIncRefLeft(&Arg, 1);
StrCompShorten(&Arg, 1);
}
Rec->Next = DecodeChain(&Arg);
}
}
/* Register, mit Skalierungsfaktor ? */
else if ((RegEvalResult = DecodeReg(&SReg, Rec->Regs + Rec->RegCnt, False)) != eIsNoReg)
{
if (RegEvalResult == eRegAbort)
ErrFlag = True;
else if (Rec->RegCnt >= 5) SetError(ErrNum_InvAddrMode);
else
{
tSymbolFlags Flags;
if (pScaleSplit)
Scale = EvalStrIntExpressionWithFlags(&ScaleArg, UInt4, &OK, &Flags);
else
{
OK = True;
Scale = 1;
Flags= eSymbolFlag_None;
}
if (mFirstPassUnknown(Flags))
Scale = 1;
if (!OK) ErrFlag = True;
else if ((Scale != 1) && (Scale != 2) && (Scale != 4) && (Scale != 8)) SetError(ErrNum_InvAddrMode);
else
{
Rec->Scales[Rec->RegCnt] = 0;
while (Scale > 1)
{
Rec->Scales[Rec->RegCnt]++;
Scale = Scale >> 1;
}
Rec->RegCnt++;
}
}
}
/* PC, mit Skalierungsfaktor ? */
else if (!as_strcasecmp(SReg.str.p_str, "PC"))
{
if (Rec->RegCnt >= 5) SetError(ErrNum_InvAddrMode);
else
{
tSymbolFlags Flags;
if (pScaleSplit)
Scale = EvalStrIntExpressionWithFlags(&ScaleArg, UInt4, &OK, &Flags);
else
{
OK = True;
Scale = 1;
Flags = eSymbolFlag_None;
}
if (mFirstPassUnknown(Flags))
Scale = 1;
if (!OK) ErrFlag = True;
else if ((Scale != 1) && (Scale != 2) && (Scale != 4) && (Scale != 8)) SetError(ErrNum_InvAddrMode);
else
{
for (z = Rec->RegCnt - 1; z >= 0; z--)
{
Rec->Regs[z + 1] = Rec->Regs[z];
Rec->Scales[z + 1] = Rec->Scales[z];
}
Rec->Scales[0] = 0;
while (Scale > 1)
{
Rec->Scales[0]++;
Scale = Scale >> 1;
}
Rec->Regs[0] = 16;
Rec->RegCnt++;
}
}
}
/* ansonsten Displacement */
else
{
SplitSize(&Arg, &(Rec->DSize));
Rec->DispAcc += EvalStrIntExpression(&Arg, Int32, &OK);
if (!OK) ErrFlag = True;
Rec->HasDisp = True;
}
if (pCompSplit)
Arg = Remainder;
}
while (pCompSplit && !ErrFlag);
if (ErrFlag)
{
return NULL;
}
else return Rec;
}
static Boolean ChkAdr(Word Mask, int Index)
{
AdrCnt2[Index]=AdrCnt1[Index] >> 1;
if ((AdrType[Index] != -1) && ((Mask & (1 << AdrType[Index])) == 0))
{
char Str[30];
AdrCnt1[Index] = AdrCnt2[Index] = 0;
AdrType[Index] = ModNone;
as_snprintf(Str, sizeof(Str), "%d", Index);
WrXError(ErrNum_InvAddrMode, Str);
return False;
}
else
return (AdrType[Index] != ModNone);
}
static Boolean DecodeAdr(const tStrComp *pArg, int Index, Word Mask)
{
LongInt AdrLong, MinReserve, MaxReserve;
int z, z2, LastChain;
Boolean OK, Error;
PChainRec RootChain, RunChain, PrevChain;
DispSize DSize;
tStrComp Arg;
AdrCnt1[Index] = 0;
AdrType[Index] = ModNone;
/* Register ? */
switch (DecodeReg(pArg, AdrMode + Index, False))
{
case eIsReg:
AdrType[Index] = ModReg;
AdrMode[Index] += 0x10;
return ChkAdr(Mask, Index);
case eIsNoReg:
break;
default:
return False;
}
/* immediate ? */
if (*pArg->str.p_str == '#')
{
switch (OpSize[Index])
{
case -1:
WrError(ErrNum_UndefOpSizes);
OK = False;
break;
case 0:
AdrVals[Index][0] = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK) & 0xff;
if (OK)
AdrCnt1[Index] = 2;
break;
case 1:
AdrVals[Index][0] = EvalStrIntExpressionOffs(pArg, 1, Int16, &OK);
if (OK)
AdrCnt1[Index] = 2;
break;
case 2:
AdrLong = EvalStrIntExpressionOffs(pArg, 1, Int32, &OK);
if (OK)
{
AdrVals[Index][0] = AdrLong >> 16;
AdrVals[Index][1] = AdrLong & 0xffff;
AdrCnt1[Index] = 4;
}
break;
}
if (OK)
{
AdrType[Index] = ModImm;
AdrMode[Index] = 0x0c;
}
return ChkAdr(Mask, Index);
}
/* indirekt ? */
if (*pArg->str.p_str == '@')
{
tStrComp IArg;
StrCompRefRight(&IArg,pArg, 1);
if (IsIndirect(IArg.str.p_str))
{
StrCompIncRefLeft(&IArg, 1);
StrCompShorten(&IArg, 1);
}
/* Stack Push ? */
if ((!as_strcasecmp(IArg.str.p_str, "-R15")) || (!as_strcasecmp(IArg.str.p_str, "-SP")))
{
AdrType[Index] = ModPush;
AdrMode[Index] = 0x05;
return ChkAdr(Mask, Index);
}
/* Stack Pop ? */
if ((!as_strcasecmp(IArg.str.p_str, "R15+")) || (!as_strcasecmp(IArg.str.p_str, "SP+")))
{
AdrType[Index] = ModPop;
AdrMode[Index] = 0x04;
return ChkAdr(Mask, Index);
}
/* Register einfach indirekt ? */
switch (DecodeReg(&IArg, AdrMode + Index, False))
{
case eIsReg:
AdrType[Index] = ModIReg;
AdrMode[Index] += 0x30;
return ChkAdr(Mask, Index);
case eIsNoReg:
break;
case eRegAbort:
return False;
}
/* zusammengesetzt indirekt ? */
ErrFlag = False;
RootChain = DecodeChain(&IArg);
if (ErrFlag);
else if (!RootChain);
/* absolut ? */
else if ((!RootChain->Next) && (RootChain->RegCnt == 0))
{
if (!RootChain->HasDisp)
RootChain->DispAcc = 0;
DecideAbs(RootChain->DispAcc, RootChain->DSize, Mask, Index);
}
/* einfaches Register/PC mit Displacement ? */
else if ((!RootChain->Next) && (RootChain->RegCnt == 1) && (RootChain->Scales[0] == 0))
{
if (RootChain->Regs[0] == 16)
RootChain->DispAcc -= EProgCounter();
/* Displacement-Groesse entscheiden */
if (RootChain->DSize == DispSizeNone)
{
if ((RootChain->DispAcc == 0) && (RootChain->Regs[0] < 16));
else
RootChain->DSize = (IsD16(RootChain->DispAcc)) ? DispSize16 : DispSize32;
}
switch (RootChain->DSize)
{
/* kein Displacement mit Register */
case DispSizeNone:
if (ChkRange(RootChain->DispAcc, 0, 0))
{
if (RootChain->Regs[0] >= 16) WrError(ErrNum_InvAddrMode);
else
{
AdrType[Index] = ModIReg;
AdrMode[Index] = 0x30 + RootChain->Regs[0];
}
}
break;
/* 16-Bit-Displacement */
case DispSize4:
case DispSize16:
if (ChkRange(RootChain->DispAcc, -32768, 32767))
{
AdrVals[Index][0] = RootChain->DispAcc & 0xffff;
AdrCnt1[Index] = 2;
if (RootChain->Regs[0] == 16)
{
AdrType[Index] = ModPCRel16;
AdrMode[Index] = 0x0d;
}
else
{
AdrType[Index] = ModDisp16;
AdrMode[Index] = 0x20 + RootChain->Regs[0];
}
}
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)
{
AdrType[Index] = ModPCRel32;
AdrMode[Index] = 0x0e;
}
else
{
AdrType[Index] = ModDisp32;
AdrMode[Index] = 0x40 + RootChain->Regs[0];
}
}
}
/* komplex: dann chained iterieren */
else
{
/* bis zum innersten Element der Indirektion als Basis laufen */
RunChain = RootChain;
while (RunChain->Next)
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) && (RunChain->Scales[z] != 0))
z++;
if (z >= RunChain->RegCnt)
{
AdrType[Index] = ModAbsChain;
AdrMode[Index] = 0x0b;
}
else
{
if (RunChain->Regs[z] == 16)
{
AdrType[Index] = ModPCChain;
AdrMode[Index] = 0x0f;
RunChain->DispAcc -= EProgCounter();
}
else
{
AdrType[Index] = ModRegChain;
AdrMode[Index] = 0x60 + RunChain->Regs[z];
}
for (z2 = z; z2 <= RunChain->RegCnt - 2; z2++)
{
RunChain->Regs[z2] = RunChain->Regs[z2 + 1];
RunChain->Scales[z2] = RunChain->Scales[z2 + 1];
}
RunChain->RegCnt--;
}
/* Jetzt ueber die einzelnen Komponenten iterieren */
LastChain = 0;
Error = False;
while ((RootChain) && (!Error))
{
RunChain = RootChain;
PrevChain = NULL;
while (RunChain->Next)
{
PrevChain = RunChain;
RunChain = RunChain->Next;
}
/* noch etwas abzulegen ? */
if ((RunChain->RegCnt != 0) || (RunChain->HasDisp))
{
LastChain = AdrCnt1[Index] >> 1;
/* Register ablegen */
if (RunChain->RegCnt != 0)
{
AdrVals[Index][LastChain] =
(RunChain->Regs[0] == 16) ? 0x0600 : RunChain->Regs[0] << 10;
AdrVals[Index][LastChain] += RunChain->Scales[0] << 5;
for (z2 = 0; z2 <= RunChain->RegCnt - 2; z2++)
{
RunChain->Regs[z2] = RunChain->Regs[z2 + 1];
RunChain->Scales[z2] = RunChain->Scales[z2 + 1];
}
RunChain->RegCnt--;
}
else
AdrVals[Index][LastChain] = 0x0200;
AdrCnt1[Index] += 2;
/* Displacement ablegen */
if (RunChain->HasDisp)
{
if ((AdrVals[Index][LastChain] & 0x3e00) == 0x0600)
RunChain->DispAcc -= EProgCounter();
if (RunChain->DSize == DispSizeNone)
{
MinReserve = 32 * RunChain->RegCnt;
MaxReserve = 28 * RunChain->RegCnt;
if (IsD4(RunChain->DispAcc))
DSize = ((RunChain->DispAcc & 3) == 0) ? DispSize4 : DispSize16;
else if ((RunChain->DispAcc >= -32 - MinReserve)
&& (RunChain->DispAcc <= 28 + MaxReserve))
DSize = DispSize4Eps;
else if (IsD16(RunChain->DispAcc))
DSize = DispSize16;
else if ((RunChain->DispAcc >= -32768 - MinReserve)
&& (RunChain->DispAcc <= 32767 + MaxReserve))
DSize = DispSize4Eps;
else
DSize = DispSize32;
}
else
DSize = RunChain->DSize;
RunChain->DSize = DispSizeNone;
switch (DSize)
{
/* Fall 1: passt komplett in 4er-Displacement */
case DispSize4:
if (ChkRange(RunChain->DispAcc, -32, 28))
{
if (RunChain->DispAcc & 3)
{
WrError(ErrNum_NotAligned);
Error = True;
}
else
{
AdrVals[Index][LastChain] += (RunChain->DispAcc >> 2) & 0x000f;
RunChain->HasDisp = False;
}
}
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)
{
AdrVals[Index][LastChain] += 0x0007;
RunChain->DispAcc -= 28;
}
else
{
AdrVals[Index][LastChain] += 0x0008;
RunChain->DispAcc += 32;
}
break;
/* Fall 3: 16 Bit */
case DispSize16:
if (ChkRange(RunChain->DispAcc, -32768, 32767))
{
AdrVals[Index][LastChain] += 0x0011;
AdrVals[Index][LastChain + 1] = RunChain->DispAcc & 0xffff;
AdrCnt1[Index] += 2;
RunChain->HasDisp = False;
}
else
Error = True;
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(ErrNum_InternalError);
Error = True;
}
}
}
/* nichts mehr drin: dann ein leeres Steuerwort erzeugen. Tritt
auf, falls alles schon im Basisadressierungsbyte verschwunden */
else if (RunChain != RootChain)
{
LastChain = AdrCnt1[Index] >> 1;
AdrVals[Index][LastChain] = 0x0200;
AdrCnt1[Index] += 2;
}
/* nichts mehr drin: wegwerfen
wenn wir noch nicht ganz vorne angekommen sind, dann ein
Indirektionsflag setzen */
if ((RunChain->RegCnt == 0) && (!RunChain->HasDisp))
{
if (RunChain != RootChain)
AdrVals[Index][LastChain] += 0x4000;
if (!PrevChain)
RootChain = NULL;
else
PrevChain->Next=NULL;
}
}
/* Ende-Kennung fuer letztes Glied */
AdrVals[Index][LastChain] += 0x8000;
}
return ChkAdr(Mask, Index);
}
/* ansonsten absolut */
DSize = DispSizeNone;
Arg = *pArg;
SplitSize(&Arg, &DSize);
AdrLong = EvalStrIntExpression(&Arg, Int32, &OK);
if (OK)
DecideAbs(AdrLong, DSize, Mask, Index);
return ChkAdr(Mask, Index);
}
static LongInt ImmVal(int Index)
{
switch (OpSize[Index])
{
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(ErrNum_InternalError);
return 0;
}
}
static Boolean IsShort(int Index)
{
return (!(AdrMode[Index] & 0xc0));
}
static void AdaptImm(int Index, Byte NSize, Boolean Signed)
{
switch (OpSize[Index])
{
case 0:
if (NSize!=0)
{
if (((AdrVals[Index][0] & 0x80) == 0x80) && (Signed))
AdrVals[Index][0] |= 0xff00;
else
AdrVals[Index][0] &= 0xff;
if (NSize == 2)
{
if (((AdrVals[Index][0] & 0x8000) == 0x8000) && (Signed))
AdrVals[Index][1] = 0xffff;
else
AdrVals[Index][1] = 0;
AdrCnt1[Index] += 2;
AdrCnt2[Index]++;
}
}
break;
case 1:
if (NSize == 0)
AdrVals[Index][0] &= 0xff;
else if (NSize == 2)
{
if (((AdrVals[Index][0] & 0x8000) == 0x8000) && (Signed))
AdrVals[Index][1] = 0xffff;
else AdrVals[Index][1] = 0;
AdrCnt1[Index] += 2;
AdrCnt2[Index]++;
}
break;
case 2:
if (NSize != 2)
{
AdrCnt1[Index] -= 2;
AdrCnt2[Index]--;
if (NSize == 0)
AdrVals[Index][0] &= 0xff;
}
break;
}
OpSize[Index] = NSize;
}
static ShortInt DefSize(Byte Mask)
{
ShortInt z;
z = 2;
while ((z >= 0) && (!(Mask & 4)))
{
Mask = (Mask << 1) & 7;
z--;
}
return z;
}
static Word RMask(Word No, Boolean Turn)
{
return (Turn) ? (0x8000 >> No) : (1 << No);
}
static Boolean DecodeRegList(const tStrComp *pArg, Word *pResult, Boolean Turn)
{
String ArgStr;
tStrComp Arg, Remainder, From, To;
char *p, *p1, *p2, *p3;
Word r1, r2, z;
StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
StrCompCopy(&Arg, pArg);
if (IsIndirect(Arg.str.p_str))
{
StrCompShorten(&Arg, 1);
StrCompIncRefLeft(&Arg, 1);
}
*pResult = 0;
do
{
p1
= strchr(Arg.
str.
p_str, ',');
p2
= strchr(Arg.
str.
p_str, '/');
p = (p1 && (p1 < p2)) ? p1 : p2;
if (p)
StrCompSplitRef(&Arg, &Remainder, &Arg, p);
p3
= strchr(Arg.
str.
p_str, '-');
if (!p3)
{
if (!DecodeReg(&Arg, &r1, True))
return False;
*pResult |= RMask(r1, Turn);
}
else
{
StrCompSplitRef(&From, &To, &Arg, p3);
if (!DecodeReg(&From, &r1, True)
|| !DecodeReg(&To, &r2, True))
return False;
if (r1 <= r2)
{
for (z = r1; z <= r2; z++)
*pResult |= RMask(z, Turn);
}
else
{
for (z = r2; z <= 15; z++)
*pResult |= RMask(z, Turn);
for (z = 0; z <= r1; z++)
*pResult |= RMask(z,Turn);
}
}
if (p)
Arg = Remainder;
}
while (p);
return True;
}
static Boolean DecodeCondition(const char *Asc, Word *Erg)
{
int z;
for (z = 0; Conditions[z].p_name; z++)
if (!as_strcasecmp(Asc, Conditions[z].p_name))
{
*Erg = z;
return True;
}
return False;
}
static Boolean DecodeStringCondition(const char *Asc, Word *pErg)
{
Boolean OK = TRUE;
if (!as_strcasecmp(Asc, "LTU"))
*pErg = 0;
else if (!as_strcasecmp(Asc, "GEU"))
*pErg = 1;
else if (!as_strcasecmp(Asc, "N"))
*pErg = 6;
else
OK = (DecodeCondition(Asc, pErg) && (*pErg > 1) && (*pErg < 6));
return OK;
}
/*------------------------------------------------------------------------*/
static Boolean CheckFormat(const char *FSet)
{
const char *p;
FormatCode = 0;
else
{
if (p)
FormatCode = p - FSet + 1;
else
WrError(ErrNum_InvFormat);
return (p != NULL);
}
return True;
}
static Boolean CheckBFieldFormat(void)
{
FormatCode = 1;
else if ((!strcmp(Format
, "G:I")) || (!strcmp(Format
, "I:G")))
FormatCode = 2;
else if ((!strcmp(Format
, "E:R")) || (!strcmp(Format
, "R:E")))
FormatCode = 3;
else if ((!strcmp(Format
, "E:I")) || (!strcmp(Format
, "I:E")))
FormatCode = 4;
else
{
WrError(ErrNum_InvFormat);
return False;
}
return True;
}
static Boolean GetOpSize(tStrComp *pArg, Byte Index)
{
char *p;
int ArgLen
= strlen(pArg
->str.
p_str);
p = RQuotPos(pArg->str.p_str, '.');
if (!p)
{
OpSize[Index] = DOpSize;
return True;
}
else if (p == pArg->str.p_str + ArgLen - 2)
{
switch (as_toupper(p[1]))
{
case 'B':
OpSize[Index] = 0;
break;
case 'H':
OpSize[Index] = 1;
break;
case 'W':
OpSize[Index] = 2;
break;
default:
WrXError(ErrNum_UndefAttr, p);
return False;
}
StrCompShorten(pArg, 2);
return True;
}
else
{
WrError(ErrNum_UndefAttr);
return False;
}
}
static void SplitOptions(void)
{
char *pSplit, *pSrc;
pSrc = OpPart.str.p_str;
*Options[0] = *Options[1] = '\0';
for (OptionCnt = 0; OptionCnt < 2; OptionCnt++)
{
pSplit = QuotPos(pSrc, '/');
if (!pSplit)
break;
strmaxcpy(Options[OptionCnt], pSplit + 1, sizeof(Options[OptionCnt]));
if (OptionCnt)
*pSplit = '\0';
else
pSplit[1] = '\0';
pSrc = Options[OptionCnt];
}
}
static void DecideBranch(LongInt Adr, Byte Index)
{
LongInt Dist = Adr - EProgCounter();
if (FormatCode == 0)
{
/* Groessenangabe erzwingt G-Format */
if (OpSize[Index] != -1)
FormatCode = 1;
/* gerade 9-Bit-Zahl kurz darstellbar */
else if (((Dist & 1) == 0) && (Dist <= 254) && (Dist >= -256))
FormatCode = 2;
/* ansonsten allgemein */
else
FormatCode = 1;
}
if ((FormatCode == 1) && (OpSize[Index] == -1))
{
if ((Dist <= 127) && (Dist >= -128))
OpSize[Index] = 0;
else if ((Dist <= 32767) && (Dist >= -32768))
OpSize[Index] = 1;
else
OpSize[Index] = 2;
}
}
static Boolean DecideBranchLength(LongInt *Addr, tSymbolFlags Flags, int Index)
{
*Addr -= EProgCounter();
if (OpSize[Index] == -1)
{
if ((*Addr >= -128) && (*Addr <= 127))
OpSize[Index] = 0;
else if ((*Addr >= -32768) && (*Addr <= 32767))
OpSize[Index] = 1;
else OpSize[Index]=2;
}
if (!mSymbolQuestionable(Flags) &&
(((OpSize[Index] == 0) && ((*Addr < -128) || (*Addr > 127)))
|| ((OpSize[Index] == 1) && ((*Addr < -32768) || (*Addr > 32767)))))
{
WrError(ErrNum_JmpDistTooBig);
return False;
}
else
return True;
}
static void Make_G(Word Code)
{
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];
}
static void Make_E(Word Code, Boolean Signed)
{
LongInt HVal, Min, Max;
Min = 128 * (-Ord(Signed));
Max = Min + 255;
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(1);
if (ChkRange(HVal, Min, Max))
{
WAsmCode[0] = 0xbf00 + (HVal & 0xff);
WAsmCode[1] = Code + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 2, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 4 + AdrCnt1[2];
}
}
}
static void Make_I(Word Code, Boolean Signed)
{
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else
{
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];
}
}
/*------------------------------------------------------------------------*/
static void DecodeFixed(Word Code)
{
if (!ChkArgCnt(0, 0));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (strcmp(Format
, " ")) WrError
(ErrNum_InvFormat
);
else
{
CodeLen = 2;
WAsmCode[0] = Code;
}
}
static void DecodeACB_SCB(Word IsSCB)
{
if (ChkArgCnt(4, 4)
&& CheckFormat("GEQR"))
{
if (GetOpSize(&ArgStr[2], 3))
if (GetOpSize(&ArgStr[4], 4))
if (GetOpSize(&ArgStr[1], 1))
if (GetOpSize(&ArgStr[3], 2))
{
Word HReg;
if ((OpSize[3] == -1) && (OpSize[2] == -1)) OpSize[3] = 2;
if ((OpSize[3] == -1) && (OpSize[2] != -1)) OpSize[3] = OpSize[2];
else if ((OpSize[3] != -1) && (OpSize[2] == -1)) OpSize[2] = OpSize[3];
if (OpSize[1] == -1) OpSize[1] = OpSize[2];
if (OpSize[3] != OpSize[2]) WrError(ErrNum_ConfOpSizes);
else if (DecodeReg(&ArgStr[2], &HReg, True))
{
Boolean OK;
tSymbolFlags Flags;
LongInt AdrLong, HVal;
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[4], Int32, &OK, &Flags);
if (OK)
{
if (DecodeAdr(&ArgStr[1], 1, Mask_Source))
{
if (DecodeAdr(&ArgStr[3], 2, Mask_Source))
{
if (FormatCode == 0)
{
if (AdrType[1] != ModImm) FormatCode = 1;
else
{
HVal = ImmVal(1);
if ((HVal == 1) && (AdrType[2] == ModReg))
FormatCode = 4;
else if ((HVal == 1) && (AdrType[2] == ModImm))
{
HVal = ImmVal(2);
if ((HVal >= 1 - IsSCB) && (HVal <= 64 - IsSCB))
FormatCode = 3;
else
FormatCode = 2;
}
else if ((HVal >= -128) && (HVal <= 127))
FormatCode = 2;
else
FormatCode = 1;
}
}
switch (FormatCode)
{
case 1:
if (DecideBranchLength(&AdrLong, Flags, 4)) /* ??? */
{
WAsmCode[0] = 0xd000 + (OpSize[1] << 8) + AdrMode[1];
memcpy(WAsmCode
+ 1, AdrVals
[1], AdrCnt1
[1]);
WAsmCode[1 + AdrCnt2[1]] = 0xf000 + (IsSCB << 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];
}
break;
case 2:
if (DecideBranchLength(&AdrLong, Flags, 4)) /* ??? */
{
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(1);
if (ChkRange(HVal, -128, 127))
{
WAsmCode[0] = 0xbf00 + (HVal & 0xff);
WAsmCode[1] = 0xf000 + (IsSCB << 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];
}
}
}
break;
case 3:
if (DecideBranchLength(&AdrLong, Flags, 4)) /* ??? */
{
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else if (ImmVal(1) != 1) WrError(ErrNum_Only1);
else if (AdrType[2] != ModImm) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(2);
if (ChkRange(HVal, 1 - IsSCB, 64 - IsSCB))
{
WAsmCode[0] = 0x03d1 + (HReg << 10) + (IsSCB << 1);
WAsmCode[1] = ((HVal & 0x3f) << 10) + (OpSize[4] << 8);
CodeLen = 4;
}
}
}
break;
case 4:
if (DecideBranchLength(&AdrLong, Flags, 4)) /* ??? */
{
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else if (ImmVal(1) != 1) WrError(ErrNum_Only1);
else if (OpSize[2] != 2) WrError(ErrNum_InvOpSize);
else if (AdrType[2] != ModReg) WrError(ErrNum_InvAddrMode);
else
{
WAsmCode[0] = 0x03d0 + (HReg << 10) + (IsSCB << 1);
WAsmCode[1] = ((AdrMode[2] & 15) << 10) + (OpSize[4] << 8);
CodeLen = 4;
}
}
break;
}
if (CodeLen>0)
{
switch (OpSize[4])
{
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;
}
}
}
}
}
}
}
}
}
static void DecodeFixedLong(Word Index)
{
BitOrder *pOrder = FixedLongOrders + Index;
if (!ChkArgCnt(0, 0));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (strcmp(Format
, " ")) WrError
(ErrNum_InvFormat
);
else
{
CodeLen = 10;
WAsmCode[0] = 0xd20c;
WAsmCode[1] = pOrder->Code1;
WAsmCode[2] = pOrder->Code2;
WAsmCode[3] = 0x9e09;
WAsmCode[4] = 0x0700;
}
}
static void DecodeMOV(Word Code)
{
LongInt HVal;
UNUSED(Code);
if (ChkArgCnt(2, 2)
&& CheckFormat("GELSZQI"))
{
if ((GetOpSize(&ArgStr[1], 1)) && (GetOpSize(&ArgStr[2], 2)))
{
if (OpSize[2] == -1)
OpSize[2] = 2;
if (OpSize[1] == -1)
OpSize[1] = OpSize[2];
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_AllGen-MModPop)))
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
HVal = ImmVal(1);
if (HVal == 0)
FormatCode = 5;
else if ((HVal >= 1) && (HVal <= 8) && (IsShort(2)))
FormatCode = 6;
else if ((HVal >= -128) && (HVal <= 127))
FormatCode = 2;
else if (IsShort(2))
FormatCode = 7;
else
FormatCode = 1;
}
else if ((AdrType[1] == ModReg) && (OpSize[1] == 2) && (IsShort(2)))
FormatCode = 4;
else if ((AdrType[2] == ModReg) && (OpSize[2] == 2) && (IsShort(1)))
FormatCode = 3;
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(0x8800);
break;
case 2:
Make_E(0x8800, True);
break;
case 3:
if ((!IsShort(1)) || (AdrType[2] != ModReg)) WrError(ErrNum_InvAddrMode);
else if (OpSize[2] != 2) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0x0040 + ((AdrMode[2] & 15) << 10) + (OpSize[1] << 8) + AdrMode[1];
memcpy(WAsmCode
+ 1, AdrVals
[1], AdrCnt1
[1]);
CodeLen = 2 + AdrCnt1[1];
}
break;
case 4:
if ((!IsShort(2)) || (AdrType[1] != ModReg)) WrError(ErrNum_InvAddrMode);
else if (OpSize[1] != 2) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0x0080 + ((AdrMode[1] & 15) << 10) + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
break;
case 5:
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(1);
if (ChkRange(HVal, 0, 0))
{
WAsmCode[0] = 0xc400 + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
break;
case 6:
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(1);
if (ChkRange(HVal, 1, 8))
{
WAsmCode[0] = 0x6000 + ((HVal & 7) << 10) + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
break;
case 7:
Make_I(0x48c0, True);
break;
}
}
}
}
}
static void DecodeOne(Word Index)
{
OneOrder *pOrder = OneOrders + Index;
if (ChkArgCnt(1, 1)
&& CheckFormat("G"))
{
if (GetOpSize(&ArgStr[1], 1))
{
if ((OpSize[1] == -1) && (pOrder->OpMask != 0))
OpSize[1] = DefSize(pOrder->OpMask);
if ((OpSize[1] != -1) && (((1 << OpSize[1]) & pOrder->OpMask) == 0)) WrError(ErrNum_InvOpSize);
else
{
if (DecodeAdr(&ArgStr[1], 1, pOrder->Mask))
{
/* da nur G, Format ignorieren */
WAsmCode[0] = pOrder->Code + AdrMode[1];
if (pOrder->OpMask != 0)
WAsmCode[0] += OpSize[1] << 8;
memcpy(WAsmCode
+ 1, AdrVals
[1], AdrCnt1
[1]);
CodeLen = 2 + AdrCnt1[1];
}
}
}
}
}
static void DecodeADD_SUB(Word IsSUB)
{
if (ChkArgCnt(2, 2)
&& CheckFormat("GELQI"))
{
if ((GetOpSize(&ArgStr[2], 2)) && (GetOpSize(&ArgStr[1], 1)))
{
if (OpSize[2] == -1) OpSize[2] = 2;
if (OpSize[1] == -1) OpSize[1] = OpSize[2];
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source)) && (DecodeAdr(&ArgStr[2], 2, Mask_PureDest)))
{
if (FormatCode==0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if (IsShort(2))
{
if ((HVal >= 1) && (HVal <= 8))
FormatCode = 4;
else
FormatCode = 5;
}
else if ((HVal >= -128) && (HVal < 127))
FormatCode = 2;
else
FormatCode = 1;
}
else if (IsShort(1) && (AdrType[2] == ModReg) && (OpSize[1] == 2) && (OpSize[2] == 2))
FormatCode = 3;
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(IsSUB << 11);
break;
case 2:
Make_E(IsSUB << 11, True);
break;
case 3:
if ((!IsShort(1)) || (AdrType[2] != ModReg)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[1] != 2) || (OpSize[2] != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0x8100 + (IsSUB << 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(ErrNum_Unpredictable);
}
break;
case 4:
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else
{
LongInt HVal = ImmVal(1);
if (ChkRange(HVal, 1, 8))
{
WAsmCode[0] = 0x4040 + (IsSUB << 13) + ((HVal & 7) << 10) + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
break;
case 5:
Make_I(0x44c0 + (IsSUB << 11), True);
break;
}
}
}
}
}
static void DecodeCMP(Word Code)
{
LongInt HVal;
UNUSED(Code);
if (ChkArgCnt(2, 2)
&& CheckFormat("GELZQI")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[2] == -1) OpSize[2] = 2;
if (OpSize[1] == -1) OpSize[1] = OpSize[2];
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_NoImmGen-MModPush)))
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
HVal = ImmVal(1);
if (HVal == 0)
FormatCode = 4;
else if ((HVal >= 1) && (HVal <= 8) && (IsShort(2)))
FormatCode = 5;
else if ((HVal >= -128) && (HVal <= 127))
FormatCode = 2;
else if (AdrType[2] == ModReg)
FormatCode = 3;
else if (IsShort(2))
FormatCode = 5;
else
FormatCode = 1;
}
else if ((IsShort(1)) && (AdrType[2] == ModReg))
FormatCode = 3;
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(0x8000);
break;
case 2:
Make_E(0x8000, True);
break;
case 3:
if ((!IsShort(1)) || (AdrType[2] != ModReg)) WrError(ErrNum_InvAddrMode);
else if (OpSize[2] != 2) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = ((AdrMode[2] & 15) << 10) + (OpSize[1] << 8) + AdrMode[1];
memcpy(WAsmCode
+ 1, AdrVals
[1], AdrCnt1
[1]);
CodeLen = 2 + AdrCnt1[1];
}
break;
case 4:
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(1);
if (ChkRange(HVal, 0, 0))
{
WAsmCode[0] = 0xc000 + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
break;
case 5:
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else
{
HVal = ImmVal(1);
if (ChkRange(HVal, 1, 8))
{
WAsmCode[0] = 0x4000 + (OpSize[2] << 8) + AdrMode[2] + ((HVal & 7) << 10);
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
break;
case 6:
Make_I(0x40c0, True);
break;
}
}
}
}
static void DecodeGE2(Word Index)
{
GE2Order *pOrder = GE2Orders + Index;
if (ChkArgCnt(2, 2)
&& CheckFormat("GE")
&& GetOpSize(&ArgStr[2], 2)
&& GetOpSize(&ArgStr[1], 1))
{
if (OpSize[2] == -1)
OpSize[2] = DefSize(pOrder->SMask2);
if (OpSize[1] == -1)
OpSize[1] = DefSize(pOrder->SMask1);
if (((pOrder->SMask1 & (1 << OpSize[1])) == 0)
|| ((pOrder->SMask2 & (1 << OpSize[2])) == 0)) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, pOrder->Mask1))
&& (DecodeAdr(&ArgStr[2], 2, pOrder->Mask2)))
{
if (FormatCode==0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((pOrder->Signed) && (HVal >= -128) && (HVal <= 127))
FormatCode = 2;
else if ((!pOrder->Signed) && (HVal >= 0) && (HVal <= 255))
FormatCode = 2;
else
FormatCode = 1;
}
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(pOrder->Code);
break;
case 2:
Make_E(pOrder->Code, pOrder->Signed);
break;
}
}
}
}
static void DecodeLog(Word Index)
{
if (ChkArgCnt(2, 2)
&& CheckFormat("GERI")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[2] == -1)
OpSize[2] = 2;
if (OpSize[1] == -1)
OpSize[1] = OpSize[2];
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_Dest - MModPush)))
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((HVal >= 0) && (HVal <= 255))
FormatCode = 2;
else if (IsShort(2))
FormatCode = 4;
else
FormatCode = 1;
}
else if ((AdrType[1] == ModReg) && (AdrType[2] == ModReg) && (OpSize[1] == 2) && (OpSize[2] == 2))
FormatCode = 3;
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(0x2000 + (Index << 10));
break;
case 2:
Make_E(0x2000 + (Index << 10), False);
break;
case 3:
if ((AdrType[1] != ModReg) || (AdrType[2] != ModReg)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[1] != 2) || (OpSize[2] != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0x00c0 + (Index << 8) + (AdrMode[1] & 15) + ((AdrMode[2] & 15) << 10);
CodeLen = 2;
}
break;
case 4:
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else
{
WAsmCode[0] = 0x50c0 + (OpSize[2] << 8) + (Index << 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];
}
break;
}
if (OpSize[1] > OpSize[2])
WrError(ErrNum_Unpredictable);
}
}
}
static void DecodeMul(Word Index)
{
Boolean Unsigned = Index & 1;
if (ChkArgCnt(2, 2)
&& CheckFormat(Unsigned ? "GE" : "GER")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[2] == -1)
OpSize[2] = 2;
if (OpSize[1] == -1)
OpSize[1] = OpSize[2];
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_PureDest)))
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((HVal >= -128 + (Unsigned << 7))
&& (HVal <= 127 + (Unsigned << 7)))
FormatCode = 2;
else
FormatCode = 1;
}
else if ((!Unsigned)
&& (AdrType[1] == ModReg) && (OpSize[1] == 2)
&& (AdrType[2] == ModReg) && (OpSize[2] == 2))
FormatCode = 3;
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(0x4000 + (Index << 10));
break;
case 2:
Make_E(0x4000 + (Index << 10), !Unsigned);
break;
case 3:
if ((AdrType[1] != ModReg) || (AdrType[2] != ModReg)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[1] != 2) || (OpSize[2] != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0x00d0
+ ((AdrMode[2] & 15) << 10)
+ (Index << 7)
+ (AdrMode[1] & 15);
CodeLen = 2;
}
}
}
}
}
static void DecodeGetPut(Word Code)
{
Word AdrWord, Mask, Mask2;
if (Code & 0x80)
{
Mask = Mask_Source; Mask2 = MModReg; AdrWord = 1;
}
else
{
Mask = MModReg; Mask2 = Mask_Dest; AdrWord = 2;
}
if (ChkArgCnt(2, 2)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[AdrWord] == -1) OpSize[AdrWord] = Code & 3;
if (OpSize[3 - AdrWord] == -1) OpSize[3 - AdrWord] = 2;
if ((OpSize[AdrWord] != (Code & 3)) || (OpSize[3 - AdrWord] != 2)) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask))
&& (DecodeAdr(&ArgStr[2], 2, Mask2)))
{
Make_G(Code & 0xff00);
WAsmCode[0] += 0x0400;
}
}
}
static void DecodeMOVA(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2)
&& CheckFormat("GR")
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[2] == -1)
OpSize[2] = 2;
OpSize[1] = 0;
if (OpSize[2] != 2) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask_PureMem))
&& (DecodeAdr(&ArgStr[2], 2, Mask_Dest)))
{
if (FormatCode == 0)
{
if ((AdrType[1] == ModDisp16) && (AdrType[2] == ModReg))
FormatCode = 2;
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(0xb400);
WAsmCode[0] += 0x800;
break;
case 2:
if ((AdrType[1] != ModDisp16) || (AdrType[2] != ModReg)) WrError(ErrNum_InvAddrMode);
else
{
WAsmCode[0] = 0x03c0 + ((AdrMode[2] & 15) << 10) + (AdrMode[1] & 15);
WAsmCode[1] = AdrVals[1][0];
CodeLen = 4;
}
break;
}
}
}
}
static void DecodeQINS_QDEL(Word IsQINS)
{
if (ChkArgCnt(2, 2)
&& CheckFormat("G")
&& (IsQINS || GetOpSize(&ArgStr[2], 2)))
{
if (OpSize[2] == -1)
OpSize[2] = 2;
OpSize[1] = 0;
if (OpSize[2] != 2) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask_PureMem))
&& (DecodeAdr(&ArgStr[2], 2, Mask_PureMem | (IsQINS ? 0 : MModReg))))
{
Make_G(0xb000 + IsQINS);
WAsmCode[0] += 0x800;
}
}
}
static void DecodeRVBY(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[2] == -1)
OpSize[2] = 2;
if (OpSize[1] == -1)
OpSize[1] = OpSize[2];
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_Dest)))
{
Make_G(0x4000);
WAsmCode[0] += 0x400;
}
}
}
static void DecodeSHL_SHA(Word IsSHA)
{
if (ChkArgCnt(2, 2)
&& CheckFormat("GEQ")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[1] == -1)
OpSize[1] = 0;
if (OpSize[2] == -1)
OpSize[2] = 2;
if (OpSize[1] != 0)
WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_PureDest)))
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((IsShort
(2)) && (abs(HVal
) >= 1) && (abs(HVal
) <= 8) && ((IsSHA
== 0) || (HVal
< 0)))
FormatCode = 3;
else if ((HVal >= -128) && (HVal <= 127))
FormatCode = 2;
else
FormatCode = 1;
}
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(0x3000 + (IsSHA << 10));
break;
case 2:
Make_E(0x3000 + (IsSHA << 10), True);
break;
case 3:
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else
{
LongInt HVal = ImmVal(1);
if (ChkRange(HVal, -8, (1 - IsSHA) << 3))
{
if (HVal == 0) WrError(ErrNum_InvShiftArg);
else
{
if (HVal < 0)
HVal += 16;
else HVal &= 7;
WAsmCode[0] = 0x4080 + (HVal << 10) + (IsSHA << 6) + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
}
break;
}
}
}
}
static void DecodeSHXL_SHXR(Word Code)
{
if (ChkArgCnt(1, 1)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 1))
{
if (OpSize[1] == -1)
OpSize[1] = 2;
if (OpSize[1] != 2) WrError(ErrNum_InvOpSize);
else if (DecodeAdr(&ArgStr[1], 1, Mask_PureDest))
{
WAsmCode[0] = 0x02f7;
WAsmCode[1] = Code + AdrMode[1];
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt1
[1]);
CodeLen = 4 + AdrCnt1[1];
}
}
}
static void DecodeCHK(Word Code)
{
UNUSED(Code);
if (OptionCnt > 1) WrError(ErrNum_WrongOptCnt);
else if (ChkArgCnt(3, 3)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 2)
&& GetOpSize(&ArgStr[2], 1)
&& GetOpSize(&ArgStr[3], 3))
{
Boolean OptOK;
Word IsSigned;
if ((OptionCnt == 0)
|| (!as_strcasecmp(Options[0], "N")))
{
OptOK = True;
IsSigned = 0;
}
else if (!as_strcasecmp(Options[0], "S"))
{
OptOK = True;
IsSigned = 1;
}
else
{
OptOK = False;
IsSigned = 0;
}
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]) || (OpSize[2] != OpSize[3])) WrError(ErrNum_ConfOpSizes);
else if (!OptOK) WrXError(ErrNum_UndefCond, Options[0]);
else if ((DecodeAdr(&ArgStr[1], 2, Mask_MemGen-MModPop-MModPush))
&& (DecodeAdr(&ArgStr[2], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[3], 3, MModReg)))
{
OpSize[2] = 2 + IsSigned;
Make_G((AdrMode[3] & 15) << 10);
WAsmCode[0] += 0x400;
}
}
}
static void DecodeCSI(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(3, 3)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 3)
&& GetOpSize(&ArgStr[2], 1)
&& GetOpSize(&ArgStr[3], 2))
{
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]) || (OpSize[2] != OpSize[3])) WrError(ErrNum_ConfOpSizes);
else if ((DecodeAdr(&ArgStr[1], 3, MModReg))
&& (DecodeAdr(&ArgStr[2], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[3], 2, Mask_PureMem)))
{
OpSize[2] = 0;
Make_G((AdrMode[3] & 15) << 10);
WAsmCode[0] += 0x400;
}
}
}
static void DecodeDIVX_MULX(Word Code)
{
if (ChkArgCnt(3, 3)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2)
&& GetOpSize(&ArgStr[3], 3))
{
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) || (OpSize[2] != 2) || (OpSize[3] != 2)) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_PureDest))
&& (DecodeAdr(&ArgStr[3], 3, MModReg)))
{
OpSize[2] = 0;
Make_G(Code + ((AdrMode[3] & 15) << 10));
WAsmCode[0] += 0x400;
}
}
}
static void DecodeWAIT(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (strcmp(Format
, " ")) WrError
(ErrNum_InvFormat
);
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_InvAddrMode);
else
{
Boolean OK;
WAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt3, &OK);
if (OK)
{
WAsmCode[0] = 0x0fd6;
CodeLen = 4;
}
}
}
static void DecodeBit(Word Index)
{
const BitOrder *pOrder = BitOrders + Index;
if (ChkArgCnt(2, 2)
&& CheckFormat(pOrder->Code2 ? "GEQ" : "GE")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[1] == -1)
OpSize[1] = 2;
if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_PureDest)))
{
if (OpSize[2] == -1)
OpSize[2] = ((AdrType[2] == ModReg) && (!pOrder->MustByte)) ? 2 : 0;
if (((AdrType[2] != ModReg) || (pOrder->MustByte)) && (OpSize[2] != 0)) WrError(ErrNum_InvOpSize);
else
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((HVal >= 0) && (HVal <= 7) && (IsShort(2)) && (pOrder->Code2 != 0) && (OpSize[2] == 0))
FormatCode = 3;
else if ((HVal >= -128) && (HVal < 127))
FormatCode = 2;
else
FormatCode = 1;
}
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
Make_G(pOrder->Code1);
break;
case 2:
Make_E(pOrder->Code1, True);
break;
case 3:
if ((AdrType[1] != ModImm) || (!IsShort(2))) WrError(ErrNum_InvAddrMode);
else if (OpSize[2] != 0) WrError(ErrNum_InvOpSize);
else
{
LongInt HVal = ImmVal(1);
if (ChkRange(HVal, 0, 7))
{
WAsmCode[0] = pOrder->Code2 + ((HVal & 7) << 10) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
CodeLen = 2 + AdrCnt1[2];
}
}
break;
}
}
}
}
}
static void DecodeBField(Word Code)
{
if (ChkArgCnt(4, 4)
&& CheckBFieldFormat()
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2)
&& GetOpSize(&ArgStr[3], 3)
&& GetOpSize(&ArgStr[4], 4))
{
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))
&& (DecodeAdr(&ArgStr[3], 3, MModReg | MModImm))
&& (DecodeAdr(&ArgStr[2], 2, Mask_Source))
&& (DecodeAdr(&ArgStr[4], 4, Mask_PureMem)))
{
if (FormatCode == 0)
{
if (AdrType[3] == ModReg)
FormatCode = (AdrType[1] == ModReg) ? 1 : 2;
else
FormatCode = (AdrType[1] == ModReg) ? 3 : 4;
}
switch (FormatCode)
{
case 1:
if ((AdrType[1] != ModReg) || (AdrType[3] != ModReg)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[1] != 2) || (OpSize[3] != 2) || (OpSize[4] != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0xd000 + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
WAsmCode[1 + AdrCnt2[2]] = 0xc200 + (Code << 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];
}
break;
case 2:
if ((AdrType[1] != ModImm) || (AdrType[3] != ModReg)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[3] != 2) || (OpSize[4] != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0xd000 + (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
WAsmCode[1 + AdrCnt2[2]] = 0xd200 + (Code << 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
{
memcpy(WAsmCode
+ (CodeLen
>> 1), AdrVals
[1], AdrCnt1
[1]);
CodeLen += AdrCnt1[1];
}
}
break;
case 3:
if ((AdrType[1] != ModReg) || (AdrType[2] != ModImm) || (AdrType[3] != ModImm)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[1] != 2) || (OpSize[4] != 2)) WrError(ErrNum_InvOpSize);
else
{
LongInt Offset = ImmVal(2);
if (ChkRange(Offset, -128, 127))
{
LongInt Width = ImmVal(3);
if (ChkRange(Width, 1, 32))
{
WAsmCode[0] = 0xbf00 + (Offset & 0xff);
WAsmCode[1] = 0xc200 + (Code << 10) + AdrMode[4];
memcpy(WAsmCode
+ 2, AdrVals
[4], AdrCnt1
[4]);
WAsmCode[2 + AdrCnt2[4]] = ((Width & 31) << 10) + (AdrMode[1] & 15);
CodeLen =6 + AdrCnt1[4];
}
}
}
break;
case 4:
if ((AdrType[1] != ModImm) || (AdrType[2] != ModImm) || (AdrType[3] != ModImm)) WrError(ErrNum_InvAddrMode);
else if (OpSize[4] != 2) WrError(ErrNum_InvOpSize);
else
{
LongInt Offset = ImmVal(2);
if (ChkRange(Offset, -128, 127))
{
LongInt Width = ImmVal(3);
if (ChkRange(Offset, 1, 32))
{
WAsmCode[0] = 0xbf00 + (Offset & 0xff);
WAsmCode[1] = 0xd200 + (Code << 10) + AdrMode[4];
memcpy(WAsmCode
+ 2, AdrVals
[4], AdrCnt1
[4]);
WAsmCode[2 + AdrCnt2[4]] = ((Width & 31) << 10) + (OpSize[1] << 8);
CodeLen = 6 + AdrCnt1[4];
if (OpSize[1] == 0)
WAsmCode[(CodeLen - 1) >> 1] += AdrVals[1][0] & 0xff;
else
{
memcpy(WAsmCode
+ (CodeLen
>> 1), AdrVals
[1], AdrCnt1
[1]);
CodeLen += AdrCnt1[1];
}
}
}
}
break;
}
}
}
}
static void DecodeBFEXT_BFEXTU(Word IsEXTU)
{
if (ChkArgCnt(4, 4)
&& CheckFormat("GE")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2)
&& GetOpSize(&ArgStr[3], 3)
&& GetOpSize(&ArgStr[4], 4))
{
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))
&& (DecodeAdr(&ArgStr[3], 3, Mask_MemGen & ~(MModPop | MModPush)))
&& (DecodeAdr(&ArgStr[2], 2, MModReg | MModImm)))
{
if (DecodeAdr(&ArgStr[1], 1, (AdrType[2] == ModReg) ? Mask_Source : MModImm))
{
if (FormatCode == 0)
FormatCode = (AdrType[2]== ModReg) ? 1 : 2;
switch (FormatCode)
{
case 1:
if ((OpSize[2] != 2) || (OpSize[3] != 2) || (OpSize[4] != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0xd000 + (OpSize[1] << 8) + AdrMode[1];
memcpy(WAsmCode
+ 1, AdrVals
[1], AdrCnt1
[1]);
WAsmCode[1 + AdrCnt2[1]] = 0xea00 + (IsEXTU << 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];
}
break;
case 2:
if ((AdrType[1] != ModImm) || (AdrType[2] != ModImm)) WrError(ErrNum_InvAddrMode);
else if ((OpSize[3] != 2) || (OpSize[4] != 2)) WrError(ErrNum_InvAddrMode);
else
{
LongInt Offset = ImmVal(1);
if (ChkRange(Offset, -128, 127))
{
LongInt Width = ImmVal(2);
if (ChkRange(Width, 1, 32))
{
WAsmCode[0] = 0xbf00 + (Offset & 0xff);
WAsmCode[1] = 0xea00 + (IsEXTU << 10) + AdrMode[3];
memcpy(WAsmCode
+ 2, AdrVals
[3], AdrCnt1
[3]);
WAsmCode[2 + AdrCnt2[3]] = ((Width & 31) << 10) + (AdrMode[4] & 15);
CodeLen = 6 + AdrCnt1[3];
}
}
}
break;
}
}
}
}
}
static void DecodeBSCH(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (OptionCnt != 1) WrError(ErrNum_WrongOptCnt);
else if ((strcmp(Options
[0], "0")) && (strcmp(Options
[0], "1"))) WrXError
(ErrNum_UndefCond
, Options
[0]);
else if ((CheckFormat("G"))
&& (GetOpSize(&ArgStr[1], 1))
&& (GetOpSize(&ArgStr[2], 2)))
{
if (OpSize[1] == -1) OpSize[1] = 2;
if (OpSize[2] == -1) OpSize[2] = 2;
if (OpSize[1] != 2) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask_Source))
&& (DecodeAdr(&ArgStr[2], 2, Mask_PureDest)))
{
/* immer G-Format */
WAsmCode[0] = 0xd600 + AdrMode[1];
memcpy(WAsmCode
+ 1, AdrVals
[1], AdrCnt1
[1]);
WAsmCode[1 + AdrCnt2[1]] = Code + ((Options[0][0] - '0') << 10)+ (OpSize[2] << 8) + AdrMode[2];
memcpy(WAsmCode
+ 2 + AdrCnt2
[1], AdrVals
[2], AdrCnt1
[2]);
CodeLen = 4 + AdrCnt1[1] + AdrCnt1[2];
}
}
}
static void DecodeBSR_BRA(Word IsBSR)
{
if (ChkArgCnt(1, 1)
&& CheckFormat("GD")
&& GetOpSize(&ArgStr[1], 1))
{
Boolean OK;
tSymbolFlags Flags;
LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
if (OK)
{
DecideBranch(AdrLong, 1);
switch (FormatCode)
{
case 2:
if (OpSize[1] != -1) WrError(ErrNum_UseLessAttr);
else
{
AdrLong -= EProgCounter();
if (!mSymbolQuestionable(Flags) && ((AdrLong < -256) || (AdrLong > 254))) WrError(ErrNum_JmpDistTooBig);
else if (Odd(AdrLong)) WrError(ErrNum_DistIsOdd);
else
{
CodeLen = 2;
WAsmCode[0] = 0xae00 + (IsBSR << 8) + Lo(AdrLong >> 1);
}
}
break;
case 1:
WAsmCode[0] = 0x20f7 + (IsBSR << 11) + (((Word)OpSize[1]) << 8);
AdrLong -= EProgCounter();
switch (OpSize[1])
{
case 0:
if (!mSymbolQuestionable(Flags) && ((AdrLong < -128) || (AdrLong > 127))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4;
WAsmCode[1] = Lo(AdrLong);
}
break;
case 1:
if (!mSymbolQuestionable(Flags) && ((AdrLong < -32768) || (AdrLong > 32767))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4;
WAsmCode[1] = AdrLong & 0xffff;
}
break;
case 2:
CodeLen = 6;
WAsmCode[1] = AdrLong >> 16;
WAsmCode[2] = AdrLong & 0xffff;
break;
}
break;
}
}
}
}
static void DecodeBcc(Word Code)
{
if (ChkArgCnt(1, 1)
&& CheckFormat("GD")
&& GetOpSize(&ArgStr[1], 1))
{
Boolean OK;
tSymbolFlags Flags;
LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
if (OK)
{
DecideBranch(AdrLong, 1);
switch (FormatCode)
{
case 2:
if (OpSize[1] != -1) WrError(ErrNum_UseLessAttr);
else
{
AdrLong -= EProgCounter();
if (!mSymbolQuestionable(Flags) && ((AdrLong < -256) || (AdrLong > 254))) WrError(ErrNum_JmpDistTooBig);
else if (Odd(AdrLong)) WrError(ErrNum_DistIsOdd);
else
{
CodeLen = 2;
WAsmCode[0] = 0x8000 + Code + Lo(AdrLong >> 1);
}
}
break;
case 1:
WAsmCode[0] = 0x00f6 + Code + (((Word)OpSize[1]) << 8);
AdrLong -= EProgCounter();
switch (OpSize[1])
{
case 0:
if ((AdrLong < -128) || (AdrLong > 127)) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4;
WAsmCode[1] = Lo(AdrLong);
}
break;
case 1:
if ((AdrLong < -32768) || (AdrLong > 32767)) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4;
WAsmCode[1] = AdrLong & 0xffff;
}
break;
case 2:
CodeLen = 6;
WAsmCode[1] = AdrLong >> 16;
WAsmCode[2] = AdrLong & 0xffff;
break;
}
break;
}
}
}
}
static void DecodeTRAP(Word Code)
{
Word Condition;
UNUSED(Code);
if (!ChkArgCnt(0, 0));
else if (OptionCnt != 1) WrError(ErrNum_WrongOptCnt);
else if (!DecodeCondition(Options[0], &Condition)) WrXError(ErrNum_UndefCond, Options[0]);
else
{
CodeLen = 2;
WAsmCode[0] = 0x03d4 | (Condition << 10);
}
}
static void DecodeTRAPA(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (strcmp(Format
, " ")) WrError
(ErrNum_InvFormat
);
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_InvAddrMode);
else
{
Word AdrWord;
Boolean OK;
AdrWord = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt4, &OK);
if (OK)
{
CodeLen = 2;
WAsmCode[0] = 0x03d5 + (AdrWord << 10);
}
}
}
static void DecodeENTER_EXITD(Word IsEXITD)
{
if (ChkArgCnt(2, 2))
{
tStrComp *pRegList = IsEXITD ? &ArgStr[1] : &ArgStr[2],
*pSizeArg = IsEXITD ? &ArgStr[2] : &ArgStr[1];
if ((CheckFormat("GE"))
&& (GetOpSize(pSizeArg, 1))
&& (GetOpSize(pRegList, 2)))
{
Word RegList;
if (OpSize[1] == -1) OpSize[1] = 2;
if (OpSize[2] == -1) OpSize[2] = 2;
if (OpSize[2] != 2) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(pSizeArg, 1, MModReg | MModImm))
&& (DecodeRegList(pRegList, &RegList, IsEXITD)))
{
if ((RegList & 0xc000) != 0) WrXError(ErrNum_InvRegList,"SP/FP");
else
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((HVal >= -128) && (HVal <= 127))
FormatCode = 2;
else
FormatCode = 1;
}
else
FormatCode = 1;
}
switch (FormatCode)
{
case 1:
WAsmCode[0] = 0x02f7;
WAsmCode[1] = 0x8c00 + (IsEXITD << 12) + (OpSize[1] << 8) + AdrMode[1];
memcpy(WAsmCode
+ 2, AdrVals
[1], AdrCnt1
[1]);
WAsmCode[2 + AdrCnt2[1]] = RegList;
CodeLen = 6 + AdrCnt1[1];
break;
case 2:
if (AdrType[1] != ModImm) WrError(ErrNum_InvAddrMode);
else
{
LongInt HVal = ImmVal(1);
if (ChkRange(HVal, -128, 127))
{
WAsmCode[0] = 0x8e00 + (IsEXITD << 12) + (HVal & 0xff);
WAsmCode[1] = RegList;
CodeLen = 4;
}
}
break;
}
}
}
}
}
}
static void DecodeSCMP(Word Code)
{
UNUSED(Code);
if (DOpSize == -1) DOpSize = 2;
if (!ChkArgCnt(0, 0));
else if (OptionCnt > 1) WrError(ErrNum_WrongOptCnt);
else
{
Boolean OK = True;
Word Condition = 6;
if (OptionCnt == 1)
OK = DecodeStringCondition(Options[0], &Condition);
if (!OK) WrXError(ErrNum_UndefCond, Options[0]);
else
{
WAsmCode[0] = 0x00e0 + (DOpSize << 8) + (Condition << 10);
CodeLen = 2;
}
}
}
static void DecodeSMOV_SSCH(Word Code)
{
if (DOpSize == -1) DOpSize = 2;
if (ChkArgCnt(0, 0))
{
int z;
Word Condition = 6, Mask = 0;
Boolean OK = True;
for (z = 0; z < OptionCnt; z++)
{
if (!as_strcasecmp(Options[z], "F"))
Mask = 0;
else if (!as_strcasecmp(Options[z], "B"))
Mask = 1;
else
OK = DecodeStringCondition(Options[z], &Condition);
if (!OK)
break;
}
if (!OK) WrXError(ErrNum_UndefCond, Options[z]);
else
{
WAsmCode[0] = 0x00e4 + (DOpSize << 8) + (Condition << 10) + Mask + Code;
CodeLen = 2;
}
}
}
static void DecodeSSTR(Word Code)
{
UNUSED(Code);
if (DOpSize == -1) DOpSize = 2;
if (ChkArgCnt(0, 0))
{
WAsmCode[0] = 0x24f7 + (DOpSize << 8);
CodeLen = 2;
}
}
static void DecodeLDM_STM(Word Code)
{
if (ChkArgCnt(2, 2)
&& CheckFormat("G"))
{
Word Mask = MModIReg | MModDisp16 | MModDisp32 | MModAbs16 | MModAbs32 | MModPCRel16 | MModPCRel32;
tStrComp *pRegList, *pMemArg;
Word RegList;
if (Code)
{
Mask |= MModPop;
pRegList = &ArgStr[2];
pMemArg = &ArgStr[1];
}
else
{
Mask |= MModPush;
pRegList = &ArgStr[1];
pMemArg = &ArgStr[2];
}
if ((GetOpSize(pRegList, 1))
&& (GetOpSize(pMemArg, 2)))
{
if (OpSize[1] == -1) OpSize[1] = 2;
if (OpSize[2] == -1) OpSize[2] = 2;
if ((OpSize[1] != 2) || (OpSize[2] != 2)) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(pMemArg, 2, Mask))
&& (DecodeRegList(pRegList, &RegList, AdrType[2] != ModPush)))
{
WAsmCode[0] = 0x8a00 + Code + AdrMode[2];
memcpy(WAsmCode
+ 1, AdrVals
[2], AdrCnt1
[2]);
WAsmCode[1 + AdrCnt2[2]] = RegList;
CodeLen = 4 + AdrCnt1[2];
}
}
}
}
static void DecodeSTC_STP(Word Code)
{
if (ChkArgCnt(2, 2)
&& CheckFormat("G")
&& GetOpSize(&ArgStr[1], 1)
&& GetOpSize(&ArgStr[2], 2))
{
if (OpSize[2] == -1) OpSize[2] = 2;
if (OpSize[1] == -1) OpSize[1] = OpSize[1];
if (OpSize[1] != OpSize[2]) WrError(ErrNum_UndefOpSizes);
else if ((!Code) && (OpSize[2] != 2)) WrError(ErrNum_InvOpSize);
else if ((DecodeAdr(&ArgStr[1], 1, Mask_PureMem))
&& (DecodeAdr(&ArgStr[2], 2, Mask_Dest)))
{
OpSize[1] = 0;
Make_G(0xa800 + Code);
WAsmCode[0] += 0x800;
}
}
}
static void DecodeJRNG(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1)
&& CheckFormat("GE")
&& GetOpSize(&ArgStr[1], 1))
{
if (OpSize[1] == -1) OpSize[1] = 1;
if (OpSize[1] != 1) WrError(ErrNum_InvOpSize);
else if (DecodeAdr(&ArgStr[1], 1, MModReg | MModImm))
{
if (FormatCode == 0)
{
if (AdrType[1] == ModImm)
{
LongInt HVal = ImmVal(1);
if ((HVal >= 0) && (HVal <= 255))
FormatCode = 2;
else
FormatCode = 1;
}
else
FormatCode = 1;
}
switch (FormatCode)
{
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(ErrNum_InvAddrMode);
else
{
LongInt HVal = ImmVal(1);
if (ChkRange(HVal, 0, 255))
{
WAsmCode[0] = 0xbe00 + (HVal & 0xff);
CodeLen = 2;
}
}
break;
}
}
}
}
/*------------------------------------------------------------------------*/
static void AddFixed(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFixed);
}
static void AddFixedLong(const char *NName, Word NCode1, Word NCode2)
{
order_array_rsv_end(FixedLongOrders, BitOrder);
FixedLongOrders[InstrZ].Code1 = NCode1;
FixedLongOrders[InstrZ].Code2 = NCode2;
AddInstTable(InstTable, NName, InstrZ++, DecodeFixedLong);
}
static void AddOne(const char *NName, Byte NOpMask, Word NMask, Word NCode)
{
order_array_rsv_end(OneOrders, OneOrder);
OneOrders[InstrZ].Code = NCode;
OneOrders[InstrZ].Mask = NMask;
OneOrders[InstrZ].OpMask = NOpMask;
AddInstTable(InstTable, NName, InstrZ++, DecodeOne);
}
static void AddGE2(const char *NName, Word NMask1, Word NMask2,
Byte NSMask1, Byte NSMask2, Word NCode,
Boolean NSigned)
{
order_array_rsv_end(GE2Orders, GE2Order);
GE2Orders[InstrZ].Mask1 = NMask1;
GE2Orders[InstrZ].Mask2 = NMask2;
GE2Orders[InstrZ].SMask1 = NSMask1;
GE2Orders[InstrZ].SMask2 = NSMask2;
GE2Orders[InstrZ].Code = NCode;
GE2Orders[InstrZ].Signed = NSigned;
AddInstTable(InstTable, NName, InstrZ++, DecodeGE2);
}
static void AddBit(const char *NName, Boolean NMust, Word NCode1, Word NCode2)
{
order_array_rsv_end(BitOrders, BitOrder);
BitOrders[InstrZ].Code1 = NCode1;
BitOrders[InstrZ].Code2 = NCode2;
BitOrders[InstrZ].MustByte = NMust;
AddInstTable(InstTable, NName, InstrZ++, DecodeBit);
}
static void AddGetPut(const char *NName, Byte NSize, Word NCode, Boolean NTurn)
{
AddInstTable(InstTable, NName, NCode | NSize | (NTurn << 7), DecodeGetPut);
}
static void Addcc(const char *p_branch_name)
{
order_array_rsv_end(Conditions, condition_t);
Conditions[InstrZ].p_name = p_branch_name + 1;
if (p_branch_name)
AddInstTable(InstTable, p_branch_name, InstrZ << 10, DecodeBcc);
InstrZ++;
}
static void InitFields(void)
{
Format
= (char*)malloc(sizeof(char) * STRINGSIZE
);
InstTable = CreateInstTable(301);
AddInstTable(InstTable, "MOV", 0, DecodeMOV);
AddInstTable(InstTable, "ADD", 0, DecodeADD_SUB);
AddInstTable(InstTable, "SUB", 1, DecodeADD_SUB);
AddInstTable(InstTable, "ACB", 0, DecodeACB_SCB);
AddInstTable(InstTable, "SCB", 1, DecodeACB_SCB);
AddInstTable(InstTable, "CMP", 0, DecodeCMP);
AddInstTable(InstTable, "MOVA", 0, DecodeMOVA);
AddInstTable(InstTable, "QINS", 1 << 11, DecodeQINS_QDEL);
AddInstTable(InstTable, "QDEL", 0 << 11, DecodeQINS_QDEL);
AddInstTable(InstTable, "RVBY", 0, DecodeRVBY);
AddInstTable(InstTable, "SHL", 0, DecodeSHL_SHA);
AddInstTable(InstTable, "SHA", 1, DecodeSHL_SHA);
AddInstTable(InstTable, "SHXL", 0x8a00, DecodeSHXL_SHXR);
AddInstTable(InstTable, "SHXR", 0x9a00, DecodeSHXL_SHXR);
AddInstTable(InstTable, "CHK", 0, DecodeCHK);
AddInstTable(InstTable, "CHK/", 0, DecodeCHK);
AddInstTable(InstTable, "CSI", 0, DecodeCSI);
AddInstTable(InstTable, "DIVX", 0x8300, DecodeDIVX_MULX);
AddInstTable(InstTable, "MULX", 0x8200, DecodeDIVX_MULX);
AddInstTable(InstTable, "WAIT", 0, DecodeWAIT);
AddInstTable(InstTable, "BFEXT", 0, DecodeBFEXT_BFEXTU);
AddInstTable(InstTable, "BFEXTU", 1, DecodeBFEXT_BFEXTU);
AddInstTable(InstTable, "BSCH/", 0x5000, DecodeBSCH);
AddInstTable(InstTable, "BSR", 1, DecodeBSR_BRA);
AddInstTable(InstTable, "BRA", 0, DecodeBSR_BRA);
AddInstTable(InstTable, "TRAPA", 0, DecodeTRAPA);
AddInstTable(InstTable, "TRAP/", 0, DecodeTRAP);
AddInstTable(InstTable, "ENTER", 0, DecodeENTER_EXITD);
AddInstTable(InstTable, "EXITD", 1, DecodeENTER_EXITD);
AddInstTable(InstTable, "SCMP", 0, DecodeSCMP);
AddInstTable(InstTable, "SCMP/", 0, DecodeSCMP);
AddInstTable(InstTable, "SMOV", 0, DecodeSMOV_SSCH);
AddInstTable(InstTable, "SMOV/", 0, DecodeSMOV_SSCH);
AddInstTable(InstTable, "SSCH", 16, DecodeSMOV_SSCH);
AddInstTable(InstTable, "SSCH/", 16, DecodeSMOV_SSCH);
AddInstTable(InstTable, "SSTR", 0, DecodeSSTR);
AddInstTable(InstTable, "LDM", 0x1000, DecodeLDM_STM);
AddInstTable(InstTable, "STM", 0x0000, DecodeLDM_STM);
AddInstTable(InstTable, "STC", 0x0000, DecodeSTC_STP);
AddInstTable(InstTable, "STP", 0x0400, DecodeSTC_STP);
AddInstTable(InstTable, "JRNG", 0, DecodeJRNG);
AddFixed("NOP" , 0x1bd6); AddFixed("PIB" , 0x0bd6);
AddFixed("RIE" , 0x08f7); AddFixed("RRNG" , 0x3bd6);
AddFixed("RTS" , 0x2bd6); AddFixed("STCTX", 0x07d6);
AddFixed("REIT" , 0x2fd6);
InstrZ = 0;
AddFixedLong("STOP", 0x5374, 0x6f70);
AddFixedLong("SLEEP", 0x5761, 0x6974);
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);
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|MModPop, 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 );
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);
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 );
InstrZ = 0;
AddInstTable(InstTable, "BFCMP" , InstrZ++, DecodeBField);
AddInstTable(InstTable, "BFCMPU", InstrZ++, DecodeBField);
AddInstTable(InstTable, "BFINS" , InstrZ++, DecodeBField);
AddInstTable(InstTable, "BFINSU", InstrZ++, DecodeBField);
InstrZ = 0;
AddInstTable(InstTable, "MUL" , InstrZ++, DecodeMul);
AddInstTable(InstTable, "MULU", InstrZ++, DecodeMul);
AddInstTable(InstTable, "DIV" , InstrZ++, DecodeMul);
AddInstTable(InstTable, "DIVU", InstrZ++, DecodeMul);
InstrZ = 0;
Addcc("BXS");
Addcc("BXC");
Addcc("BEQ");
Addcc("BNE");
Addcc("BLT");
Addcc("BGE");
Addcc("BLE");
Addcc("BGT");
Addcc("BVS");
Addcc("BVC");
Addcc("BMS");
Addcc("BMC");
Addcc("BFS");
Addcc("BFC");
Addcc(NULL);
InstrZ = 0;
AddInstTable(InstTable, "AND", InstrZ++, DecodeLog);
AddInstTable(InstTable, "OR" , InstrZ++, DecodeLog);
AddInstTable(InstTable, "XOR", InstrZ++, DecodeLog);
AddInstTable(InstTable, "REG", 0, CodeREG);
}
static void DeinitFields(void)
{
order_array_free(Conditions);
order_array_free(Format);
order_array_free(FixedLongOrders);
order_array_free(OneOrders);
order_array_free(GE2Orders);
order_array_free(BitOrders);
DestroyInstTable(InstTable);
}
/*------------------------------------------------------------------------*/
static Boolean DecodeAttrPart_M16(void)
{
char *p;
switch (AttrSplit)
{
case '.':
p
= strchr(AttrPart.
str.
p_str, ':');
if (p)
{
if (p
< AttrPart.
str.
p_str + strlen(AttrPart.
str.
p_str) - 1)
strmaxcpy(Format, p + 1, STRINGSIZE);
else
*p = '\0';
}
else
break;
case ':':
p
= strchr(AttrPart.
str.
p_str, '.');
if (!p)
{
strmaxcpy(Format, AttrPart.str.p_str, STRINGSIZE);
*AttrPart.str.p_str = '\0';
}
else
{
*p = '\0';
if (p == AttrPart.str.p_str)
else
strmaxcpy(Format, AttrPart.str.p_str, STRINGSIZE);
}
break;
default:
}
NLS_UpString(Format);
if (*AttrPart.str.p_str)
switch (as_toupper(*AttrPart.str.p_str))
{
case 'B':
AttrPartOpSize[0] = eSymbolSize8Bit; break;
case 'H':
AttrPartOpSize[0] = eSymbolSize16Bit; break;
case 'W':
AttrPartOpSize[0] = eSymbolSize32Bit; break;
default:
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart); return False;
}
return True;
}
static void MakeCode_M16(void)
{
int z;
DOpSize = AttrPartOpSize[0];
for (z = 1; z <= ArgCnt; OpSize[z++] = eSymbolSizeUnknown);
/* zu ignorierendes */
if (Memo(""))
return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(False))
return;
SplitOptions();
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_M16(void)
{
return Memo("REG");
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_M16(char *pArg, TempResult *pResult)
* \brief handle built-in (register) symbols for M16
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_M16(char *pArg, TempResult *pResult)
{
Word RegNum;
if (DecodeRegCore(pArg, &RegNum))
{
pResult->Typ = TempReg;
pResult->DataSize = eSymbolSize32Bit;
pResult->Contents.RegDescr.Reg = RegNum;
pResult->Contents.RegDescr.Dissect = DissectReg_M16;
pResult->Contents.RegDescr.compare = NULL;
}
}
static void SwitchFrom_M16(void)
{
DeinitFields();
}
static void SwitchTo_M16(void)
{
TurnWords = True;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "$";
HeaderID = 0x13;
NOPCode = 0x1bd6;
DivideChars=",";
HasAttrs = True;
AttrChars = ".:";
ValidSegs = 1 << SegCode;
Grans[SegCode] = 1;
ListGrans[SegCode] = 2;
SegInits[SegCode] = 0;
SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
DecodeAttrPart = DecodeAttrPart_M16;
MakeCode = MakeCode_M16;
IsDef = IsDef_M16;
DissectReg = DissectReg_M16;
InternSymbol = InternSymbol_M16;
SwitchFrom = SwitchFrom_M16;
InitFields();
}
void codem16_init(void)
{
CPUM16 = AddCPU("M16", SwitchTo_M16);
}