/* code68k.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator 680x0-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "nls.h"
#include "bpemu.h"
#include "be_le.h"
#include "ieeefloat.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmcode.h"
#include "motpseudo.h"
#include "asmitree.h"
#include "codevars.h"
#include "errmsg.h"
#include "codepseudo.h"
#include "code68k.h"
typedef enum
{
e68KGen1a, /* 68008/68000 */
e68KGen1b, /* 68010/68012 */
eColdfire,
eCPU32,
e68KGen2, /* 68020/68030 */
e68KGen3 /* 68040 */
} tFamily;
typedef enum
{
eCfISA_None,
eCfISA_A,
eCfISA_APlus,
eCfISA_B,
eCfISA_C
} tCfISA;
typedef enum
{
eFlagNone = 0,
eFlagLogCCR = 1 << 0,
eFlagIdxScaling = 1 << 1,
eFlagCALLM_RTM = 1 << 2,
eFlagIntFPU = 1 << 3,
eFlagExtFPU = 1 << 4,
eFlagIntPMMU = 1 << 5,
eFlagBranch32 = 1 << 6,
eFlagMAC = 1 << 7,
eFlagEMAC = 1 << 8
} tSuppFlags;
#define eSymbolSizeShiftCnt ((tSymbolSize)8)
#ifdef __cplusplus
# include "code68k.hpp"
#endif
enum
{
Std_Variant = 0,
I_Variant = 4,
A_Variant = 8,
VariantMask = 12
};
typedef struct
{
const char *Name;
Word Code;
} tCtReg;
#define MAX_CTREGS_GROUPS 4
typedef struct
{
const char *pName;
LongWord AddrSpaceMask;
tFamily Family;
tCfISA CfISA;
tSuppFlags SuppFlags;
const tCtReg *pCtRegs[MAX_CTREGS_GROUPS];
} tCPUProps;
typedef struct
{
Word Code;
Boolean MustSup;
Word FamilyMask;
} FixedOrder;
typedef struct
{
Byte Code;
Boolean Dya;
tSuppFlags NeedsSuppFlags;
} FPUOp;
typedef struct
{
const char *pName;
tSymbolSize Size;
Word Code;
} PMMUReg;
#define EMACAvailName "HASEMAC"
#define REG_SP 15
#define REG_FPCTRL 8
#define REG_FPCR 4
#define REG_FPSR 2
#define REG_FPIAR 1
typedef enum
{
ModNone = 0,
ModData = 1,
ModAdr = 2,
ModAdrI = 3,
ModPost = 4,
ModPre = 5,
ModDAdrI = 6,
ModAIX = 7,
ModPC = 8,
ModPCIdx = 9,
ModAbs = 10,
ModImm = 11,
ModFPn = 12,
ModFPCR = 13
} adrmode_t;
enum
{
MModData = 1 << (ModData - 1),
MModAdr = 1 << (ModAdr - 1),
MModAdrI = 1 << (ModAdrI - 1),
MModPost = 1 << (ModPost - 1),
MModPre = 1 << (ModPre - 1),
MModDAdrI = 1 << (ModDAdrI - 1),
MModAIX = 1 << (ModAIX - 1),
MModPC = 1 << (ModPC - 1),
MModPCIdx = 1 << (ModPCIdx - 1),
MModAbs = 1 << (ModAbs - 1),
MModImm = 1 << (ModImm - 1),
MModFPn = 1 << (ModFPn - 1),
MModFPCR = 1 << (ModFPCR - 1)
};
typedef struct
{
adrmode_t AdrMode;
Word AdrPart;
Word Vals[10];
tSymbolFlags ImmSymFlags;
int Cnt;
} tAdrResult;
static tSymbolSize OpSize;
static ShortInt RelPos;
static Boolean FullPMMU; /* voller PMMU-Befehlssatz? */
static FixedOrder *FixedOrders;
static FPUOp *FPUOps;
static PMMUReg *PMMURegs;
static const tCPUProps *pCurrCPUProps;
static tSymbolSize NativeFloatSize;
static const Byte FSizeCodes[10] =
{
6, 4, 0, 7, 0, 1, 5, 2, 0, 3
};
/*-------------------------------------------------------------------------*/
/* Unterroutinen */
#define CopyAdrVals(Dest, pAdrResult) memcpy(Dest, (pAdrResult)->Vals, (pAdrResult)->Cnt)
static Boolean CheckFamilyCore(unsigned FamilyMask)
{
return !!((FamilyMask >> pCurrCPUProps->Family) & 1);
}
static Boolean CheckFamily(unsigned FamilyMask)
{
if (CheckFamilyCore(FamilyMask))
return True;
WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
CodeLen = 0;
return False;
}
static Boolean CheckISA(unsigned ISAMask)
{
if ((ISAMask >> pCurrCPUProps->CfISA) & 1)
return True;
WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
CodeLen = 0;
return False;
}
static Boolean CheckNoFamily(unsigned FamilyMask)
{
if (!CheckFamilyCore(FamilyMask))
return True;
WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
CodeLen = 0;
return False;
}
static void CheckSup(void)
{
if (!SupAllowed)
WrStrErrorPos(ErrNum_PrivOrder, &OpPart);
}
static Boolean CheckColdSize(void)
{
if ((OpSize > eSymbolSize32Bit) || ((pCurrCPUProps->Family == eColdfire) && (OpSize < eSymbolSize32Bit)))
{
WrError(ErrNum_InvOpSize);
return False;
}
else
return True;
}
static Boolean CheckFloatSize(void)
{
if (!*AttrPart.str.p_str)
OpSize = NativeFloatSize;
switch (OpSize)
{
case eSymbolSize8Bit:
case eSymbolSize16Bit:
case eSymbolSize32Bit:
case eSymbolSizeFloat32Bit:
case eSymbolSizeFloat64Bit:
return True;
case eSymbolSizeFloat96Bit:
case eSymbolSizeFloatDec96Bit:
if (pCurrCPUProps->Family != eColdfire)
return True;
/* else fall-through */
default:
WrError(ErrNum_InvOpSize);
return False;
}
}
static Boolean FloatOpSizeFitsDataReg(tSymbolSize OpSize)
{
return (OpSize <= eSymbolSize32Bit) || (OpSize == eSymbolSizeFloat32Bit);
}
static Boolean ValReg(char Ch)
{
return ((Ch >= '0') && (Ch <= '7'));
}
/*-------------------------------------------------------------------------*/
/* Register Symbols */
/*!------------------------------------------------------------------------
* \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;
return True;
}
return False;
if ((*pResult = pArg[1] - '0') > 7)
return False;
switch (as_toupper(*pArg))
{
case 'D':
return True;
case 'A':
*pResult |= 8;
return True;
default:
return False;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeFPRegCore(const char *pArg, Word *pResult)
* \brief check whether argument is an FPU register
* \param pArg argument to check
* \param pResult numeric register value if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeFPRegCore(const char *pArg, Word *pResult)
{
if (!as_strcasecmp(pArg, "FPCR"))
{
*pResult = REG_FPCTRL | REG_FPCR;
return True;
}
if (!as_strcasecmp(pArg, "FPSR"))
{
*pResult = REG_FPCTRL | REG_FPSR;
return True;
}
if (!as_strcasecmp(pArg, "FPIAR"))
{
*pResult = REG_FPCTRL | REG_FPIAR;
return True;
}
return False;
if (as_strncasecmp(pArg, "FP", 2))
return False;
if ((*pResult = pArg[2] - '0') > 7)
return False;
return True;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_68K(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - 68K variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_68K(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
{
if (InpSize == NativeFloatSize)
{
switch (Value)
{
case REG_FPCTRL | REG_FPCR:
as_snprintf(pDest, DestSize, "FPCR");
break;
case REG_FPCTRL | REG_FPSR:
as_snprintf(pDest, DestSize, "FPSR");
break;
case REG_FPCTRL | REG_FPIAR:
as_snprintf(pDest, DestSize, "FPIAR");
break;
default:
as_snprintf(pDest, DestSize, "FP%u", (unsigned)Value);
}
}
else if (InpSize == eSymbolSize32Bit)
{
switch (Value)
{
case REGSYM_FLAG_ALIAS | REG_SP:
as_snprintf(pDest, DestSize, "SP");
break;
default:
as_snprintf(pDest, DestSize, "%c%u", Value & 8 ? 'A' : 'D', (unsigned)(Value & 7));
}
}
else
as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
}
/*!------------------------------------------------------------------------
* \fn compare_reg_68k(tRegInt reg1_num, tSymbolSize reg1_size, tRegInt reg2_num, tRegInt reg2_size)
* \brief compare two register symbols
* \param reg1_num 1st register's number
* \param reg1_size 1st register's data size
* \param reg2_num 2nd register's number
* \param reg2_size 2nd register's data size
* \return 0, -1, 1, -2
* ------------------------------------------------------------------------ */
static int compare_reg_68k(tRegInt reg1_num, tSymbolSize reg1_size, tRegInt reg2_num, tSymbolSize reg2_size)
{
/* FP and Integer registers in different register files: */
if (reg1_size != reg2_size)
return -2;
if (reg1_size == NativeFloatSize)
{
/* only FP data registers have an ordering: */
if ((reg1_num & REG_FPCTRL) || (reg2_num & REG_FPCTRL))
return (reg1_num == reg2_num) ? 0 : -2;
}
else if (reg1_size == eSymbolSize32Bit)
{
reg1_num &= ~REGSYM_FLAG_ALIAS;
reg2_num &= ~REGSYM_FLAG_ALIAS;
}
if (reg1_num < reg2_num)
return -1;
else if (reg1_num > reg2_num)
return 1;
else
return 0;
}
/*-------------------------------------------------------------------------*/
/* Adressparser */
typedef enum
{
PC, AReg, Index, indir, Disp, None
} CompType;
/* static const char *CompNames[] = { "PC", "AReg", "Index", "indir", "Disp", "None" }; */
typedef struct
{
tStrComp Comp;
CompType Art;
Word ANummer, INummer;
Boolean Long;
Word Scale;
ShortInt Size;
LongInt Wert;
} AdrComp;
static void ClrAdrVals(tAdrResult *pResult)
{
pResult->AdrMode = ModNone;
pResult->Cnt = 0;
}
static Boolean ACheckFamily(unsigned FamilyMask, const tStrComp *pAdrComp, tAdrResult *pResult)
{
if (CheckFamilyCore(FamilyMask))
return True;
WrStrErrorPos(ErrNum_AddrModeNotSupported, pAdrComp);
ClrAdrVals(pResult);
return False;
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, Word *pErg, Boolean MustBeReg)
* \brief check whether argument is a CPU register or register alias
* \param pArg argument to check
* \param pResult numeric register value if yes
* \param MustBeReg argument is expected to be a register
* \return RegEvalResult
* ------------------------------------------------------------------------ */
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;
}
/*!------------------------------------------------------------------------
* \fn DecodeFPReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
* \brief check whether argument is a FPU register or register alias
* \param pArg argument to check
* \param pResult numeric register value if yes
* \param MustBeReg argument is expected to be a register
* \return RegEvalResult
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeFPReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
if (DecodeFPRegCore(pArg->str.p_str, pResult))
{
*pResult &= ~REGSYM_FLAG_ALIAS;
return eIsReg;
}
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, NativeFloatSize, MustBeReg);
*pResult = RegDescr.Reg;
return RegEvalResult;
}
/*!------------------------------------------------------------------------
* \fn DecodeRegOrFPReg(const tStrComp *pArg, Word *pErg, tSymbolSize *pSize, Boolean MustBeReg)
* \brief check whether argument is an CPU/FPU register or register alias
* \param pArg argument to check
* \param pResult numeric register value if yes
* \param pSize size of register if yes
* \param MustBeReg argument is expected to be a register
* \return RegEvalResult
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeRegOrFPReg(const tStrComp *pArg, Word *pResult, tSymbolSize *pSize, Boolean MustBeReg)
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
if (DecodeRegCore(pArg->str.p_str, pResult))
{
*pResult &= ~REGSYM_FLAG_ALIAS;
*pSize = eSymbolSize32Bit;
return eIsReg;
}
if (DecodeFPRegCore(pArg->str.p_str, pResult))
{
*pSize = NativeFloatSize;
return eIsReg;
}
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
*pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
*pSize = EvalResult.DataSize;
return RegEvalResult;
}
static Boolean DecodeRegPair(tStrComp *pArg, Word *Erg1, Word *Erg2)
{
char *pSep
= strchr(pArg
->str.
p_str, ':');
tStrComp Left, Right;
if (!pSep)
return False;
StrCompSplitRef(&Left, &Right, pArg, pSep);
return (DecodeReg(&Left, Erg1, False) == eIsReg)
&& (*Erg1 <= 7)
&& (DecodeReg(&Right, Erg2, False) == eIsReg)
&& (*Erg2 <= 7);
}
static Boolean CodeIndRegPair(tStrComp *pArg, Word *Erg1, Word *Erg2)
{
char *pSep
= strchr(pArg
->str.
p_str, ':');
tStrComp Left, Right;
if (!pSep)
return False;
StrCompSplitRef(&Left, &Right, pArg, pSep);
if (!IsIndirect(Left.str.p_str) || !IsIndirect(Right.str.p_str))
return False;
StrCompShorten(&Left, 1);
StrCompIncRefLeft(&Left, 1);
StrCompShorten(&Right, 1);
StrCompIncRefLeft(&Right, 1);
return (DecodeReg(&Left, Erg1, False) == eIsReg)
&& (DecodeReg(&Right, Erg2, False) == eIsReg);
}
static Boolean CodeCache(char *Asc, Word *Erg)
{
if (!as_strcasecmp(Asc, "IC"))
*Erg = 2;
else if (!as_strcasecmp(Asc, "DC"))
*Erg = 1;
else if (!as_strcasecmp(Asc, "IC/DC"))
*Erg = 3;
else if (!as_strcasecmp(Asc, "DC/IC"))
*Erg = 3;
else
return False;
return True;
}
static Boolean DecodeCtrlReg(char *Asc, Word *Erg)
{
int Grp;
String Asc_N;
const tCtReg *pReg;
strmaxcpy(Asc_N, Asc, STRINGSIZE);
NLS_UpString(Asc_N);
Asc = Asc_N;
for (Grp = 0; Grp < MAX_CTREGS_GROUPS; Grp++)
{
pReg = pCurrCPUProps->pCtRegs[Grp];
if (!pReg)
return False;
for (; pReg->Name; pReg++)
{
*Erg = pReg->Code;
return True;
}
}
return False;
}
static Boolean OneField(const tStrComp *pArg, Word *Erg, Boolean Ab1)
{
switch (DecodeReg(pArg, Erg, False))
{
case eIsReg:
if (*Erg > 7)
return False;
*Erg |= 0x20;
return True;
case eIsNoReg:
{
Boolean ValOK;
*Erg = EvalStrIntExpression(pArg, Int8, &ValOK);
if (Ab1 && (*Erg == 32))
*Erg = 0;
return (ValOK && (*Erg < 32));
}
default:
return False;
}
}
static Boolean SplitBitField(tStrComp *pArg, Word *Erg)
{
char *p;
Word OfsVal;
tStrComp FieldArg, OffsArg, WidthArg;
p
= strchr(pArg
->str.
p_str, '{');
if (!p)
return False;
StrCompSplitRef(pArg, &FieldArg, pArg, p);
if ((!*FieldArg.
str.
p_str) || (FieldArg.
str.
p_str[strlen(FieldArg.
str.
p_str) - 1] != '}'))
return False;
StrCompShorten(&FieldArg, 1);
p
= strchr(FieldArg.
str.
p_str, ':');
if (!p)
return False;
StrCompSplitRef(&OffsArg, &WidthArg, &FieldArg, p);
if (!OneField(&OffsArg, &OfsVal, False))
return False;
if (!OneField(&WidthArg, Erg, True))
return False;
*Erg += OfsVal << 6;
return True;
}
static Boolean SplitSize(tStrComp *pArg, ShortInt *DispLen, unsigned OpSizeMask)
{
ShortInt NewLen = -1;
int ArgLen
= strlen(pArg
->str.
p_str);
if ((ArgLen > 2) && (pArg->str.p_str[ArgLen - 2] == '.'))
{
switch (as_toupper(pArg->str.p_str[ArgLen - 1]))
{
case 'B':
if (OpSizeMask & 1)
NewLen = 0;
else
goto wrong;
break;
case 'W':
if (OpSizeMask & 2)
NewLen = 1;
else
goto wrong;
break;
case 'L':
if (OpSizeMask & 2)
NewLen = 2;
else
goto wrong;
break;
default:
wrong:
WrError(ErrNum_InvOpSize);
return False;
}
if ((*DispLen != -1) && (*DispLen != NewLen))
{
WrError(ErrNum_ConfOpSizes);
return False;
}
*DispLen = NewLen;
StrCompShorten(pArg, 2);
}
return True;
}
static Boolean ClassComp(AdrComp *C)
{
int comp_len
= strlen(C
->Comp.
str.
p_str), reg_len
;
char save, c_scale, c_size;
C->Art = None;
C->ANummer = C->INummer = 0;
C->Long = False;
C->Scale = 0;
C->Size = -1;
C->Wert = 0;
if ((*C->Comp.str.p_str == '[') && (C->Comp.str.p_str[comp_len - 1] == ']'))
{
C->Art = indir;
return True;
}
if (!as_strcasecmp(C->Comp.str.p_str, "PC"))
{
C->Art = PC;
return True;
}
/* assume register, splitting off scale & size first: */
reg_len = comp_len;
c_scale = c_size = '\0';
if ((reg_len > 2) && (C->Comp.str.p_str[reg_len - 2] == '*'))
{
c_scale = C->Comp.str.p_str[reg_len - 1];
reg_len -= 2;
}
if ((reg_len > 2) && (C->Comp.str.p_str[reg_len - 2] == '.'))
{
c_size = C->Comp.str.p_str[reg_len - 1];
reg_len -= 2;
}
save = C->Comp.str.p_str[reg_len];
C->Comp.str.p_str[reg_len] = '\0';
switch (DecodeReg(&C->Comp, &C->ANummer, False))
{
case eRegAbort:
return False;
case eIsReg:
C->Comp.str.p_str[reg_len] = save;
break;
default: /* eIsNoReg */
C->Comp.str.p_str[reg_len] = save;
goto is_disp;
}
/* OK, we know it's a register, with optional scale & size: */
if ((C->ANummer > 7) && !c_scale && !c_size)
{
C->Art = AReg;
C->ANummer -= 8;
return True;
}
if (c_size)
{
switch (as_toupper(c_size))
{
case 'L':
C->Long = True;
break;
case 'W':
C->Long = False;
break;
default:
return False;
}
}
else
C->Long = (pCurrCPUProps->Family == eColdfire);
if (c_scale)
{
switch (c_scale)
{
case '1':
C->Scale = 0;
break;
case '2':
C->Scale = 1;
break;
case '4':
C->Scale = 2;
break;
case '8':
if (pCurrCPUProps->Family == eColdfire)
return False;
C->Scale = 3;
break;
default:
return False;
}
}
else
C->Scale = 0;
C->INummer = C->ANummer;
C->Art = Index;
return True;
is_disp:
C->Art = Disp;
if ((comp_len >= 2) && (C->Comp.str.p_str[comp_len - 2] == '.'))
{
switch (as_toupper(C->Comp.str.p_str[comp_len - 1]))
{
case 'L':
C->Size = 2;
break;
case 'W':
C->Size = 1;
break;
default:
return False;
}
StrCompShorten(&C->Comp, 2);
}
else
C->Size = -1;
C->Art = Disp;
return True;
}
static void SwapAdrComps(AdrComp *pComp1, AdrComp *pComp2)
{
AdrComp Tmp;
Tmp = *pComp1;
*pComp1 = *pComp2;
*pComp2 = Tmp;
}
static void AdrCompToIndex(AdrComp *pComp)
{
pComp->Art = Index;
pComp->INummer = pComp->ANummer + 8;
pComp->Long = False;
pComp->Scale = 0;
}
static Boolean IsShortAdr(LongInt Addr)
{
LongWord OrigAddr = (LongWord)Addr, ExtAddr;
/* Assuming we would code this address as short address... */
ExtAddr = OrigAddr & 0xffff;
if (ExtAddr & 0x8000)
ExtAddr |= 0xffff0000ul;
/* ...would this result in the same address on the bus? */
return (ExtAddr & pCurrCPUProps->AddrSpaceMask) == (OrigAddr & pCurrCPUProps->AddrSpaceMask);
}
static Boolean IsDisp8(LongInt Disp)
{
return ((Disp >= -128) && (Disp <= 127));
}
static Boolean IsDisp16(LongInt Disp)
{
return ((Disp >= -32768) && (Disp <= 32767));
}
ShortInt GetDispLen(LongInt Disp)
{
if (IsDisp8(Disp))
return 0;
else if (IsDisp16(Disp))
return 1;
else
return 2;
}
static void ChkEven(LongInt Adr)
{
switch (pCurrCPUProps->Family)
{
case e68KGen1a:
case e68KGen1b:
case eColdfire:
if (Odd(Adr))
WrError(ErrNum_AddrNotAligned);
break;
default:
break;
}
}
static void DecodeAbs(const tStrComp *pArg, ShortInt Size, tAdrResult *pResult)
{
Boolean ValOK;
tSymbolFlags Flags;
LongInt HVal;
Integer HVal16;
pResult->Cnt = 0;
HVal = EvalStrIntExpressionWithFlags(pArg, Int32, &ValOK, &Flags);
if (ValOK)
{
if (!mFirstPassUnknown(Flags) && (OpSize > eSymbolSize8Bit))
ChkEven(HVal);
HVal16 = HVal;
if (Size == -1)
Size = (IsShortAdr(HVal)) ? 1 : 2;
pResult->AdrMode = ModAbs;
if (Size == 1)
{
if (!IsShortAdr(HVal))
{
WrError(ErrNum_NoShortAddr);
pResult->AdrMode = ModNone;
}
else
{
pResult->AdrPart = 0x38;
pResult->Vals[0] = HVal16;
pResult->Cnt = 2;
}
}
else
{
pResult->AdrPart = 0x39;
pResult->Vals[0] = HVal >> 16;
pResult->Vals[1] = HVal & 0xffff;
pResult->Cnt = 4;
}
}
}
static Byte DecodeAdr(const tStrComp *pArg, Word Erl, tAdrResult *pResult)
{
Byte i;
int ArgLen;
char *p;
Word rerg;
Byte lklamm, rklamm, lastrklamm;
Boolean doklamm;
AdrComp AdrComps[3], OneComp;
Byte CompCnt;
ShortInt OutDispLen = -1;
Boolean PreInd;
LongInt HVal;
Integer HVal16;
ShortInt HVal8;
Double DVal;
Boolean ValOK;
tSymbolFlags Flags;
Word SwapField[6];
String ArgStr;
tStrComp Arg;
String CReg;
tStrComp CRegArg;
const unsigned ExtAddrFamilyMask = (1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32);
IntType DispIntType;
tSymbolSize RegSize;
/* some insns decode the same arg twice, so we must keep the original string intact. */
StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
StrCompCopy(&Arg, pArg);
KillPrefBlanksStrComp(&Arg);
KillPostBlanksStrComp(&Arg);
ArgLen
= strlen(Arg.
str.
p_str);
ClrAdrVals(pResult);
StrCompMkTemp(&CRegArg, CReg, sizeof(CReg));
/* immediate : */
if (*Arg.str.p_str == '#')
{
tStrComp ImmArg;
StrCompRefRight(&ImmArg, &Arg, 1);
KillPrefBlanksStrComp(&ImmArg);
pResult->AdrMode = ModImm;
pResult->AdrPart = 0x3c;
switch (OpSize)
{
case eSymbolSize8Bit:
pResult->Cnt = 2;
HVal8 = EvalStrIntExpressionWithFlags(&ImmArg, Int8, &ValOK, &pResult->ImmSymFlags);
if (ValOK)
pResult->Vals[0] = (Word)((Byte) HVal8);
break;
case eSymbolSize16Bit:
pResult->Cnt = 2;
HVal16 = EvalStrIntExpressionWithFlags(&ImmArg, Int16, &ValOK, &pResult->ImmSymFlags);
if (ValOK)
pResult->Vals[0] = (Word) HVal16;
break;
case eSymbolSize32Bit:
pResult->Cnt = 4;
HVal = EvalStrIntExpressionWithFlags(&ImmArg, Int32, &ValOK, &pResult->ImmSymFlags);
if (ValOK)
{
pResult->Vals[0] = HVal >> 16;
pResult->Vals[1] = HVal & 0xffff;
}
break;
case eSymbolSize64Bit:
{
LargeInt QVal = EvalStrIntExpressionWithFlags(&ImmArg, LargeIntType, &ValOK, &pResult->ImmSymFlags);
pResult->Cnt = 8;
if (ValOK)
{
#ifdef HAS64
pResult->Vals[0] = (QVal >> 48) & 0xffff;
pResult->Vals[1] = (QVal >> 32) & 0xffff;
#else
pResult->Vals[0] =
pResult->Vals[1] = (QVal & 0x80000000ul) ? 0xffff : 0x0000;
#endif
pResult->Vals[2] = (QVal >> 16) & 0xffff;
pResult->Vals[3] = (QVal ) & 0xffff;
}
break;
}
case eSymbolSizeFloat32Bit:
pResult->Cnt = 4;
DVal = EvalStrFloatExpression(&ImmArg, Float32, &ValOK);
if (ValOK)
{
Double_2_ieee4(DVal, (Byte *) SwapField, HostBigEndian);
if (HostBigEndian)
DWSwap((Byte *) SwapField, 4);
pResult->Vals[0] = SwapField[1];
pResult->Vals[1] = SwapField[0];
}
break;
case eSymbolSizeFloat64Bit:
pResult->Cnt = 8;
DVal = EvalStrFloatExpression(&ImmArg, Float64, &ValOK);
if (ValOK)
{
Double_2_ieee8(DVal, (Byte *) SwapField, HostBigEndian);
if (HostBigEndian)
QWSwap((Byte *) SwapField, 8);
pResult->Vals[0] = SwapField[3];
pResult->Vals[1] = SwapField[2];
pResult->Vals[2] = SwapField[1];
pResult->Vals[3] = SwapField[0];
}
break;
case eSymbolSizeFloat96Bit:
pResult->Cnt = 12;
DVal = EvalStrFloatExpression(&ImmArg, Float64, &ValOK);
if (ValOK)
{
Double_2_ieee10(DVal, (Byte *) SwapField, False);
if (HostBigEndian)
WSwap((Byte *) SwapField, 10);
pResult->Vals[0] = SwapField[4];
pResult->Vals[1] = 0;
pResult->Vals[2] = SwapField[3];
pResult->Vals[3] = SwapField[2];
pResult->Vals[4] = SwapField[1];
pResult->Vals[5] = SwapField[0];
}
break;
case eSymbolSizeFloatDec96Bit:
pResult->Cnt = 12;
DVal = EvalStrFloatExpression(&ImmArg, Float64, &ValOK);
if (ValOK)
{
ConvertMotoFloatDec(DVal, (Byte *) SwapField, False);
pResult->Vals[0] = SwapField[5];
pResult->Vals[1] = SwapField[4];
pResult->Vals[2] = SwapField[3];
pResult->Vals[3] = SwapField[2];
pResult->Vals[4] = SwapField[1];
pResult->Vals[5] = SwapField[0];
}
break;
case eSymbolSizeShiftCnt: /* special arg 1..8 */
pResult->Cnt = 2;
HVal8 = EvalStrIntExpressionWithFlags(&ImmArg, UInt4, &ValOK, &pResult->ImmSymFlags);
if (ValOK)
{
if (mFirstPassUnknown(pResult->ImmSymFlags))
HVal8 = 1;
ValOK = ChkRange(HVal8, 1, 8);
}
if (ValOK)
pResult->Vals[0] = (Word)((Byte) HVal8);
break;
default:
break;
}
goto chk;
}
/* CPU/FPU-Register direkt: */
switch (DecodeRegOrFPReg(&Arg, &pResult->AdrPart, &RegSize, False))
{
case eIsReg:
pResult->Cnt = 0;
if (RegSize == NativeFloatSize)
{
pResult->AdrMode = (pResult->AdrPart > 7) ? ModFPCR : ModFPn;
pResult->AdrPart &= 7;
}
else
pResult->AdrMode = (pResult->AdrPart >> 3) ? ModAdr : ModData;
/* fall-through */
case eRegAbort:
goto chk;
default:
break;
}
/* Adressregister indirekt mit Predekrement: */
if ((ArgLen >= 4) && (*Arg.str.p_str == '-') && (Arg.str.p_str[1] == '(') && (Arg.str.p_str[ArgLen - 1] == ')'))
{
StrCompCopySub(&CRegArg, &Arg, 2, ArgLen - 3);
if ((DecodeReg(&CRegArg, &rerg, False) == eIsReg) && (rerg > 7))
{
pResult->AdrPart = rerg + 24;
pResult->Cnt = 0;
pResult->AdrMode = ModPre;
goto chk;
}
}
/* Adressregister indirekt mit Postinkrement */
if ((ArgLen >= 4) && (*Arg.str.p_str == '(') && (Arg.str.p_str[ArgLen - 2] == ')') && (Arg.str.p_str[ArgLen - 1] == '+'))
{
StrCompCopySub(&CRegArg, &Arg, 1, ArgLen - 3);
if ((DecodeReg(&CRegArg, &rerg, False) == eIsReg) && (rerg > 7))
{
pResult->AdrPart = rerg + 16;
pResult->Cnt = 0;
pResult->AdrMode = ModPost;
goto chk;
}
}
/* Unterscheidung direkt<->indirekt: */
lklamm = 0;
rklamm = 0;
lastrklamm = 0;
doklamm = True;
for (p = Arg.str.p_str; *p; p++)
{
if (*p == '[')
doklamm = False;
if (*p == ']')
doklamm = True;
if (doklamm)
{
if (*p == '(')
lklamm++;
else if (*p == ')')
{
rklamm++;
lastrklamm = p - Arg.str.p_str;
}
}
}
if ((lklamm == 1) && (rklamm == 1) && (lastrklamm == ArgLen - 1))
{
tStrComp OutDisp, IndirComps, Remainder;
char *pCompSplit;
/* aeusseres Displacement abspalten, Klammern loeschen: */
p
= strchr(Arg.
str.
p_str, '(');
*p = '\0';
StrCompSplitRef(&OutDisp, &IndirComps, &Arg, p);
OutDispLen = -1;
if (!SplitSize(&OutDisp, &OutDispLen, 7))
return ModNone;
StrCompShorten(&IndirComps, 1);
/* in Komponenten zerteilen: */
CompCnt = 0;
do
{
doklamm = True;
pCompSplit = IndirComps.str.p_str;
do
{
if (*pCompSplit == '[')
doklamm = False;
else if (*pCompSplit == ']')
doklamm = True;
pCompSplit++;
}
while (((!doklamm) || (*pCompSplit != ',')) && (*pCompSplit != '\0'));
if (*pCompSplit == '\0')
{
AdrComps[CompCnt].Comp = IndirComps;
pCompSplit = NULL;
}
else
{
StrCompSplitRef(&AdrComps[CompCnt].Comp, &Remainder, &IndirComps, pCompSplit);
IndirComps = Remainder;
}
KillPrefBlanksStrCompRef(&AdrComps[CompCnt].Comp);
KillPostBlanksStrComp(&AdrComps[CompCnt].Comp);
/* ignore empty component */
if (!AdrComps[CompCnt].Comp.str.p_str[0])
continue;
if (!ClassComp(&AdrComps[CompCnt]))
{
WrStrErrorPos(ErrNum_InvAddrMode, &AdrComps[CompCnt].Comp);
return ModNone;
}
/* Base register position is already occupied and we get another one: */
if ((CompCnt == 1) && ((AdrComps[CompCnt].Art == AReg) || (AdrComps[CompCnt].Art == PC)))
{
/* Index register at "base position": just swap comp 0 & 1, so we get (An,Xi) or (PC,Xi): */
if (AdrComps[0].Art == Index)
SwapAdrComps(&AdrComps[CompCnt], &AdrComps[0]);
/* Address register at "base position" and we add PC: also swap and convert it to index so we get again (PC,Xi): */
else if ((AdrComps[0].Art == AReg) && (AdrComps[CompCnt].Art == PC))
{
SwapAdrComps(&AdrComps[CompCnt], &AdrComps[0]);
AdrCompToIndex(&AdrComps[CompCnt]);
}
/* Otherwise, convert address to general index register. Result may require 68020++ modes: */
else
AdrCompToIndex(&AdrComps[CompCnt]);
CompCnt++;
}
/* a displacement found inside (...), but outside [...]. Explicit
sizes must be consistent, implicitly checked by SplitSize(). */
else if (AdrComps[CompCnt].Art == Disp)
{
if (*OutDisp.str.p_str)
{
WrError(ErrNum_InvAddrMode);
return ModNone;
}
OutDisp = AdrComps[CompCnt].Comp;
OutDispLen = AdrComps[CompCnt].Size;
}
/* no second index */
else if ((AdrComps[CompCnt].Art != Index) && (CompCnt != 0))
{
WrError(ErrNum_InvAddrMode);
return ModNone;
}
else
CompCnt++;
}
while (pCompSplit);
if ((CompCnt > 2) || ((CompCnt > 1) && (AdrComps[0].Art == Index)))
{
WrError(ErrNum_InvAddrMode);
return ModNone;
}
/* 0. Absolut in Klammern (d) */
if (CompCnt == 0)
{
DecodeAbs(&OutDisp, OutDispLen, pResult);
}
/* 1. Variante (An....), d(An....) */
else if (AdrComps[0].Art == AReg)
{
/* 1.1. Variante (An), d(An) */
if (CompCnt == 1)
{
/* 1.1.1. Variante (An) */
if ((*OutDisp.str.p_str == '\0') && ((MModAdrI & Erl) != 0))
{
pResult->AdrPart = 0x10 + AdrComps[0].ANummer;
pResult->AdrMode = ModAdrI;
pResult->Cnt = 0;
goto chk;
}
/* 1.1.2. Variante d(An) */
else
{
/* only try 32-bit displacement if explicitly requested, or 68020++ and no size given */
if (OutDispLen < 0)
DispIntType = CheckFamilyCore(ExtAddrFamilyMask) ? SInt32 : SInt16;
else
DispIntType = (OutDispLen >= 2) ? SInt32 : SInt16;
HVal = EvalStrIntExpression(&OutDisp, DispIntType, &ValOK);
if (!ValOK)
return ModNone;
if (ValOK && (HVal == 0) && ((MModAdrI & Erl) != 0) && (OutDispLen == -1))
{
pResult->AdrPart = 0x10 + AdrComps[0].ANummer;
pResult->AdrMode = ModAdrI;
pResult->Cnt = 0;
goto chk;
}
if (OutDispLen == -1)
OutDispLen = (IsDisp16(HVal)) ? 1 : 2;
switch (OutDispLen)
{
case 1: /* d16(An) */
pResult->AdrPart = 0x28 + AdrComps[0].ANummer;
pResult->AdrMode = ModDAdrI;
pResult->Cnt = 2;
pResult->Vals[0] = HVal & 0xffff;
goto chk;
case 2: /* d32(An) */
pResult->AdrPart = 0x30 + AdrComps[0].ANummer;
pResult->AdrMode = ModAIX;
pResult->Cnt = 6;
pResult->Vals[0] = 0x0170;
pResult->Vals[1] = (HVal >> 16) & 0xffff;
pResult->Vals[2] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
}
}
}
/* 1.2. Variante d(An,Xi) */
else
{
pResult->Vals[0] = (AdrComps[1].INummer << 12) + (Ord(AdrComps[1].Long) << 11) + (AdrComps[1].Scale << 9);
pResult->AdrPart = 0x30 + AdrComps[0].ANummer;
/* only try 32-bit displacement if explicitly requested, or 68020++ and no size given */
if (OutDispLen < 0)
DispIntType = CheckFamilyCore(ExtAddrFamilyMask) ? SInt32 : SInt8;
else
DispIntType = (OutDispLen >= 2) ? SInt32 : (OutDispLen >= 1 ? SInt16 : SInt8);
HVal = EvalStrIntExpression(&OutDisp, DispIntType, &ValOK);
if (ValOK)
switch (OutDispLen)
{
case 0:
if (!IsDisp8(HVal))
{
WrError(ErrNum_OverRange);
ValOK = FALSE;
}
break;
case 1:
if (!IsDisp16(HVal))
{
WrError(ErrNum_OverRange);
ValOK = FALSE;
}
break;
}
if (ValOK)
{
if (OutDispLen == -1)
OutDispLen = GetDispLen(HVal);
switch (OutDispLen)
{
case 0:
pResult->AdrMode = ModAIX;
pResult->Cnt = 2;
pResult->Vals[0] += (HVal & 0xff);
if ((AdrComps[1].Scale != 0) && (!(pCurrCPUProps->SuppFlags & eFlagIdxScaling)))
{
WrStrErrorPos(ErrNum_AddrModeNotSupported, &AdrComps[1].Comp);
ClrAdrVals(pResult);
}
goto chk;
case 1:
pResult->AdrMode = ModAIX;
pResult->Cnt = 4;
pResult->Vals[0] += 0x120;
pResult->Vals[1] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
case 2:
pResult->AdrMode = ModAIX;
pResult->Cnt = 6;
pResult->Vals[0] += 0x130;
pResult->Vals[1] = HVal >> 16;
pResult->Vals[2] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
}
}
}
}
/* 2. Variante d(PC....) */
else if (AdrComps[0].Art == PC)
{
/* 2.1. Variante d(PC) */
if (CompCnt == 1)
{
HVal = EvalStrIntExpressionWithFlags(&OutDisp, Int32, &ValOK, &Flags) - (EProgCounter() + RelPos);
if (!ValOK)
return ModNone;
if (OutDispLen < 0)
{
if (mSymbolQuestionable(Flags) && !CheckFamilyCore(ExtAddrFamilyMask))
HVal &= 0x7fff;
OutDispLen = (IsDisp16(HVal)) ? 1 : 2;
}
switch (OutDispLen)
{
case 1:
pResult->AdrPart = 0x3a;
if (!mSymbolQuestionable(Flags) && !IsDisp16(HVal))
{
WrError(ErrNum_DistTooBig);
return ModNone;
}
pResult->AdrMode = ModPC;
pResult->Cnt = 2;
pResult->Vals[0] = HVal & 0xffff;
goto chk;
case 2:
pResult->AdrPart = 0x3b;
pResult->AdrMode = ModPCIdx;
pResult->Cnt = 6;
pResult->Vals[0] = 0x170;
pResult->Vals[1] = HVal >> 16;
pResult->Vals[2] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
}
}
/* 2.2. Variante d(PC,Xi) */
else
{
pResult->Vals[0] = (AdrComps[1].INummer << 12) + (Ord(AdrComps[1].Long) << 11) + (AdrComps[1].Scale << 9);
HVal = EvalStrIntExpressionWithFlags(&OutDisp, Int32, &ValOK, &Flags) - (EProgCounter() + RelPos);
if (!ValOK)
return ModNone;
if (OutDispLen < 0)
{
if (mSymbolQuestionable(Flags) && !CheckFamilyCore(ExtAddrFamilyMask))
HVal &= 0x7f;
OutDispLen = GetDispLen(HVal);
}
pResult->AdrPart = 0x3b;
switch (OutDispLen)
{
case 0:
if (!mSymbolQuestionable(Flags) && !IsDisp8(HVal))
{
WrError(ErrNum_DistTooBig);
return ModNone;
}
pResult->Vals[0] += (HVal & 0xff);
pResult->Cnt = 2;
pResult->AdrMode = ModPCIdx;
if ((AdrComps[1].Scale != 0) && (!(pCurrCPUProps->SuppFlags & eFlagIdxScaling)))
{
WrStrErrorPos(ErrNum_AddrModeNotSupported, &AdrComps[1].Comp);
ClrAdrVals(pResult);
}
goto chk;
case 1:
if (!mSymbolQuestionable(Flags) && !IsDisp16(HVal))
{
WrError(ErrNum_DistTooBig);
return ModNone;
}
pResult->Vals[0] += 0x120;
pResult->Cnt = 4;
pResult->AdrMode = ModPCIdx;
pResult->Vals[1] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
case 2:
pResult->Vals[0] += 0x130;
pResult->Cnt = 6;
pResult->AdrMode = ModPCIdx;
pResult->Vals[1] = HVal >> 16;
pResult->Vals[2] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
}
}
}
/* 3. Variante (Xi), d(Xi) */
else if (AdrComps[0].Art == Index)
{
pResult->Vals[0] = (AdrComps[0].INummer << 12) + (Ord(AdrComps[0].Long) << 11) + (AdrComps[0].Scale << 9) + 0x180;
pResult->AdrPart = 0x30;
if (*OutDisp.str.p_str == '\0')
{
pResult->Vals[0] = pResult->Vals[0] + 0x0010;
pResult->Cnt = 2;
pResult->AdrMode = ModAIX;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
}
else
{
HVal = EvalStrIntExpression(&OutDisp, (OutDispLen != 1) ? SInt32 : SInt16, &ValOK);
if (ValOK)
{
if (OutDispLen == -1)
OutDispLen = IsDisp16(HVal) ? 1 : 2;
switch (OutDispLen)
{
case 0:
case 1:
pResult->Vals[0] = pResult->Vals[0] + 0x0020;
pResult->Vals[1] = HVal & 0xffff;
pResult->AdrMode = ModAIX;
pResult->Cnt = 4;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
case 2:
pResult->Vals[0] = pResult->Vals[0] + 0x0030;
pResult->AdrMode = ModAIX;
pResult->Cnt = 6;
pResult->Vals[1] = HVal >> 16;
pResult->Vals[2] = HVal & 0xffff;
ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
goto chk;
}
}
}
}
/* 4. Variante indirekt: */
else if (AdrComps[0].Art == indir)
{
/* erst ab 68020 erlaubt */
if (!ACheckFamily((1 << e68KGen3) | (1 << e68KGen2), pArg, pResult))
return ModNone;
/* Unterscheidung Vor- <---> Nachindizierung: */
if (CompCnt == 2)
{
PreInd = False;
AdrComps[2] = AdrComps[1];
}
else
{
PreInd = True;
AdrComps[2].Art = None;
}
/* indirektes Argument herauskopieren: */
StrCompRefRight(&IndirComps, &AdrComps[0].Comp, 1);
StrCompShorten(&IndirComps, 1);
/* Felder loeschen: */
for (i = 0; i < 2; AdrComps[i++].Art = None);
/* indirekten Ausdruck auseinanderfieseln: */
do
{
/* abschneiden & klassifizieren: */
pCompSplit
= strchr(IndirComps.
str.
p_str, ',');
if (!pCompSplit)
OneComp.Comp = IndirComps;
else
{
StrCompSplitRef(&OneComp.Comp, &Remainder, &IndirComps, pCompSplit);
IndirComps = Remainder;
}
KillPrefBlanksStrCompRef(&OneComp.Comp);
KillPostBlanksStrComp(&OneComp.Comp);
if (!ClassComp(&OneComp))
{
WrError(ErrNum_InvAddrMode);
return ModNone;
}
/* passend einsortieren: */
if ((AdrComps[1].Art != None) && (OneComp.Art == AReg))
{
OneComp.Art = Index;
OneComp.INummer = OneComp.ANummer + 8;
OneComp.Long = False;
OneComp.Scale = 0;
}
switch (OneComp.Art)
{
case Disp:
i = 0;
break;
case AReg:
case PC:
i = 1;
break;
case Index:
i = 2;
break;
default:
i = 3;
}
if ((i >= 3) || AdrComps[i].Art != None)
{
WrError(ErrNum_InvAddrMode);
return ModNone;
}
else
AdrComps[i] = OneComp;
}
while (pCompSplit);
/* extension word: 68020 format */
pResult->Vals[0] = 0x100;
/* bit 2 = post-indexed. */
if (!PreInd)
pResult->Vals[0] |= 0x0004;
/* Set post-indexed also for no index register for compatibility with older versions. */
if (AdrComps[2].Art == None)
pResult->Vals[0] |= 0x0040 | 0x0004;
else
pResult->Vals[0] |= (AdrComps[2].INummer << 12) + (Ord(AdrComps[2].Long) << 11) + (AdrComps[2].Scale << 9);
/* 4.1 Variante d([...PC...]...) */
if (AdrComps[1].Art == PC)
{
if (AdrComps[0].Art == None)
{
pResult->AdrPart = 0x3b;
pResult->Vals[0] |= 0x10;
pResult->AdrMode = ModAIX;
pResult->Cnt = 2;
}
else
{
HVal = EvalStrIntExpression(&AdrComps[0].Comp, Int32, &ValOK);
HVal -= EProgCounter() + RelPos;
if (!ValOK)
return ModNone;
switch (AdrComps[0].Size)
{
case -1:
if (IsDisp16(HVal))
goto PCIs16;
else
goto PCIs32;
case 1:
if (!IsDisp16(HVal))
{
WrError(ErrNum_DistTooBig);
return ModNone;
}
PCIs16:
pResult->Vals[1] = HVal & 0xffff;
pResult->AdrPart = 0x3b;
pResult->Vals[0] += 0x20;
pResult->AdrMode = ModAIX;
pResult->Cnt = 4;
break;
case 2:
PCIs32:
pResult->Vals[1] = HVal >> 16;
pResult->Vals[2] = HVal & 0xffff;
pResult->AdrPart = 0x3b;
pResult->Vals[0] += 0x30;
pResult->AdrMode = ModAIX;
pResult->Cnt = 6;
break;
}
}
}
/* 4.2 Variante d([...An...]...) */
else
{
if (AdrComps[1].Art == None)
{
pResult->AdrPart = 0x30;
pResult->Vals[0] += 0x80;
}
else
pResult->AdrPart = 0x30 + AdrComps[1].ANummer;
if (AdrComps[0].Art == None)
{
pResult->AdrMode = ModAIX;
pResult->Cnt = 2;
pResult->Vals[0] += 0x10;
}
else
{
HVal = EvalStrIntExpression(&AdrComps[0].Comp, Int32, &ValOK);
if (!ValOK)
return ModNone;
switch (AdrComps[0].Size)
{
case -1:
if (IsDisp16(HVal))
goto AnIs16;
else
goto AnIs32;
case 1:
if (!IsDisp16(HVal))
{
WrError(ErrNum_DistTooBig);
return ModNone;
}
AnIs16:
pResult->Vals[0] += 0x20;
pResult->Vals[1] = HVal & 0xffff;
pResult->AdrMode = ModAIX;
pResult->Cnt = 4;
break;
case 2:
AnIs32:
pResult->Vals[0] += 0x30;
pResult->Vals[1] = HVal >> 16;
pResult->Vals[2] = HVal & 0xffff;
pResult->AdrMode = ModAIX;
pResult->Cnt = 6;
break;
}
}
}
/* aeusseres Displacement: */
HVal = EvalStrIntExpression(&OutDisp, (OutDispLen == 1) ? SInt16 : SInt32, &ValOK);
if (!ValOK)
{
pResult->AdrMode = ModNone;
pResult->Cnt = 0;
return ModNone;
}
if (OutDispLen == -1)
OutDispLen = IsDisp16(HVal) ? 1 : 2;
if (*OutDisp.str.p_str == '\0')
{
pResult->Vals[0]++;
goto chk;
}
else
switch (OutDispLen)
{
case 0:
case 1:
pResult->Vals[pResult->Cnt >> 1] = HVal & 0xffff;
pResult->Cnt += 2;
pResult->Vals[0] += 2;
break;
case 2:
pResult->Vals[(pResult->Cnt >> 1) ] = HVal >> 16;
pResult->Vals[(pResult->Cnt >> 1) + 1] = HVal & 0xffff;
pResult->Cnt += 4;
pResult->Vals[0] += 3;
break;
}
goto chk;
}
}
/* absolut: */
else
{
if (!SplitSize(&Arg, &OutDispLen, 6))
return ModNone;
DecodeAbs(&Arg, OutDispLen, pResult);
}
chk:
if ((pResult->AdrMode > 0) && (!(Erl & (1 << (pResult->AdrMode - 1)))))
{
WrStrErrorPos(ErrNum_InvAddrMode, pArg);
ClrAdrVals(pResult);
}
return pResult->AdrMode;
}
static Boolean DecodeMACACC(const char *pArg, Word *pResult)
{
/* interprete ACC like ACC0, independent of MAC or EMAC: */
if (!as_strcasecmp(pArg, "ACC"))
*pResult = 0;
else if (!as_strncasecmp
(pArg
, "ACC", 3) && (strlen(pArg
) == 4) && (pArg
[3] >= '0') && (pArg
[3] <= '3'))
*pResult = pArg[3] - '0';
else
return False;
/* allow ACC1..3 only on EMAC: */
if ((!(pCurrCPUProps->SuppFlags & eFlagEMAC)) && *pResult)
return False;
return True;
}
static Boolean DecodeMACReg(const char *pArg, Word *pResult)
{
if (!as_strcasecmp(pArg, "MACSR"))
{
*pResult = 4;
return True;
}
if (!as_strcasecmp(pArg, "MASK"))
{
*pResult = 6;
return True;
}
/* ACCEXT01/23 only on EMAC: */
if (pCurrCPUProps->SuppFlags & eFlagEMAC)
{
if (!as_strcasecmp(pArg, "ACCEXT01"))
{
*pResult = 5;
return True;
}
if (!as_strcasecmp(pArg, "ACCEXT23"))
{
*pResult = 7;
return True;
}
}
return DecodeMACACC(pArg, pResult);
}
static Boolean DecodeRegList(const tStrComp *pArg, Word *Erg)
{
Word h, h2;
Byte z;
char *p, *p2;
String ArgStr;
tStrComp Arg, Remainder, From, To;
StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
StrCompCopy(&Arg, pArg);
*Erg = 0;
do
{
p
= strchr(Arg.
str.
p_str, '/');
if (p)
StrCompSplitRef(&Arg, &Remainder, &Arg, p);
p2
= strchr(Arg.
str.
p_str, '-');
if (!p2)
{
if (DecodeReg(&Arg, &h, False) != eIsReg)
return False;
*Erg |= 1 << h;
}
else
{
StrCompSplitRef(&From, &To, &Arg, p2);
if (!*From.str.p_str || !*To.str.p_str)
return False;
if ((DecodeReg(&From, &h, False) != eIsReg)
|| (DecodeReg(&To, &h2, False) != eIsReg))
return False;
if (h <= h2)
{
for (z = h; z <= h2; z++)
*Erg |= 1 << z;
}
else
{
for (z = h; z <= 15; z++)
*Erg |= 1 << z;
for (z = 0; z <= h2; z++)
*Erg |= 1 << z;
}
}
if (p)
Arg = Remainder;
}
while (p);
return True;
}
static Boolean DecodeMACScale(const tStrComp *pArg, Word *pResult)
{
int l
= strlen(pArg
->str.
p_str);
tStrComp ShiftArg;
Boolean Left = False, OK;
Word ShiftCnt;
/* allow empty argument */
if (!l)
{
*pResult = 0;
return True;
}
/* left or right? */
if (l < 2)
return False;
if (!strncmp(pArg
->str.
p_str, "<<", 2))
Left = True;
else if (!strncmp(pArg
->str.
p_str, ">>", 2))
Left = False;
else
return False;
/* evaluate shift cnt - empty count counts as one */
StrCompRefRight(&ShiftArg, pArg, 2);
KillPrefBlanksStrCompRef(&ShiftArg);
if (!*ShiftArg.str.p_str)
{
ShiftCnt = 1;
OK = True;
}
else
ShiftCnt = EvalStrIntExpression(&ShiftArg, UInt1, &OK);
if (!OK)
return False;
/* codify */
if (ShiftCnt)
*pResult = Left ? 1 : 3;
else
*pResult = 0;
return True;
}
static Boolean SplitMACUpperLower(Word *pResult, tStrComp *pArg)
{
char *pSplit;
tStrComp HalfComp;
*pResult = 0;
pSplit
= strrchr(pArg
->str.
p_str, '.');
if (!pSplit)
{
WrStrErrorPos(ErrNum_InvReg, pArg);
return False;
}
StrCompSplitRef(pArg, &HalfComp, pArg, pSplit);
KillPostBlanksStrComp(pArg);
if (!as_strcasecmp(HalfComp.str.p_str, "L"))
*pResult = 0;
else if (!as_strcasecmp(HalfComp.str.p_str, "U"))
*pResult = 1;
else
{
WrStrErrorPos(ErrNum_InvReg, &HalfComp);
return False;
}
return True;
}
static Boolean SplitMACANDMASK(Word *pResult, tStrComp *pArg)
{
char *pSplit, Save;
tStrComp MaskComp, AddrComp;
*pResult = 0;
pSplit
= strrchr(pArg
->str.
p_str, '&');
if (!pSplit)
return True;
Save = StrCompSplitRef(&AddrComp, &MaskComp, pArg, pSplit);
KillPrefBlanksStrCompRef(&MaskComp);
/* if no MASK argument, be sure to revert pArg to original state: */
if (!strcmp(MaskComp.
str.
p_str, "") || !as_strcasecmp
(MaskComp.
str.
p_str, "MASK"))
{
KillPostBlanksStrComp(&AddrComp);
*pArg = AddrComp;
*pResult = 1;
}
else
*pSplit = Save;
return True;
}
/*-------------------------------------------------------------------------*/
/* Dekodierroutinen: Integer-Einheit */
/* 0=MOVE 1=MOVEA */
static void DecodeMOVE(Word Index)
{
Word MACReg;
unsigned Variant = Index & VariantMask;
if (!ChkArgCnt(2, 2));
else if (!as_strcasecmp(ArgStr[1].str.p_str, "USP"))
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if ((pCurrCPUProps->Family != eColdfire) || CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_B) | (1 << eCfISA_C)))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModAdr, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = 0x4e68 | (AdrResult.AdrPart & 7);
CheckSup();
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "USP"))
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if ((pCurrCPUProps->Family != eColdfire) || CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_B) | (1 << eCfISA_C)))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = 0x4e60 | (AdrResult.AdrPart & 7);
CheckSup();
}
}
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "SR"))
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x40c0 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (pCurrCPUProps->Family != e68KGen1a)
CheckSup();
}
}
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "CCR"))
{
if (*AttrPart.str.p_str && (OpSize > eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else if (!CheckNoFamily(1 << e68KGen1a));
else
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[2], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x42c0 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
else if ((pCurrCPUProps->SuppFlags & eFlagMAC) && (DecodeMACReg(ArgStr[1].str.p_str, &MACReg)))
{
Word DestMACReg;
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if ((MACReg == 4) && (!as_strcasecmp(ArgStr[2].str.p_str, "CCR")))
{
WAsmCode[0] = 0xa9c0;
CodeLen = 2;
}
else if ((MACReg < 4) && DecodeMACReg(ArgStr[2].str.p_str, &DestMACReg) && (DestMACReg < 4) && (pCurrCPUProps->SuppFlags & eFlagEMAC))
{
WAsmCode[0] = 0xa110 | (DestMACReg << 9) | (MACReg << 0);
CodeLen = 2;
}
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = 0xa180 | (AdrResult.AdrPart & 15) | (MACReg << 9);
}
}
}
else if ((pCurrCPUProps->SuppFlags & eFlagMAC) && (DecodeMACReg(ArgStr[2].str.p_str, &MACReg)))
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModAdr | MModImm, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0xa100 | (AdrResult.AdrPart) | (MACReg << 9);
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "SR"))
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModImm | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs), &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x46c0 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CheckSup();
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "CCR"))
{
if (*AttrPart.str.p_str && (OpSize > eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModImm | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs), &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x44c0 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
else
{
if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
DecodeAdr(&ArgStr[1], ((Variant == I_Variant) ? 0 : MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs) | MModImm, &AdrResult);
/* Is An as source in byte mode allowed for ColdFire? No corresponding footnote in CFPRM... */
if ((AdrResult.AdrMode == ModAdr) && (OpSize == eSymbolSize8Bit) && (pCurrCPUProps->Family != eColdfire)) WrError(ErrNum_InvOpSize);
else if (AdrResult.AdrMode != ModNone)
{
unsigned SrcAdrNum = AdrResult.AdrMode;
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (OpSize == eSymbolSize8Bit)
WAsmCode[0] = 0x1000;
else if (OpSize == eSymbolSize16Bit)
WAsmCode[0] = 0x3000;
else
WAsmCode[0] = 0x2000;
WAsmCode[0] |= AdrResult.AdrPart;
DecodeAdr(&ArgStr[2], ((Variant == A_Variant) ? 0 : MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs) | MModAdr, &AdrResult);
if ((AdrResult.AdrMode == ModAdr) && (OpSize == eSymbolSize8Bit))
{
CodeLen = 0;
WrError(ErrNum_InvOpSize);
}
else if (AdrResult.AdrMode == ModNone)
CodeLen = 0;
else
{
Boolean CombinationOK;
/* ColdFire does not allow all combinations of src+dest: */
if (pCurrCPUProps->Family == eColdfire)
switch (SrcAdrNum)
{
case ModData: /* Dn */
case ModAdr: /* An */
case ModAdrI: /* (An) */
case ModPost: /* (An)+ */
case ModPre: /* -(An) */
CombinationOK = True;
break;
case ModDAdrI: /* (d16,An) */
case ModPC: /* (d16,PC) */
CombinationOK = (AdrResult.AdrMode != ModAIX) /* no (d8,An,Xi) */
&& (AdrResult.AdrMode != ModAbs); /* no (xxx).W/L */
break;
case ModAIX: /* (d8,An,Xi) */
case ModPCIdx: /* (d8,PC,Xi) */
case ModAbs: /* (xxx).W/L */
CombinationOK = (AdrResult.AdrMode != ModDAdrI) /* no (d16,An) */
&& (AdrResult.AdrMode != ModAIX) /* no (d8,An,Xi) */
&& (AdrResult.AdrMode != ModAbs); /* no (xxx).W/L */
break;
case ModImm: /* #xxx */
if (AdrResult.AdrMode == ModDAdrI) /* (d16,An) OK for 8/16 bit starting with ISA B */
CombinationOK = (pCurrCPUProps->CfISA >= eCfISA_B) && (OpSize <= eSymbolSize16Bit);
else
CombinationOK = (AdrResult.AdrMode != ModAIX) /* no (d8,An,Xi) */
&& (AdrResult.AdrMode != ModAbs); /* no (xxx).W/L */
break;
default: /* should not occur */
CombinationOK = False;
}
else
CombinationOK = True;
if (!CombinationOK)
{
WrError(ErrNum_InvAddrMode);
CodeLen = 0;
}
else
{
AdrResult.AdrPart = ((AdrResult.AdrPart & 7) << 3) | (AdrResult.AdrPart >> 3);
WAsmCode[0] |= AdrResult.AdrPart << 6;
CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
CodeLen += AdrResult.Cnt;
}
}
}
}
}
}
static void DecodeLEA(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(2, 2));
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModAdr, &AdrResult))
{
OpSize = eSymbolSize8Bit;
WAsmCode[0] = 0x41c0 | ((AdrResult.AdrPart & 7) << 9);
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
{
WAsmCode[0] |= AdrResult.AdrPart;
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
}
/* 0=ASR 1=ASL 2=LSR 3=LSL 4=ROXR 5=ROXL 6=ROR 7=ROL */
static void DecodeShift(Word Index)
{
Boolean ValOK;
Byte HVal8;
Word LFlag = (Index >> 2), Op = Index & 3;
if (!ChkArgCnt(1, 2));
else if ((*OpPart.str.p_str == 'R') && (!CheckNoFamily(1 << eColdfire)));
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[ArgCnt], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult) == ModData)
{
if (CheckColdSize())
{
WAsmCode[0] = 0xe000 | AdrResult.AdrPart | (Op << 3) | (OpSize << 6) | (LFlag << 8);
OpSize = eSymbolSizeShiftCnt;
if (ArgCnt == 2)
DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult);
else
{
AdrResult.AdrMode = ModImm;
AdrResult.Vals[0] = 1;
}
if ((AdrResult.AdrMode == ModData) || ((AdrResult.AdrMode == ModImm) && (Lo(AdrResult.Vals[0]) >= 1) && (Lo(AdrResult.Vals[0]) <= 8)))
{
CodeLen = 2;
WAsmCode[0] |= (AdrResult.AdrMode == ModData) ? 0x20 | (AdrResult.AdrPart << 9) : ((AdrResult.Vals[0] & 7) << 9);
}
else
WrStrErrorPos(ErrNum_InvShiftArg, &ArgStr[1]);
}
}
else if (AdrResult.AdrMode != ModNone)
{
if (pCurrCPUProps->Family == eColdfire) WrError(ErrNum_InvAddrMode);
else
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0xe0c0 | AdrResult.AdrPart | (Op << 9) | (LFlag << 8);
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (2 == ArgCnt)
{
HVal8 = EvalStrIntExpressionOffs(&ArgStr[1], !!(*ArgStr[1].str.p_str == '#'), Int8, &ValOK);
}
else
{
HVal8 = 1;
ValOK = True;
}
if ((ValOK) && (HVal8 == 1))
CodeLen = 2 + AdrResult.Cnt;
else
WrStrErrorPos(ErrNum_Only1, &ArgStr[1]);
}
}
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeADDQSUBQ(Word Index)
* \brief Handle ADDQ/SUBQ Instructions
* \param Index ADDQ=0 SUBQ=1
* ------------------------------------------------------------------------ */
static void DecodeADDQSUBQ(Word Index)
{
LongWord ImmVal;
Boolean ValOK;
tSymbolFlags Flags;
tAdrResult AdrResult;
if (!CheckColdSize())
return;
if (!ChkArgCnt(2, 2))
return;
if (!DecodeAdr(&ArgStr[2], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
return;
if ((ModAdr == AdrResult.AdrMode) && (eSymbolSize8Bit == OpSize))
{
WrError(ErrNum_InvOpSize);
return;
}
WAsmCode[0] = 0x5000 | AdrResult.AdrPart | (OpSize << 6) | (Index << 8);
CopyAdrVals(WAsmCode + 1, &AdrResult);
ImmVal = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '#'), UInt32, &ValOK, &Flags);
if (mFirstPassUnknownOrQuestionable(Flags))
ImmVal = 1;
if (ValOK && ((ImmVal < 1) || (ImmVal > 8)))
{
WrError(ErrNum_Range18);
ValOK = False;
}
if (ValOK)
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] |= (ImmVal & 7) << 9;
}
}
/* 0=SUBX 1=ADDX */
static void DecodeADDXSUBX(Word Index)
{
if (CheckColdSize())
{
if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModPre, &AdrResult))
{
WAsmCode[0] = 0x9100 | (OpSize << 6) | (AdrResult.AdrPart & 7) | (Index << 14);
if (AdrResult.AdrMode == ModPre)
WAsmCode[0] |= 8;
if (DecodeAdr(&ArgStr[2], 1 << (AdrResult.AdrMode - 1), &AdrResult))
{
CodeLen = 2;
WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
}
}
}
}
}
static void DecodeCMPM(Word Index)
{
UNUSED(Index);
if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2)
&& CheckNoFamily(1 << eColdfire))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModPost, &AdrResult) == ModPost)
{
WAsmCode[0] = 0xb108 | (OpSize << 6) | (AdrResult.AdrPart & 7);
if (DecodeAdr(&ArgStr[2], MModPost, &AdrResult) == ModPost)
{
WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
CodeLen = 2;
}
}
}
}
/* 0=SUB 1=CMP 2=ADD +4=..I +8=..A */
static void DecodeADDSUBCMP(Word Index)
{
Word Op = Index & 3, Reg;
unsigned Variant = Index & VariantMask;
Word DestMask, SrcMask;
Boolean OpSizeOK;
if (I_Variant == Variant)
SrcMask = MModImm;
else
SrcMask = MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm;
if (A_Variant == Variant)
DestMask = MModAdr;
else
{
DestMask = MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs;
/* Since CMP only reads operands, PC-relative addressing is also
allowed for the second operand on 68020++ */
if ((as_toupper(*OpPart.str.p_str) == 'C')
&& (pCurrCPUProps->Family > e68KGen1b))
DestMask |= MModPC | MModPCIdx;
}
/* ColdFire ISA B ff. allows 8/16 bit operand size of CMP: */
if (OpSize > eSymbolSize32Bit)
OpSizeOK = False;
else if (OpSize == eSymbolSize32Bit)
OpSizeOK = True;
else
OpSizeOK = (pCurrCPUProps->Family != eColdfire)
|| ((pCurrCPUProps->CfISA >= eCfISA_B) && (Op == 1));
if (!OpSizeOK) WrError(ErrNum_InvOpSize);
else
{
if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
switch (DecodeAdr(&ArgStr[2], DestMask, &AdrResult))
{
case ModAdr: /* ADDA/SUBA/CMPA ? */
if (OpSize == eSymbolSize8Bit) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = 0x90c0 | ((AdrResult.AdrPart & 7) << 9) | (Op << 13);
if (OpSize == eSymbolSize32Bit) WAsmCode[0] |= 0x100;
if (DecodeAdr(&ArgStr[1], SrcMask, &AdrResult))
{
WAsmCode[0] |= AdrResult.AdrPart;
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
break;
case ModData: /* ADD/SUB/CMP <ea>,Dn ? */
WAsmCode[0] = 0x9000 | (OpSize << 6) | ((Reg = AdrResult.AdrPart) << 9) | (Op << 13);
DecodeAdr(&ArgStr[1], SrcMask, &AdrResult);
/* CMP.B An,Dn allowed for Coldfire? */
if ((AdrResult.AdrMode == ModAdr) && (OpSize == eSymbolSize8Bit) && (pCurrCPUProps->Family != eColdfire)) WrError(ErrNum_InvOpSize);
if (AdrResult.AdrMode != ModNone)
{
if ((AdrResult.AdrMode == ModImm) && (Variant == I_Variant))
{
if (Op == 1) Op = 8;
WAsmCode[0] = 0x400 | (OpSize << 6) | (Op << 8) | Reg;
}
else
WAsmCode[0] |= AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CodeLen = 2 + AdrResult.Cnt;
}
break;
case ModNone:
break;
default: /* CMP/ADD/SUB <ea>, Dn */
if (DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult) == ModImm) /* ADDI/SUBI/CMPI ? */
{
/* we have to set the PC offset before we decode the destination operand. Luckily,
this is only needed afterwards for an immediate source operand, so we know the
# of words ahead: */
if (*ArgStr[1].str.p_str == '#')
RelPos += (OpSize == eSymbolSize32Bit) ? 4 : 2;
if (Op == 1) Op = 8;
WAsmCode[0] = 0x400 | (OpSize << 6) | (Op << 8);
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (DecodeAdr(&ArgStr[2], (pCurrCPUProps->Family == eColdfire) ? (Word)MModData : DestMask, &AdrResult))
{
WAsmCode[0] |= AdrResult.AdrPart;
CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
CodeLen += AdrResult.Cnt;
}
else
CodeLen = 0;
}
else if (AdrResult.AdrMode != ModNone) /* ADD Dn,<EA> ? */
{
if (Op == 1) WrError(ErrNum_InvCmpMode);
else
{
WAsmCode[0] = 0x9100 | (OpSize << 6) | (AdrResult.AdrPart << 9) | (Op << 13);
if (DecodeAdr(&ArgStr[2], DestMask, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 1, &AdrResult);
WAsmCode[0] |= AdrResult.AdrPart;
}
}
}
}
}
}
}
/* 0=OR 1=AND +4=..I */
static void DecodeANDOR(Word Index)
{
Word Op = Index & 3, Reg;
char Variant = Index & VariantMask;
tAdrResult AdrResult;
if (!ChkArgCnt(2, 2));
else if (CheckColdSize())
{
if (!as_strcasecmp(ArgStr[2].str.p_str, "CCR")) /* AND #...,CCR */
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
else if (!(pCurrCPUProps->SuppFlags & eFlagLogCCR)) WrError(ErrNum_InstructionNotSupported);
{
WAsmCode[0] = 0x003c | (Op << 9);
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
CodeLen = 4;
WAsmCode[1] = AdrResult.Vals[0];
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "SR")) /* AND #...,SR */
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else if (CheckNoFamily(1 << eColdfire))
{
WAsmCode[0] = 0x007c | (Op << 9);
OpSize = eSymbolSize16Bit;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
CodeLen = 4;
WAsmCode[1] = AdrResult.Vals[0];
CheckSup();
}
}
}
else
{
DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult);
if (AdrResult.AdrMode == ModData) /* AND <EA>,Dn */
{
Reg = AdrResult.AdrPart;
WAsmCode[0] = 0x8000 | (OpSize << 6) | (Reg << 9) | (Op << 14);
if (DecodeAdr(&ArgStr[1], ((Variant == I_Variant) ? 0 : MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs) | MModImm, &AdrResult))
{
if ((AdrResult.AdrMode == ModImm) && (Variant == I_Variant))
WAsmCode[0] = (OpSize << 6) | (Op << 9) | Reg;
else
WAsmCode[0] |= AdrResult.AdrPart;
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
else if (AdrResult.AdrMode != ModNone) /* AND ...,<EA> */
{
if (DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult) == ModImm) /* AND #..,<EA> */
{
WAsmCode[0] = (OpSize << 6) | (Op << 9);
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] |= AdrResult.AdrPart;
CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
CodeLen += AdrResult.Cnt;
}
else
CodeLen = 0;
}
else if (AdrResult.AdrMode != ModNone) /* AND Dn,<EA> ? */
{
WAsmCode[0] = 0x8100 | (OpSize << 6) | (AdrResult.AdrPart << 9) | (Op << 14);
if (DecodeAdr(&ArgStr[2], MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
WAsmCode[0] |= AdrResult.AdrPart;
}
}
}
}
}
}
/* 0=EOR 4=EORI */
static void DecodeEOR(Word Index)
{
unsigned Variant = Index | VariantMask;
tAdrResult AdrResult;
if (!ChkArgCnt(2, 2));
else if (!as_strcasecmp(ArgStr[2].str.p_str, "CCR"))
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
else if (CheckNoFamily(1 << eColdfire))
{
WAsmCode[0] = 0xa3c;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
CodeLen = 4;
WAsmCode[1] = AdrResult.Vals[0];
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "SR"))
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else if (CheckNoFamily(1 << eColdfire))
{
WAsmCode[0] = 0xa7c;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
CodeLen = 4;
WAsmCode[1] = AdrResult.Vals[0];
CheckSup();
}
}
}
else if (CheckColdSize())
{
if (DecodeAdr(&ArgStr[1], ((Variant == I_Variant) ? 0 : MModData) | MModImm, &AdrResult) == ModData)
{
WAsmCode[0] = 0xb100 | (AdrResult.AdrPart << 9) | (OpSize << 6);
if (DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
WAsmCode[0] |= AdrResult.AdrPart;
}
}
else if (AdrResult.AdrMode == ModImm)
{
WAsmCode[0] = 0x0a00 | (OpSize << 6);
CopyAdrVals(WAsmCode + 1, &AdrResult);
CodeLen = 2 + AdrResult.Cnt;
if (DecodeAdr(&ArgStr[2], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
{
CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
CodeLen += AdrResult.Cnt;
WAsmCode[0] |= AdrResult.AdrPart;
}
else CodeLen = 0;
}
}
}
static void DecodePEA(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_UseLessAttr);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x4840 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
static void DecodeCLRTST(Word IsTST)
{
if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
Word w1 = MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs;
tAdrResult AdrResult;
switch (pCurrCPUProps->Family)
{
case eCPU32:
case e68KGen2:
case e68KGen3:
if (IsTST)
{
w1 |= MModPC | MModPCIdx | MModImm;
if (OpSize != eSymbolSize8Bit)
w1 |= MModAdr;
}
break;
default:
break;
}
if (DecodeAdr(&ArgStr[1], w1, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x4200 | (IsTST << 11) | (OpSize << 6) | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
/* 0=JSR 1=JMP */
static void DecodeJSRJMP(Word Index)
{
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x4e80 | (Index << 6) | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
/* 0=TAS 1=NBCD */
static void DecodeNBCDTAS(Word Index)
{
Boolean Allowed;
/* TAS is allowed on ColdFire ISA B ff. ... */
if (pCurrCPUProps->Family != eColdfire)
Allowed = True;
else
Allowed = Index ? False : (pCurrCPUProps->CfISA >= eCfISA_B);
if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
else if (!Allowed) WrError(ErrNum_InstructionNotSupported);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
/* ...but not on data register: */
if (DecodeAdr(&ArgStr[1], ((pCurrCPUProps->Family == eColdfire) ? 0 : MModData) | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = (Index == 1) ? 0x4800 : 0x4ac0;
WAsmCode[0] |= AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
/* 0=NEGX 2=NEG 3=NOT */
static void DecodeNEGNOT(Word Index)
{
if (ChkArgCnt(1, 1)
&& CheckColdSize())
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], (pCurrCPUProps->Family == eColdfire) ? MModData : (MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0x4000 | (Index << 9) | (OpSize << 6) | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
static void DecodeSWAP(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = 0x4840 | AdrResult.AdrPart;
}
}
}
static void DecodeUNLK(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = 0x4e58 | AdrResult.AdrPart;
}
}
}
static void DecodeEXT(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if ((OpSize == eSymbolSize8Bit) || (OpSize > eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult) == ModData)
{
WAsmCode[0] = 0x4880 | AdrResult.AdrPart | (((Word)OpSize - 1) << 6);
CodeLen = 2;
}
}
}
static void DecodeWDDATA(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (CheckFamily(1 << eColdfire))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] = 0xf400 + (OpSize << 6) + AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CodeLen = 2 + AdrResult.Cnt;
CheckSup();
}
}
}
static void DecodeWDEBUG(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(1, 1)
&& CheckFamily(1 << eColdfire)
&& CheckColdSize())
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI, &AdrResult))
{
WAsmCode[0] = 0xfbc0 + AdrResult.AdrPart;
WAsmCode[1] = 0x0003;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
CheckSup();
}
}
}
static void DecodeFixed(Word Index)
{
FixedOrder *FixedZ = FixedOrders + Index;
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (ChkArgCnt(0, 0)
&& CheckFamily(FixedZ->FamilyMask))
{
CodeLen = 2;
WAsmCode[0] = FixedZ->Code;
if (FixedZ->MustSup)
CheckSup();
}
}
static void DecodeMOVEM(Word Index)
{
int z;
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if ((OpSize < eSymbolSize16Bit) || (OpSize > eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if ((pCurrCPUProps->Family == eColdfire) && (OpSize == 1)) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
RelPos = 4;
if (DecodeRegList(&ArgStr[2], WAsmCode + 1))
{
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModPost | MModAIX | MModPC | MModPCIdx | MModAbs), &AdrResult))
{
WAsmCode[0] = 0x4c80 | AdrResult.AdrPart | ((OpSize - 1) << 6);
CodeLen = 4 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 2, &AdrResult);
}
}
else if (DecodeRegList(&ArgStr[1], WAsmCode + 1))
{
if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModPre | MModAIX | MModAbs), &AdrResult))
{
WAsmCode[0] = 0x4880 | AdrResult.AdrPart | ((OpSize - 1) << 6);
CodeLen = 4 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 2, &AdrResult);
if (AdrResult.AdrMode == ModPre)
{
Word Tmp = WAsmCode[1];
WAsmCode[1] = 0;
for (z = 0; z < 16; z++)
{
WAsmCode[1] = (WAsmCode[1] << 1) + (Tmp & 1);
Tmp >>= 1;
}
}
}
}
else WrError(ErrNum_InvRegList);
}
}
static void DecodeMOVEQ(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if ((*AttrPart.str.p_str) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (*ArgStr[1].str.p_str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
{
Boolean OK;
tSymbolFlags Flags;
LongWord Value;
WAsmCode[0] = 0x7000 | (AdrResult.AdrPart << 9);
Value = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, Int32, &OK, &Flags);
if (mFirstPassUnknown(Flags))
Value &= 0x7f;
else if ((Value > 0xff) && (Value < 0xffffff80ul))
WrStrErrorPos((Value & 0x80000000ul) ? ErrNum_UnderRange : ErrNum_OverRange, &ArgStr[1]);
else
{
if ((Value >= 0x80) && (Value <= 0xff))
{
char str[40];
LargeWord v1 = Value, v2 = Value | 0xffffff00ul;
as_snprintf(str, sizeof(str), "%llx -> %llx", v1, v2);
WrXErrorPos(ErrNum_SignExtension, str, &ArgStr[1].Pos);
}
CodeLen = 2;
WAsmCode[0] |= Value & 0xff;
}
}
}
}
static void DecodeSTOP(Word Index)
{
Word HVal;
Boolean ValOK;
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(1, 1));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
else
{
HVal = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int16, &ValOK);
if (ValOK)
{
CodeLen = 4;
WAsmCode[0] = 0x4e72;
WAsmCode[1] = HVal;
CheckSup();
}
}
}
static void DecodeLPSTOP(Word Index)
{
Word HVal;
Boolean ValOK;
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(1, 1));
else if (!CheckFamily(1 << eCPU32));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
else
{
HVal = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int16, &ValOK);
if (ValOK)
{
CodeLen = 6;
WAsmCode[0] = 0xf800;
WAsmCode[1] = 0x01c0;
WAsmCode[2] = HVal;
CheckSup();
}
}
}
static void DecodeTRAP(Word Index)
{
Byte HVal8;
Boolean ValOK;
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(1, 1));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
else
{
HVal8 = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int4, &ValOK);
if (ValOK)
{
CodeLen = 2;
WAsmCode[0] = 0x4e40 + (HVal8 & 15);
}
}
}
static void DecodeBKPT(Word Index)
{
Byte HVal8;
Boolean ValOK;
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(1, 1));
else if (!CheckNoFamily((1 << e68KGen1a) | (1 << eColdfire)));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
else
{
HVal8 = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt3, &ValOK);
if (ValOK)
{
CodeLen = 2;
WAsmCode[0] = 0x4848 + (HVal8 & 7);
}
}
UNUSED(Index);
}
static void DecodeRTD(Word Index)
{
Word HVal;
Boolean ValOK;
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(1, 1));
else if (!CheckNoFamily((1 << e68KGen1a) | (1 << eColdfire)));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
else
{
HVal = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int16, &ValOK);
if (ValOK)
{
CodeLen = 4;
WAsmCode[0] = 0x4e74;
WAsmCode[1] = HVal;
}
}
}
static void DecodeEXG(Word Index)
{
Word HReg;
UNUSED(Index);
if ((*AttrPart.str.p_str) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2)
&& CheckNoFamily(1 << eColdfire))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult) == ModData)
{
WAsmCode[0] = 0xc100 | (AdrResult.AdrPart << 9);
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult) == ModData)
{
WAsmCode[0] |= 0x40 | AdrResult.AdrPart;
CodeLen = 2;
}
else if (AdrResult.AdrMode == ModAdr)
{
WAsmCode[0] |= 0x88 | (AdrResult.AdrPart & 7);
CodeLen = 2;
}
}
else if (AdrResult.AdrMode == ModAdr)
{
WAsmCode[0] = 0xc100;
HReg = AdrResult.AdrPart & 7;
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult) == ModData)
{
WAsmCode[0] |= 0x88 | (AdrResult.AdrPart << 9) | HReg;
CodeLen = 2;
}
else
{
WAsmCode[0] |= 0x48 | (HReg << 9) | (AdrResult.AdrPart & 7);
CodeLen = 2;
}
}
}
}
static void DecodeMOVE16(Word Index)
{
Word z, z2, w1, w2;
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (ChkArgCnt(2, 2)
&& CheckFamily(1 << e68KGen3))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModPost | MModAdrI | MModAbs, &AdrResult))
{
w1 = AdrResult.AdrMode;
z = AdrResult.AdrPart & 7;
if ((w1 == ModAbs) && (AdrResult.Cnt == 2))
{
AdrResult.Vals[1] = AdrResult.Vals[0];
AdrResult.Vals[0] = 0 - (AdrResult.Vals[1] >> 15);
}
if (DecodeAdr(&ArgStr[2], MModPost | MModAdrI | MModAbs, &AdrResult))
{
w2 = AdrResult.AdrMode;
z2 = AdrResult.AdrPart & 7;
if ((w2 == ModAbs) && (AdrResult.Cnt == 2))
{
AdrResult.Vals[1] = AdrResult.Vals[0];
AdrResult.Vals[0] = 0 - (AdrResult.Vals[1] >> 15);
}
if ((w1 == ModPost) && (w2 == ModPost))
{
WAsmCode[0] = 0xf620 + z;
WAsmCode[1] = 0x8000 + (z2 << 12);
CodeLen = 4;
}
else
{
WAsmCode[1] = AdrResult.Vals[0];
WAsmCode[2] = AdrResult.Vals[1];
CodeLen = 6;
if ((w1 == ModPost) && (w2 == ModAbs))
WAsmCode[0] = 0xf600 + z;
else if ((w1 == ModAbs) && (w2 == ModPost))
WAsmCode[0] = 0xf608 + z2;
else if ((w1 == ModAdrI) && (w2 == ModAbs))
WAsmCode[0] = 0xf610 + z;
else if ((w1 == ModAbs) && (w2 == ModAdrI))
WAsmCode[0] = 0xf618 + z2;
else
{
WrError(ErrNum_InvAddrMode);
CodeLen = 0;
}
}
}
}
}
}
static void DecodeCacheAll(Word Index)
{
Word w1;
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(1, 1));
else if (!CheckFamily(1 << e68KGen3));
else if (!CodeCache(ArgStr[1].str.p_str, &w1)) WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
else
{
WAsmCode[0] = 0xf418 + (w1 << 6) + (Index << 5);
CodeLen = 2;
CheckSup();
}
}
static void DecodeCache(Word Index)
{
Word w1;
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!ChkArgCnt(2, 2));
else if (!CheckFamily(1 << e68KGen3));
else if (!CodeCache(ArgStr[1].str.p_str, &w1)) WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModAdrI, &AdrResult))
{
WAsmCode[0] = 0xf400 + (w1 << 6) + (Index << 3) + (AdrResult.AdrPart & 7);
CodeLen = 2;
CheckSup();
}
}
}
static void DecodeMUL_DIV(Word Code)
{
tAdrResult AdrResult;
if (!ChkArgCnt(2, 2));
else if ((*OpPart.str.p_str == 'D') && !CheckNoFamily(1 << eColdfire));
else if (OpSize == eSymbolSize16Bit)
{
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
{
WAsmCode[0] = 0x80c0 | (AdrResult.AdrPart << 9) | (Code & 0x0100);
if (!(Code & 1))
WAsmCode[0] |= 0x4000;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
{
WAsmCode[0] |= AdrResult.AdrPart;
CodeLen = 2 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
else if (OpSize == eSymbolSize32Bit)
{
Word w1, w2;
Boolean OK;
if (strchr(ArgStr
[2].
str.
p_str, ':'))
OK = DecodeRegPair(&ArgStr[2], &w1, &w2);
else
{
OK = DecodeReg(&ArgStr[2], &w1, True) && (w1 < 8);
w2 = w1;
}
if (!OK) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[2]);
else
{
WAsmCode[1] = w1 | (w2 << 12) | ((Code & 0x0100) << 3);
RelPos = 4;
if (w1 != w2)
WAsmCode[1] |= 0x400;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
{
WAsmCode[0] = 0x4c00 + AdrResult.AdrPart + (Lo(Code) << 6);
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32) | ((w1 == w2) ? (1 << eColdfire) : 0));
}
}
}
else
WrError(ErrNum_InvOpSize);
}
static void DecodeDIVL(Word Index)
{
Word w1, w2;
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize32Bit;
if (!ChkArgCnt(2, 2));
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32)));
else if (OpSize != eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (!DecodeRegPair(&ArgStr[2], &w1, &w2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[2]);
else
{
tAdrResult AdrResult;
RelPos = 4;
WAsmCode[1] = w1 | (w2 << 12) | (Index << 11);
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
{
WAsmCode[0] = 0x4c40 + AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
}
}
static void DecodeASBCD(Word Index)
{
if ((OpSize != eSymbolSize8Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2)
&& CheckNoFamily(1 << eColdfire))
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModData | MModPre, &AdrResult))
{
WAsmCode[0] = 0x8100 | (AdrResult.AdrPart & 7) | (Index << 14) | ((AdrResult.AdrMode == ModPre) ? 8 : 0);
if (DecodeAdr(&ArgStr[2], 1 << (AdrResult.AdrMode - 1), &AdrResult))
{
CodeLen = 2;
WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
}
}
}
}
static void DecodeCHK(Word Index)
{
UNUSED(Index);
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2)
&& CheckNoFamily(1 << eColdfire))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
{
WAsmCode[0] = 0x4000 | AdrResult.AdrPart | ((4 - OpSize) << 7);
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult) == ModData)
WAsmCode[0] |= WAsmCode[0] | (AdrResult.AdrPart << 9);
else
CodeLen = 0;
}
}
}
static void DecodeLINK(Word Index)
{
UNUSED(Index);
if (!*AttrPart.str.p_str && (pCurrCPUProps->Family == eColdfire)) OpSize = eSymbolSize16Bit;
if ((OpSize < 1) || (OpSize > 2)) WrError(ErrNum_InvOpSize);
else if ((OpSize == eSymbolSize32Bit) && !CheckFamily((1 << eCPU32) | (1 << e68KGen2) | (1 << e68KGen3)));
else if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
{
WAsmCode[0] = (OpSize == eSymbolSize16Bit) ? 0x4e50 : 0x4808;
WAsmCode[0] += AdrResult.AdrPart & 7;
if (DecodeAdr(&ArgStr[2], MModImm, &AdrResult) == ModImm)
{
CodeLen = 2 + AdrResult.Cnt;
memcpy(WAsmCode
+ 1, AdrResult.
Vals, AdrResult.
Cnt);
}
}
}
}
static void DecodeMOVEP(Word Index)
{
UNUSED(Index);
if ((OpSize == eSymbolSize8Bit) || (OpSize > eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2)
&& CheckNoFamily(1 << eColdfire))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModDAdrI, &AdrResult) == ModData)
{
WAsmCode[0] = 0x188 | ((OpSize - 1) << 6) | (AdrResult.AdrPart << 9);
if (DecodeAdr(&ArgStr[2], MModDAdrI, &AdrResult) == ModDAdrI)
{
WAsmCode[0] |= AdrResult.AdrPart & 7;
CodeLen = 4;
WAsmCode[1] = AdrResult.Vals[0];
}
}
else if (AdrResult.AdrMode == ModDAdrI)
{
WAsmCode[0] = 0x108 | ((OpSize - 1) << 6) | (AdrResult.AdrPart & 7);
WAsmCode[1] = AdrResult.Vals[0];
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult) == ModData)
{
WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
CodeLen = 4;
}
}
}
}
static void DecodeMOVEC(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
if (DecodeCtrlReg(ArgStr[1].str.p_str, WAsmCode + 1))
{
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
{
CodeLen = 4;
WAsmCode[0] = 0x4e7a;
WAsmCode[1] |= AdrResult.AdrPart << 12;
CheckSup();
}
}
else if (DecodeCtrlReg(ArgStr[2].str.p_str, WAsmCode + 1))
{
if (DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
{
CodeLen = 4;
WAsmCode[0] = 0x4e7b;
WAsmCode[1] |= AdrResult.AdrPart << 12; CheckSup();
}
}
else
WrError(ErrNum_InvCtrlReg);
}
}
static void DecodeMOVES(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (CheckNoFamily((1 << e68KGen1a) | (1 << eColdfire)))
{
tAdrResult AdrResult;
switch (DecodeAdr(&ArgStr[1], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
case ModData:
case ModAdr:
{
WAsmCode[1] = 0x800 | (AdrResult.AdrPart << 12);
if (DecodeAdr(&ArgStr[2], MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] = 0xe00 | AdrResult.AdrPart | (OpSize << 6);
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CheckSup();
}
break;
}
case ModNone:
break;
default:
{
WAsmCode[0] = 0xe00 | AdrResult.AdrPart | (OpSize << 6);
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
{
WAsmCode[1] = AdrResult.AdrPart << 12;
CheckSup();
}
else
CodeLen = 0;
}
}
}
}
static void DecodeCALLM(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!(pCurrCPUProps->SuppFlags & eFlagCALLM_RTM)) WrError(ErrNum_InstructionNotSupported);
else if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
WAsmCode[1] = AdrResult.Vals[0];
RelPos = 4;
if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
{
WAsmCode[0] = 0x06c0 + AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
}
}
}
static void DecodeCAS(Word Index)
{
UNUSED(Index);
if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(3, 3)
&& CheckFamily((1 << e68KGen3) | (1 << e68KGen2)))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
WAsmCode[1] = AdrResult.AdrPart;
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
{
RelPos = 4;
WAsmCode[1] += (((Word)AdrResult.AdrPart) << 6);
if (DecodeAdr(&ArgStr[3], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] = 0x08c0 + AdrResult.AdrPart + (((Word)OpSize + 1) << 9);
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
}
}
}
}
static void DecodeCAS2(Word Index)
{
Word w1, w2;
UNUSED(Index);
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(3, 3));
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
else if (!DecodeRegPair(&ArgStr[1], WAsmCode + 1, WAsmCode + 2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[1]);
else if (!DecodeRegPair(&ArgStr[2], &w1, &w2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[2]);
else
{
WAsmCode[1] += (w1 << 6);
WAsmCode[2] += (w2 << 6);
if (!CodeIndRegPair(&ArgStr[3], &w1, &w2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[3]);
else
{
WAsmCode[1] += (w1 << 12);
WAsmCode[2] += (w2 << 12);
WAsmCode[0] = 0x0cfc + (((Word)OpSize - 1) << 9);
CodeLen = 6;
}
}
}
static void DecodeCMPCHK2(Word Index)
{
if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32)));
else if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
{
RelPos = 4;
WAsmCode[1] = (((Word)AdrResult.AdrPart) << 12) | (Index << 11);
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
{
WAsmCode[0] = 0x00c0 + (((Word)OpSize) << 9) + AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
}
}
}
static void DecodeEXTB(Word Index)
{
UNUSED(Index);
if ((OpSize != eSymbolSize32Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32)));
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
WAsmCode[0] = 0x49c0 + AdrResult.AdrPart;
CodeLen = 2;
}
}
}
static void DecodePACK(Word Index)
{
if (!ChkArgCnt(3, 3));
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModPre, &AdrResult))
{
WAsmCode[0] = (0x8140 + (Index << 6)) | (AdrResult.AdrPart & 7);
if (AdrResult.AdrMode == ModPre)
WAsmCode[0] += 8;
if (DecodeAdr(&ArgStr[2], 1 << (AdrResult.AdrMode - 1), &AdrResult))
{
WAsmCode[0] |= ((AdrResult.AdrPart & 7) << 9);
if (DecodeAdr(&ArgStr[3], MModImm, &AdrResult))
{
WAsmCode[1] = AdrResult.Vals[0];
CodeLen = 4;
}
}
}
}
}
static void DecodeRTM(Word Index)
{
UNUSED(Index);
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!(pCurrCPUProps->SuppFlags & eFlagCALLM_RTM)) WrError(ErrNum_InstructionNotSupported);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
{
WAsmCode[0] = 0x06c0 + AdrResult.AdrPart;
CodeLen = 2;
}
}
}
static void DecodeTBL(Word Index)
{
char *p;
Word w2, Mode;
if (!ChkArgCnt(2, 2));
else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (CheckFamily(1 << eCPU32))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
{
Mode = AdrResult.AdrPart;
p
= strchr(ArgStr
[1].
str.
p_str, ':');
if (!p)
{
RelPos = 4;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX| MModAbs | MModPC | MModPCIdx, &AdrResult))
{
WAsmCode[0] = 0xf800 | AdrResult.AdrPart;
WAsmCode[1] = 0x0100 | (OpSize << 6) | (Mode << 12) | (Index << 10);
memcpy(WAsmCode
+ 2, AdrResult.
Vals, AdrResult.
Cnt);
CodeLen = 4 + AdrResult.Cnt;
}
}
else
{
strcpy(ArgStr
[3].
str.
p_str, p
+ 1);
*p = '\0';
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
w2 = AdrResult.AdrPart;
if (DecodeAdr(&ArgStr[3], MModData, &AdrResult))
{
WAsmCode[0] = 0xf800 | w2;
WAsmCode[1] = 0x0000 | (OpSize << 6) | (Mode << 12) | AdrResult.AdrPart;
if (OpPart.str.p_str[3] == 'S')
WAsmCode[1] |= 0x0800;
if (OpPart.
str.
p_str[strlen(OpPart.
str.
p_str) - 1] == 'N')
WAsmCode[1] |= 0x0400;
CodeLen = 4;
}
}
}
}
}
}
/* 0=BTST 1=BCHG 2=BCLR 3=BSET */
static void DecodeBits(Word Index)
{
Word Mask, BitNum, BitMax;
tSymbolSize SaveOpSize;
unsigned ResCodeLen;
Boolean BitNumUnknown = False;
tAdrResult AdrResult;
if (!ChkArgCnt(2, 2))
return;
WAsmCode[0] = (Index << 6);
ResCodeLen = 1;
SaveOpSize = OpSize;
OpSize = eSymbolSize8Bit;
switch (DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult))
{
case ModData:
WAsmCode[0] |= 0x100 | (AdrResult.AdrPart << 9);
BitNum = 0; /* implicitly suppresses bit pos check */
break;
case ModImm:
WAsmCode[0] |= 0x800;
WAsmCode[ResCodeLen++] = BitNum = AdrResult.Vals[0];
BitNumUnknown = mFirstPassUnknown(AdrResult.ImmSymFlags);
break;
default:
return;
}
OpSize = SaveOpSize;
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize8Bit;
Mask = MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs;
if (!Index)
Mask |= MModPC | MModPCIdx | MModImm;
RelPos = ResCodeLen << 1;
DecodeAdr(&ArgStr[2], Mask, &AdrResult);
if (!*AttrPart.str.p_str)
OpSize = (AdrResult.AdrMode == ModData) ? eSymbolSize32Bit : eSymbolSize8Bit;
if (!AdrResult.AdrMode)
return;
if (((AdrResult.AdrMode == ModData) && (OpSize != eSymbolSize32Bit)) || ((AdrResult.AdrMode != ModData) && (OpSize != eSymbolSize8Bit)))
{
WrError(ErrNum_InvOpSize);
return;
}
BitMax = (AdrResult.AdrMode == ModData) ? 31 : 7;
WAsmCode[0] |= AdrResult.AdrPart;
CopyAdrVals(WAsmCode + ResCodeLen, &AdrResult);
CodeLen = (ResCodeLen << 1) + AdrResult.Cnt;
if (!BitNumUnknown && (BitNum > BitMax))
WrError(ErrNum_BitNumberTruncated);
}
/* 0=BFTST 1=BFCHG 2=BFCLR 3=BFSET */
static void DecodeFBits(Word Index)
{
if (!ChkArgCnt(1, 1));
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!SplitBitField(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvBitMask);
else
{
tAdrResult AdrResult;
RelPos = 4;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModDAdrI | MModAIX | MModAbs | (Memo("BFTST") ? (MModPC | MModPCIdx) : 0), &AdrResult))
{
WAsmCode[0] = 0xe8c0 | AdrResult.AdrPart | (Index << 10);
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
}
}
/* 0=BFEXTU 1=BFEXTS 2=BFFFO */
static void DecodeEBits(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!SplitBitField(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvBitMask);
else
{
tAdrResult AdrResult;
RelPos = 4;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
{
LongInt ThisCodeLen = 4 + AdrResult.Cnt;
WAsmCode[0] = 0xe9c0 + AdrResult.AdrPart + (Index << 9); CopyAdrVals(WAsmCode + 2, &AdrResult);
if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
{
WAsmCode[1] |= AdrResult.AdrPart << 12;
CodeLen = ThisCodeLen;
}
}
}
}
static void DecodeBFINS(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!SplitBitField(&ArgStr[2], WAsmCode + 1)) WrError(ErrNum_InvBitMask);
else
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
LongInt ThisCodeLen = 4 + AdrResult.Cnt;
WAsmCode[0] = 0xefc0 + AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 2, &AdrResult);
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
WAsmCode[1] |= AdrResult.AdrPart << 12;
CodeLen = ThisCodeLen;
}
}
}
}
/* bedingte Befehle */
static void DecodeBcc(Word CondCode)
{
/* .W, .S, .L, .X erlaubt */
if ((OpSize > eSymbolSize32Bit) && (OpSize != eSymbolSizeFloat32Bit) && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
/* nur ein Operand erlaubt */
else if (ChkArgCnt(1, 1))
{
LongInt HVal;
Integer HVal16;
ShortInt HVal8;
Boolean ValOK, IsBSR = (1 == CondCode);
tSymbolFlags Flags;
/* Zieladresse ermitteln, zum Programmzaehler relativieren */
HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags);
HVal = HVal - (EProgCounter() + 2);
/* Bei Automatik Groesse festlegen */
if (!*AttrPart.str.p_str)
{
if (IsDisp8(HVal))
{
/* BSR with zero displacement cannot be converted to NOP. Generate a
16 bit displacement instead. */
if (!HVal && IsBSR)
OpSize = eSymbolSize32Bit;
/* if the jump target is the address right behind the BSR, keep
16 bit displacement to avoid oscillating back and forth between
8 and 16 bits: */
else if ((Flags & eSymbolFlag_NextLabelAfterBSR) && (HVal == 2) && IsBSR)
OpSize = eSymbolSize32Bit;
else
OpSize = eSymbolSizeFloat32Bit;
}
else if (IsDisp16(HVal))
OpSize = eSymbolSize32Bit;
else
OpSize = eSymbolSizeFloat96Bit;
}
if (ValOK)
{
/* 16 Bit ? */
if ((OpSize == eSymbolSize32Bit) || (OpSize == eSymbolSize16Bit))
{
/* zu weit ? */
HVal16 = HVal;
if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
/* Code erzeugen */
CodeLen = 4;
WAsmCode[0] = 0x6000 | (CondCode << 8);
WAsmCode[1] = HVal16;
}
}
/* 8 Bit ? */
else if ((OpSize == eSymbolSizeFloat32Bit) || (OpSize == eSymbolSize8Bit))
{
/* zu weit ? */
HVal8 = HVal;
if (!IsDisp8(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
/* cannot generate short BSR with zero displacement, and BSR cannot
be replaced with NOP -> error */
else if ((HVal == 0) && IsBSR && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
/* Code erzeugen */
else
{
CodeLen = 2;
if ((HVal8 != 0) || IsBSR)
{
WAsmCode[0] = 0x6000 | (CondCode << 8) | ((Byte)HVal8);
}
else
{
WAsmCode[0] = NOPCode;
if ((!Repass) && *AttrPart.str.p_str)
WrError(ErrNum_DistNull);
}
}
}
/* 32 Bit ? */
else if (!(pCurrCPUProps->SuppFlags & eFlagBranch32)) WrError(ErrNum_InstructionNotSupported);
else
{
CodeLen = 6;
WAsmCode[0] = 0x60ff | (CondCode << 8);
WAsmCode[1] = HVal >> 16;
WAsmCode[2] = HVal & 0xffff;
}
}
if ((CodeLen > 0) && IsBSR)
AfterBSRAddr = EProgCounter() + CodeLen;
}
}
static void DecodeScc(Word CondCode)
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
else if (ArgCnt != 1) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
{
WAsmCode[0] = 0x50c0 | (CondCode << 8) | AdrResult.AdrPart;
CodeLen = 2 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
}
}
}
static void DecodeDBcc(Word CondCode)
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2)
&& CheckNoFamily(1 << eColdfire))
{
Boolean ValOK;
tSymbolFlags Flags;
LongInt HVal = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &ValOK, &Flags);
Integer HVal16;
if (ValOK)
{
HVal -= (EProgCounter() + 2);
HVal16 = HVal;
if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
tAdrResult AdrResult;
CodeLen = 4;
WAsmCode[0] = 0x50c8 | (CondCode << 8);
WAsmCode[1] = HVal16;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult) == ModData)
WAsmCode[0] |= AdrResult.AdrPart;
else
CodeLen = 0;
}
}
}
}
static void DecodeTRAPcc(Word CondCode)
{
int ExpectArgCnt;
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize8Bit;
ExpectArgCnt = (OpSize == eSymbolSize8Bit) ? 0 : 1;
if (OpSize > 2) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(ExpectArgCnt, ExpectArgCnt));
else if ((CondCode != 1) && !CheckNoFamily(1 << eColdfire));
else
{
WAsmCode[0] = 0x50f8 + (CondCode << 8);
if (OpSize == eSymbolSize8Bit)
{
WAsmCode[0] += 4;
CodeLen = 2;
}
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
WAsmCode[0] += OpSize + 1;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CodeLen = 2 + AdrResult.Cnt;
}
}
CheckFamily((1 << eColdfire) | (1 << eCPU32) | (1 << e68KGen2) | (1 << e68KGen3));
}
}
/*-------------------------------------------------------------------------*/
/* Dekodierroutinen Gleitkommaeinheit */
enum { eFMovemTypNone = 0, eFMovemTypDyn = 1, eFMovemTypStatic = 2, eFMovemTypCtrl = 3 };
static void DecodeFRegList(const tStrComp *pArg, Byte *pTyp, Byte *pList)
{
Word hw, Reg, RegFrom, RegTo;
Byte z;
char *p, *p2;
String ArgStr;
tStrComp Arg, Remainder, From, To;
StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
StrCompCopy(&Arg, pArg);
*pTyp = eFMovemTypNone;
if (*Arg.str.p_str == '\0')
return;
switch (DecodeReg(&Arg, &Reg, False))
{
case eIsReg:
if (Reg & 8)
return;
*pTyp = eFMovemTypDyn;
*pList = Reg << 4;
return;
case eRegAbort:
return;
default:
break;
}
hw = 0;
do
{
p
= strchr(Arg.
str.
p_str, '/');
if (p)
StrCompSplitRef(&Arg, &Remainder, &Arg, p);
p2
= strchr(Arg.
str.
p_str, '-');
if (p2)
{
StrCompSplitRef(&From, &To, &Arg, p2);
|| (DecodeFPReg(&From, &RegFrom, False) != eIsReg)
|| (RegFrom & REG_FPCTRL)
|| (DecodeFPReg(&To, &RegTo, False) != eIsReg)
|| (RegTo & REG_FPCTRL))
return;
if (RegFrom <= RegTo)
for (z = RegFrom; z <= RegTo; z++) hw |= (1 << (7 - z));
else
{
for (z = RegFrom; z <= 7; z++) hw |= (1 << (7 - z));
for (z = 0; z <= RegTo; z++) hw |= (1 << (7 - z));
}
}
else
{
if (DecodeFPReg(&Arg, &Reg, False) != eIsReg)
return;
if (Reg & REG_FPCTRL)
hw |= (Reg & 7) << 8;
else
hw |= (1 << (7 - Reg));
}
if (p)
Arg = Remainder;
}
while (p);
if (Hi(hw) == 0)
{
*pTyp = eFMovemTypStatic;
*pList = Lo(hw);
}
else if (Lo(hw) == 0)
{
*pTyp = eFMovemTypCtrl;
*pList = Hi(hw);
}
}
static Byte Mirror8(Byte List)
{
Byte hList;
int z;
hList = List; List = 0;
for (z = 0; z < 8; z++)
{
List = List << 1;
if (hList & 1)
List |= 1;
hList = hList >> 1;
}
return List;
}
static void GenerateMovem(Byte Typ, Byte List, tAdrResult *pResult)
{
if (pResult->AdrMode == ModNone)
return;
CodeLen = 4 + pResult->Cnt;
CopyAdrVals(WAsmCode + 2, pResult);
WAsmCode[0] = 0xf200 | pResult->AdrPart;
switch (Typ)
{
case eFMovemTypDyn:
case eFMovemTypStatic:
WAsmCode[1] |= 0xc000;
if (Typ == eFMovemTypDyn)
WAsmCode[1] |= 0x800;
if (pResult->AdrMode != ModPre)
WAsmCode[1] |= 0x1000;
if ((pResult->AdrMode == ModPre) && (Typ == eFMovemTypStatic))
List = Mirror8(List);
WAsmCode[1] |= List;
break;
case eFMovemTypCtrl:
WAsmCode[1] |= 0x8000 | (((Word)List) << 10);
break;
}
}
/*-------------------------------------------------------------------------*/
static void DecodeFPUOp(Word Index)
{
FPUOp *Op = FPUOps + Index;
tStrComp *pArg2 = &ArgStr[2];
if ((ArgCnt == 1) && (!Op->Dya))
{
pArg2 = &ArgStr[1];
ArgCnt = 2;
}
if (!CheckFloatSize());
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if ((pCurrCPUProps->SuppFlags & Op->NeedsSuppFlags) != Op->NeedsSuppFlags) WrError(ErrNum_InstructionNotSupported);
else if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
if (DecodeAdr(pArg2, MModFPn, &AdrResult) == ModFPn)
{
Word SrcMask;
WAsmCode[0] = 0xf200;
WAsmCode[1] = Op->Code | (AdrResult.AdrPart << 7);
RelPos = 4;
SrcMask = MModAdrI | MModDAdrI | MModPost | MModPre | MModPC | MModFPn;
if (FloatOpSizeFitsDataReg(OpSize))
SrcMask |= MModData;
if (pCurrCPUProps->Family != eColdfire)
SrcMask |= MModAIX | MModAbs | MModPCIdx | MModImm;
if (DecodeAdr(&ArgStr[1], SrcMask, &AdrResult) == ModFPn)
{
WAsmCode[1] |= AdrResult.AdrPart << 10;
if (OpSize == NativeFloatSize)
CodeLen = 4;
else
WrError(ErrNum_InvOpSize);
}
else if (AdrResult.AdrMode != ModNone)
{
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
WAsmCode[0] |= AdrResult.AdrPart;
WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
}
}
}
}
static void DecodeFSAVE(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0xf300 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CheckSup();
}
}
}
static void DecodeFRESTORE(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModPost | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0xf340 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CheckSup();
}
}
}
static void DecodeFNOP(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(0, 0));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else
{
CodeLen = 4;
WAsmCode[0] = 0xf280;
WAsmCode[1] = 0;
}
}
/* TODO: does a { } suffix to <dest> as k factor conflict
with other features, like stringification? Maybe better
check whether this is a valid k factor (register (symbol)
or immediate) and only cut off if yes. We might not be
able to use DecodeAdr() for this any more: */
static char *split_k(tStrComp *p_arg, tStrComp *p_k)
{
int l
= strlen(p_arg
->str.
p_str);
char *p_sep;
if ((l < 2) || (p_arg->str.p_str[l - 1] != '}'))
return NULL;
p_sep = RQuotPos(p_arg->str.p_str, '{');
if (!p_sep)
return NULL;
StrCompSplitRef(p_arg, p_k, p_arg, p_sep);
StrCompShorten(p_k, 1);
KillPostBlanksStrComp(p_arg);
KillPrefBlanksStrCompRef(p_k);
return p_sep;
}
static void DecodeFMOVE(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (!CheckFloatSize());
else
{
Word DestMask, SrcMask;
tAdrResult AdrResult;
tStrComp KArg;
/* k-Faktor abspalten */
LineCompReset(&KArg.Pos);
if (OpSize == eSymbolSizeFloatDec96Bit)
{
if (!split_k(&AttrPart, &KArg))
split_k(&ArgStr[2], &KArg);
}
DestMask = MModAdrI | MModPost | MModPre | MModDAdrI | MModFPCR | MModFPn;
if (pCurrCPUProps->Family != eColdfire)
DestMask |= MModAIX | MModAbs | MModImm;
if (FloatOpSizeFitsDataReg(OpSize))
DestMask |= MModData;
if (DecodeAdr(&ArgStr[2], DestMask, &AdrResult) == ModFPn) /* FMOVE.x <ea>/FPm,FPn ? */
{
WAsmCode[0] = 0xf200;
WAsmCode[1] = AdrResult.AdrPart << 7;
RelPos = 4;
SrcMask = MModAdrI | MModPost | MModPre | MModDAdrI | MModPC | MModFPn;
if (pCurrCPUProps->Family != eColdfire)
SrcMask |= MModAIX | MModAbs | MModImm | MModPCIdx;
if (FloatOpSizeFitsDataReg(OpSize))
SrcMask |= MModData;
if (DecodeAdr(&ArgStr[1], SrcMask, &AdrResult) == ModFPn) /* FMOVE.X FPm,FPn ? */
{
WAsmCode[1] |= AdrResult.AdrPart << 10;
if (OpSize == NativeFloatSize)
CodeLen = 4;
else
WrError(ErrNum_InvOpSize);
}
else if (AdrResult.AdrMode != ModNone) /* FMOVE.x <ea>,FPn ? */
{
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
WAsmCode[0] |= AdrResult.AdrPart;
WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
}
}
else if (AdrResult.AdrMode == ModFPCR) /* FMOVE.L <ea>,FPcr ? */
{
if ((OpSize != eSymbolSize32Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else
{
RelPos = 4;
WAsmCode[0] = 0xf200;
WAsmCode[1] = 0x8000 | (AdrResult.AdrPart << 10);
SrcMask = MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModPC;
if (pCurrCPUProps->Family != eColdfire)
SrcMask |= MModAIX | MModAbs | MModImm | MModPCIdx;
if (AdrResult.AdrMode != ModData) /* only for FPIAR */
SrcMask |= MModAdr;
if (DecodeAdr(&ArgStr[1], SrcMask, &AdrResult))
{
WAsmCode[0] |= AdrResult.AdrPart;
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
}
}
}
else if (AdrResult.AdrMode != ModNone) /* FMOVE.x ????,<ea> ? */
{
WAsmCode[0] = 0xf200 | AdrResult.AdrPart;
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
switch (DecodeAdr(&ArgStr[1], (AdrResult.AdrMode == ModAdr) ? MModFPCR : MModFPn | MModFPCR, &AdrResult))
{
case ModFPn: /* FMOVE.x FPn,<ea> ? */
{
WAsmCode[1] = 0x6000 | (((Word)FSizeCodes[OpSize]) << 10) | (AdrResult.AdrPart << 7);
if (OpSize == eSymbolSizeFloatDec96Bit)
{
if (KArg.Pos.Len > 0)
{
OpSize = eSymbolSize8Bit;
switch (DecodeAdr(&KArg, MModData | MModImm, &AdrResult))
{
case ModData:
WAsmCode[1] |= (AdrResult.AdrPart << 4) | 0x1000;
break;
case ModImm:
WAsmCode[1] |= (AdrResult.Vals[0] & 127);
break;
default:
CodeLen = 0;
}
}
else
WAsmCode[1] |= 17;
}
break;
}
case ModFPCR: /* FMOVE.L FPcr,<ea> ? */
{
if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit))
{
WrError(ErrNum_InvOpSize);
CodeLen = 0;
}
else
{
WAsmCode[1] = 0xa000 | (AdrResult.AdrPart << 10);
if ((AdrResult.AdrPart != 1) && ((WAsmCode[0] & 0x38) == 8))
{
WrError(ErrNum_InvAddrMode);
CodeLen = 0;
}
}
break;
}
default:
CodeLen = 0;
}
}
}
}
static void DecodeFMOVECR(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (!CheckNoFamily(1 << eColdfire));
else if (*AttrPart.str.p_str && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModFPn, &AdrResult) == ModFPn)
{
WAsmCode[0] = 0xf200;
WAsmCode[1] = 0x5c00 | (AdrResult.AdrPart << 7);
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult) == ModImm)
{
if (AdrResult.Vals[0] > 63) WrError(ErrNum_RomOffs063);
else
{
CodeLen = 4;
WAsmCode[1] |= AdrResult.Vals[0];
}
}
}
}
}
static void DecodeFTST(Word Code)
{
UNUSED(Code);
if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (!CheckFloatSize());
else if (ChkArgCnt(1, 1))
{
Word Mask;
tAdrResult AdrResult;
RelPos = 4;
Mask = MModAdrI | MModPost | MModPre | MModDAdrI | MModPC | MModFPn;
if (pCurrCPUProps->Family != eColdfire)
Mask |= MModAIX | MModPCIdx | MModAbs | MModImm;
if (FloatOpSizeFitsDataReg(OpSize))
Mask |= MModData;
if (DecodeAdr(&ArgStr[1], Mask, &AdrResult) == ModFPn)
{
WAsmCode[0] = 0xf200;
WAsmCode[1] = 0x3a | (AdrResult.AdrPart << 10);
CodeLen = 4;
}
else if (AdrResult.AdrMode != ModNone)
{
WAsmCode[0] = 0xf200 | AdrResult.AdrPart;
WAsmCode[1] = 0x403a | (((Word)FSizeCodes[OpSize]) << 10);
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
}
}
}
static void DecodeFSINCOS(Word Code)
{
UNUSED(Code);
if (!*AttrPart.str.p_str)
OpSize = NativeFloatSize;
if (OpSize == 3) WrError(ErrNum_InvOpSize);
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (!CheckNoFamily(1 << eColdfire));
else if (ChkArgCnt(2, 3))
{
tStrComp *pArg2, *pArg3, Arg2, Arg3;
tAdrResult AdrResult;
if (3 == ArgCnt)
{
pArg2 = &ArgStr[2];
pArg3 = &ArgStr[3];
}
else
{
char *pKSep
= strrchr(ArgStr
[2].
str.
p_str, ':');
if (!pKSep)
{
WrError(ErrNum_WrongArgCnt);
return;
}
StrCompSplitRef(&Arg2, &Arg3, &ArgStr[2], pKSep);
pArg2 = &Arg2;
pArg3 = &Arg3;
}
if (DecodeAdr(pArg2, MModFPn, &AdrResult) == ModFPn)
{
WAsmCode[1] = AdrResult.AdrPart | 0x30;
if (DecodeAdr(pArg3, MModFPn, &AdrResult) == ModFPn)
{
WAsmCode[1] |= (AdrResult.AdrPart << 7);
RelPos = 4;
switch (DecodeAdr(&ArgStr[1], ((OpSize <= eSymbolSize32Bit) || (OpSize == eSymbolSizeFloat32Bit))
? MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm | MModFPn
: MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm | MModFPn, &AdrResult))
{
case ModFPn:
WAsmCode[0] = 0xf200;
WAsmCode[1] |= (AdrResult.AdrPart << 10);
CodeLen = 4;
break;
case ModNone:
break;
default:
WAsmCode[0] = 0xf200 | AdrResult.AdrPart;
WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
}
}
}
}
}
static void DecodeFDMOVE_FSMOVE(Word Code)
{
if (!ChkArgCnt(2, 2));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (CheckFamily((1 << e68KGen3) | (1 << eColdfire)))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModFPn, &AdrResult) == ModFPn)
{
unsigned Mask;
WAsmCode[0] = 0xf200;
WAsmCode[1] = Code | AdrResult.AdrPart << 7;
RelPos = 4;
if (!*AttrPart.str.p_str)
OpSize = NativeFloatSize;
Mask = MModFPn | MModAdrI | MModPost | MModPre | MModDAdrI | MModPC;
if (pCurrCPUProps->Family != eColdfire)
Mask |= MModAIX | MModAbs | MModPCIdx | MModImm;
if (FloatOpSizeFitsDataReg(OpSize))
Mask |= MModData;
if (DecodeAdr(&ArgStr[1], Mask, &AdrResult) == ModFPn)
{
CodeLen = 4;
WAsmCode[1] |= (AdrResult.AdrPart << 10);
}
else if (AdrResult.AdrMode != ModNone)
{
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
WAsmCode[0] |= AdrResult.AdrPart;
WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
}
}
}
}
static void DecodeFMOVEM(Word Code)
{
Byte Typ, List;
Word Mask;
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else
{
tAdrResult AdrResult;
DecodeFRegList(&ArgStr[2], &Typ, &List);
if (Typ != eFMovemTypNone)
{
if (*AttrPart.str.p_str
&& (((Typ < eFMovemTypCtrl) && (OpSize != NativeFloatSize))
|| ((Typ == eFMovemTypCtrl) && (OpSize != eSymbolSize32Bit))))
WrError(ErrNum_InvOpSize);
else if ((Typ != eFMovemTypStatic) && (pCurrCPUProps->Family == eColdfire))
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
else
{
RelPos = 4;
Mask = MModAdrI | MModDAdrI | MModPC;
if (pCurrCPUProps->Family != eColdfire)
Mask |= MModPost | MModAIX | MModPCIdx | MModAbs;
if (Typ == eFMovemTypCtrl) /* Steuerregister auch Predekrement */
{
Mask |= MModPre;
if ((List == REG_FPCR) | (List == REG_FPSR) | (List == REG_FPIAR)) /* nur ein Register */
Mask |= MModData | MModImm;
if (List == REG_FPIAR) /* nur FPIAR */
Mask |= MModAdr;
}
if (DecodeAdr(&ArgStr[1], Mask, &AdrResult))
{
WAsmCode[1] = 0x0000;
GenerateMovem(Typ, List, &AdrResult);
}
}
}
else
{
DecodeFRegList(&ArgStr[1], &Typ, &List);
if (Typ != eFMovemTypNone)
{
if (*AttrPart.str.p_str && (((Typ < eFMovemTypCtrl) && (OpSize != NativeFloatSize)) || ((Typ == eFMovemTypCtrl) && (OpSize != eSymbolSize32Bit)))) WrError(ErrNum_InvOpSize);
else if ((Typ != eFMovemTypStatic) && (pCurrCPUProps->Family == eColdfire)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
else
{
Mask = MModAdrI | MModDAdrI;
if (pCurrCPUProps->Family != eColdfire)
Mask |= MModPre | MModAIX | MModAbs;
if (Typ == eFMovemTypCtrl) /* Steuerregister auch Postinkrement */
{
Mask |= MModPre;
if ((List == REG_FPCR) | (List == REG_FPSR) | (List == REG_FPIAR)) /* nur ein Register */
Mask |= MModData;
if (List == REG_FPIAR) /* nur FPIAR */
Mask |= MModAdr;
}
if (DecodeAdr(&ArgStr[2], Mask, &AdrResult))
{
WAsmCode[1] = 0x2000;
GenerateMovem(Typ, List, &AdrResult);
}
}
}
else
WrError(ErrNum_InvRegList);
}
}
}
static void DecodeFBcc(Word CondCode)
{
if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else
{
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit) && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
LongInt HVal;
Integer HVal16;
Boolean ValOK;
tSymbolFlags Flags;
HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags) - (EProgCounter() + 2);
HVal16 = HVal;
if (!*AttrPart.str.p_str)
{
OpSize = (IsDisp16(HVal)) ? eSymbolSize32Bit : eSymbolSizeFloat96Bit;
}
if ((OpSize == eSymbolSize32Bit) || (OpSize == eSymbolSize16Bit))
{
if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4;
WAsmCode[0] = 0xf280 | CondCode;
WAsmCode[1] = HVal16;
}
}
else
{
CodeLen = 6;
WAsmCode[0] = 0xf2c0 | CondCode;
WAsmCode[2] = HVal & 0xffff;
WAsmCode[1] = HVal >> 16;
if (IsDisp16(HVal) && (PassNo > 1) && !*AttrPart.str.p_str)
{
WrError(ErrNum_ShortJumpPossible);
WAsmCode[0] ^= 0x40;
CodeLen -= 2;
WAsmCode[1] = WAsmCode[2];
StopfZahl++;
}
}
}
}
}
static void DecodeFDBcc(Word CondCode)
{
if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (CheckNoFamily(1 << eColdfire))
{
if ((OpSize != eSymbolSize16Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(2, 2))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
LongInt HVal;
Integer HVal16;
Boolean ValOK;
tSymbolFlags Flags;
WAsmCode[0] = 0xf248 | AdrResult.AdrPart;
WAsmCode[1] = CondCode;
HVal = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &ValOK, &Flags) - (EProgCounter() + 4);
if (ValOK)
{
HVal16 = HVal;
WAsmCode[2] = HVal16;
if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else CodeLen = 6;
}
}
}
}
}
static void DecodeFScc(Word CondCode)
{
if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (!CheckNoFamily(1 << eColdfire));
else if ((OpSize != eSymbolSize8Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 4 + AdrResult.Cnt;
WAsmCode[0] = 0xf240 | AdrResult.AdrPart;
WAsmCode[1] = CondCode;
CopyAdrVals(WAsmCode + 2, &AdrResult);
}
}
}
static void DecodeFTRAPcc(Word CondCode)
{
if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
else if (!CheckNoFamily(1 << eColdfire));
else
{
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize8Bit;
if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(OpSize ? 1 : 0, OpSize ? 1 : 0))
{
WAsmCode[0] = 0xf278;
WAsmCode[1] = CondCode;
if (OpSize == eSymbolSize8Bit)
{
WAsmCode[0] |= 4;
CodeLen = 4;
}
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
WAsmCode[0] |= (OpSize + 1);
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
}
}
}
}
/*-------------------------------------------------------------------------*/
/* Hilfsroutinen MMU: */
static Boolean DecodeFC(const tStrComp *pArg, Word *erg)
{
Boolean OK;
Word Val;
if (!as_strcasecmp(pArg->str.p_str, "SFC"))
{
*erg = 0;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "DFC"))
{
*erg = 1;
return True;
}
switch (DecodeReg(pArg, erg, False))
{
case eIsReg:
if (*erg < 8)
{
*erg += 8;
return True;
}
break;
case eIsNoReg:
break;
default:
return False;
}
if (*pArg->str.p_str == '#')
{
Val = EvalStrIntExpressionOffs(pArg, 1, Int4, &OK);
if (OK)
*erg = Val + 16;
return OK;
}
return False;
}
static Boolean DecodePMMUReg(char *Asc, Word *erg, tSymbolSize *pSize)
{
Byte z;
if ((strlen(Asc
) == 4) && (!as_strncasecmp
(Asc
, "BAD", 3)) && ValReg
(Asc
[3]))
{
*pSize = eSymbolSize16Bit;
*erg = 0x7000 + ((Asc[3] - '0') << 2);
return True;
}
if ((strlen(Asc
) == 4) && (!as_strncasecmp
(Asc
, "BAC", 3)) && ValReg
(Asc
[3]))
{
*pSize = eSymbolSize16Bit;
*erg = 0x7400 + ((Asc[3] - '0') << 2);
return True;
}
for (z = 0; PMMURegs[z].pName; z++)
if (!as_strcasecmp(Asc, PMMURegs[z].pName))
{
*pSize = PMMURegs[z].Size;
*erg = PMMURegs[z].Code << 10;
return True;
}
return False;
}
/*-------------------------------------------------------------------------*/
static void DecodePSAVE(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0xf100 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CheckSup();
}
}
}
static void DecodePRESTORE(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 2 + AdrResult.Cnt;
WAsmCode[0] = 0xf140 | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CheckSup();
}
}
}
static void DecodePFLUSHA(Word Code)
{
UNUSED(Code);
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (ChkArgCnt(0, 0))
{
switch (pCurrCPUProps->Family)
{
case e68KGen3:
CodeLen = 2;
WAsmCode[0] = 0xf518;
break;
default:
CodeLen = 4;
WAsmCode[0] = 0xf000;
WAsmCode[1] = 0x2400;
break;
}
CheckSup();
}
}
static void DecodePFLUSHAN(Word Code)
{
UNUSED(Code);
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (ChkArgCnt(0, 0)
&& CheckFamily(1 << e68KGen3))
{
CodeLen = 2;
WAsmCode[0] = 0xf510;
CheckSup();
}
}
static void DecodePFLUSH_PFLUSHS(Word Code)
{
tAdrResult AdrResult;
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (pCurrCPUProps->Family == e68KGen3)
{
if (Code) WrError(ErrNum_FullPMMUNotEnabled);
else if (ChkArgCnt(1, 1))
{
if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
{
WAsmCode[0] = 0xf508 + (AdrResult.AdrPart & 7);
CodeLen = 2;
CheckSup();
}
}
}
else if (!ChkArgCnt(2, 3));
else if ((Code) && (!FullPMMU)) WrError(ErrNum_FullPMMUNotEnabled);
else if (!DecodeFC(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvFCode);
else
{
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[2], MModImm, &AdrResult))
{
if (AdrResult.Vals[0] > 15) WrError(ErrNum_InvFMask);
else
{
WAsmCode[1] |= (AdrResult.Vals[0] << 5) | 0x3000 | Code;
WAsmCode[0] = 0xf000;
CodeLen = 4;
CheckSup();
if (ArgCnt == 3)
{
WAsmCode[1] |= 0x800;
if (!DecodeAdr(&ArgStr[3], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
CodeLen = 0;
else
{
WAsmCode[0] |= AdrResult.AdrPart;
CodeLen += AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
}
}
}
}
}
}
static void DecodePFLUSHN(Word Code)
{
UNUSED(Code);
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (ChkArgCnt(1, 1)
&& CheckFamily(1 << e68KGen3))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
{
WAsmCode[0] = 0xf500 + (AdrResult.AdrPart & 7);
CodeLen = 2;
CheckSup();
}
}
}
static void DecodePFLUSHR(Word Code)
{
UNUSED(Code);
if (*AttrPart.str.p_str)
OpSize = eSymbolSize64Bit;
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
if (OpSize != eSymbolSize64Bit) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(1, 1));
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
tAdrResult AdrResult;
RelPos = 4;
if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModPost | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
{
WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
WAsmCode[1] = 0xa000;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt; CheckSup();
}
}
}
static void DecodePLOADR_PLOADW(Word Code)
{
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (!ChkArgCnt(2, 2));
else if (!DecodeFC(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvFCode);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
WAsmCode[1] |= Code;
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CheckSup();
}
}
}
static void DecodePMOVE_PMOVEFD(Word Code)
{
tSymbolSize RegSize;
unsigned Mask;
tAdrResult AdrResult;
if (!ChkArgCnt(2, 2));
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else
{
if (DecodePMMUReg(ArgStr[1].str.p_str, WAsmCode + 1, &RegSize))
{
WAsmCode[1] |= 0x200;
if (!*AttrPart.str.p_str)
OpSize = RegSize;
if (OpSize != RegSize) WrError(ErrNum_InvOpSize);
else
{
Mask = MModAdrI | MModDAdrI | MModAIX | MModAbs;
if (FullPMMU)
{
Mask *= MModPost | MModPre;
if (RegSize != eSymbolSize64Bit)
Mask += MModData | MModAdr;
}
if (DecodeAdr(&ArgStr[2], Mask, &AdrResult))
{
WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CheckSup();
}
}
}
else if (DecodePMMUReg(ArgStr[2].str.p_str, WAsmCode + 1, &RegSize))
{
if (!*AttrPart.str.p_str)
OpSize = RegSize;
if (OpSize != RegSize) WrError(ErrNum_InvOpSize);
else
{
RelPos = 4;
Mask = MModAdrI | MModDAdrI | MModAIX | MModAbs;
if (FullPMMU)
{
Mask += MModPost | MModPre | MModPC | MModPCIdx | MModImm;
if (RegSize != eSymbolSize64Bit)
Mask += MModData | MModAdr;
}
if (DecodeAdr(&ArgStr[1], Mask, &AdrResult))
{
WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
WAsmCode[1] += Code;
CheckSup();
}
}
}
else
WrError(ErrNum_InvMMUReg);
}
}
static void DecodePTESTR_PTESTW(Word Code)
{
tAdrResult AdrResult;
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (pCurrCPUProps->Family == e68KGen3)
{
if (ChkArgCnt(1, 1))
{
if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
{
WAsmCode[0] = 0xf548 + (AdrResult.AdrPart & 7) + (Code << 5);
CodeLen = 2;
CheckSup();
}
}
}
else if (ChkArgCnt(3, 4))
{
if (!DecodeFC(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvFCode);
else
{
if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
CodeLen = 4 + AdrResult.Cnt;
WAsmCode[1] |= 0x8000 | (Code << 9);
CopyAdrVals(WAsmCode + 2, &AdrResult);
if (DecodeAdr(&ArgStr[3], MModImm, &AdrResult))
{
if (AdrResult.Vals[0] > 7)
{
WrError(ErrNum_Level07);
CodeLen = 0;
}
else
{
WAsmCode[1] |= AdrResult.Vals[0] << 10;
if (ArgCnt == 4)
{
if (!DecodeAdr(&ArgStr[4], MModAdr, &AdrResult))
CodeLen = 0;
else
WAsmCode[1] |= AdrResult.AdrPart << 5;
CheckSup();
}
}
}
else
CodeLen = 0;
}
}
}
}
static void DecodePVALID(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
WAsmCode[1] = 0x2800;
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 1, &AdrResult);
if (!as_strcasecmp(ArgStr[1].str.p_str, "VAL"));
else
{
if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
WAsmCode[1] |= 0x400 | (AdrResult.AdrPart & 7);
else
CodeLen = 0;
}
}
}
}
static void DecodePBcc(Word CondCode)
{
if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else
{
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit) && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(1, 1));
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
LongInt HVal;
Integer HVal16;
Boolean ValOK;
tSymbolFlags Flags;
HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags) - (EProgCounter() + 2);
HVal16 = HVal;
if (!*AttrPart.str.p_str)
OpSize = (IsDisp16(HVal)) ? eSymbolSize32Bit : eSymbolSizeFloat96Bit;
if ((OpSize == eSymbolSize32Bit) || (OpSize == eSymbolSize16Bit))
{
if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4;
WAsmCode[0] = 0xf080 | CondCode;
WAsmCode[1] = HVal16;
CheckSup();
}
}
else
{
CodeLen = 6;
WAsmCode[0] = 0xf0c0 | CondCode;
WAsmCode[2] = HVal & 0xffff;
WAsmCode[1] = HVal >> 16;
CheckSup();
}
}
}
}
static void DecodePDBcc(Word CondCode)
{
if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else
{
if ((OpSize != eSymbolSize16Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(2, 2));
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
LongInt HVal;
Integer HVal16;
Boolean ValOK;
tSymbolFlags Flags;
WAsmCode[0] = 0xf048 | AdrResult.AdrPart;
WAsmCode[1] = CondCode;
HVal = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &ValOK, &Flags) - (EProgCounter() + 4);
if (ValOK)
{
HVal16 = HVal;
WAsmCode[2] = HVal16;
if ((!IsDisp16(HVal)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
CodeLen = 6;
CheckSup();
}
}
}
}
}
static void DecodePScc(Word CondCode)
{
if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else
{
if ((OpSize != eSymbolSize8Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(1, 1));
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
{
CodeLen = 4 + AdrResult.Cnt;
WAsmCode[0] = 0xf040 | AdrResult.AdrPart;
WAsmCode[1] = CondCode;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CheckSup();
}
}
}
}
static void DecodePTRAPcc(Word CondCode)
{
if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
else
{
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize8Bit;
if (OpSize > 2) WrError(ErrNum_InvOpSize);
else if (!ChkArgCnt(OpSize ? 1 : 0, OpSize ? 1 : 0));
else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
else
{
WAsmCode[0] = 0xf078;
WAsmCode[1] = CondCode;
if (OpSize == eSymbolSize8Bit)
{
WAsmCode[0] |= 4;
CodeLen = 4;
CheckSup();
}
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
WAsmCode[0] |= (OpSize + 1);
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
CheckSup();
}
}
}
}
}
static void DecodeColdBit(Word Code)
{
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize32Bit;
if (ChkArgCnt(1, 1)
&& CheckColdSize()
&& CheckFamily(1 << eColdfire)
&& CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_C)))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = Code | (AdrResult.AdrPart & 7);
}
}
}
static void DecodeSTLDSR(Word Code)
{
UNUSED(Code);
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize16Bit;
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1)
&& CheckFamily(1 << eColdfire)
&& CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_C)))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
{
CodeLen = 6;
WAsmCode[0] = 0x40e7;
WAsmCode[1] = 0x46fc;
WAsmCode[2] = AdrResult.Vals[0];
}
}
}
static void DecodeINTOUCH(Word Code)
{
UNUSED(Code);
if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1)
&& CheckFamily(1 << eColdfire)
&& (pCurrCPUProps->CfISA >= eCfISA_B))
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
{
CodeLen = 2;
WAsmCode[0] = 0xf428 | (AdrResult.AdrPart & 7);
CheckSup();
}
}
}
static void DecodeMOV3Q(Word Code)
{
Boolean OK;
tSymbolFlags Flags;
ShortInt Val;
tAdrResult AdrResult;
UNUSED(Code);
if (!ChkArgCnt(2, 2)
|| !CheckFamily(1 << eColdfire)
|| (pCurrCPUProps->CfISA < eCfISA_B)
|| !CheckColdSize())
return;
if (!DecodeAdr(&ArgStr[2], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
return;
if (*ArgStr[1].str.p_str != '#')
{
WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
return;
}
Val = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, SInt4, &OK, &Flags);
if (!OK)
return;
if (mFirstPassUnknown(Flags))
Val = 1;
if (Val == -1)
Val = 0;
else if (!ChkRange(Val, 1, 7))
return;
WAsmCode[0] = 0xa140 | ((Val & 7) << 9) | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CodeLen = 2 + AdrResult.Cnt;
}
static void DecodeMVS_MVZ(Word Code)
{
Word DestReg;
tAdrResult AdrResult;
if (!ChkArgCnt(2, 2)
|| !CheckFamily(1 << eColdfire)
|| (pCurrCPUProps->CfISA < eCfISA_B))
return;
if (!*AttrPart.str.p_str)
OpSize = eSymbolSize16Bit;
if (OpSize > eSymbolSize16Bit)
{
WrError(ErrNum_InvOpSize);
return;
}
if (!DecodeAdr(&ArgStr[2], MModData, &AdrResult))
return;
DestReg = AdrResult.AdrPart & 7;
if (DecodeAdr(&ArgStr[1], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs | MModImm | MModPC | MModPCIdx, &AdrResult))
{
WAsmCode[0] = Code | (DestReg << 9) | (OpSize << 6) | AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 1, &AdrResult);
CodeLen = 2 + AdrResult.Cnt;
}
}
static void DecodeSATS(Word Code)
{
tAdrResult AdrResult;
UNUSED(Code);
if (!ChkArgCnt(1, 1)
|| !CheckFamily(1 << eColdfire)
|| (pCurrCPUProps->CfISA < eCfISA_B)
|| !CheckColdSize())
return;
if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
{
WAsmCode[0] = 0x4c80 | (AdrResult.AdrPart & 7);
CodeLen = 2;
}
}
static void DecodeMAC_MSAC(Word Code)
{
Word Rx, Ry, Rw, Ux = 0, Uy = 0, Scale = 0, Mask, AccNum = 0;
int CurrArg, RemArgCnt;
Boolean ExplicitLoad = !!(Code & 0x8000);
tAdrResult AdrResult;
Code &= 0x7fff;
if (!(pCurrCPUProps->SuppFlags & eFlagMAC))
{
WrError(ErrNum_InstructionNotSupported);
return;
}
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit))
{
WrError(ErrNum_InvOpSize);
return;
}
/* 2 args is the absolute minimum. 6 is the maximum (Ry, Rx, scale, <ea>, Rw, ACC) */
if (!ChkArgCnt(2, 6))
return;
/* Ry and Rx are always present, and are always the first arguments: */
if (OpSize == eSymbolSize16Bit)
{
if (!SplitMACUpperLower(&Uy, &ArgStr[1])
|| !SplitMACUpperLower(&Ux, &ArgStr[2]))
return;
}
if (!DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
return;
Ry = AdrResult.AdrPart & 15;
if (!DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
return;
Rx = AdrResult.AdrPart & 15;
CurrArg = 3;
/* Is a scale given as next argument? */
if ((ArgCnt >= CurrArg) && DecodeMACScale(&ArgStr[CurrArg], &Scale))
CurrArg++;
/* We now have between 0 and 3 args left:
0 -> no load, ACC0
1 -> ACCn
2 -> load, ACC0
3 -> load, ACCn
If the 'L' variant (MACL, MSACL) was given, a parallel
load was specified explicitly and there MUST be the <ea> and Rw arguments: */
RemArgCnt = ArgCnt - CurrArg + 1;
if ((RemArgCnt > 3)
|| (ExplicitLoad && (RemArgCnt < 2)))
{
WrError(ErrNum_WrongArgCnt);
return;
}
/* assumed ACC(0) if no accumulator given */
if (Odd(RemArgCnt))
{
if (!DecodeMACACC(ArgStr[ArgCnt].str.p_str, &AccNum))
{
WrStrErrorPos(ErrNum_InvReg, &ArgStr[ArgCnt]);
return;
}
}
/* If parallel load, bit 7 of first word is set for MAC. This bit is
used on EMAC to store accumulator # LSB. To keep things upward-compatible,
accumulator # LSB is stored inverted on EMAC if a parallel load is present.
Since MAC only uses accumulator #0, this works for either target: */
if (RemArgCnt >= 2)
AccNum ^= 1;
/* Common things for variant with and without parallel load: */
WAsmCode[0] = 0xa000 | ((AccNum & 1) << 7);
WAsmCode[1] = ((OpSize - 1) << 11) | (Scale << 9) | Code | (Ux << 7) | (Uy << 6) | ((AccNum & 2) << 3);
/* With parallel load? */
if (RemArgCnt >= 2)
{
tStrComp CurrArgStr;
if (!DecodeAdr(&ArgStr[CurrArg + 1], MModData | MModAdr, &AdrResult))
return;
Rw = AdrResult.AdrPart & 15;
StrCompRefRight(&CurrArgStr, &ArgStr[CurrArg], 0);
if (!SplitMACANDMASK(&Mask, &CurrArgStr))
return;
if (!DecodeAdr(&CurrArgStr, MModAdrI | MModPre | MModPost | MModDAdrI, &AdrResult))
return;
WAsmCode[0] |= ((Rw & 7) << 9) | ((Rw & 8) << 3) | AdrResult.AdrPart;
WAsmCode[1] |= (Mask << 5) | (Rx << 12) | (Ry << 0);
CodeLen = 4 + AdrResult.Cnt;
CopyAdrVals(WAsmCode + 2, &AdrResult);
}
/* multiply/accumulate only */
else
{
WAsmCode[0] |= Ry | ((Rx & 7) << 9) | ((Rx & 8) << 3);
CodeLen = 4;
}
}
static void DecodeMOVCLR(Word Code)
{
Word ACCReg;
UNUSED(Code);
if (!ChkArgCnt(2,2));
else if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else if (!(pCurrCPUProps->SuppFlags & eFlagEMAC)) WrError(ErrNum_InstructionNotSupported);
else if (!DecodeMACACC(ArgStr[1].str.p_str, &ACCReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
else
{
tAdrResult AdrResult;
if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
{
WAsmCode[0] = 0xa1c0 | AdrResult.AdrPart | (ACCReg << 9);
CodeLen = 2;
}
}
}
static void DecodeMxxAC(Word Code)
{
Word Rx, Ry, Ux, Uy, Scale = 0, ACCx, ACCw;
tAdrResult AdrResult;
if (!(pCurrCPUProps->SuppFlags & eFlagEMAC)
|| (pCurrCPUProps->CfISA < eCfISA_B))
{
WrError(ErrNum_InstructionNotSupported);
return;
}
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit))
{
WrError(ErrNum_InvOpSize);
return;
}
if (!ChkArgCnt(4, 5))
return;
if (!DecodeMACACC(ArgStr[ArgCnt - 1].str.p_str, &ACCx))
{
WrStrErrorPos(ErrNum_InvReg, &ArgStr[ArgCnt - 1]);
return;
}
if (!DecodeMACACC(ArgStr[ArgCnt].str.p_str, &ACCw))
{
WrStrErrorPos(ErrNum_InvReg, &ArgStr[ArgCnt]);
return;
}
if (5 == ArgCnt)
{
if (!DecodeMACScale(&ArgStr[3], &Scale))
{
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[3]);
return;
}
}
if (OpSize == eSymbolSize16Bit)
{
if (!SplitMACUpperLower(&Uy, &ArgStr[1])
|| !SplitMACUpperLower(&Ux, &ArgStr[2]))
return;
}
else
Ux = Uy = 0;
if (!DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
return;
Ry = AdrResult.AdrPart & 15;
if (!DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
return;
Rx = AdrResult.AdrPart & 15;
WAsmCode[0] = 0xa000 | ((Rx & 7) << 9) | ((Rx & 8) << 3) | Ry | ((ACCx & 1) << 7);
WAsmCode[1] = Code | ((OpSize - 1) << 11) | (Scale << 9) | (Ux << 7) | (Uy << 6) | ((ACCx & 2) << 3) | (ACCw << 2);
CodeLen = 4;
}
static void DecodeCPBCBUSY(Word Code)
{
if (pCurrCPUProps->CfISA == eCfISA_None) WrError(ErrNum_InstructionNotSupported);
else if (*AttrPart.str.p_str && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else if (ChkArgCnt(1, 1))
{
Boolean OK;
tSymbolFlags Flags;
LongInt Dist;
Dist = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags) - (EProgCounter() + 2);
if (OK)
{
if (!mSymbolQuestionable(Flags) && !IsDisp16(Dist)) WrError(ErrNum_JmpDistTooBig);
else
{
WAsmCode[0] = Code;
WAsmCode[1] = Dist & 0xffff;
CodeLen = 4;
}
}
}
}
static void DecodeCPLDST(Word Code)
{
if (pCurrCPUProps->CfISA == eCfISA_None) WrError(ErrNum_InstructionNotSupported);
else if (ChkArgCnt(1, 4))
{
Boolean OK;
Word Reg;
const tStrComp *pEAArg = NULL, *pRnArg = NULL, *pETArg = NULL;
WAsmCode[0] = Code | (OpSize << 6);
/* CMD is always present and i bits 0..8 - immediate marker is optional
since it is always a constant. */
WAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[ArgCnt], !!(*ArgStr[ArgCnt].str.p_str == '#'), UInt16, &OK);
if (!OK)
return;
if (ArgCnt >= 2)
pEAArg = &ArgStr[1];
switch (ArgCnt)
{
case 4:
pRnArg = &ArgStr[2];
pETArg = &ArgStr[3];
break;
case 3:
if (DecodeReg(&ArgStr[2], &Reg, False) == eIsReg)
pRnArg = &ArgStr[2];
else
pETArg = &ArgStr[2];
break;
}
if (pRnArg)
{
if (DecodeReg(pRnArg, &Reg, True) != eIsReg)
return;
WAsmCode[1] |= Reg << 12;
}
if (pETArg)
{
Word ET;
ET = EvalStrIntExpression(pETArg, UInt3, &OK);
if (!OK)
return;
WAsmCode[1] |= ET << 9;
}
if (pEAArg)
{
tAdrResult AdrResult;
if (!DecodeAdr(pEAArg, MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI, &AdrResult))
return;
WAsmCode[0] |= AdrResult.AdrPart;
CopyAdrVals(WAsmCode + 2, &AdrResult);
CodeLen = 4 + AdrResult.Cnt;
}
else
CodeLen = 4;
}
}
static void DecodeCPNOP(Word Code)
{
if (pCurrCPUProps->CfISA == eCfISA_None) WrError(ErrNum_InstructionNotSupported);
else if (ChkArgCnt(0, 1))
{
WAsmCode[0] = Code | (OpSize << 6);
/* CMD is always present and i bits 0..8 - immediate marker is optional
since it is always a constant. */
if (ArgCnt > 0)
{
Word ET;
Boolean OK;
ET = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
if (!OK)
return;
WAsmCode[1] |= ET << 9;
}
CodeLen = 4;
}
}
/*-------------------------------------------------------------------------*/
/* Dekodierroutinen Pseudoinstruktionen: */
static void PutByte(Byte b)
{
if ((CodeLen & 1) && !HostBigEndian)
{
BAsmCode[CodeLen] = BAsmCode[CodeLen - 1];
BAsmCode[CodeLen - 1] = b;
}
else
{
BAsmCode[CodeLen] = b;
}
CodeLen++;
}
static void DecodeSTR(Word Index)
{
int l, z;
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (((l
= strlen(ArgStr
[1].
str.
p_str)) < 2)
|| (*ArgStr[1].str.p_str != '\'')
|| (ArgStr[1].str.p_str[l - 1] != '\'')) WrStrErrorPos(ErrNum_ExpectString, &ArgStr[1]);
else
{
PutByte(l - 2);
for (z = 1; z < l - 1; z++)
PutByte(as_chartrans_xlate(CurrTransTable->p_table, ((usint) ArgStr[1].str.p_str[z]) & 0xff));
}
}
/*-------------------------------------------------------------------------*/
/* Codetabellenverwaltung */
static void AddFixed(const char *NName, Word NCode, Boolean NSup, unsigned NMask)
{
order_array_rsv_end(FixedOrders, FixedOrder);
FixedOrders[InstrZ].Code = NCode;
FixedOrders[InstrZ].MustSup = NSup;
FixedOrders[InstrZ].FamilyMask = NMask;
AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
}
static void AddCond(const char *NName, Byte NCode)
{
char TmpName[30];
if (NCode >= 2) /* BT is BRA and BF is BSR */
{
as_snprintf(TmpName, sizeof(TmpName), "B%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeBcc);
}
as_snprintf(TmpName, sizeof(TmpName), "S%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeScc);
as_snprintf(TmpName, sizeof(TmpName), "DB%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeDBcc);
as_snprintf(TmpName, sizeof(TmpName), "TRAP%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeTRAPcc);
}
static void AddFPUOp(const char *NName, Byte NCode, Boolean NDya, tSuppFlags NeedFlags)
{
order_array_rsv_end(FPUOps, FPUOp);
FPUOps[InstrZ].Code = NCode;
FPUOps[InstrZ].Dya = NDya;
FPUOps[InstrZ].NeedsSuppFlags = NeedFlags;
AddInstTable(InstTable, NName, InstrZ++, DecodeFPUOp);
}
static void AddFPUCond(const char *NName, Byte NCode)
{
char TmpName[30];
as_snprintf(TmpName, sizeof(TmpName), "FB%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeFBcc);
as_snprintf(TmpName, sizeof(TmpName), "FDB%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeFDBcc);
as_snprintf(TmpName, sizeof(TmpName), "FS%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeFScc);
as_snprintf(TmpName, sizeof(TmpName), "FTRAP%s", NName);
AddInstTable(InstTable, TmpName, NCode, DecodeFTRAPcc);
}
static void AddPMMUCond(const char *NName)
{
char TmpName[30];
as_snprintf(TmpName, sizeof(TmpName), "PB%s", NName);
AddInstTable(InstTable, TmpName, InstrZ, DecodePBcc);
as_snprintf(TmpName, sizeof(TmpName), "PDB%s", NName);
AddInstTable(InstTable, TmpName, InstrZ, DecodePDBcc);
as_snprintf(TmpName, sizeof(TmpName), "PS%s", NName);
AddInstTable(InstTable, TmpName, InstrZ, DecodePScc);
as_snprintf(TmpName, sizeof(TmpName), "PTRAP%s", NName);
AddInstTable(InstTable, TmpName, InstrZ, DecodePTRAPcc);
InstrZ++;
}
static void AddPMMUReg(const char *Name, tSymbolSize Size, Word Code)
{
order_array_rsv_end(PMMURegs, PMMUReg);
PMMURegs[InstrZ].pName = Name;
PMMURegs[InstrZ].Size = Size;
PMMURegs[InstrZ++].Code = Code;
}
static void InitFields(void)
{
InstTable = CreateInstTable(607);
SetDynamicInstTable(InstTable);
AddInstTable(InstTable, "MOVE" , Std_Variant, DecodeMOVE);
AddInstTable(InstTable, "MOVEA" , A_Variant, DecodeMOVE);
AddInstTable(InstTable, "MOVEI" , I_Variant, DecodeMOVE);
AddInstTable(InstTable, "LEA" , 0, DecodeLEA);
AddInstTable(InstTable, "ASR" , 0, DecodeShift);
AddInstTable(InstTable, "ASL" , 4, DecodeShift);
AddInstTable(InstTable, "LSR" , 1, DecodeShift);
AddInstTable(InstTable, "LSL" , 5, DecodeShift);
AddInstTable(InstTable, "ROXR" , 2, DecodeShift);
AddInstTable(InstTable, "ROXL" , 6, DecodeShift);
AddInstTable(InstTable, "ROR" , 3, DecodeShift);
AddInstTable(InstTable, "ROL" , 7, DecodeShift);
AddInstTable(InstTable, "ADDQ" , 0, DecodeADDQSUBQ);
AddInstTable(InstTable, "SUBQ" , 1, DecodeADDQSUBQ);
AddInstTable(InstTable, "ADDX" , 1, DecodeADDXSUBX);
AddInstTable(InstTable, "SUBX" , 0, DecodeADDXSUBX);
AddInstTable(InstTable, "CMPM" , 0, DecodeCMPM);
AddInstTable(InstTable, "SUB" , Std_Variant + 0, DecodeADDSUBCMP);
AddInstTable(InstTable, "CMP" , Std_Variant + 1, DecodeADDSUBCMP);
AddInstTable(InstTable, "ADD" , Std_Variant + 2, DecodeADDSUBCMP);
AddInstTable(InstTable, "SUBI" , I_Variant + 0, DecodeADDSUBCMP);
AddInstTable(InstTable, "CMPI" , I_Variant + 1, DecodeADDSUBCMP);
AddInstTable(InstTable, "ADDI" , I_Variant + 2, DecodeADDSUBCMP);
AddInstTable(InstTable, "SUBA" , A_Variant + 0, DecodeADDSUBCMP);
AddInstTable(InstTable, "CMPA" , A_Variant + 1, DecodeADDSUBCMP);
AddInstTable(InstTable, "ADDA" , A_Variant + 2, DecodeADDSUBCMP);
AddInstTable(InstTable, "AND" , Std_Variant + 1, DecodeANDOR);
AddInstTable(InstTable, "OR" , Std_Variant + 0, DecodeANDOR);
AddInstTable(InstTable, "ANDI" , I_Variant + 1, DecodeANDOR);
AddInstTable(InstTable, "ORI" , I_Variant + 0, DecodeANDOR);
AddInstTable(InstTable, "EOR" , Std_Variant, DecodeEOR);
AddInstTable(InstTable, "EORI" , I_Variant, DecodeEOR);
AddInstTable(InstTable, "PEA" , 0, DecodePEA);
AddInstTable(InstTable, "CLR" , 0, DecodeCLRTST);
AddInstTable(InstTable, "TST" , 1, DecodeCLRTST);
AddInstTable(InstTable, "JSR" , 0, DecodeJSRJMP);
AddInstTable(InstTable, "JMP" , 1, DecodeJSRJMP);
AddInstTable(InstTable, "TAS" , 0, DecodeNBCDTAS);
AddInstTable(InstTable, "NBCD" , 1, DecodeNBCDTAS);
AddInstTable(InstTable, "NEGX" , 0, DecodeNEGNOT);
AddInstTable(InstTable, "NEG" , 2, DecodeNEGNOT);
AddInstTable(InstTable, "NOT" , 3, DecodeNEGNOT);
AddInstTable(InstTable, "SWAP" , 0, DecodeSWAP);
AddInstTable(InstTable, "UNLK" , 0, DecodeUNLK);
AddInstTable(InstTable, "EXT" , 0, DecodeEXT);
AddInstTable(InstTable, "WDDATA" , 0, DecodeWDDATA);
AddInstTable(InstTable, "WDEBUG" , 0, DecodeWDEBUG);
AddInstTable(InstTable, "MOVEM" , 0, DecodeMOVEM);
AddInstTable(InstTable, "MOVEQ" , 0, DecodeMOVEQ);
AddInstTable(InstTable, "STOP" , 0, DecodeSTOP);
AddInstTable(InstTable, "LPSTOP" , 0, DecodeLPSTOP);
AddInstTable(InstTable, "TRAP" , 0, DecodeTRAP);
AddInstTable(InstTable, "BKPT" , 0, DecodeBKPT);
AddInstTable(InstTable, "RTD" , 0, DecodeRTD);
AddInstTable(InstTable, "EXG" , 0, DecodeEXG);
AddInstTable(InstTable, "MOVE16" , 0, DecodeMOVE16);
AddInstTable(InstTable, "MULU" , 0x0000, DecodeMUL_DIV);
AddInstTable(InstTable, "MULS" , 0x0100, DecodeMUL_DIV);
AddInstTable(InstTable, "DIVU" , 0x0001, DecodeMUL_DIV);
AddInstTable(InstTable, "DIVS" , 0x0101, DecodeMUL_DIV);
AddInstTable(InstTable, "DIVUL" , 0, DecodeDIVL);
AddInstTable(InstTable, "DIVSL" , 1, DecodeDIVL);
AddInstTable(InstTable, "ABCD" , 1, DecodeASBCD);
AddInstTable(InstTable, "SBCD" , 0, DecodeASBCD);
AddInstTable(InstTable, "CHK" , 0, DecodeCHK);
AddInstTable(InstTable, "LINK" , 0, DecodeLINK);
AddInstTable(InstTable, "MOVEP" , 0, DecodeMOVEP);
AddInstTable(InstTable, "MOVEC" , 0, DecodeMOVEC);
AddInstTable(InstTable, "MOVES" , 0, DecodeMOVES);
AddInstTable(InstTable, "CALLM" , 0, DecodeCALLM);
AddInstTable(InstTable, "CAS" , 0, DecodeCAS);
AddInstTable(InstTable, "CAS2" , 0, DecodeCAS2);
AddInstTable(InstTable, "CMP2" , 0, DecodeCMPCHK2);
AddInstTable(InstTable, "CHK2" , 1, DecodeCMPCHK2);
AddInstTable(InstTable, "EXTB" , 0, DecodeEXTB);
AddInstTable(InstTable, "PACK" , 0, DecodePACK);
AddInstTable(InstTable, "UNPK" , 1, DecodePACK);
AddInstTable(InstTable, "RTM" , 0, DecodeRTM);
AddInstTable(InstTable, "TBLU" , 0, DecodeTBL);
AddInstTable(InstTable, "TBLUN" , 1, DecodeTBL);
AddInstTable(InstTable, "TBLS" , 2, DecodeTBL);
AddInstTable(InstTable, "TBLSN" , 3, DecodeTBL);
AddInstTable(InstTable, "BTST" , 0, DecodeBits);
AddInstTable(InstTable, "BSET" , 3, DecodeBits);
AddInstTable(InstTable, "BCLR" , 2, DecodeBits);
AddInstTable(InstTable, "BCHG" , 1, DecodeBits);
AddInstTable(InstTable, "BFTST" , 0, DecodeFBits);
AddInstTable(InstTable, "BFSET" , 3, DecodeFBits);
AddInstTable(InstTable, "BFCLR" , 2, DecodeFBits);
AddInstTable(InstTable, "BFCHG" , 1, DecodeFBits);
AddInstTable(InstTable, "BFEXTU" , 0, DecodeEBits);
AddInstTable(InstTable, "BFEXTS" , 1, DecodeEBits);
AddInstTable(InstTable, "BFFFO" , 2, DecodeEBits);
AddInstTable(InstTable, "BFINS" , 0, DecodeBFINS);
AddInstTable(InstTable, "CINVA" , 0, DecodeCacheAll);
AddInstTable(InstTable, "CPUSHA" , 1, DecodeCacheAll);
AddInstTable(InstTable, "CINVL" , 1, DecodeCache);
AddInstTable(InstTable, "CPUSHL" , 5, DecodeCache);
AddInstTable(InstTable, "CINVP" , 2, DecodeCache);
AddInstTable(InstTable, "CPUSHP" , 6, DecodeCache);
AddInstTable(InstTable, "STR" , 0, DecodeSTR);
InstrZ = 0;
AddFixed("NOP" , 0x4e71, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
AddFixed("RESET" , 0x4e70, True, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32));
AddFixed("ILLEGAL", 0x4afc, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
AddFixed("TRAPV" , 0x4e76, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32));
AddFixed("RTE" , 0x4e73, True , (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
AddFixed("RTR" , 0x4e77, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32));
AddFixed("RTS" , 0x4e75, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
AddFixed("BGND" , 0x4afa, False, (1 << eCPU32));
AddFixed("HALT" , 0x4ac8, True , (1 << eColdfire));
AddFixed("PULSE" , 0x4acc, True , (1 << eColdfire));
AddCond("T" , 0); AddCond("F" , 1); AddCond("HI", 2); AddCond("LS", 3);
AddCond("CC", 4); AddCond("CS", 5); AddCond("NE", 6); AddCond("EQ", 7);
AddCond("VC", 8); AddCond("VS", 9); AddCond("PL",10); AddCond("MI",11);
AddCond("GE",12); AddCond("LT",13); AddCond("GT",14); AddCond("LE",15);
AddCond("HS", 4); AddCond("LO", 5);
AddInstTable(InstTable, "BRA", 0, DecodeBcc);
AddInstTable(InstTable, "BSR", 1, DecodeBcc);
AddInstTable(InstTable, "DBRA", 1, DecodeDBcc);
InstrZ = 0;
AddFPUOp("FINT" , 0x01, False, eFlagNone ); AddFPUOp("FSINH" , 0x02, False, eFlagExtFPU);
AddFPUOp("FINTRZ" , 0x03, False, eFlagNone ); AddFPUOp("FSQRT" , 0x04, False, eFlagNone );
AddFPUOp("FSSQRT" , 0x41, False, eFlagIntFPU); AddFPUOp("FDSQRT" , 0x45, False, eFlagIntFPU);
AddFPUOp("FLOGNP1", 0x06, False, eFlagExtFPU); AddFPUOp("FETOXM1", 0x08, False, eFlagExtFPU);
AddFPUOp("FTANH" , 0x09, False, eFlagExtFPU); AddFPUOp("FATAN" , 0x0a, False, eFlagExtFPU);
AddFPUOp("FASIN" , 0x0c, False, eFlagExtFPU); AddFPUOp("FATANH" , 0x0d, False, eFlagExtFPU);
AddFPUOp("FSIN" , 0x0e, False, eFlagExtFPU); AddFPUOp("FTAN" , 0x0f, False, eFlagExtFPU);
AddFPUOp("FETOX" , 0x10, False, eFlagExtFPU); AddFPUOp("FTWOTOX", 0x11, False, eFlagExtFPU);
AddFPUOp("FTENTOX", 0x12, False, eFlagExtFPU); AddFPUOp("FLOGN" , 0x14, False, eFlagExtFPU);
AddFPUOp("FLOG10" , 0x15, False, eFlagExtFPU); AddFPUOp("FLOG2" , 0x16, False, eFlagExtFPU);
AddFPUOp("FABS" , 0x18, False, eFlagNone ); AddFPUOp("FSABS" , 0x58, False, eFlagIntFPU);
AddFPUOp("FDABS" , 0x5c, False, eFlagIntFPU); AddFPUOp("FCOSH" , 0x19, False, eFlagExtFPU);
AddFPUOp("FNEG" , 0x1a, False, eFlagNone ); AddFPUOp("FACOS" , 0x1c, False, eFlagExtFPU);
AddFPUOp("FCOS" , 0x1d, False, eFlagExtFPU); AddFPUOp("FGETEXP", 0x1e, False, eFlagExtFPU);
AddFPUOp("FGETMAN", 0x1f, False, eFlagExtFPU); AddFPUOp("FDIV" , 0x20, True , eFlagNone );
AddFPUOp("FSDIV" , 0x60, False, eFlagIntFPU); AddFPUOp("FDDIV" , 0x64, True , eFlagIntFPU);
AddFPUOp("FMOD" , 0x21, True , eFlagExtFPU); AddFPUOp("FADD" , 0x22, True , eFlagNone );
AddFPUOp("FSADD" , 0x62, True , eFlagIntFPU); AddFPUOp("FDADD" , 0x66, True , eFlagIntFPU);
AddFPUOp("FMUL" , 0x23, True , eFlagNone ); AddFPUOp("FSMUL" , 0x63, True , eFlagIntFPU);
AddFPUOp("FDMUL" , 0x67, True , eFlagIntFPU); AddFPUOp("FSGLDIV", 0x24, True , eFlagExtFPU);
AddFPUOp("FREM" , 0x25, True , eFlagExtFPU); AddFPUOp("FSCALE" , 0x26, True , eFlagExtFPU);
AddFPUOp("FSGLMUL", 0x27, True , eFlagExtFPU); AddFPUOp("FSUB" , 0x28, True , eFlagNone );
AddFPUOp("FSSUB" , 0x68, True , eFlagIntFPU); AddFPUOp("FDSUB" , 0x6c, True , eFlagIntFPU);
AddFPUOp("FCMP" , 0x38, True , eFlagNone );
AddInstTable(InstTable, "FSAVE", 0, DecodeFSAVE);
AddInstTable(InstTable, "FRESTORE", 0, DecodeFRESTORE);
AddInstTable(InstTable, "FNOP", 0, DecodeFNOP);
AddInstTable(InstTable, "FMOVE", 0, DecodeFMOVE);
AddInstTable(InstTable, "FMOVECR", 0, DecodeFMOVECR);
AddInstTable(InstTable, "FTST", 0, DecodeFTST);
AddInstTable(InstTable, "FSINCOS", 0, DecodeFSINCOS);
AddInstTable(InstTable, "FDMOVE", 0x0044, DecodeFDMOVE_FSMOVE);
AddInstTable(InstTable, "FSMOVE", 0x0040, DecodeFDMOVE_FSMOVE);
AddInstTable(InstTable, "FMOVEM", 0, DecodeFMOVEM);
AddFPUCond("EQ" , 0x01); AddFPUCond("NE" , 0x0e);
AddFPUCond("GT" , 0x12); AddFPUCond("NGT" , 0x1d);
AddFPUCond("GE" , 0x13); AddFPUCond("NGE" , 0x1c);
AddFPUCond("LT" , 0x14); AddFPUCond("NLT" , 0x1b);
AddFPUCond("LE" , 0x15); AddFPUCond("NLE" , 0x1a);
AddFPUCond("GL" , 0x16); AddFPUCond("NGL" , 0x19);
AddFPUCond("GLE" , 0x17); AddFPUCond("NGLE", 0x18);
AddFPUCond("OGT" , 0x02); AddFPUCond("ULE" , 0x0d);
AddFPUCond("OGE" , 0x03); AddFPUCond("ULT" , 0x0c);
AddFPUCond("OLT" , 0x04); AddFPUCond("UGE" , 0x0b);
AddFPUCond("OLE" , 0x05); AddFPUCond("UGT" , 0x0a);
AddFPUCond("OGL" , 0x06); AddFPUCond("UEQ" , 0x09);
AddFPUCond("OR" , 0x07); AddFPUCond("UN" , 0x08);
AddFPUCond("F" , 0x00); AddFPUCond("T" , 0x0f);
AddFPUCond("SF" , 0x10); AddFPUCond("ST" , 0x1f);
AddFPUCond("SEQ" , 0x11); AddFPUCond("SNE" , 0x1e);
AddPMMUCond("BS"); AddPMMUCond("BC"); AddPMMUCond("LS"); AddPMMUCond("LC");
AddPMMUCond("SS"); AddPMMUCond("SC"); AddPMMUCond("AS"); AddPMMUCond("AC");
AddPMMUCond("WS"); AddPMMUCond("WC"); AddPMMUCond("IS"); AddPMMUCond("IC");
AddPMMUCond("GS"); AddPMMUCond("GC"); AddPMMUCond("CS"); AddPMMUCond("CC");
AddInstTable(InstTable, "PSAVE", 0, DecodePSAVE);
AddInstTable(InstTable, "PRESTORE", 0, DecodePRESTORE);
AddInstTable(InstTable, "PFLUSHA", 0, DecodePFLUSHA);
AddInstTable(InstTable, "PFLUSHAN", 0, DecodePFLUSHAN);
AddInstTable(InstTable, "PFLUSH", 0x0000, DecodePFLUSH_PFLUSHS);
AddInstTable(InstTable, "PFLUSHS", 0x0400, DecodePFLUSH_PFLUSHS);
AddInstTable(InstTable, "PFLUSHN", 0, DecodePFLUSHN);
AddInstTable(InstTable, "PFLUSHR", 0, DecodePFLUSHR);
AddInstTable(InstTable, "PLOADR", 0x2200, DecodePLOADR_PLOADW);
AddInstTable(InstTable, "PLOADW", 0x2000, DecodePLOADR_PLOADW);
AddInstTable(InstTable, "PMOVE", 0x0000, DecodePMOVE_PMOVEFD);
AddInstTable(InstTable, "PMOVEFD", 0x0100, DecodePMOVE_PMOVEFD);
AddInstTable(InstTable, "PTESTR", 1, DecodePTESTR_PTESTW);
AddInstTable(InstTable, "PTESTW", 0, DecodePTESTR_PTESTW);
AddInstTable(InstTable, "PVALID", 0, DecodePVALID);
AddInstTable(InstTable, "BITREV", 0x00c0, DecodeColdBit);
AddInstTable(InstTable, "BYTEREV", 0x02c0, DecodeColdBit);
AddInstTable(InstTable, "FF1", 0x04c0, DecodeColdBit);
AddInstTable(InstTable, "STLDSR", 0x0000, DecodeSTLDSR);
AddInstTable(InstTable, "INTOUCH", 0x0000, DecodeINTOUCH);
AddInstTable(InstTable, "MOV3Q", 0x0000, DecodeMOV3Q);
/* MOVEI? */
AddInstTable(InstTable, "MVS", 0x7100, DecodeMVS_MVZ);
AddInstTable(InstTable, "MVZ", 0x7180, DecodeMVS_MVZ);
AddInstTable(InstTable, "SATS", 0x0000, DecodeSATS);
AddInstTable(InstTable, "MAC" , 0x0000, DecodeMAC_MSAC);
AddInstTable(InstTable, "MSAC", 0x0100, DecodeMAC_MSAC);
AddInstTable(InstTable, "MACL" , 0x8000, DecodeMAC_MSAC);
AddInstTable(InstTable, "MSACL", 0x8100, DecodeMAC_MSAC);
AddInstTable(InstTable, "MOVCLR" , 0x0000, DecodeMOVCLR);
AddInstTable(InstTable, "MAAAC" , 0x0001, DecodeMxxAC);
AddInstTable(InstTable, "MASAC" , 0x0003, DecodeMxxAC);
AddInstTable(InstTable, "MSAAC" , 0x0101, DecodeMxxAC);
AddInstTable(InstTable, "MSSAC" , 0x0103, DecodeMxxAC);
AddInstTable(InstTable, "CP0BCBUSY", 0xfcc0, DecodeCPBCBUSY);
AddInstTable(InstTable, "CP1BCBUSY", 0xfec0, DecodeCPBCBUSY);
AddInstTable(InstTable, "CP0LD", 0xfc00, DecodeCPLDST);
AddInstTable(InstTable, "CP1LD", 0xfe00, DecodeCPLDST);
AddInstTable(InstTable, "CP0ST", 0xfd00, DecodeCPLDST);
AddInstTable(InstTable, "CP1ST", 0xff00, DecodeCPLDST);
AddInstTable(InstTable, "CP0NOP", 0xfc00, DecodeCPNOP);
AddInstTable(InstTable, "CP1NOP", 0xfe00, DecodeCPNOP);
InstrZ = 0;
AddPMMUReg("TC" , eSymbolSize32Bit, 16); AddPMMUReg("DRP" , eSymbolSize64Bit, 17);
AddPMMUReg("SRP" , eSymbolSize64Bit, 18); AddPMMUReg("CRP" , eSymbolSize64Bit, 19);
AddPMMUReg("CAL" , eSymbolSize8Bit, 20); AddPMMUReg("VAL" , eSymbolSize8Bit, 21);
AddPMMUReg("SCC" , eSymbolSize8Bit, 22); AddPMMUReg("AC" , eSymbolSize16Bit, 23);
AddPMMUReg("PSR" , eSymbolSize16Bit, 24); AddPMMUReg("PCSR" , eSymbolSize16Bit, 25);
AddPMMUReg("TT0" , eSymbolSize32Bit, 2); AddPMMUReg("TT1" , eSymbolSize32Bit, 3);
AddPMMUReg("MMUSR", eSymbolSize16Bit, 24); AddPMMUReg(NULL , eSymbolSizeUnknown, 0);
AddInstTable(InstTable, "REG", 0, CodeREG);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
order_array_free(FixedOrders);
order_array_free(FPUOps);
order_array_free(PMMURegs);
}
/*-------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn InternSymbol_68K(char *pArg, TempResult *pResult)
* \brief handle built-in (register) symbols for 68K
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_68K(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_68K;
pResult->Contents.RegDescr.compare = compare_reg_68k;
}
else if (DecodeFPRegCore(pArg, &RegNum))
{
pResult->Typ = TempReg;
pResult->DataSize = NativeFloatSize;
pResult->Contents.RegDescr.Reg = RegNum;
pResult->Contents.RegDescr.Dissect = DissectReg_68K;
pResult->Contents.RegDescr.compare = compare_reg_68k;
}
}
static Boolean DecodeAttrPart_68K(void)
{
return DecodeMoto16AttrSize(*AttrPart.str.p_str, &AttrPartOpSize[0], False);
}
static void MakeCode_68K(void)
{
CodeLen = 0;
OpSize = (AttrPartOpSize[0] != eSymbolSizeUnknown)
? AttrPartOpSize[0]
: ((pCurrCPUProps->Family == eColdfire) ? eSymbolSize32Bit : eSymbolSize16Bit);
DontPrint = False; RelPos = 2;
/* Nullanweisung */
if ((*OpPart.str.p_str == '\0') && !*AttrPart.str.p_str && (ArgCnt == 0))
return;
/* Pseudoanweisungen */
if (DecodeMoto16Pseudo(OpSize, True))
return;
/* Befehlszaehler ungerade ? */
if (Odd(EProgCounter()))
{
if (DoPadding)
InsertPadding(1, False);
else
WrError(ErrNum_AddrNotAligned);
}
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_68K(void)
{
return Memo("REG");
}
static void SwitchTo_68K(void *pUser)
{
TurnWords = True;
SetIntConstMode(eIntConstModeMoto);
PCSymbol = "*";
HeaderID = 0x01;
NOPCode = 0x4e71;
DivideChars = ",";
HasAttrs = True;
AttrChars = ".";
ValidSegs = (1 << SegCode);
Grans[SegCode] = 1;
ListGrans[SegCode] = 2;
SegInits[SegCode] = 0;
SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
pCurrCPUProps = (const tCPUProps*)pUser;
DecodeAttrPart = DecodeAttrPart_68K;
MakeCode = MakeCode_68K;
IsDef = IsDef_68K;
DissectReg = DissectReg_68K;
InternSymbol = InternSymbol_68K;
SwitchFrom = DeinitFields;
InitFields();
onoff_fpu_add();
onoff_pmmu_add();
onoff_supmode_add();
if (onoff_test_and_set(e_onoff_reg_fullpmmu))
SetFlag(&FullPMMU, FullPMMUName, True);
AddONOFF(FullPMMUName, &FullPMMU , FullPMMUName , False);
AddMoto16PseudoONOFF(True);
SetFlag(&FullPMMU, FullPMMUName, !(pCurrCPUProps->SuppFlags & eFlagIntPMMU));
NativeFloatSize = (pCurrCPUProps->Family == eColdfire) ? eSymbolSizeFloat64Bit : eSymbolSizeFloat96Bit;
}
static const tCtReg CtRegs_40[] =
{
{ "TC" , 0x003 },
{ "ITT0" , 0x004 },
{ "ITT1" , 0x005 },
{ "DTT0" , 0x006 },
{ "DTT1" , 0x007 },
{ "MMUSR", 0x805 },
{ "URP" , 0x806 },
{ "SRP" , 0x807 },
{ "IACR0", 0x004 },
{ "IACR1", 0x005 },
{ "DACR0", 0x006 },
{ "DACR1", 0x007 },
{ NULL , 0x000 },
},
CtRegs_2030[] =
{
{ "CAAR" , 0x802 },
{ NULL , 0x000 },
},
CtRegs_2040[] =
{
{ "CACR" , 0x002 },
{ "MSP" , 0x803 },
{ "ISP" , 0x804 },
{ NULL , 0x000 },
},
CtRegs_1040[] =
{
{ "SFC" , 0x000 },
{ "DFC" , 0x001 },
{ "USP" , 0x800 },
{ "VBR" , 0x801 },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_5202[] =
{
{ "CACR" , 0x002 },
{ "ACR0" , 0x004 },
{ "ACR1" , 0x005 },
{ "VBR" , 0x801 },
{ "SR" , 0x80e },
{ "PC" , 0x80f },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_5202_5204[] =
{
{ "RAMBAR" , 0xc04 },
{ "MBAR" , 0xc0f },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_5202_5208[] =
{
{ "RGPIOBAR", 0x009},
{ "RAMBAR" , 0xc05 },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_5202_5307[] =
{
{ "ACR2" , 0x006 },
{ "ACR3" , 0x007 },
{ "RAMBAR0", 0xc04 },
{ "RAMBAR1", 0xc05 },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_5202_5329[] =
{
{ "RAMBAR" , 0xc05 },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_5202_5407[] =
{
{ "ACR2" , 0x006 },
{ "ACR3" , 0x007 },
{ "RAMBAR0", 0xc04 },
{ "RAMBAR1", 0xc05 },
{ "MBAR" , 0xc0f },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_Cf_CPU[] =
{
{ "D0_LOAD" , 0x080 },
{ "D1_LOAD" , 0x081 },
{ "D2_LOAD" , 0x082 },
{ "D3_LOAD" , 0x083 },
{ "D4_LOAD" , 0x084 },
{ "D5_LOAD" , 0x085 },
{ "D6_LOAD" , 0x086 },
{ "D7_LOAD" , 0x087 },
{ "A0_LOAD" , 0x088 },
{ "A1_LOAD" , 0x089 },
{ "A2_LOAD" , 0x08a },
{ "A3_LOAD" , 0x08b },
{ "A4_LOAD" , 0x08c },
{ "A5_LOAD" , 0x08d },
{ "A6_LOAD" , 0x08e },
{ "A7_LOAD" , 0x08f },
{ "D0_STORE" , 0x180 },
{ "D1_STORE" , 0x181 },
{ "D2_STORE" , 0x182 },
{ "D3_STORE" , 0x183 },
{ "D4_STORE" , 0x184 },
{ "D5_STORE" , 0x185 },
{ "D6_STORE" , 0x186 },
{ "D7_STORE" , 0x187 },
{ "A0_STORE" , 0x188 },
{ "A1_STORE" , 0x189 },
{ "A2_STORE" , 0x18a },
{ "A3_STORE" , 0x18b },
{ "A4_STORE" , 0x18c },
{ "A5_STORE" , 0x18d },
{ "A6_STORE" , 0x18e },
{ "A7_STORE" , 0x18f },
{ "OTHER_A7" , 0x800 },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_Cf_EMAC[] =
{
{ "MACSR" , 0x804 },
{ "MASK" , 0x805 },
{ "ACC0" , 0x806 },
{ "ACCEXT01" , 0x807 },
{ "ACCEXT23" , 0x808 },
{ "ACC1" , 0x809 },
{ "ACC2" , 0x80a },
{ "ACC3" , 0x80b },
{ NULL , 0x000 },
};
static const tCtReg CtRegs_MCF51[] =
{
{ "VBR" , 0x801 },
{ "CPUCR" , 0x802 },
{ NULL , 0x000 },
};
static const tCPUProps CPUProps[] =
{
/* 68881/68882 may be attached memory-mapped and emulated on pre-68020 devices */
{ "68008", 0x000ffffful, e68KGen1a, eCfISA_None , eFlagExtFPU | eFlagLogCCR, { NULL } },
{ "68000", 0x00fffffful, e68KGen1a, eCfISA_None , eFlagExtFPU | eFlagLogCCR, { NULL } },
{ "68010", 0x00fffffful, e68KGen1b, eCfISA_None , eFlagExtFPU | eFlagLogCCR, { CtRegs_1040 } },
{ "68012", 0x7ffffffful, e68KGen1b, eCfISA_None , eFlagExtFPU | eFlagLogCCR, { CtRegs_1040 } },
{ "MCF5202", 0xfffffffful, eColdfire, eCfISA_A , eFlagIntFPU | eFlagIdxScaling, { CtRegs_5202 } },
{ "MCF5204", 0xfffffffful, eColdfire, eCfISA_A , eFlagIntFPU | eFlagIdxScaling, { CtRegs_5202, CtRegs_5202_5204 } },
{ "MCF5206", 0xfffffffful, eColdfire, eCfISA_A , eFlagIntFPU | eFlagIdxScaling, { CtRegs_5202, CtRegs_5202_5204 } },
{ "MCF5208", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5208, CtRegs_Cf_CPU, CtRegs_Cf_EMAC } }, /* V2 */
{ "MCF52274", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5208, CtRegs_Cf_CPU, CtRegs_Cf_EMAC } }, /* V2 */
{ "MCF52277", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5208, CtRegs_Cf_CPU, CtRegs_Cf_EMAC } }, /* V2 */
{ "MCF5307", 0xfffffffful, eColdfire, eCfISA_A , eFlagIntFPU | eFlagIdxScaling | eFlagMAC, { CtRegs_5202, CtRegs_5202_5307 } }, /* V3 */
{ "MCF5329", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5329 } }, /* V3 */
{ "MCF5373", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5329 } }, /* V3 */
{ "MCF5407", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4 */
{ "MCF5470", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
{ "MCF5471", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
{ "MCF5472", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
{ "MCF5473", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
{ "MCF5474", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
{ "MCF5475", 0xfffffffful, eColdfire, eCfISA_B , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
{ "MCF51QM", 0xfffffffful, eColdfire, eCfISA_C , eFlagBranch32 | eFlagMAC | eFlagIdxScaling | eFlagEMAC, { CtRegs_MCF51 } }, /* V1 */
{ "68332", 0xfffffffful, eCPU32 , eCfISA_None , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling, { CtRegs_1040 } },
{ "68340", 0xfffffffful, eCPU32 , eCfISA_None , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling, { CtRegs_1040 } },
{ "68360", 0xfffffffful, eCPU32 , eCfISA_None , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling, { CtRegs_1040 } },
{ "68020", 0xfffffffful, e68KGen2 , eCfISA_None , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling | eFlagExtFPU | eFlagCALLM_RTM, { CtRegs_1040, CtRegs_2040, CtRegs_2030 } },
{ "68030", 0xfffffffful, e68KGen2 , eCfISA_None , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling | eFlagExtFPU | eFlagIntPMMU, { CtRegs_1040, CtRegs_2040, CtRegs_2030 } },
/* setting eFlagExtFPU assumes instructions of external FPU are emulated/provided by M68040FPSP! */
{ "68040", 0xfffffffful, e68KGen3 , eCfISA_None , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling | eFlagIntPMMU | eFlagExtFPU | eFlagIntFPU, { CtRegs_1040, CtRegs_2040, CtRegs_40 } },
{ NULL , 0 , e68KGen1a, eCfISA_None , eFlagNone, { NULL } },
};
void code68k_init(void)
{
const tCPUProps *pProp;
for (pProp = CPUProps; pProp->pName; pProp++)
(void)AddCPUUser(pProp->pName, SwitchTo_68K, (void*)pProp, NULL);
}