/* codeh16.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Code Generator Hitachi H16 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "chunks.h"
#include "headids.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmitree.h"
#include "asmstructs.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "nls.h"
#include "codeh16.h"
/*---------------------------------------------------------------------------*/
static CPUVar CPU641016
;
static tSymbolSize OpSize
;
static tStrComp FormatPart
;
#define REG_SP 15
typedef enum
{
eAdrModeNone
= -1,
eAdrModeReg
= 0,
eAdrModeIReg
= 1,
eAdrModePost
= 2,
eAdrModePre
= 3,
eAdrModeImm
= 4,
eAdrModeAbs
= 5,
eAdrModeIRegScale
= 6,
eAdrModeIdxScale
= 7,
eAdrModePCIdxScale
= 8,
eAdrModePCRel
= 9,
eAdrModeDoubleIndir
= 10
} tAdrMode
;
#define MModeReg (1 << eAdrModeReg)
#define MModeIReg (1 << eAdrModeIReg)
#define MModePost (1 << eAdrModePost)
#define MModePre (1 << eAdrModePre)
#define MModeImm (1 << eAdrModeImm)
#define MModeAbs (1 << eAdrModeAbs)
#define MModeIRegScale (1 << eAdrModeIRegScale)
#define MModeIdxScale (1 << eAdrModeIdxScale)
#define MModePCIdxScale (1 << eAdrModePCIdxScale)
#define MModePCRel (1 << eAdrModePCRel)
#define MModeDoubleIndir (1 << eAdrModeDoubleIndir)
#define MModeAll (MModeReg | MModeIReg | MModePost | MModePre | MModeImm | MModeAbs | MModeIRegScale | MModeIdxScale | MModePCIdxScale | MModePCRel | MModeDoubleIndir)
typedef enum
{
eFormatNone
,
eFormatG
,
eFormatQ
,
eFormatR
,
eFormatRQ
,
eFormatF
/* no source-side format; used for MOV->MOVF conversion */
} tFormat
;
#ifdef __cplusplus
# include "codeh16.hpp"
#endif
typedef struct
{
tAdrMode Mode
;
unsigned Cnt
;
Byte Vals
[10];
} tAdrVals
;
#define NOREG 255
#define PCREG 254
#define NormalReg(Reg) ((Reg) <= 15)
#define DefIndexRegSize eSymbolSize32Bit /* correct? */
#define PREFIX_CRn 0x70
#define PREFIX_PRn 0x74
#define eSymbolSize5Bit ((tSymbolSize)-2) /* for shift cnt/bit pos arg */
#define eSymbolSize4Bit ((tSymbolSize)-3) /* for bit pos arg */
#define eSymbolSize3Bit ((tSymbolSize)-4) /* for bit pos arg */
typedef struct
{
LongInt OuterDisp
, InnerDisp
;
Boolean OuterDispPresent
, InnerDispPresent
;
tSymbolSize OuterDispSize
, InnerDispSize
;
Byte BaseReg
, IndexReg
, InnerReg
;
ShortInt BaseRegIncr
, IndexRegSize
;
Byte IndexRegScale
;
Byte RegPrefix
;
} tAdrComps
;
/*---------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn SetOpSize(tSymbolSize NewOpSize)
* \brief set (instruction) operand size; complain if size mismatch
* \param NewOpSize size to set
* \return True if setting/confirmation succeeded
* ------------------------------------------------------------------------ */
static Boolean SetOpSize
(tSymbolSize NewOpSize
)
{
if ((OpSize
!= eSymbolSizeUnknown
) && (NewOpSize
!= OpSize
))
{
WrError
(ErrNum_ConfOpSizes
);
return False
;
}
OpSize
= NewOpSize
;
return True
;
}
/*!------------------------------------------------------------------------
* \fn ChkOpSize(tSymbolSize DefaultSize, Word Mask)
* \brief possibly set & check instruction operand size
* \param DefaultSize size to set if size is unknown so far
* \param Mask bit mask of allowed sizes (8/16/32 -> bit 0/1/2)
* \return True if operand size is OK
* ------------------------------------------------------------------------ */
static Boolean ChkOpSize
(tSymbolSize DefaultSize
, Word Mask
)
{
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= DefaultSize
;
if (!((Mask
>> OpSize
) & 1))
{
WrError
(ErrNum_InvOpSize
);
return False
;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeFormat(unsigned FormatMask)
* \brief decode instruction's format to internal enum
* \param FormatMask bit mask of allowed formats
* \return resulting format or FormatNone if unknown/disallowed
* ------------------------------------------------------------------------ */
static tFormat DecodeFormat
(unsigned FormatMask
)
{
static const char Formats
[][3] = { "G", "Q", "R", "RQ", "" };
tFormat Result
;
FormatMask
>>= 1;
for (Result
= (tFormat
)0; *Formats
[Result
]; Result
++, FormatMask
>>= 1)
if ((FormatMask
& 1) && !as_strcasecmp
(FormatPart.
str.
p_str, Formats
[Result
]))
return Result
+ 1;
return eFormatNone
;
}
/*!------------------------------------------------------------------------
* \fn ChkEmptyFormat(void)
* \brief check whether no format spec was given and complain if there is one
* \return True if no format spec was given
* ------------------------------------------------------------------------ */
static Boolean ChkEmptyFormat
(void)
{
if (*FormatPart.
str.
p_str)
{
WrStrErrorPos
(ErrNum_InvFormat
, &FormatPart
);
return False
;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn ResetAdrVals(tAdrVals *pAdrVals)
* \brief reset tAdrVals structure to initial state
* \param pAdrVals struct to reset
* ------------------------------------------------------------------------ */
static void ResetAdrVals
(tAdrVals
*pAdrVals
)
{
pAdrVals
->Mode
= eAdrModeNone
;
pAdrVals
->Cnt
= 0;
}
/*!------------------------------------------------------------------------
* \fn AppendAdrVals(tAdrVals *pAdrVals, Byte Value)
* \brief append another byte to tAdrVals' expansion byte list; check for overflow
* \param pAdrVals AdrVals to extend
* \param Value new value to append
* ------------------------------------------------------------------------ */
static void AppendAdrVals
(tAdrVals
*pAdrVals
, Byte Value
)
{
if (pAdrVals
->Cnt
>= (sizeof(pAdrVals
->Vals
) / sizeof(*pAdrVals
->Vals
)))
{
WrError
(ErrNum_CodeOverflow
);
return;
}
pAdrVals
->Vals
[pAdrVals
->Cnt
++] = Value
;
}
/*!------------------------------------------------------------------------
* \fn AppendRegPrefix(tAdrVals *pAdrVals, Byte RegPrefix)
* \brief append register prefix to tAdrVals if not a global bank register
* \param pAdrVals AdrVals to extend
* \param RegPrefix register prefix (0x70/0x74 or 0x00 for no prefix)
* ------------------------------------------------------------------------ */
static void AppendRegPrefix
(tAdrVals
*pAdrVals
, Byte RegPrefix
)
{
if (RegPrefix
)
AppendAdrVals
(pAdrVals
, RegPrefix
);
}
/*!------------------------------------------------------------------------
* \fn AppendBySize(Byte *pDest, LongInt Value, tSymbolSize OpSize)
* \brief append an integer value to byte array, BE order
* \param pDest where to write
* \param Value integer value to append
* \param OpSize operand size of value (3/4/5/8/16/32 bits)
* \return # of bytes appended
* ------------------------------------------------------------------------ */
static unsigned GetH16SymbolSizeBytes
(tSymbolSize Size
)
{
return (Size
<= eSymbolSize5Bit
) ? 1 : GetSymbolSizeBytes
(Size
);
}
static unsigned AppendBySize
(Byte
*pDest
, LongInt Value
, tSymbolSize OpSize
)
{
int z
;
unsigned Cnt
= GetH16SymbolSizeBytes
(OpSize
);
for (z
= Cnt
- 1; z
>= 0; z
--)
{
pDest
[z
] = Value
& 0xff;
Value
>>= 8;
}
return Cnt
;
}
/*!------------------------------------------------------------------------
* \fn AppendToAdrValsBySize(tAdrVals *pAdrVals, LongInt Value, tSymbolSize OpSize)
* \brief append an integer value to tAdrVals
* \param pAdrVals AdrVals to extend
* \param Value integer value to append
* \param OpSize operand size of value (3/4/5/8/16/32 bits)
* ------------------------------------------------------------------------ */
static void AppendToAdrValsBySize
(tAdrVals
*pAdrVals
, LongInt Value
, tSymbolSize OpSize
)
{
unsigned Cnt
= GetH16SymbolSizeBytes
(OpSize
);
if ((pAdrVals
->Cnt
+ Cnt
) > (sizeof(pAdrVals
->Vals
) / sizeof(*pAdrVals
->Vals
)))
{
WrError
(ErrNum_CodeOverflow
);
return;
}
AppendBySize
(pAdrVals
->Vals
+ pAdrVals
->Cnt
, Value
, OpSize
);
pAdrVals
->Cnt
+= Cnt
;
}
/*!------------------------------------------------------------------------
* \fn ResetAdrComps(tAdrComps *pComps)
* \brief reset indirect address parser context to empty state
* \param pComps context to reset
* ------------------------------------------------------------------------ */
static void ResetAdrComps
(tAdrComps
*pComps
)
{
pComps
->OuterDisp
= pComps
->InnerDisp
= 0;
pComps
->OuterDispPresent
= pComps
->InnerDispPresent
= False
;
pComps
->OuterDispSize
= pComps
->InnerDispSize
= eSymbolSizeUnknown
;
pComps
->BaseReg
= pComps
->IndexReg
= pComps
->InnerReg
= NOREG
;
pComps
->IndexRegScale
= pComps
->BaseRegIncr
= 0;
pComps
->IndexRegSize
= DefIndexRegSize
;
pComps
->RegPrefix
= 0x00;
}
/*!------------------------------------------------------------------------
* \fn SplitOpSize(tStrComp *pArg, tSymbolSize *pSize)
* \brief split off explicit size spec from argument
* \param pArg argument to treat
* \param pSize resulting size if suffix was present
* \return True if a suffix was split off
* ------------------------------------------------------------------------ */
static Boolean SplitOpSize
(tStrComp
*pArg
, tSymbolSize
*pSize
)
{
static const char Suffixes
[][4] = { ".B", ":8", ".W", ":16", ".L", ":32" };
int l
= strlen(pArg
->str.
p_str), l2
;
unsigned z
;
for (z
= 0; z
< sizeof(Suffixes
) / sizeof(*Suffixes
); z
++)
{
l2
= strlen(Suffixes
[z
]);
if ((l
> l2
) && !as_strcasecmp
(pArg
->str.
p_str + l
- l2
, Suffixes
[z
]))
{
StrCompShorten
(pArg
, l2
);
*pSize
= (tSymbolSize
)(z
/ 2);
return True
;
}
}
return False
;
}
/*!------------------------------------------------------------------------
* \fn SplitScale(tStrComp *pArg, Byte *pScale)
* \brief split off scaling option from (register) argument
* \param pArg argument to treat
* \param pScale resulting scale if suffix was present
* \return True if a suffix was split off
* ------------------------------------------------------------------------ */
static const char ScaleSuffixes
[][3] = { "*1", "*2", "*4", "*8" };
static char SplitScale
(tStrComp
*pArg
, Byte
*pScale
)
{
int l
= strlen(pArg
->str.
p_str);
unsigned z
;
if (l
>= 2)
for (z
= 0; z
< sizeof(ScaleSuffixes
) / sizeof(*ScaleSuffixes
); z
++)
if (!as_strcasecmp
(pArg
->str.
p_str + l
- 2, ScaleSuffixes
[z
]))
{
StrCompShorten
(pArg
, 2);
*pScale
= z
;
return *ScaleSuffixes
[z
];
}
return '\0';
}
/*!------------------------------------------------------------------------
* \fn AppendScale(tStrComp *pArg, Byte Scale)
* \brief append scaling option to (register) argument
* \param pArg argument to augment by scaling
* \param Scale Scale to append
* ------------------------------------------------------------------------ */
static void AppendScale
(tStrComp
*pArg
, Byte Scale
)
{
strcat(pArg
->str.
p_str, ScaleSuffixes
[Scale
]);
pArg
->Pos.
Len += 2;
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, Byte *pResult, Byte *pPrefix)
* \brief check whether argument is a register and return register # if yes
* \param pArg argument to check
* \param pResult register # if argument is a valid (general) register
* \param pPrefix prefix for previous/current bank registers; 0 for global bank registers
* \return True if argument is a register
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore
(const char *pArg
, Byte
*pResult
, Byte
*pPrefix
)
{
Boolean OK
;
if (!as_strcasecmp
(pArg
, "SP"))
{
*pResult
= REGSYM_FLAG_ALIAS
| REG_SP
;
*pPrefix
= 0x00;
return True
;
}
if ((strlen(pArg
) > 1)
&& (as_toupper
(*pArg
) == 'R'))
*pPrefix
= 0x00;
else if ((strlen(pArg
) > 2)
&& (as_toupper
(*pArg
) == 'C')
&& (as_toupper
(pArg
[1]) == 'R'))
*pPrefix
= PREFIX_CRn
;
else if ((strlen(pArg
) > 2)
&& (as_toupper
(*pArg
) == 'P')
&& (as_toupper
(pArg
[1]) == 'R'))
*pPrefix
= PREFIX_PRn
;
else
return False
;
*pResult
= ConstLongInt
(pArg
+ 1 + !!*pPrefix
, &OK
, 10);
return (OK
&& (*pResult
<= 15));
}
/*!------------------------------------------------------------------------
* \fn DissectReg_H16(char *pDest, size_t DestSize, tRegInt Reg, tSymbolSize Size)
* \brief dissect register symbols - H16 variant
* \param pDest destination buffer
* \param DestSize size of destination buffer
* \param Reg register number
* \param Size register size
* ------------------------------------------------------------------------ */
static void DissectReg_H16
(char *pDest
, size_t DestSize
, tRegInt Reg
, tSymbolSize Size
)
{
switch (Size
)
{
case eSymbolSize32Bit
:
if (Reg
== (REGSYM_FLAG_ALIAS
| REG_SP
))
as_snprintf
(pDest
, DestSize
, "SP");
else
{
if (Hi
(Reg
) == PREFIX_CRn
)
as_snprintf
(pDest
, DestSize
, "CR");
else if (Hi
(Reg
) == PREFIX_PRn
)
as_snprintf
(pDest
, DestSize
, "PR");
else if (!Hi
(Reg
))
as_snprintf
(pDest
, DestSize
, "R");
else
as_snprintf
(pDest
, DestSize
, "%u-", Hi
(Reg
));
as_snprcatf
(pDest
, DestSize
, "%u", Lo
(Reg
));
}
break;
default:
as_snprintf
(pDest
, DestSize
, "%d-%u", Size
, Reg
);
}
}
/*!------------------------------------------------------------------------
* \fn compare_reg_h16(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_h16
(tRegInt reg1_num
, tSymbolSize size1
, tRegInt reg2_num
, tSymbolSize size2
)
{
if ((size1
!= eSymbolSize32Bit
)
|| (size2
!= eSymbolSize32Bit
)
|| (Hi
(reg1_num
) != Hi
(reg2_num
)))
return -2;
reg1_num
= Lo
(reg1_num
) & ~REGSYM_FLAG_ALIAS
;
reg2_num
= Lo
(reg2_num
) & ~REGSYM_FLAG_ALIAS
;
if (reg1_num
< reg2_num
)
return -1;
else if (reg1_num
> reg2_num
)
return 1;
else
return 0;
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, Byte *pReg, Byte *pPrefix, Boolean AllowPrefix, Boolean MustBeReg)
* \brief check whether argument is CPU register or register alias
* \param pArg source argument
* \param pReg register number
* \param pPrefix prefix for previous/current bank registers; 0 for global bank registers
* \param AllowPrefix allow previous/current bank registers
* \param MustBeReg argument must be register
* \return True if argument is a register
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg
(const tStrComp
*pArg
, Byte
*pReg
, Byte
*pPrefix
, Boolean AllowPrefix
, Boolean MustBeReg
)
{
tRegDescr RegDescr
;
tEvalResult EvalResult
;
tRegEvalResult RegEvalResult
;
if (DecodeRegCore
(pArg
->str.
p_str, pReg
, pPrefix
))
RegEvalResult
= eIsReg
;
else
{
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize32Bit
, MustBeReg
);
*pPrefix
= Hi
(RegDescr.
Reg);
*pReg
= Lo
(RegDescr.
Reg);
}
if (RegEvalResult
== eIsReg
)
{
if (!AllowPrefix
&& *pPrefix
)
{
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
RegEvalResult
= MustBeReg
? eIsNoReg
: eRegAbort
;
}
}
*pReg
&= ~REGSYM_FLAG_ALIAS
;
return RegEvalResult
;
}
/*!------------------------------------------------------------------------
* \fn DecodeRegList(Word *pDest, int StartIdx, int StopIdx)
* \brief parse a register list
* \param pDest destination buffer for register bit field
* \param StartIdx index of first argument of list
* \param StopIdx index of last argument of list
* \return True if parsing succeeded
* ------------------------------------------------------------------------ */
static Boolean DecodeRegList
(Word
*pDest
, int StartIdx
, int StopIdx
)
{
int Index
;
char *pSep
;
Byte RegStart
, RegStop
, Prefix
;
Word Mask
;
*pDest
= 0;
for (Index
= StartIdx
; Index
<= StopIdx
; Index
++)
{
pSep
= strchr(ArgStr
[Index
].
str.
p_str, '-');
if (pSep
)
{
tStrComp StartComp
, StopComp
;
StrCompSplitRef
(&StartComp
, &StopComp
, &ArgStr
[Index
], pSep
);
KillPostBlanksStrComp
(&StartComp
);
KillPrefBlanksStrCompRef
(&StopComp
);
if (!DecodeReg
(&StartComp
, &RegStart
, &Prefix
, False
, True
))
return False
;
if (!DecodeReg
(&StopComp
, &RegStop
, &Prefix
, False
, True
))
return False
;
if (RegStart
> RegStop
)
{
Prefix
= RegStart
;
RegStart
= RegStop
;
RegStop
= Prefix
;
}
Mask
= ((1ul
<< (RegStop
+ 1)) - 1) & ~
((1ul
<< (RegStart
)) - 1);
}
else
{
if (!DecodeReg
(&ArgStr
[Index
], &RegStart
, &Prefix
, False
, True
))
return False
;
Mask
= 1ul
<< RegStart
;
}
if (*pDest
& Mask
)
{
WrStrErrorPos
(ErrNum_DoubleReg
, &ArgStr
[Index
]);
return False
;
}
*pDest
|= Mask
;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeRegWithSize(const tStrComp *pArg, Byte *pReg, tSymbolSize *pSize, Byte *pPrefix, Boolean MustBeReg)
* \brief check whether argument is register with possible size spec
* \param pArg argument to check
* \param pReg returns register # if argument is a register
* \param pSize returns size spec if argument is a register (may be SizeUnknown)
* \param pPrefix prefix for previous/current bank registers; 0 for global bank registers
* \param MustBeReg argument must be register
* \return RegEval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeRegWithSize
(const tStrComp
*pArg
, Byte
*pReg
, tSymbolSize
*pSize
, Byte
*pPrefix
, Boolean MustBeReg
)
{
String Str
;
tStrComp Copy
;
StrCompMkTemp
(&Copy
, Str
, sizeof(Str
));
StrCompCopy
(&Copy
, pArg
);
if (!SplitOpSize
(&Copy
, pSize
))
*pSize
= eSymbolSizeUnknown
;
return DecodeReg
(&Copy
, pReg
, pPrefix
, True
, MustBeReg
);
}
/*!------------------------------------------------------------------------
* \fn CheckSup(const tStrComp *pArg)
* \brief check whether supervisor mode is enabled and warn if not
* \param pArg possible argument to print if sup mode is not enabled
* \return True (only a warning, no error)
* ------------------------------------------------------------------------ */
static Boolean CheckSup
(const tStrComp
*pArg
)
{
if (!SupAllowed
)
WrStrErrorPos
(ErrNum_PrivOrder
, pArg
);
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeCReg(const tStrComp *pArg, Byte *pResult)
* \brief check whether argument id a control register
* \param pArg argument to check
* \param pResult control register # if argument is a control register
* \return True if argument is a control register
* ------------------------------------------------------------------------ */
typedef struct
{
const char *pName
;
Byte Code
;
tSymbolSize Size
;
} tCReg
;
static const tCReg CRegs
[] =
{
{ "CCR" , 0x20, eSymbolSize8Bit
},
{ "VBNR" , 0x01, eSymbolSize8Bit
},
{ "CBNR" , 0x40, eSymbolSize32Bit
},
{ "BSP" , 0x41, eSymbolSize32Bit
},
{ "BMR" , 0x80, eSymbolSize8Bit
},
{ "GBNR" , 0x81, eSymbolSize8Bit
},
{ "SR" , 0xa0, eSymbolSize16Bit
},
{ "EBR" , 0xc0, eSymbolSize32Bit
},
{ "RBR" , 0xc1, eSymbolSize32Bit
},
{ "USP" , 0xc2, eSymbolSize32Bit
},
{ "IBR" , 0xc3, eSymbolSize32Bit
},
{ NULL
, 0x00, eSymbolSizeUnknown
},
};
static Boolean DecodeCReg
(const tStrComp
*pArg
, Byte
*pResult
)
{
const tCReg
*pReg
;
for (pReg
= CRegs
; pReg
->pName
; pReg
++)
if (!as_strcasecmp
(pArg
->str.
p_str, pReg
->pName
))
{
if ((pReg
->Code
& 0x80) && !CheckSup
(pArg
))
return False
;
if (!SetOpSize
(pReg
->Size
))
return False
;
*pResult
= pReg
->Code
;
return True
;
}
WrStrErrorPos
(ErrNum_InvCtrlReg
, pArg
);
return False
;
}
/*!------------------------------------------------------------------------
* \fn DeduceSize(LongInt Value)
* \brief deduce minimum operand size needed to represent value, assuming sign-extension
* \param Value value to judge
* \return resulting minimum size
* ------------------------------------------------------------------------ */
static tSymbolSize DeduceSize
(LongInt Value
)
{
if ((Value
>= -128) && (Value
<= 127))
return eSymbolSize8Bit
;
if ((Value
>= -32768) && (Value
<= 32767))
return eSymbolSize16Bit
;
return eSymbolSize32Bit
;
}
/*!------------------------------------------------------------------------
* \fn DeduceSize8_32(LongInt Value)
* \brief similar to DeduceSize, but excluding 16 bits
* \param Value value to judge
* \return resulting minimum size
* ------------------------------------------------------------------------ */
static tSymbolSize DeduceSize8_32
(LongInt Value
)
{
if ((Value
>= -128) && (Value
<= 127))
return eSymbolSize8Bit
;
return eSymbolSize32Bit
;
}
/*!------------------------------------------------------------------------
* \fn ChkSize(LongInt Value, tSymbolSize OpSize)
* \brief check whether given value can be represented with given size, assuming sign extension
* \param Value value to judge
* \param OpSize proposed operand size
* \return True if value can be represented with this size
* ------------------------------------------------------------------------ */
static Boolean ChkSize
(LongInt Value
, tSymbolSize OpSize
)
{
switch (OpSize
)
{
case eSymbolSize8Bit
: return ChkRange
(Value
, -128, 127);
case eSymbolSize16Bit
: return ChkRange
(Value
, -32768, 32767);
default: return True
;
}
}
/*!------------------------------------------------------------------------
* \fn DeduceSize16M(LongInt Value)
* \brief deduce minimum size to represent memory address, assuming sign-extension
* \param Value address to judge
* \return minimum operand size (8/16/32)
* ------------------------------------------------------------------------ */
static tSymbolSize DeduceSize16M
(LongInt Value
)
{
LongWord TmpVal
;
TmpVal
= Value
& 0xff;
if (TmpVal
& 0x80) TmpVal
|= 0xffffff00;
if ((TmpVal
& 0xffffff) == ((LongWord
)Value
& 0xffffff))
return eSymbolSize8Bit
;
TmpVal
= Value
& 0xffff;
if (TmpVal
& 0x8000) TmpVal
|= 0xff0000;
if ((TmpVal
& 0xffffff) == ((LongWord
)Value
& 0xffffff))
return eSymbolSize16Bit
;
return eSymbolSize32Bit
;
}
/*!------------------------------------------------------------------------
* \fn ChkSize16M(LongInt Value, tSymbolSize OpSize)
* \brief check whether given memory address can be represented with given size, assuming sign extension
* \param Value address to judge
* \param OpSize proposed operand size
* \return True if value can be represented with this size
* ------------------------------------------------------------------------ */
static Boolean ChkSize16M
(LongInt Value
, tSymbolSize OpSize
)
{
LongWord TmpVal
;
Boolean OK
;
switch (OpSize
)
{
case eSymbolSize8Bit
:
TmpVal
= Value
& 0xff;
if (TmpVal
& 0x80) TmpVal
|= 0xffffff00;
break;
case eSymbolSize16Bit
:
TmpVal
= Value
& 0xffff;
if (TmpVal
& 0x8000) TmpVal
|= 0xff0000;
break;
default:
TmpVal
= Value
;
}
OK
= (Value
& 0xffffff) == (TmpVal
& 0xffffff);
if (!OK
)
WrError
(ErrNum_OverRange
);
return OK
;
}
/*!------------------------------------------------------------------------
* \fn DeduceSizePCRel(LongInt AbsAddr, LongInt DispAddr)
* \brief deduce minimum size to represent memory address as distance, assuming PC-relative addressing
* \param AbsAddr absolute memory addess in question
* \param DispAddr address of PC-relative displacement in code
* \return minimum displacement size (8/16/32)
* ------------------------------------------------------------------------ */
static tSymbolSize DeduceSizePCRel
(LongInt AbsAddr
, LongInt DispAddr
)
{
LongInt PCValue
, Dist
;
PCValue
= DispAddr
+ 1;
Dist
= PCValue
- AbsAddr
;
if ((Dist
>= -128) && (Dist
<= 127))
return eSymbolSize8Bit
;
PCValue
= DispAddr
+ 2;
Dist
= PCValue
- AbsAddr
;
if ((Dist
>= -32768) && (Dist
<= 32767))
return eSymbolSize16Bit
;
return eSymbolSize32Bit
;
}
/*!------------------------------------------------------------------------
* \fn ChkSizePCRelDisplacement(LongInt *pAbsAddr, tSymbolSize SymbolSize, LongInt DispAddr)
* \brief check whether given address can be represented with given size, assuming PC-relative addressing
* \param pAbsAddr (in) absolute memory addess in question (out) resulting displacement
* \param SymbolSize proposed displacement size
* \param DispAddr address of PC-relative displacement in code
* \return True if value can be represented with this size and displacement was computed
* ------------------------------------------------------------------------ */
static Boolean ChkSizePCRelDisplacement
(LongInt
*pAbsAddr
, tSymbolSize SymbolSize
, LongInt DispAddr
)
{
switch (SymbolSize
)
{
case eSymbolSize8Bit
:
*pAbsAddr
-= DispAddr
+ 1;
return ChkRange
(*pAbsAddr
, -128, 127);
case eSymbolSize16Bit
:
*pAbsAddr
-= DispAddr
+ 2;
return ChkRange
(*pAbsAddr
, -32768, 32767);
case eSymbolSize32Bit
:
*pAbsAddr
-= DispAddr
+ 4;
return True
;
default:
return False
;
}
}
/*!------------------------------------------------------------------------
* \fn ChkSizePCRelBranch(const tStrComp *pArg, LongInt *pAbsAddr, tSymbolSize SymbolSize, tSymbolFlags Flags, LongInt DispAddr)
* \brief same as ChkSizePCRel(), but use error messages appropriate for branches
* \param pAbsAddr (in) destination address of branch (out) resulting displacement
* \param SymbolSize proposed displacement size
* \param Flags symbol flags returned along with pAbsAddr
* \param DispAddr address of PC-relative displacement in code
* \return True if displacement can be represented with this size and was computed
* ------------------------------------------------------------------------ */
static Boolean ChkSizePCRelBranch
(const tStrComp
*pArg
, LongInt
*pAbsAddr
, tSymbolSize SymbolSize
, tSymbolFlags Flags
, LongInt DispAddr
)
{
Boolean OK
;
switch (SymbolSize
)
{
case eSymbolSize8Bit
:
*pAbsAddr
-= DispAddr
+ 1;
OK
= mSymbolQuestionable
(Flags
) || RangeCheck
(*pAbsAddr
, SInt8
);
break;
case eSymbolSize16Bit
:
*pAbsAddr
-= DispAddr
+ 2;
OK
= mSymbolQuestionable
(Flags
) || RangeCheck
(*pAbsAddr
, SInt16
);
break;
case eSymbolSize32Bit
:
*pAbsAddr
-= DispAddr
+ 4;
OK
= True
;
break;
default:
OK
= False
;
}
if (!OK
)
WrStrErrorPos
(ErrNum_JmpDistTooBig
, pArg
);
return OK
;
}
/*!------------------------------------------------------------------------
* \fn SetRegPrefix(Byte *pDest, Byte Src, const tStrComp *pArg)
* \brief set (new) previous/current bank register prefix
* \param pDest current prefix
* \param Src new prefix to set/confirm
* \param pArg argument to print in error msg if bank mismatch
* \return True if register bank was set or confirmed
* ------------------------------------------------------------------------ */
static Boolean SetRegPrefix
(Byte
*pDest
, Byte Src
, const tStrComp
*pArg
)
{
if (*pDest
&& (*pDest
!= Src
))
{
WrStrErrorPos
(ErrNum_RegBankMismatch
, pArg
);
return False
;
}
*pDest
= Src
;
return True
;
}
/*!------------------------------------------------------------------------
* \fn EvalArg(const tStrComp *pArg, int Offset, tSymbolSize OpSize, Boolean *pOK)
* \brief evaluate integer expression accoring to operand size
* \param pArg argument to evaluate
* \param Offset offset into argument where expression begins
* \param OpSize operand size to use
* \param pOK returns True if evaluation succeeded
* \return result of evaluation
* ------------------------------------------------------------------------ */
static LongInt EvalArg
(const tStrComp
*pArg
, int Offset
, tSymbolSize OpSize
, Boolean
*pOK
)
{
switch ((int)OpSize
)
{
case eSymbolSize8Bit
:
return EvalStrIntExpressionOffs
(pArg
, Offset
, Int8
, pOK
);
case eSymbolSize16Bit
:
return EvalStrIntExpressionOffs
(pArg
, Offset
, Int16
, pOK
);
case eSymbolSize32Bit
:
return EvalStrIntExpressionOffs
(pArg
, Offset
, Int32
, pOK
);
case eSymbolSize5Bit
:
return EvalStrIntExpressionOffs
(pArg
, Offset
, UInt5
, pOK
);
case eSymbolSize4Bit
:
return EvalStrIntExpressionOffs
(pArg
, Offset
, UInt4
, pOK
);
case eSymbolSize3Bit
:
return EvalStrIntExpressionOffs
(pArg
, Offset
, UInt3
, pOK
);
default:
*pOK
= False
;
return 0;
}
}
/*!------------------------------------------------------------------------
* \fn ValidBaseRegSize(tSymbolSize Size)
* \brief check whether operand size is appropriate for base reg in indirect expression
* \param Size operand size to check
* \return True if OK
* ------------------------------------------------------------------------ */
static Boolean ValidBaseRegSize
(tSymbolSize Size
)
{
return (Size
== eSymbolSizeUnknown
) /* no size given: regarded as 32 bits */
|| (Size
== eSymbolSize32Bit
);
}
/*!------------------------------------------------------------------------
* \fn ValidIndexRegSize(tSymbolSize Size)
* \brief check whether operand size is appropriate for indirect reg in indirect expression
* \param Size operand size to check
* \return True if OK
* ------------------------------------------------------------------------ */
static Boolean ValidIndexRegSize
(tSymbolSize Size
)
{
return (Size
== eSymbolSizeUnknown
) /* no size given: regarded as default index reg size */
|| (Size
== eSymbolSize16Bit
)
|| (Size
== eSymbolSize32Bit
);
}
/*!------------------------------------------------------------------------
* \fn ClassComp(tStrComp *pArg, tAdrComps *pComps)
* \brief classify/parse argument of indirect address expression
* \param pComps indirect address evaluation context to update/augment
* \param pArg argument to parse
* \return True if parsing and context update succeeded
* ------------------------------------------------------------------------ */
static Boolean ClassCompList
(tAdrComps
*pComps
, tStrComp
*pArg
);
static Boolean ClassComp
(tStrComp
*pArg
, tAdrComps
*pComps
)
{
tSymbolSize OpSize
;
Byte Reg
, Scale
, Prefix
;
char Save
;
LongInt Value
;
Boolean OK
;
KillPrefBlanksStrCompRef
(pArg
);
KillPostBlanksStrComp
(pArg
);
if (!as_strcasecmp
(pArg
->str.
p_str, "PC"))
{
if (pComps
->BaseReg
== NOREG
)
{
pComps
->BaseReg
= PCREG
;
pComps
->BaseRegIncr
= 0;
return True
;
}
else if (pComps
->IndexReg
== NOREG
)
{
pComps
->IndexReg
= pComps
->BaseReg
;
pComps
->IndexRegScale
= 0;
pComps
->IndexRegSize
= eSymbolSize32Bit
;
pComps
->BaseReg
= PCREG
;
pComps
->BaseRegIncr
= 0;
return True
;
}
else
return False
;
}
if (*pArg
->str.
p_str == '@')
{
tAdrComps InnerComps
;
tStrComp InnerList
;
if (pComps
->InnerReg
!= NOREG
)
return False
;
StrCompRefRight
(&InnerList
, pArg
, 1);
if (!ClassCompList
(&InnerComps
, &InnerList
))
return False
;
if (!InnerComps.
InnerDispPresent
&& (InnerComps.
InnerReg == NOREG
)
&& (InnerComps.
IndexReg == NOREG
)
&& (InnerComps.
BaseReg != NOREG
)
&& !InnerComps.
BaseRegIncr)
{
pComps
->InnerReg
= InnerComps.
BaseReg;
pComps
->InnerDispPresent
= InnerComps.
OuterDispPresent;
pComps
->InnerDisp
= InnerComps.
OuterDisp;
pComps
->InnerDispSize
= InnerComps.
OuterDispSize;
}
return True
;
}
switch (DecodeRegWithSize
(pArg
, &Reg
, &OpSize
, &Prefix
, False
))
{
case eIsReg
:
if (!SetRegPrefix
(&pComps
->RegPrefix
, Prefix
, pArg
))
return False
;
if ((pComps
->BaseReg
== NOREG
) && (OpSize
== eSymbolSizeUnknown
))
{
pComps
->BaseReg
= Reg
;
pComps
->BaseRegIncr
= 0;
return True
;
}
else if ((pComps
->IndexReg
== NOREG
) && ValidIndexRegSize
(OpSize
))
{
pComps
->IndexReg
= Reg
;
pComps
->IndexRegScale
= 0;
if (OpSize
!= eSymbolSizeUnknown
)
pComps
->IndexRegSize
= OpSize
;
return True
;
}
else
return False
;
case eIsNoReg
:
break;
case eRegAbort
:
return False
;
}
if (*pArg
->str.
p_str == '-')
{
tStrComp RegComp
;
StrCompRefRight
(&RegComp
, pArg
, 1);
switch (DecodeReg
(&RegComp
, &Reg
, &Prefix
, True
, False
))
{
case eIsReg
:
if (!SetRegPrefix
(&pComps
->RegPrefix
, Prefix
, pArg
))
return False
;
if (pComps
->BaseReg
== NOREG
)
{
pComps
->BaseReg
= Reg
;
pComps
->BaseRegIncr
= -1;
return True
;
}
else
return False
;
case eRegAbort
:
return False
;
case eIsNoReg
:
break;
}
}
if (pArg
->str.
p_str[pArg
->Pos.
Len - 1] == '+')
{
pArg
->str.
p_str[pArg
->Pos.
Len - 1] = '\0';
switch (DecodeReg
(pArg
, &Reg
, &Prefix
, True
, False
))
{
case eIsReg
:
if (!SetRegPrefix
(&pComps
->RegPrefix
, Prefix
, pArg
))
return False
;
if (pComps
->BaseReg
== NOREG
)
{
pComps
->BaseReg
= Reg
;
pComps
->BaseRegIncr
= +1;
return True
;
}
else
return False
;
case eRegAbort
:
return False
;
case eIsNoReg
:
pArg
->str.
p_str[pArg
->Pos.
Len - 1] = '+';
break;
}
}
Save
= SplitScale
(pArg
, &Scale
);
if (Save
)
{
switch (DecodeRegWithSize
(pArg
, &Reg
, &OpSize
, &Prefix
, False
))
{
case eIsReg
:
if (!SetRegPrefix
(&pComps
->RegPrefix
, Prefix
, pArg
))
return False
;
if ((pComps
->IndexReg
== NOREG
) && ValidIndexRegSize
(OpSize
))
{
pComps
->IndexReg
= Reg
;
pComps
->IndexRegScale
= Scale
;
if (OpSize
!= eSymbolSizeUnknown
)
pComps
->IndexRegSize
= OpSize
;
}
else if (pComps
->BaseReg
== NOREG
)
{
if ((Scale
== 0) && ValidBaseRegSize
(OpSize
))
pComps
->BaseReg
= Reg
;
else if ((Scale
!= 0) && (pComps
->IndexRegScale
== 0) && (pComps
->IndexRegSize
== eSymbolSize32Bit
))
{
pComps
->BaseReg
= pComps
->IndexReg
;
pComps
->IndexReg
= Reg
;
pComps
->IndexRegScale
= Scale
;
pComps
->IndexRegSize
= (OpSize
== eSymbolSizeUnknown
) ? DefIndexRegSize
: OpSize
;
}
else
return False
;
}
else
return False
;
return True
;
case eIsNoReg
:
AppendScale
(pArg
, Scale
);
break;
case eRegAbort
:
return False
;
}
}
if (!SplitOpSize
(pArg
, &OpSize
))
OpSize
= eSymbolSizeUnknown
;
Value
= EvalArg
(pArg
, 0, eSymbolSize32Bit
, &OK
);
if (!OK
)
return False
;
pComps
->OuterDispPresent
= True
;
if (OpSize
> pComps
->OuterDispSize
)
pComps
->OuterDispSize
= OpSize
;
pComps
->OuterDisp
+= Value
;
return True
;
}
/*!------------------------------------------------------------------------
* \fn ClassCompList(tAdrComps *pComps, tStrComp *pArg)
* \brief classify/parse argument list of indirect address expression
* \param pComps indirect address evaluation context to fill
* \param pArg address expression argument
* \return True if parsing succeeded
* ------------------------------------------------------------------------ */
static Boolean ClassCompList
(tAdrComps
*pComps
, tStrComp
*pArg
)
{
ResetAdrComps
(pComps
);
if (IsIndirect
(pArg
->str.
p_str))
{
char *pSplit
;
tStrComp Remainder
;
StrCompIncRefLeft
(pArg
, 1);
StrCompShorten
(pArg
, 1);
do
{
pSplit
= QuotPos
(pArg
->str.
p_str, ',');
if (pSplit
)
StrCompSplitRef
(pArg
, &Remainder
, pArg
, pSplit
);
if (!ClassComp
(pArg
, pComps
))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
return False
;
}
if (pSplit
)
*pArg
= Remainder
;
}
while (pSplit
);
}
else
{
if (!ClassComp
(pArg
, pComps
))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
return False
;
}
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeAdr(const tStrComp *pArg, unsigned Mask, tAdrVals *pAdrVals, LongInt EAAddr)
* \brief parse address expression
* \param pArg expression to parse
* \param Mask bit mask of allowed addressing modes
* \param pAdrVals returns parsed addressing mode
* \param EAAddr position of associared EA byte in code (needed for PC-relative addressing)
* \return True if parsing succeeded
* ------------------------------------------------------------------------ */
static Boolean DecodeAdr
(const tStrComp
*pArg
, unsigned Mask
, tAdrVals
*pAdrVals
, LongInt EAAddr
)
{
Byte Reg
, Prefix
;
tStrComp Arg
;
ResetAdrVals
(pAdrVals
);
StrCompRefRight
(&Arg
, pArg
, 0);
while (True
)
{
if (!as_strncasecmp
(Arg.
str.
p_str, "<CRn>", 5)
|| !as_strncasecmp
(Arg.
str.
p_str, "<PRn>", 5))
{
AppendAdrVals
(pAdrVals
, (toupper(Arg.
str.
p_str[1]) == 'C') ? PREFIX_CRn
: PREFIX_PRn
);
StrCompIncRefLeft
(&Arg
, 5);
KillPrefBlanksStrCompRef
(&Arg
);
}
else
break;
}
switch (DecodeReg
(&Arg
, &Reg
, &Prefix
, True
, False
))
{
case eIsReg
:
pAdrVals
->Mode
= eAdrModeReg
;
AppendRegPrefix
(pAdrVals
, Prefix
);
AppendAdrVals
(pAdrVals
, 0x40 | Reg
);
goto Check
;
case eIsNoReg
:
break;
case eRegAbort
:
return False
;
}
if (*Arg.
str.
p_str == '#')
{
tSymbolSize ImmOpSize
;
LongInt ArgVal
;
Boolean OK
;
if (!SplitOpSize
(&Arg
, &ImmOpSize
))
ImmOpSize
= OpSize
;
ArgVal
= EvalArg
(&Arg
, 1, ImmOpSize
, &OK
);
if (OK
)
{
AppendAdrVals
(pAdrVals
, 0x70 | (ImmOpSize
+ 1));
AppendToAdrValsBySize
(pAdrVals
, ArgVal
, ImmOpSize
);
pAdrVals
->Mode
= eAdrModeImm
;
}
goto Check
;
}
if (*Arg.
str.
p_str == '@')
{
tStrComp IndirComp
;
tAdrComps Comps
;
StrCompRefRight
(&IndirComp
, &Arg
, 1);
if (!ClassCompList
(&Comps
, &IndirComp
))
return False
;
/* only base register, no indirection, and optional displacement: */
if (!Comps.
InnerDispPresent
&& (Comps.
InnerReg == NOREG
)
&& (Comps.
IndexReg == NOREG
)
&& NormalReg
(Comps.
BaseReg)
&& !Comps.
BaseRegIncr)
{
if (Comps.
OuterDispPresent)
{
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSize
(Comps.
OuterDisp);
if (!ChkSize
(Comps.
OuterDisp, Comps.
OuterDispSize))
goto Check
;
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, ((Comps.
OuterDispSize + 1) << 4) | Comps.
BaseReg);
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
}
else
AppendAdrVals
(pAdrVals
, 0x00 | Comps.
BaseReg);
pAdrVals
->Mode
= eAdrModeIReg
;
goto Check
;
}
/* postinc/predec */
if (!Comps.
InnerDispPresent
&& !Comps.
OuterDispPresent
&& (Comps.
InnerReg == NOREG
)
&& (Comps.
IndexReg == NOREG
)
&& NormalReg
(Comps.
BaseReg)
&& Comps.
BaseRegIncr)
{
if (Comps.
BaseRegIncr > 0)
{
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, 0x50 | Comps.
BaseReg);
pAdrVals
->Mode
= eAdrModePost
;
}
else
{
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, 0x60 | Comps.
BaseReg);
pAdrVals
->Mode
= eAdrModePre
;
}
goto Check
;
}
/* absolute */
if (!Comps.
InnerDispPresent
&& Comps.
OuterDispPresent
&& (Comps.
InnerReg == NOREG
)
&& (Comps.
IndexReg == NOREG
)
&& (Comps.
BaseReg == NOREG
))
{
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSize16M
(Comps.
OuterDisp);
if (!ChkSize16M
(Comps.
OuterDisp, Comps.
OuterDispSize))
goto Check
;
AppendAdrVals
(pAdrVals
, 0x74 | (Comps.
OuterDispSize + 1));
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
pAdrVals
->Mode
= eAdrModeAbs
;
goto Check
;
}
/* register indirect with scale */
if (!Comps.
InnerDispPresent
&& (Comps.
InnerReg == NOREG
)
&& (Comps.
BaseReg == NOREG
)
&& NormalReg
(Comps.
IndexReg)
&& (Comps.
IndexRegSize == eSymbolSize32Bit
))
{
Byte EAVal
= 0x78;
if (Comps.
OuterDispPresent)
{
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSize
(Comps.
OuterDisp);
if (!ChkSize
(Comps.
OuterDisp, Comps.
OuterDispSize))
goto Check
;
EAVal
|= (1 + Comps.
OuterDispSize);
}
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, EAVal
);
AppendAdrVals
(pAdrVals
, (Comps.
IndexRegScale << 4) | Comps.
IndexReg);
if (Comps.
OuterDispPresent)
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
pAdrVals
->Mode
= eAdrModeIRegScale
;
goto Check
;
}
/* register indirect with (scaled) index */
if (!Comps.
InnerDispPresent
&& (Comps.
InnerReg == NOREG
)
&& NormalReg
(Comps.
BaseReg)
&& NormalReg
(Comps.
IndexReg))
{
Byte Exp1Val
= ((Comps.
IndexRegSize - 1) << 6) | Comps.
BaseReg;
if (Comps.
OuterDispPresent)
{
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSize
(Comps.
OuterDisp);
if (!ChkSize
(Comps.
OuterDisp, Comps.
OuterDispSize))
goto Check
;
Exp1Val
|= (1 + Comps.
OuterDispSize) << 4;
}
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, 0x7c);
AppendAdrVals
(pAdrVals
, Exp1Val
);
AppendAdrVals
(pAdrVals
, (Comps.
IndexRegScale << 4) | Comps.
IndexReg);
if (Comps.
OuterDispPresent)
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
pAdrVals
->Mode
= eAdrModeIdxScale
;
goto Check
;
}
/* PC-relative with (scaled) index */
if (!Comps.
InnerDispPresent
&& (Comps.
InnerReg == NOREG
)
&& (Comps.
BaseReg == PCREG
)
&& NormalReg
(Comps.
IndexReg))
{
Byte Exp1Val
= ((Comps.
IndexRegSize - 1) << 6);
if (Comps.
OuterDispPresent)
{
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSizePCRel
(Comps.
OuterDisp, EAAddr
+ 3);
if (!ChkSizePCRelDisplacement
(&Comps.
OuterDisp, Comps.
OuterDispSize, EAAddr
+ 3))
goto Check
;
Exp1Val
|= (1 + Comps.
OuterDispSize) << 4;
}
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, 0x7d);
AppendAdrVals
(pAdrVals
, Exp1Val
);
AppendAdrVals
(pAdrVals
, (Comps.
IndexRegScale << 4) | Comps.
IndexReg);
if (Comps.
OuterDispPresent)
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
pAdrVals
->Mode
= eAdrModePCIdxScale
;
goto Check
;
}
/* PC-relative */
if (!Comps.
InnerDispPresent
&& (Comps.
InnerReg == NOREG
)
&& (Comps.
BaseReg == PCREG
)
&& (Comps.
IndexReg == NOREG
))
{
Byte Exp1Val
= 0x80;
if (Comps.
OuterDispPresent)
{
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSizePCRel
(Comps.
OuterDisp, EAAddr
+ 2);
if (!ChkSizePCRelDisplacement
(&Comps.
OuterDisp, Comps.
OuterDispSize, EAAddr
+ 2))
goto Check
;
Exp1Val
|= (1 + Comps.
OuterDispSize) << 4;
}
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix); /* should never occur, no Rn in expression */
AppendAdrVals
(pAdrVals
, 0x7d);
AppendAdrVals
(pAdrVals
, Exp1Val
);
if (Comps.
OuterDispPresent)
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
pAdrVals
->Mode
= eAdrModePCRel
;
goto Check
;
}
/* Register double indirect */
if (NormalReg
(Comps.
InnerReg)
&& (Comps.
BaseReg == NOREG
)
&& (Comps.
IndexReg == NOREG
))
{
/* no disp not allowed -> convert zero-disp to 8 bits */
if (Comps.
OuterDispSize == eSymbolSizeUnknown
)
Comps.
OuterDispSize = DeduceSize8_32
(Comps.
OuterDisp);
if (Comps.
InnerDispSize == eSymbolSizeUnknown
)
Comps.
InnerDispSize = DeduceSize8_32
(Comps.
InnerDisp);
AppendRegPrefix
(pAdrVals
, Comps.
RegPrefix);
AppendAdrVals
(pAdrVals
, 0x7e);
AppendAdrVals
(pAdrVals
, Comps.
InnerReg | ((Comps.
InnerDispSize + 1) << 4) | ((Comps.
OuterDispSize + 1) << 6));
AppendToAdrValsBySize
(pAdrVals
, Comps.
InnerDisp, Comps.
InnerDispSize);
AppendToAdrValsBySize
(pAdrVals
, Comps.
OuterDisp, Comps.
OuterDispSize);
pAdrVals
->Mode
= eAdrModeDoubleIndir
;
goto Check
;
}
WrStrErrorPos
(ErrNum_InvAddrMode
, &Arg
);
}
/* None of this. Should we treat it as absolute? */
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
Check
:
if ((pAdrVals
->Mode
!= eAdrModeNone
)
&& !((Mask
>> pAdrVals
->Mode
) & 1))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
ResetAdrVals
(pAdrVals
);
return False
;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn GlobalBankReg(const tAdrVals *pAdrVals)
* \brief check whether parsed address expression is a global bank register
* \param pAdrVals parsed expression
* \return True if it is a global bank register
* ------------------------------------------------------------------------ */
static Boolean GlobalBankReg
(const tAdrVals
*pAdrVals
)
{
return (pAdrVals
->Mode
== eAdrModeReg
)
&& (pAdrVals
->Cnt
== 1);
}
/*!------------------------------------------------------------------------
* \fn ImmValS8(const tAdrVals *pAdrVals)
* \brief check whether parsed address expression is an immediate value representable as 8 bits,
assuming sign extension
* \param pAdrVals parsed expression
* \return True if immediate & value range OK
* ------------------------------------------------------------------------ */
static Boolean ImmValS8
(const tAdrVals
*pAdrVals
)
{
Byte Sign
;
unsigned z
;
if ((pAdrVals
->Mode
!= eAdrModeImm
)
|| (pAdrVals
->Cnt
< 1))
return False
;
Sign
= (pAdrVals
->Vals
[pAdrVals
->Cnt
- 1] & 0x80) ? 0xff: 0x00;
for (z
= 1; z
< pAdrVals
->Cnt
- 1; z
++)
if (pAdrVals
->Vals
[z
] != Sign
)
return False
;
return True
;
}
/*!------------------------------------------------------------------------
* \fn ImmValS4(const tAdrVals *pAdrVals)
* \brief check whether parsed address expression is an immediate value representable as 4 bits,
assuming sign extension
* \param pAdrVals parsed expression
* \return True if immediate & value range OK
* ------------------------------------------------------------------------ */
static Boolean ImmValS4
(const tAdrVals
*pAdrVals
)
{
Byte Sign
;
if (!ImmValS8
(pAdrVals
))
return False
;
Sign
= (pAdrVals
->Vals
[pAdrVals
->Cnt
- 1] & 0x08) ? 0xf0: 0x00;
return (pAdrVals
->Vals
[pAdrVals
->Cnt
- 1] & 0xf0) == Sign
;
}
/*!------------------------------------------------------------------------
* \fn AppendAdrValsToCode(const tAdrVals *pAdrVals)
* \brief append parsed address expression to instruction's code
* \param pAdrVals parsed expression
* ------------------------------------------------------------------------ */
static void AppendAdrValsToCode
(const tAdrVals
*pAdrVals
)
{
memcpy(&BAsmCode
[CodeLen
], pAdrVals
->Vals
, pAdrVals
->Cnt
);
CodeLen
+= pAdrVals
->Cnt
;
}
/*!------------------------------------------------------------------------
* \fn AppendAdrValPair(tAdrVals *pSrcAdrVals, const tAdrVals *pDestAdrVals)
* \brief append source & destination address expression to instruction's code
* \param pSrcAdrVals parsed source address expression
* \param pDestAdrVals parsed destination address expression
* ------------------------------------------------------------------------ */
static void AppendAdrValPair
(tAdrVals
*pSrcAdrVals
, const tAdrVals
*pDestAdrVals
)
{
Byte
*pEASrc
= &BAsmCode
[CodeLen
];
AppendAdrValsToCode
(pSrcAdrVals
);
if (pDestAdrVals
->Vals
[0] == 0x40) /* EA=0x40 -> R0 -> accumulator mode */
*pEASrc
|= 0x80;
else
AppendAdrValsToCode
(pDestAdrVals
);
}
/*--------------------------------------------------------------------------*/
/* Bit Symbol Handling */
/*
* Compact representation of bits and bit fields in symbol table:
* bits 0..2/3/4: (start) bit position
* bits 3/4/5...26/27/28: register address
* bits 30/31: register size (0/1/2 for 8/16/32 bits)
*/
/*!------------------------------------------------------------------------
* \fn EvalBitPosition(const char *pBitArg, Boolean *pOK, tSymbolSize OpSize)
* \brief evaluate constant bit position, with bit range depending on operand size
* \param pBitArg bit position argument
* \param pOK returns True if OK
* \param OpSize operand size (0,1,2 -> 8,16,32 bits)
* \return bit position as number
* ------------------------------------------------------------------------ */
static Byte EvalBitPosition
(const tStrComp
*pBitArg
, Boolean
*pOK
, tSymbolSize OpSize
)
{
int Offset
= !!(*pBitArg
->str.
p_str == '#');
switch (OpSize
)
{
case eSymbolSize8Bit
:
return EvalStrIntExpressionOffs
(pBitArg
, Offset
, UInt3
, pOK
);
case eSymbolSize16Bit
:
return EvalStrIntExpressionOffs
(pBitArg
, Offset
, UInt4
, pOK
);
case eSymbolSize32Bit
:
return EvalStrIntExpressionOffs
(pBitArg
, Offset
, UInt5
, pOK
);
default:
WrError
(ErrNum_InvOpSize
);
*pOK
= False
;
return 0;
}
}
/*!------------------------------------------------------------------------
* \fn AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address)
* \brief build the compact internal representation of a bit field symbol
* \param BitPos bit position in word
* \param Width width of bit field
* \param OpSize operand size (8/16/32 bit)
* \param Address register address
* \return compact representation
* ------------------------------------------------------------------------ */
static LongWord AssembleBitSymbol
(Byte BitPos
, tSymbolSize OpSize
, LongWord Address
)
{
int AddrShift
= 3 + OpSize
;
return BitPos
| ((Address
& 0xfffffful
) << AddrShift
)
| ((LongWord
)OpSize
<< 30);
}
/*!------------------------------------------------------------------------
* \fn DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize)
* \brief transform compact represenation of bit (field) symbol into components
* \param BitSymbol compact storage
* \param pAddress (I/O) register address
* \param pBitPos (start) bit position
* \param pOpSize returns register size (0/1/2 for 8/16/32 bits)
* \return constant True
* ------------------------------------------------------------------------ */
static Boolean DissectBitSymbol
(LongWord BitSymbol
, LongWord
*pAddress
, Byte
*pBitPos
, tSymbolSize
*pOpSize
)
{
*pOpSize
= (tSymbolSize
)((BitSymbol
>> 30) & 3);
switch (*pOpSize
)
{
case eSymbolSize8Bit
:
*pAddress
= (BitSymbol
>> 3) & 0xfffffful
;
*pBitPos
= BitSymbol
& 7;
break;
case eSymbolSize16Bit
:
*pAddress
= (BitSymbol
>> 4) & 0xfffffful
;
*pBitPos
= BitSymbol
& 15;
break;
case eSymbolSize32Bit
:
*pAddress
= (BitSymbol
>> 5) & 0xfffffful
;
*pBitPos
= BitSymbol
& 31;
break;
default:
*pAddress
= 0;
*pBitPos
= 0;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn DissectBit_H16(char *pDest, size_t DestSize, LargeWord Inp)
* \brief dissect compact storage of bit (field) into readable form for listing
* \param pDest destination for ASCII representation
* \param DestSize destination buffer size
* \param Inp compact storage
* ------------------------------------------------------------------------ */
static void DissectBit_H16
(char *pDest
, size_t DestSize
, LargeWord Inp
)
{
Byte BitPos
;
LongWord Address
;
tSymbolSize OpSize
;
char Attribute
;
DissectBitSymbol
(Inp
, &Address
, &BitPos
, &OpSize
);
Attribute
= "bwl"[OpSize
];
as_snprintf
(pDest
, DestSize
, "$%lx(%c).%u", (unsigned long)Address
, Attribute
, (unsigned)BitPos
);
}
/*!------------------------------------------------------------------------
* \fn ExpandH16Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
* \brief expands bit definition when a structure is instantiated
* \param pVarName desired symbol name
* \param pStructElem element definition
* \param Base base address of instantiated structure
* ------------------------------------------------------------------------ */
static void ExpandH16Bit
(const tStrComp
*pVarName
, const struct sStructElem
*pStructElem
, LargeWord Base
)
{
tSymbolSize OpSize
= (pStructElem
->OpSize
< 0) ? eSymbolSize8Bit
: pStructElem
->OpSize
;
LongWord Address
= Base
+ pStructElem
->Offset
;
if (!ChkRange
(Address
, 0, 0xfffffful
)
|| !ChkRange
(pStructElem
->BitPos
, 0, (8 << OpSize
) - 1))
return;
PushLocHandle
(-1);
EnterIntSymbol
(pVarName
, AssembleBitSymbol
(pStructElem
->BitPos
, OpSize
, Address
), SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, tSymbolSize OpSize)
* \brief encode a bit symbol, address & bit position separated
* \param pResult resulting encoded bit
* \param pRegArg register argument
* \param pBitArg bit argument
* \param OpSize register size (0/1/2 = 8/16/32 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg2
(LongWord
*pResult
, const tStrComp
*pRegArg
, const tStrComp
*pBitArg
, tSymbolSize OpSize
)
{
Boolean OK
;
LongWord Addr
;
Byte BitPos
;
BitPos
= EvalBitPosition
(pBitArg
, &OK
, OpSize
);
if (!OK
)
return False
;
Addr
= EvalStrIntExpressionOffs
(pRegArg
, !!(*pRegArg
->str.
p_str == '@'), UInt24
, &OK
);
if (!OK
)
return False
;
*pResult
= AssembleBitSymbol
(BitPos
, OpSize
, Addr
);
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg(LongWord *pResult, int Start, int Stop)
* \brief encode a bit symbol from instruction argument(s)
* \param pResult resulting encoded bit
* \param Start first argument
* \param Stop last argument
* \param OpSize register size (0/1/2 = 8/16/32 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg
(LongWord
*pResult
, int Start
, int Stop
, tSymbolSize OpSize
)
{
*pResult
= 0;
/* Just one argument -> parse as bit argument */
if (Start
== Stop
)
{
tEvalResult EvalResult
;
*pResult
= EvalStrIntExpressionWithResult
(&ArgStr
[Start
], UInt32
, &EvalResult
);
if (EvalResult.
OK)
ChkSpace
(SegBData
, EvalResult.
AddrSpaceMask);
return EvalResult.
OK;
}
/* Register & bit position are given as separate arguments:
use same argument positions as for machine instructions */
else if (Stop
== Start
+ 1)
return DecodeBitArg2
(pResult
, &ArgStr
[Stop
], &ArgStr
[Start
], OpSize
);
/* other # of arguments not allowed */
else
{
WrError
(ErrNum_WrongArgCnt
);
return False
;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeStringReg(Word Code)
* \brief decode register argument for string instruction
* \param pComp argument to parse
* \param Mask bit mask of allowed addressing modes
* \param pResult returns (global) register number
* ------------------------------------------------------------------------ */
static Boolean DecodeStringReg
(tStrComp
*pComp
, unsigned Mask
, Byte
*pResult
)
{
tAdrVals AdrVals
;
if (!DecodeAdr
(pComp
, Mask
, &AdrVals
, EProgCounter
() + 2))
return False
;
switch (AdrVals.
Mode)
{
case eAdrModeReg
:
if (!GlobalBankReg
(&AdrVals
))
{
WrStrErrorPos
(ErrNum_InvReg
, pComp
);
return False
;
}
break;
case eAdrModeIReg
:
if (AdrVals.
Cnt != 1)
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pComp
);
return False
;
}
break;
case eAdrModePost
:
case eAdrModePre
:
break;
default:
return False
;
}
*pResult
= AdrVals.
Vals[0] & 15;
return True
;
}
/*!------------------------------------------------------------------------
* \fn ExtractDisp(const Byte *pVals, Byte SizeCode)
* \brief extract variable-length signed value
* \param pVals storage of value
* \param SizeCode # of bytes used (0..3 for 0/1/2/4 bytes)
* \return effective value
* ------------------------------------------------------------------------ */
static LongInt ExtractDisp
(const Byte
*pVals
, Byte SizeCode
)
{
LongInt Result
= 0;
switch (SizeCode
)
{
case 3:
Result
= (Result
<< 8) | (*pVals
++);
Result
= (Result
<< 8) | (*pVals
++);
Result
= (Result
<< 8) | (*pVals
++);
Result
= (Result
<< 8) | (*pVals
++);
break;
case 2:
Result
= (Result
<< 8) | (*pVals
++);
Result
= (Result
<< 8) | (*pVals
++);
if (Result
& 0x8000ul
)
Result
-= 0x10000ul
;
break;
case 1:
Result
= (Result
<< 8) | (*pVals
++);
if (Result
& 0x80ul
)
Result
-= 0x100;
break;
default:
Result
= 0;
}
return Result
;
}
/*!------------------------------------------------------------------------
* \fn PCDistOK(const tAdrVals *pAdrVals, int Delta)
* \brief if expression is PC-relative, check whether change of distance does not change displacement size
* \param pAdrVals parsed address expression
* \param Delta displacement change
* ------------------------------------------------------------------------ */
static Boolean PCDistOK
(tAdrVals
*pAdrVals
, int Delta
)
{
Byte DispSizeCode
;
LongInt NewDisp
;
int DispOffs
;
tSymbolSize DispSize
;
/* only relevant for EA values that use PC-relative addressing: */
if (pAdrVals
->Vals
[0] != 0x7d)
return True
;
DispOffs
= (pAdrVals
->Vals
[1] & 0x80) ? 2 : 3;
/* extract displacement size Sd */
DispSizeCode
= (pAdrVals
->Vals
[1] >> 4) & 3;
DispSize
= (tSymbolSize
)(DispSizeCode
- 1);
/* compute new displacement after correction */
NewDisp
= ExtractDisp
(pAdrVals
->Vals
+ DispOffs
, DispSizeCode
) + Delta
;
/* still fits size? */
if (DeduceSize
(NewDisp
) != DispSize
)
return False
;
AppendBySize
(pAdrVals
->Vals
+ DispOffs
, NewDisp
, DispSize
);
return True
;
}
/*!------------------------------------------------------------------------
* \fn NegSignedValOK(tAdrVals *pAdrVals)
* \brief tests whether negated (8 bit) immediate value still fits size
* \param pAdrVals parsed address expression
* \return True if successfully inverted
* ------------------------------------------------------------------------ */
static Boolean NegSigned8ValOK
(tAdrVals
*pAdrVals
)
{
Byte DispSizeCode
;
LongInt Value
;
tSymbolSize DispSize
;
/* only treats immediate argument: */
if (pAdrVals
->Mode
!= eAdrModeImm
)
return False
;
DispSizeCode
= pAdrVals
->Vals
[0] & 3;
if (!DispSizeCode
)
return False
;
DispSize
= (tSymbolSize
)(DispSizeCode
- 1);
/* extract immediate value */
Value
= ExtractDisp
(pAdrVals
->Vals
+ 1, DispSizeCode
) * (-1);
/* still fits size? */
if (DeduceSize
(Value
) > eSymbolSize8Bit
)
return False
;
AppendBySize
(pAdrVals
->Vals
+ 1, Value
, DispSize
);
return True
;
}
/*---------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn DecodeMOV_ADD_SUB_CMP(Word Code)
* \brief instruction parser for MOV, ADD, CMP and SUB
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMOV_ADD_SUB_CMP
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
tFormat Format
;
unsigned DestMask
;
Boolean IsSUB
= (Code
== 0x04),
IsCMP
= (Code
== 0x08);
if (!ChkOpSize
(eSymbolSize16Bit
, 7))
return;
/* Immediate is allowed as destination for CMP since the result is
anyway discarded: */
DestMask
= MModeAll
;
if (!IsCMP
)
DestMask
&= ~MModeImm
;
if (ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], DestMask
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
/* TODO: auto-convert SUB:Q n,<ea> to ADD:q -n,<ea>? */
if (!*FormatPart.
str.
p_str)
{
/* R format (all instructions) */
if (GlobalBankReg
(&SrcAdrVals
) && GlobalBankReg
(&DestAdrVals
))
Format
= eFormatR
;
/* MOV R0,<ea> -> MOVF <ea> if PC-relative distance size does not change. */
else if (GlobalBankReg
(&SrcAdrVals
) && (SrcAdrVals.
Vals[0] == 0x40) && PCDistOK
(&DestAdrVals
, SrcAdrVals.
Cnt))
Format
= eFormatF
;
else if (ImmValS4
(&SrcAdrVals
) && GlobalBankReg
(&DestAdrVals
))
Format
= eFormatRQ
;
/* SUB:Q #n,<ea> does not exist. Convert to ADD:Q #-n,<ea> if possible..
TODO: should not do this at all if immediate size >= 16 bit was forced. */
else if (ImmValS8
(&SrcAdrVals
) && (!IsSUB
|| NegSigned8ValOK
(&SrcAdrVals
)))
{
if (IsSUB
)
{
Code
= 0x00;
IsSUB
= False
;
}
Format
= eFormatQ
;
}
else
Format
= eFormatG
;
}
else if (!(Format
= DecodeFormat
((1 << eFormatG
) | (1 << eFormatQ
) | (1 << eFormatR
) | (1 << eFormatRQ
))))
{
WrStrErrorPos
(ErrNum_InvFormat
, &FormatPart
);
return;
}
switch (Format
)
{
case eFormatG
:
BAsmCode
[CodeLen
++] = 0x00 | Code
| OpSize
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
break;
case eFormatR
:
if (!GlobalBankReg
(&SrcAdrVals
)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else if (!GlobalBankReg
(&DestAdrVals
)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
else
{
BAsmCode
[CodeLen
++] = 0x20 | Code
| OpSize
;
BAsmCode
[CodeLen
++] = ((SrcAdrVals.
Vals[0] & 15) << 4) | (DestAdrVals.
Vals[0] & 15);
}
break;
case eFormatRQ
:
if (SrcAdrVals.
Mode != eAdrModeImm
) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else if (!ImmValS4
(&SrcAdrVals
)) WrStrErrorPos
(ErrNum_OverRange
, &ArgStr
[1]);
else if (!GlobalBankReg
(&DestAdrVals
)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
else
{
BAsmCode
[CodeLen
++] = 0x30 | Code
| OpSize
;
BAsmCode
[CodeLen
++] = ((DestAdrVals.
Vals[0] & 15) << 4) | (SrcAdrVals.
Vals[SrcAdrVals.
Cnt - 1] & 15);
}
break;
case eFormatQ
:
if (IsSUB
) WrStrErrorPos
(ErrNum_InvAddrMode
, &AttrPart
);
else if (SrcAdrVals.
Mode != eAdrModeImm
) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else if (!ImmValS8
(&SrcAdrVals
)) WrStrErrorPos
(ErrNum_OverRange
, &ArgStr
[1]);
else
{
BAsmCode
[CodeLen
++] = 0x10 | Code
| OpSize
;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Vals[SrcAdrVals.
Cnt - 1];
AppendAdrValsToCode
(&DestAdrVals
);
}
break;
case eFormatF
:
if (!GlobalBankReg
(&SrcAdrVals
) || (SrcAdrVals.
Vals[0] != 0x40)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else
{
BAsmCode
[CodeLen
++] = 0x5c | OpSize
;
AppendAdrValsToCode
(&DestAdrVals
);
}
break;
default:
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeSignExt(Word Code)
* \brief instruction parser for MOVS, ADDS, CMPS and SUBS
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeSignExt
(Word Code
)
{
tSymbolSize SrcOpSize
;
tAdrVals SrcAdrVals
, DestAdrVals
;
Boolean IsCMPS
= (Code
== 0x48);
unsigned DestMask
;
/* Immediate is allowed as destination for CMPS since the result is
anyway discarded: */
DestMask
= MModeAll
;
if (!IsCMPS
)
DestMask
&= ~MModeImm
;
if (!ChkEmptyFormat
()
|| !ChkOpSize
(eSymbolSize16Bit
, 7)
|| !ChkArgCnt
(2, 2)
|| !DecodeAdr
(&ArgStr
[1], MModeAll
, &SrcAdrVals
, EProgCounter
() + 1))
return;
SrcOpSize
= OpSize
;
OpSize
= eSymbolSize32Bit
;
if (DecodeAdr
(&ArgStr
[2], DestMask
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
| SrcOpSize
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeTwo(Word Code)
* \brief instruction parser for generic two-operand instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeTwo
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
Boolean Only8
= (Code
& 3) == 3;
if (ChkEmptyFormat
()
&& ChkOpSize
(Only8
? eSymbolSize8Bit
: eSymbolSize16Bit
, Only8
? 1 : 7)
&& ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], MModeAll
- MModeImm
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
| OpSize
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeOne(Word Code)
* \brief instruction parser for generic one-operand instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeOne
(Word Code
)
{
tAdrVals AdrVals
;
Boolean Only8
= !!(Code
& 3);
unsigned Mask
;
Mask
= MModeAll
;
if (Code
!= 0x58) /* TST */
Mask
&= ~MModeImm
;
if (ChkEmptyFormat
()
&& ChkOpSize
(Only8
? eSymbolSize8Bit
: eSymbolSize16Bit
, Only8
? 1 : 7)
&& ChkArgCnt
(1, 1)
&& DecodeAdr
(&ArgStr
[1], Mask
, &AdrVals
, EProgCounter
() + 1))
{
BAsmCode
[CodeLen
++] = Code
| OpSize
;
AppendAdrValsToCode
(&AdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMUL_DIV(Word Code)
* \brief instruction parser for multiply and divide instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMUL_DIV
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (!ChkEmptyFormat
()
|| !ChkOpSize
(eSymbolSize16Bit
, 3)
|| !ChkArgCnt
(2, 2)
|| !DecodeAdr
(&ArgStr
[1], MModeAll
, &SrcAdrVals
, EProgCounter
() + 2))
return;
OpSize
++;
if (!DecodeAdr
(&ArgStr
[2], MModeAll
- MModeImm
, &DestAdrVals
, EProgCounter
() + 2 + SrcAdrVals.
Cnt))
return;
OpSize
--;
BAsmCode
[CodeLen
++] = 0xee | (Code
& 0x01);
BAsmCode
[CodeLen
++] = (Code
& 0x70) | (OpSize
<< 4);
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
/*!------------------------------------------------------------------------
* \fn DecodeEXT(Word Code)
* \brief instruction parser for EXTS/EXTU
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeEXT
(Word Code
)
{
Byte Reg
, Prefix
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 7)
&& ChkArgCnt
(1, 1))
{
if (DecodeReg
(&ArgStr
[1], &Reg
, &Prefix
, False
, True
))
{
OpSize
= (OpSize
== eSymbolSize8Bit
) ? eSymbolSize32Bit
: (OpSize
- 1);
BAsmCode
[CodeLen
++] = Code
| OpSize
;
BAsmCode
[CodeLen
++] = Reg
;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeCInstr(Word Code)
* \brief instruction decoder for control-register related instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeCInstr
(Word Code
)
{
Byte CReg
;
unsigned Mask
= MModeAll
;
int CIdx
= 2, EAIdx
= 1;
tAdrVals AdrVals
;
if (0xfc == Code
) /* STC */
{
CIdx
= 1;
EAIdx
= 2;
Mask
&= ~MModeImm
;
}
if (ChkEmptyFormat
()
&& ChkArgCnt
(2, 2)
&& DecodeCReg
(&ArgStr
[CIdx
], &CReg
)
&& DecodeAdr
(&ArgStr
[EAIdx
], Mask
, &AdrVals
, EProgCounter
() + 2))
{
BAsmCode
[CodeLen
++] = Code
;
BAsmCode
[CodeLen
++] = CReg
;
AppendAdrValsToCode
(&AdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBranch(Word Code)
* \brief instruction decoder for non-generic branch instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeBranch
(Word Code
)
{
LongInt Addr
;
Boolean OK
;
tSymbolFlags Flags
;
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(1, 1))
return;
Addr
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[1], !!(*ArgStr
[1].
str.
p_str == '@'), UInt24
, &OK
, &Flags
);
if (!OK
)
return;
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= DeduceSizePCRel
(Addr
, EProgCounter
() + 1);
if (!ChkSizePCRelBranch
(&ArgStr
[1], &Addr
, OpSize
, Flags
, EProgCounter
() + 1))
return;
BAsmCode
[CodeLen
++] = Code
| OpSize
;
CodeLen
+= AppendBySize
(BAsmCode
+ CodeLen
, Addr
, OpSize
);
}
/*!------------------------------------------------------------------------
* \fn DecodeBranchGen(Word Code)
* \brief instruction decoder for generic branch instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeBranchGen
(Word Code
)
{
LongInt Addr
;
Boolean OK
;
tSymbolFlags Flags
;
tFormat Format
;
if (!ChkArgCnt
(1, 1))
return;
if (!*FormatPart.
str.
p_str)
{
if (Code
== 7)
{
DecodeBranch
(0xa0);
return;
}
if (Code
== 6)
{
DecodeBranch
(0xb0);
return;
}
}
else
{
Format
= DecodeFormat
(1 << eFormatG
);
if (!Format
)
{
WrStrErrorPos
(ErrNum_InvFormat
, &FormatPart
);
return;
}
}
Addr
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[1], !!(*ArgStr
[1].
str.
p_str == '@'), UInt24
, &OK
, &Flags
);
if (!OK
)
return;
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= DeduceSizePCRel
(Addr
, EProgCounter
() + 2);
if (!ChkSizePCRelBranch
(&ArgStr
[1], &Addr
, OpSize
, Flags
, EProgCounter
() + 2))
return;
BAsmCode
[CodeLen
++] = 0xa4 | OpSize
;
BAsmCode
[CodeLen
++] = Code
;
CodeLen
+= AppendBySize
(BAsmCode
+ CodeLen
, Addr
, OpSize
);
}
/*!------------------------------------------------------------------------
* \fn DecodeFixed(Word Code)
* \brief instruction decoder for instructions without argument
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeFixed
(Word Code
)
{
if (ChkEmptyFormat
()
&& (!(Code
& 0x8000) || CheckSup
(&OpPart
))
&& ChkArgCnt
(0, 0))
BAsmCode
[CodeLen
++] = Lo
(Code
);
}
/*!------------------------------------------------------------------------
* \fn Decode(Word Code)
* \brief instruction decoder for shift & rotate instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeShift
(Word Code
)
{
tAdrVals ShiftAdrVals
, OpAdrVals
;
tSymbolSize SaveOpSize
;
if (!ChkEmptyFormat
()
|| !ChkOpSize
(eSymbolSize16Bit
, 7)
|| !ChkArgCnt
(2, 2)
|| !DecodeAdr
(&ArgStr
[2], MModeAll
- MModeImm
, &OpAdrVals
, EProgCounter
() + 2))
return;
SaveOpSize
= OpSize
;
OpSize
= eSymbolSize5Bit
;
(void)DecodeAdr
(&ArgStr
[1], MModeImm
| MModeReg
, &ShiftAdrVals
, EProgCounter
() + 1);
switch (ShiftAdrVals.
Mode)
{
case eAdrModeReg
:
if (ShiftAdrVals.
Cnt > 1) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
{
BAsmCode
[CodeLen
++] = 0x60 | SaveOpSize
;
BAsmCode
[CodeLen
++] = Code
| (ShiftAdrVals.
Vals[0] & 15);
goto common
;
}
break;
case eAdrModeImm
:
BAsmCode
[CodeLen
++] = 0x64 | SaveOpSize
;
BAsmCode
[CodeLen
++] = Code
| (ShiftAdrVals.
Vals[1] & 31);
goto common
;
default:
break;
common
:
AppendAdrValsToCode
(&OpAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeSET(Word Code)
* \brief instruction decoder for SET/cc instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeSET
(Word Code
)
{
tAdrVals AdrVals
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize8Bit
, 1)
&& ChkArgCnt
(1, 1)
&& DecodeAdr
(&ArgStr
[1], MModeAll
- MModeImm
, &AdrVals
, EProgCounter
() + 2))
{
BAsmCode
[CodeLen
++] = 0xb7;
BAsmCode
[CodeLen
++] = Code
;
AppendAdrValsToCode
(&AdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeTRAP(Word Code)
* \brief instruction decoder for TRAP/cc instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeTRAP
(Word Code
)
{
if (ChkEmptyFormat
()
&& ChkArgCnt
(0, 0))
{
BAsmCode
[CodeLen
++] = 0xf3;
BAsmCode
[CodeLen
++] = Code
;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeSCB(Word Code)
* \brief instruction decoder for SCB/cc instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeSCB
(Word Code
)
{
LongInt Addr
;
Boolean OK
;
tSymbolFlags Flags
;
Byte Reg
, Prefix
;
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(2, 2))
return;
if (!DecodeReg
(&ArgStr
[1], &Reg
, &Prefix
, False
, True
))
return;
Addr
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[2], !!(*ArgStr
[1].
str.
p_str == '@'), UInt24
, &OK
, &Flags
);
if (!OK
)
return;
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= DeduceSizePCRel
(Addr
, EProgCounter
() + 2);
if (!ChkSizePCRelBranch
(&ArgStr
[2], &Addr
, OpSize
, Flags
, EProgCounter
() + 2))
return;
BAsmCode
[CodeLen
++] = 0xb4 | OpSize
;
BAsmCode
[CodeLen
++] = (Reg
<< 4) | Code
;
CodeLen
+= AppendBySize
(BAsmCode
+ CodeLen
, Addr
, OpSize
);
}
/*!------------------------------------------------------------------------
* \fn DecodeJMP_JSR(Word Code)
* \brief instruction decoder for JMP and JSR instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeJMP_JSR
(Word Code
)
{
tAdrVals Arg
;
if (ChkEmptyFormat
()
&& ChkArgCnt
(1, 1)
&& DecodeAdr
(&ArgStr
[1], MModeAll
- MModeReg
- MModeImm
, &Arg
, EProgCounter
() + 1))
{
BAsmCode
[CodeLen
++] = Code
;
AppendAdrValsToCode
(&Arg
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeSWAP(Word Code)
* \brief instruction decoder for SWAP instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeSWAP
(Word Code
)
{
tAdrVals Arg
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 3)
&& ChkArgCnt
(1, 1)
&& DecodeAdr
(&ArgStr
[1], MModeAll
- MModeImm
, &Arg
, EProgCounter
() + 1))
{
BAsmCode
[CodeLen
++] = Code
| OpSize
;
AppendAdrValsToCode
(&Arg
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeXCH(Word Code)
* \brief instruction decoder for XCH instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeXCH
(Word Code
)
{
Byte RegX
, RegY
, PrefixX
, PrefixY
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize32Bit
, 4)
&& ChkArgCnt
(2, 2))
{
if (DecodeReg
(&ArgStr
[1], &RegX
, &PrefixX
, False
, True
)
&& DecodeReg
(&ArgStr
[2], &RegY
, &PrefixY
, False
, True
))
{
BAsmCode
[CodeLen
++] = Code
;
BAsmCode
[CodeLen
++] = (RegX
<< 4) | RegY
;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeLINK(Word Code)
* \brief instruction decoder for LINK instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeLINK
(Word Code
)
{
Byte Reg
, Prefix
;
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(2, 2))
return;
if (!DecodeReg
(&ArgStr
[1], &Reg
, &Prefix
, False
, True
));
else if (*ArgStr
[2].
str.
p_str != '#') WrStrErrorPos
(ErrNum_OnlyImmAddr
, &ArgStr
[2]);
else
{
Boolean OK
;
LongInt Val
= EvalArg
(&ArgStr
[2], 1, (OpSize
== eSymbolSizeUnknown
) ? eSymbolSize32Bit
: OpSize
, &OK
);
if (OK
)
{
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= DeduceSize
(Val
);
BAsmCode
[CodeLen
++] = Code
| OpSize
;
BAsmCode
[CodeLen
++] = Reg
;
CodeLen
+= AppendBySize
(BAsmCode
+ CodeLen
, Val
, OpSize
);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeUNLK(Word Code)
* \brief instruction decoder for UNLK instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeUNLK
(Word Code
)
{
Byte Reg
, Prefix
;
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(1, 1))
return;
if (DecodeReg
(&ArgStr
[1], &Reg
, &Prefix
, False
, True
))
{
BAsmCode
[CodeLen
++] = Code
;
BAsmCode
[CodeLen
++] = Reg
;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeTRAPA(Word Code)
* \brief instruction decoder for TRAPA instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeTRAPA
(Word Code
)
{
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(1, 1))
return;
if (*ArgStr
[1].
str.
p_str != '#') WrStrErrorPos
(ErrNum_OnlyImmAddr
, &ArgStr
[1]);
else
{
Boolean OK
;
Byte Val
= EvalStrIntExpressionOffs
(&ArgStr
[1], 1, UInt4
, &OK
);
if (OK
)
{
BAsmCode
[CodeLen
++] = Code
;
BAsmCode
[CodeLen
++] = Val
;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRTD(Word Code)
* \brief instruction decoder for RTD instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeRTD
(Word Code
)
{
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(1, 1))
return;
else if (*ArgStr
[1].
str.
p_str != '#') WrStrErrorPos
(ErrNum_OnlyImmAddr
, &ArgStr
[1]);
else
{
Boolean OK
;
LongInt Val
= EvalArg
(&ArgStr
[1], 1, (OpSize
== eSymbolSizeUnknown
) ? eSymbolSize32Bit
: OpSize
, &OK
);
if (OK
)
{
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= DeduceSize
(Val
);
BAsmCode
[CodeLen
++] = Code
| OpSize
;
CodeLen
+= AppendBySize
(BAsmCode
+ CodeLen
, Val
, OpSize
);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeLDM_STM(Word Code)
* \brief instruction decoder for LDM and STM instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeLDM_STM
(Word Code
)
{
Word RegList
;
tAdrVals AdrVals
;
Boolean IsLDM
= !!(Code
== 0x74);
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 7)
&& ChkArgCnt
(2, ArgCntMax
)
&& DecodeRegList
(&RegList
, 1 + IsLDM
, ArgCnt
- 1 + IsLDM
)
&& DecodeAdr
(&ArgStr
[IsLDM
? 1 : ArgCnt
], MModeAll
- MModeImm
- MModeReg
, &AdrVals
, EProgCounter
() + 1))
{
BAsmCode
[CodeLen
++] = Code
| OpSize
;
AppendAdrValsToCode
(&AdrVals
);
BAsmCode
[CodeLen
++] = Hi
(RegList
);
BAsmCode
[CodeLen
++] = Lo
(RegList
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeCGBN(Word Code)
* \brief instruction decoder for CGBN instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeCGBN
(Word Code
)
{
tAdrVals AdrVals
;
if (ChkEmptyFormat
()
&& CheckSup
(&OpPart
)
&& ChkOpSize
(eSymbolSize8Bit
, 1)
&& ChkArgCnt
(1, ArgCntMax
)
&& DecodeAdr
(&ArgStr
[1], MModeReg
| MModeImm
, &AdrVals
, EProgCounter
() + 1))
{
Word RegList
= 0;
if (ArgCnt
>= 2)
{
if (!DecodeRegList
(&RegList
, 2, ArgCnt
))
return;
}
BAsmCode
[CodeLen
++] = Code
| ((AdrVals.
Mode == eAdrModeImm
) ? 2 : 0) | !!RegList
;
BAsmCode
[CodeLen
++] = (AdrVals.
Mode == eAdrModeImm
) ? AdrVals.
Vals[1] : (AdrVals.
Vals[0] & 0x0f);
if (RegList
)
{
BAsmCode
[CodeLen
++] = Hi
(RegList
);
BAsmCode
[CodeLen
++] = Lo
(RegList
);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodePGBN(Word Code)
* \brief instruction decoder for PGBN instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodePGBN
(Word Code
)
{
if (ChkEmptyFormat
()
&& CheckSup
(&OpPart
)
&& ChkOpSize
(eSymbolSize8Bit
, 1)
&& ChkArgCnt
(0, ArgCntMax
))
{
Word RegList
= 0;
if (ArgCnt
>= 1)
{
if (!DecodeRegList
(&RegList
, 1, ArgCnt
))
return;
}
BAsmCode
[CodeLen
++] = Code
| !!RegList
;
if (RegList
)
{
BAsmCode
[CodeLen
++] = Hi
(RegList
);
BAsmCode
[CodeLen
++] = Lo
(RegList
);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMOVFP(Word Code)
* \brief instruction decoder for MOVFP instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMOVFP
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 6)
&& ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
- MModeReg
- MModePre
- MModePost
- MModeImm
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], MModeAll
- MModeImm
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
| (OpSize
- 1);
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMOVFPE(Word Code)
* \brief instruction decoder for MOVFPE instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMOVFPE
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 7)
&& ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
- MModeReg
- MModePre
- MModePost
- MModeImm
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], MModeAll
- MModeImm
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
| OpSize
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMOVTP(Word Code)
* \brief instruction decoder for MOVTP instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMOVTP
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 6)
&& ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], MModeAll
- MModeReg
- MModePre
- MModePost
- MModeImm
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
| (OpSize
- 1);
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMOVTPE(Word Code)
* \brief instruction decoder for MOVTPE instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMOVTPE
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 7)
&& ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], MModeAll
- MModeReg
- MModePre
- MModePost
- MModeImm
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
| OpSize
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMOVA(Word Code)
* \brief instruction decoder for MOVA instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeMOVA
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize32Bit
, 4)
&& ChkArgCnt
(2, 2)
&& DecodeAdr
(&ArgStr
[1], MModeAll
- MModeReg
- MModeImm
, &SrcAdrVals
, EProgCounter
() + 1)
&& DecodeAdr
(&ArgStr
[2], MModeAll
- MModeImm
, &DestAdrVals
, EProgCounter
() + 1 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeString(Word Code)
* \brief decode string instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeString
(Word Code
)
{
int ExpectArgCnt
= (Code
& 0x80) ? 4 : 3;
unsigned SrcMask
, DestMask
= MModeReg
| ((Code
& 0x40) ? MModePre
: MModePost
);
Byte SrcReg
, DestReg
, CntReg
, FinalReg
, Prefix
;
SrcMask
= MModeReg
;
if (Code
& 0x30) /* SCMP/SMOV */
SrcMask
|= (Code
& 0x40) ? MModePre
: MModePost
;
else if (Code
& 0x80) /* SSCH */
SrcMask
|= MModeIReg
;
if (ChkEmptyFormat
()
&& ChkOpSize
(eSymbolSize16Bit
, 3)
&& ChkArgCnt
(ExpectArgCnt
, ExpectArgCnt
)
&& DecodeStringReg
(&ArgStr
[1], SrcMask
, &SrcReg
)
&& DecodeStringReg
(&ArgStr
[2], DestMask
, &DestReg
))
{
if (DecodeReg
(&ArgStr
[3], &CntReg
, &Prefix
, False
, True
))
{
if (4 == ExpectArgCnt
)
{
if (!DecodeReg
(&ArgStr
[4], &FinalReg
, &Prefix
, False
, True
))
return;
}
BAsmCode
[CodeLen
++] = 0x94 | OpSize
;
BAsmCode
[CodeLen
++] = Code
| CntReg
;
BAsmCode
[CodeLen
++] = (SrcReg
<< 4) | DestReg
;
if (4 == ExpectArgCnt
)
BAsmCode
[CodeLen
++] = (FinalReg
<< 4) | Hi
(Code
);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBField(Word Code)
* \brief decode bit field instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeBField
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
Byte PosReg
, CntReg
;
if (OpSize
!= eSymbolSizeUnknown
) WrError
(ErrNum_InvOpSize
);
else if (ChkEmptyFormat
()
&& ChkArgCnt
(4, 4)
&& DecodeStringReg
(&ArgStr
[1], MModeReg
, &PosReg
)
&& DecodeStringReg
(&ArgStr
[2], MModeReg
, &CntReg
)
&& DecodeAdr
(&ArgStr
[3], MModeAll
- MModePre
- MModePost
- MModeImm
, &SrcAdrVals
, EProgCounter
() + 2)
&& DecodeAdr
(&ArgStr
[4], MModeAll
- MModePre
- MModePost
- MModeImm
, &DestAdrVals
, EProgCounter
() + 2 + SrcAdrVals.
Cnt))
{
BAsmCode
[CodeLen
++] = Code
;
BAsmCode
[CodeLen
++] = (PosReg
<< 4) | CntReg
;
AppendAdrValPair
(&SrcAdrVals
, &DestAdrVals
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBFMOV(Word Code)
* \brief decode bit field move instruction which is different from other bit field instructions
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeBFMOV
(Word Code
)
{
Byte XReg
, BReg
, YReg
, OReg
, SReg
, DReg
;
if (OpSize
!= eSymbolSizeUnknown
) WrError
(ErrNum_InvOpSize
);
else if (ChkEmptyFormat
()
&& ChkArgCnt
(6, 6)
&& DecodeStringReg
(&ArgStr
[1], MModeReg
, &XReg
)
&& DecodeStringReg
(&ArgStr
[2], MModeReg
, &BReg
)
&& DecodeStringReg
(&ArgStr
[3], MModeReg
, &YReg
)
&& DecodeStringReg
(&ArgStr
[4], MModeReg
, &OReg
)
&& DecodeStringReg
(&ArgStr
[5], MModeReg
| MModeIReg
, &SReg
)
&& DecodeStringReg
(&ArgStr
[6], MModeReg
| MModeIReg
, &DReg
))
{
BAsmCode
[CodeLen
++] = Code
;
BAsmCode
[CodeLen
++] = (XReg
<< 4) | BReg
;
BAsmCode
[CodeLen
++] = (YReg
<< 4) | OReg
;
BAsmCode
[CodeLen
++] = (SReg
<< 4) | DReg
;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBit(Word Code)
* \brief decode CPU bit handling instruction
* \param Code specific instruction code
* ------------------------------------------------------------------------ */
static void DecodeBit
(Word Code
)
{
tSymbolSize ThisOpSize
;
if (!ChkEmptyFormat
()
|| !ChkArgCnt
(1, 2))
return;
/* bit "object": */
if (1 == ArgCnt
)
{
LongWord BitArg
, Address
;
Byte ImmPos
;
if (DecodeBitArg
(&BitArg
, 1, 1, OpSize
)
&& DissectBitSymbol
(BitArg
, &Address
, &ImmPos
, &ThisOpSize
)
&& SetOpSize
(ThisOpSize
))
{
tSymbolSize AddressSize
= DeduceSize16M
(Address
);
/* SetOpSize() has set OpSize to 0..2 or confirmed it, no need to check for invalid size */
BAsmCode
[CodeLen
++] = 0x6c | OpSize
;
BAsmCode
[CodeLen
++] = Code
| ImmPos
;
BAsmCode
[CodeLen
++] = 0x74 | (AddressSize
+ 1);
CodeLen
+= AppendBySize
(BAsmCode
+ CodeLen
, Address
, AddressSize
);
}
}
/* bit + <ea> */
else
{
tAdrVals EAAdrVals
, BitAdrVals
;
unsigned Mask
= MModeAll
- ((Code
== 0x60) ? 0 : MModeImm
);
if (ChkOpSize
(eSymbolSize16Bit
, 7)
&& DecodeAdr
(&ArgStr
[2], Mask
, &EAAdrVals
, EProgCounter
() + 2))
{
ThisOpSize
= OpSize
;
OpSize
= eSymbolSize3Bit
+ OpSize
;
if (DecodeAdr
(&ArgStr
[1], MModeImm
| MModeReg
, &BitAdrVals
, EProgCounter
() + 1))
{
switch (BitAdrVals.
Mode)
{
case eAdrModeReg
:
if (!GlobalBankReg
(&BitAdrVals
))
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
return;
}
BAsmCode
[CodeLen
++] = 0x64 | ThisOpSize
;
BAsmCode
[CodeLen
++] = Code
| (BitAdrVals.
Vals[0] & 15);
break;
case eAdrModeImm
:
BAsmCode
[CodeLen
++] = 0x6c | ThisOpSize
;
BAsmCode
[CodeLen
++] = Code
| BitAdrVals.
Vals[1];
break;
default:
return;
}
AppendAdrValsToCode
(&EAAdrVals
);
}
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBIT(Word Code)
* \brief decode bit declaration instruction
* ------------------------------------------------------------------------ */
static void DecodeBIT
(Word Code
)
{
LongWord BitSpec
;
UNUSED
(Code
);
/* if in structure definition, add special element to structure */
if (ActPC
== StructSeg
)
{
Boolean OK
;
Byte BitPos
;
PStructElem pElement
;
if (!ChkArgCnt
(2, 2))
return;
BitPos
= EvalBitPosition
(&ArgStr
[1], &OK
, (OpSize
== eSymbolSizeUnknown
) ? eSymbolSize32Bit
: OpSize
);
if (!OK
)
return;
pElement
= CreateStructElem
(&LabPart
);
if (!pElement
)
return;
pElement
->pRefElemName
= as_strdup
(ArgStr
[2].
str.
p_str);
/* undefined op size -> take over from ref elem */
pElement
->OpSize
= OpSize
;
pElement
->BitPos
= BitPos
;
pElement
->ExpandFnc
= ExpandH16Bit
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElement
);
}
else
{
if (!ChkOpSize
(eSymbolSize16Bit
, 7))
return;
if (DecodeBitArg
(&BitSpec
, 1, ArgCnt
, OpSize
))
{
*ListLine
= '=';
DissectBit_H16
(ListLine
+ 1, STRINGSIZE
- 3, BitSpec
);
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, BitSpec
, SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
}
/*---------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn AddCondition(const char *pName, Word Code)
* \brief register condition to instruction hash table
* \param pName name of condition
* \param Code binary coding of condition
* ------------------------------------------------------------------------ */
static void AddCondition
(const char *pName
, Word Code
)
{
char Name
[20];
as_snprintf
(Name
, sizeof(Name
), "B%s", pName
);
AddInstTable
(InstTable
, Name
, Code
, DecodeBranchGen
);
as_snprintf
(Name
, sizeof(Name
), "SET/%s", pName
);
AddInstTable
(InstTable
, Name
, Code
, DecodeSET
);
as_snprintf
(Name
, sizeof(Name
), "TRAP/%s", pName
);
AddInstTable
(InstTable
, Name
, Code
, DecodeTRAP
);
as_snprintf
(Name
, sizeof(Name
), "SCB/%s", pName
);
AddInstTable
(InstTable
, Name
, Code
, DecodeSCB
);
as_snprintf
(Name
, sizeof(Name
), "SCMP/%s/F", pName
);
AddInstTable
(InstTable
, Name
, 0x00a0 | (Code
<< 8), DecodeString
);
as_snprintf
(Name
, sizeof(Name
), "SCMP/%s/B", pName
);
AddInstTable
(InstTable
, Name
, 0x00d0 | (Code
<< 8), DecodeString
);
as_snprintf
(Name
, sizeof(Name
), "SSCH/%s/F", pName
);
AddInstTable
(InstTable
, Name
, 0x0080 | (Code
<< 8), DecodeString
);
as_snprintf
(Name
, sizeof(Name
), "SSCH/%s/B", pName
);
/* per-instr. description gives 000 for both SSCH variants, taken from Figure 16-9: */
AddInstTable
(InstTable
, Name
, 0x00c0 | (Code
<< 8), DecodeString
);
}
/*!------------------------------------------------------------------------
* \fn InitFields(void)
* \brief build up instruction hash table
* ------------------------------------------------------------------------ */
static void InitFields
(void)
{
InstTable
= CreateInstTable
(307);
SetDynamicInstTable
(InstTable
);
AddInstTable
(InstTable
, "MOV", 0x0c, DecodeMOV_ADD_SUB_CMP
);
AddInstTable
(InstTable
, "ADD", 0x00, DecodeMOV_ADD_SUB_CMP
);
AddInstTable
(InstTable
, "SUB", 0x04, DecodeMOV_ADD_SUB_CMP
);
AddInstTable
(InstTable
, "CMP", 0x08, DecodeMOV_ADD_SUB_CMP
);
AddInstTable
(InstTable
, "MOVS", 0x4c, DecodeSignExt
);
AddInstTable
(InstTable
, "ADDS", 0x40, DecodeSignExt
);
AddInstTable
(InstTable
, "SUBS", 0x44, DecodeSignExt
);
AddInstTable
(InstTable
, "CMPS", 0x48, DecodeSignExt
);
AddInstTable
(InstTable
, "ADDX", 0x50, DecodeTwo
);
AddInstTable
(InstTable
, "SUBX", 0x54, DecodeTwo
);
AddInstTable
(InstTable
, "AND" , 0x80, DecodeTwo
);
AddInstTable
(InstTable
, "OR" , 0x88, DecodeTwo
);
AddInstTable
(InstTable
, "XOR" , 0x84, DecodeTwo
);
AddInstTable
(InstTable
, "DADD", 0x83, DecodeTwo
);
AddInstTable
(InstTable
, "DSUB", 0x87, DecodeTwo
);
AddInstTable
(InstTable
, "MULXS" , 0x00, DecodeMUL_DIV
);
AddInstTable
(InstTable
, "MULXU" , 0x40, DecodeMUL_DIV
);
AddInstTable
(InstTable
, "DIVXS" , 0x01, DecodeMUL_DIV
);
AddInstTable
(InstTable
, "DIVXU" , 0x41, DecodeMUL_DIV
);
AddInstTable
(InstTable
, "NEG" , 0x8c, DecodeOne
);
AddInstTable
(InstTable
, "NEGX" , 0x9c, DecodeOne
);
AddInstTable
(InstTable
, "NOT" , 0x90, DecodeOne
);
AddInstTable
(InstTable
, "TST" , 0x58, DecodeOne
);
AddInstTable
(InstTable
, "CLR" , 0x14, DecodeOne
);
AddInstTable
(InstTable
, "DNEG" , 0xaf, DecodeOne
);
AddInstTable
(InstTable
, "TAS" , 0xee, DecodeOne
);
AddInstTable
(InstTable
, "MOVF" , 0x5c, DecodeOne
);
AddInstTable
(InstTable
, "EXTS" , 0xbc, DecodeEXT
);
AddInstTable
(InstTable
, "EXTU" , 0xac, DecodeEXT
);
AddInstTable
(InstTable
, "ANDC" , 0xf8, DecodeCInstr
);
AddInstTable
(InstTable
, "ORC" , 0xf9, DecodeCInstr
);
AddInstTable
(InstTable
, "XORC" , 0xfa, DecodeCInstr
);
AddInstTable
(InstTable
, "LDC" , 0xfb, DecodeCInstr
);
AddInstTable
(InstTable
, "STC" , 0xfc, DecodeCInstr
);
AddInstTable
(InstTable
, "BRA" , 0x98, DecodeBranch
);
AddInstTable
(InstTable
, "BSR" , 0xa8, DecodeBranch
);
AddCondition
("CC" , 0x04);
AddCondition
("HS" , 0x04);
AddCondition
("CS" , 0x05);
AddCondition
("LO" , 0x05);
AddCondition
("NE" , 0x06);
AddCondition
("EQ" , 0x07);
AddCondition
("GE" , 0x0c);
AddCondition
("LT" , 0x0d);
AddCondition
("GT" , 0x0e);
AddCondition
("LE" , 0x0f);
AddCondition
("HI" , 0x02);
AddCondition
("LS" , 0x03);
AddCondition
("PL" , 0x0a);
AddCondition
("MI" , 0x0b);
AddCondition
("VC" , 0x08);
AddCondition
("VS" , 0x09);
AddCondition
("T" , 0x00);
AddCondition
("F" , 0x01);
AddInstTable
(InstTable
, "RTS" , 0x00bb, DecodeFixed
);
AddInstTable
(InstTable
, "RESET", 0x80f0, DecodeFixed
);
AddInstTable
(InstTable
, "RTE" , 0x80f1, DecodeFixed
);
AddInstTable
(InstTable
, "RTR" , 0x00f4, DecodeFixed
);
AddInstTable
(InstTable
, "SLEEP", 0x80f5, DecodeFixed
);
AddInstTable
(InstTable
, "NOP" , 0x00ff, DecodeFixed
);
AddInstTable
(InstTable
, "DCBN" , 0x00fe, DecodeFixed
);
AddInstTable
(InstTable
, "ICBN" , 0x00fd, DecodeFixed
);
AddInstTable
(InstTable
, "SHAR" , 0 << 5, DecodeShift
);
AddInstTable
(InstTable
, "SHLR" , 1 << 5, DecodeShift
);
AddInstTable
(InstTable
, "ROTR" , 2 << 5, DecodeShift
);
AddInstTable
(InstTable
, "ROTXR" , 3 << 5, DecodeShift
);
AddInstTable
(InstTable
, "SHAL" , 4 << 5, DecodeShift
);
AddInstTable
(InstTable
, "SHLL" , 5 << 5, DecodeShift
);
AddInstTable
(InstTable
, "ROTL" , 6 << 5, DecodeShift
);
AddInstTable
(InstTable
, "ROTXL" , 7 << 5, DecodeShift
);
AddInstTable
(InstTable
, "JMP" , 0x9b, DecodeJMP_JSR
);
AddInstTable
(InstTable
, "JSR" , 0xab, DecodeJMP_JSR
);
AddInstTable
(InstTable
, "SWAP", 0xea, DecodeSWAP
);
AddInstTable
(InstTable
, "XCH" , 0xb3, DecodeXCH
);
AddInstTable
(InstTable
, "LINK", 0xd0, DecodeLINK
);
AddInstTable
(InstTable
, "UNLK", 0xd3, DecodeUNLK
);
AddInstTable
(InstTable
, "TRAPA",0xf2, DecodeTRAPA
);
AddInstTable
(InstTable
, "RTD" , 0xb8, DecodeRTD
);
AddInstTable
(InstTable
, "LDM" , 0x74, DecodeLDM_STM
);
AddInstTable
(InstTable
, "STM" , 0x70, DecodeLDM_STM
);
AddInstTable
(InstTable
, "CGBN", 0xe4, DecodeCGBN
);
AddInstTable
(InstTable
, "PGBN", 0xe8, DecodePGBN
);
AddInstTable
(InstTable
, "MOVFP",0xe2, DecodeMOVFP
);
AddInstTable
(InstTable
, "MOVFPE",0x7c, DecodeMOVFPE
);
AddInstTable
(InstTable
, "MOVTP",0xe0, DecodeMOVTP
);
AddInstTable
(InstTable
, "MOVTPE",0x78, DecodeMOVTPE
);
AddInstTable
(InstTable
, "MOVA", 0xbf, DecodeMOVA
);
AddInstTable
(InstTable
, "SMOV/F", 0x0020, DecodeString
);
AddInstTable
(InstTable
, "SMOV/B", 0x0050, DecodeString
);
AddInstTable
(InstTable
, "SSTR/F", 0x0000, DecodeString
);
AddInstTable
(InstTable
, "SSTR/B", 0x0040, DecodeString
);
AddInstTable
(InstTable
, "BFEXT", 0xd4, DecodeBField
);
AddInstTable
(InstTable
, "BFINS", 0xd5, DecodeBField
);
AddInstTable
(InstTable
, "BFSCH", 0xd6, DecodeBField
);
AddInstTable
(InstTable
, "BFMOV", 0xd7, DecodeBFMOV
);
AddInstTable
(InstTable
, "BCLR", 0x40, DecodeBit
);
AddInstTable
(InstTable
, "BNOT", 0x20, DecodeBit
);
AddInstTable
(InstTable
, "BSET", 0x00, DecodeBit
);
AddInstTable
(InstTable
, "BTST", 0x60, DecodeBit
);
AddInstTable
(InstTable
, "BIT", 0, DecodeBIT
);
AddInstTable
(InstTable
, "REG", 0, CodeREG
);
}
/*!------------------------------------------------------------------------
* \fn DeinitFields(void)
* \brief tear down instruction hash table
* ------------------------------------------------------------------------ */
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
}
/*---------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn MakeCode_H16(void)
* \brief general entry point to parse machine instructions
* ------------------------------------------------------------------------ */
static Boolean DecodeAttrPart_H16
(void)
{
tStrComp SizePart
;
char *p
;
static char EmptyStr
[] = "";
/* split off format and operand size */
switch (AttrSplit
)
{
case '.':
p
= strchr(AttrPart.
str.
p_str, ':');
if (p
)
StrCompSplitRef
(&SizePart
, &FormatPart
, &AttrPart
, p
);
else
{
StrCompRefRight
(&SizePart
, &AttrPart
, 0);
StrCompMkTemp
(&FormatPart
, EmptyStr
, 0);
}
break;
case ':':
p
= strchr(AttrPart.
str.
p_str, '.');
if (p
)
StrCompSplitRef
(&FormatPart
, &SizePart
, &AttrPart
, p
);
else
{
StrCompRefRight
(&FormatPart
, &AttrPart
, 0);
StrCompMkTemp
(&SizePart
, EmptyStr
, 0);
}
break;
default:
StrCompMkTemp
(&FormatPart
, EmptyStr
, 0);
StrCompMkTemp
(&SizePart
, EmptyStr
, 0);
break;
}
/* process operand size part of attribute */
if (*SizePart.
str.
p_str)
{
if (!DecodeMoto16AttrSizeStr
(&SizePart
, &AttrPartOpSize
[0], False
))
return False
;
}
return True
;
}
static void MakeCode_H16
(void)
{
CodeLen
= 0; DontPrint
= False
;
/* zu ignorierendes */
if (Memo
("")) return;
OpSize
= AttrPartOpSize
[0];
if (DecodeMoto16Pseudo
(OpSize
, True
))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
/*!------------------------------------------------------------------------
* \fn IsDef_H16(void)
* \brief instruction that uses up label field?
* \return true if label field shall not be stored as label
* ------------------------------------------------------------------------ */
static Boolean IsDef_H16
(void)
{
return Memo
("BIT") || Memo
("REG");
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_H16(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on H16
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_H16
(char *pArg
, TempResult
*pResult
)
{
Byte Reg
, Prefix
;
if (DecodeRegCore
(pArg
, &Reg
, &Prefix
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize32Bit
;
pResult
->Contents.
RegDescr.
Reg = ((Word
)Prefix
) << 8 | Reg
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_H16
;
pResult
->Contents.
RegDescr.
compare = compare_reg_h16
;
}
}
/*!------------------------------------------------------------------------
* \fn SwitchTo_H16(void)
* \brief things to do when switching to H16 as target
* ------------------------------------------------------------------------ */
static void SwitchTo_H16
(void)
{
const TFamilyDescr
*pDescr
= FindFamilyByName
("H16");
TurnWords
= False
;
SetIntConstMode
(eIntConstModeMoto
);
PCSymbol
= "*";
HeaderID
= pDescr
->Id
;
NOPCode
= 0xff;
DivideChars
= ",";
HasAttrs
= True
;
AttrChars
= ".:";
ValidSegs
= (1 << SegCode
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = 0xffffff;
DecodeAttrPart
= DecodeAttrPart_H16
;
MakeCode
= MakeCode_H16
;
IsDef
= IsDef_H16
;
SwitchFrom
= DeinitFields
;
DissectBit
= DissectBit_H16
;
DissectReg
= DissectReg_H16
;
InternSymbol
= InternSymbol_H16
;
InitFields
();
onoff_supmode_add
();
/* H16 code is byte-oriented, so no padding by default */
AddMoto16PseudoONOFF
(False
);
}
/*!------------------------------------------------------------------------
* \fn codeh16_init(void)
* \brief register H16 to upper layers as target
* ------------------------------------------------------------------------ */
void codeh16_init
(void)
{
CPU641016
= AddCPU
("HD641016", SwitchTo_H16
);
}