/* 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
;
}
if (strlen(pArg
) != 2)
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
;
}
if (strlen(pArg
) != 3)
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
++)
if (!strcmp(pReg
->Name
, Asc
))
{
*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
);
if (!strlen(To.
str.
p_str)
|| (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
);
}