/* codest7.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator SGS-Thomson ST7/STM8 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include "bpemu.h"
#include "strutil.h"
#include "nls.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "asmstructs.h"
#include "asmallg.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "codest7.h"
typedef enum
{
eModNone = -1,
eModImm = 0, /* #byte */
eModAbs8, /* shortmem */
eModAbs16, /* longmem */
eModAbs24, /* extmem */
eModIX, /* (X) */
eModIX8, /* (shortoff,X) */
eModIX16, /* (longoff,X) */
eModIX24, /* (extoff,X) */
eModIY, /* (Y) */
eModIY8, /* (shortoff,Y) */
eModIY16, /* (longoff,Y) */
eModIY24, /* (extoff,Y) */
eModISP8, /* (shortoff,SP) (STM8 only) */
eModIAbs8, /* [shortptr.b] (ST7 only) */
eModIAbs16, /* [shortptr.w] */
eModI16Abs16, /* [longptr.w] (STM8 only) */
eModI16Abs24, /* [longptr.e] (STM8 only) */
eModIXAbs8, /* ([shortptr.b],X) */
eModIXAbs16, /* ([<longptr.w],X) */
eModI16XAbs16, /* ([>longptr.w],X) (STM8 only) */
eModI16XAbs24, /* ([>longptr.e],X) (STM8 only) */
eModIYAbs8, /* ([shortptr.b],Y) */
eModIYAbs16, /* ([<longptr.w],Y) */
eModI16YAbs24, /* ([>longptr.e],Y) (STM8 only) */
eModA, /* A */
eModX, /* X */
eModXL, /* XL (STM8 only) */
eModXH, /* XH (STM8 only) */
eModY, /* Y */
eModYL, /* YL (STM8 only) */
eModYH, /* YH (STM8 only) */
eModS /* SP */
/* bit mask is full, 32 modes! */
} tAdrMode;
#define MModImm (1ul << eModImm)
#define MModAbs8 (1ul << eModAbs8)
#define MModAbs16 (1ul << eModAbs16)
#define MModAbs24 (1ul << eModAbs24)
#define MModIX (1ul << eModIX)
#define MModIX8 (1ul << eModIX8)
#define MModIX16 (1ul << eModIX16)
#define MModIX24 (1ul << eModIX24)
#define MModIY (1ul << eModIY)
#define MModIY8 (1ul << eModIY8)
#define MModIY16 (1ul << eModIY16)
#define MModIY24 (1ul << eModIY24)
#define MModISP8 (1ul << eModISP8)
#define MModIAbs8 (1ul << eModIAbs8)
#define MModIAbs16 (1ul << eModIAbs16)
#define MModI16Abs16 (1ul << eModI16Abs16)
#define MModI16Abs24 (1ul << eModI16Abs24)
#define MModIXAbs8 (1ul << eModIXAbs8)
#define MModIXAbs16 (1ul << eModIXAbs16)
#define MModI16XAbs16 (1ul << eModI16XAbs16)
#define MModI16XAbs24 (1ul << eModI16XAbs24)
#define MModIYAbs8 (1ul << eModIYAbs8)
#define MModIYAbs16 (1ul << eModIYAbs16)
#define MModI16YAbs24 (1ul << eModI16YAbs24)
#define MModA (1ul << eModA)
#define MModX (1ul << eModX)
#define MModXL (1ul << eModXL)
#define MModXH (1ul << eModXH)
#define MModY (1ul << eModY)
#define MModYL (1ul << eModYL)
#define MModYH (1ul << eModYH)
#define MModS (1ul << eModS)
typedef enum
{
eCoreST7,
eCoreSTM8
} tCPUCore;
typedef struct
{
const char *pName;
IntType AddrIntType;
tCPUCore Core;
} tCPUProps;
typedef struct
{
tAdrMode Mode;
Byte Part;
unsigned Cnt;
Byte Vals[3];
} tAdrVals;
static const tCPUProps *pCurrCPUProps;
static tSymbolSize OpSize;
static Byte PrefixCnt;
/*--------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn ResetAdrVals(tAdrVals *pAdrVals)
* \brief clear AdrVals structure
* \param pAdrVals struct to clear/reset
* ------------------------------------------------------------------------ */
static void ResetAdrVals(tAdrVals *pAdrVals)
{
pAdrVals->Mode = eModNone;
pAdrVals->Part = 0;
pAdrVals->Cnt = 0;
}
static void FillAdrVals(tAdrVals *pAdrVals, LongWord Value, tSymbolSize Size)
{
pAdrVals->Cnt = 0;
switch (Size)
{
case eSymbolSize24Bit:
pAdrVals->Vals[pAdrVals->Cnt++] = (Value >> 16) & 255;
/* fall-through */
case eSymbolSize16Bit:
pAdrVals->Vals[pAdrVals->Cnt++] = (Value >> 8) & 255;
/* fall-through */
case eSymbolSize8Bit:
pAdrVals->Vals[pAdrVals->Cnt++] = Value & 255;
/* fall-through */
default:
break;
}
}
static void ExtendAdrVals(tAdrVals *pAdrVals)
{
switch (pAdrVals->Mode)
{
case eModAbs8:
pAdrVals->Mode = eModAbs16;
pAdrVals->Vals[1] = pAdrVals->Vals[0];
pAdrVals->Vals[0] = 0;
pAdrVals->Cnt = 2;
break;
default:
break;
}
}
/*!------------------------------------------------------------------------
* \fn AddPrefix(Byte Pref)
* \brief add another prefix byte
* \param Pref prefix to add
* ------------------------------------------------------------------------ */
static void AddPrefix(Byte Pref)
{
BAsmCode[PrefixCnt++] = Pref;
}
/*!------------------------------------------------------------------------
* \fn ModeInMask(LongWord Mask, tAdrMode Mode)
* \brief check whether certain addressing mode is set in mask
* \param Mask list of allowed modes
* \param Mode addressing mode to check
* ------------------------------------------------------------------------ */
static Boolean ModeInMask(LongWord Mask, tAdrMode Mode)
{
return !!((Mask >> Mode) & 1);
}
/*!------------------------------------------------------------------------
* \fn CutSizeSuffix(tStrComp *pArg)
* \brief cut off possible size suffix (.b .w .e) from argument
* \param pArg argument
* \return deduced size or unknown if no known suffix
* ------------------------------------------------------------------------ */
static tSymbolSize CutSizeSuffix(const tStrComp *pArg)
{
int l
= strlen(pArg
->str.
p_str);
if ((l >= 3) && (pArg->str.p_str[l - 2] == '.'))
{
switch (as_toupper(pArg->str.p_str[l - 1]))
{
case 'B':
pArg->str.p_str[l - 2] = '\0';
return eSymbolSize8Bit;
case 'W':
pArg->str.p_str[l - 2] = '\0';
return eSymbolSize16Bit;
case 'E':
pArg->str.p_str[l - 2] = '\0';
return eSymbolSize24Bit;
default:
break;
}
}
return eSymbolSizeUnknown;
}
/*!------------------------------------------------------------------------
* \fn DecideSize(LongWord Mask, const tStrComp *pArg, tAdrMode Mode8, tAdrMode Mode16, tAdrMode Mode24, Byte Part8, Byte Part16, Byte Part24, Boolean IsCode, tAdrVals *pAdrVals)
* \brief decide about length of absolute or indexed operand
* \param Mask bit mask of allowed modes
* \param pArg address argument
* \param Mode8 AdrMode for 8-bit address/displacement
* \param Mode16 AdrMode for 16-bit address/displacement
* \param Mode24 AdrMode for 24-bit address/displacement
* \param Part8 AdrPart for 8-bit address/displacement
* \param Part16 AdrPart for 16-bit address/displacement
* \param Part24 AdrPart for 24-bit address/displacement
* \param IsCode Address is in code space (check for same page)
* \param pAdrVals destination to fill out
* ------------------------------------------------------------------------ */
static void DecideSize(LongWord Mask, const tStrComp *pArg, tAdrMode Mode8, tAdrMode Mode16, tAdrMode Mode24, Byte Part8, Byte Part16, Byte Part24, Boolean IsCode, tAdrVals *pAdrVals)
{
tSymbolSize Size = eSymbolSizeUnknown;
IntType SizeType;
LongWord Value;
Boolean OK;
tSymbolFlags Flags;
if ((Mode8 != eModNone) && !ModeInMask(Mask, Mode8))
Mode8 = eModNone;
if ((Mode16 != eModNone) && !ModeInMask(Mask, Mode16))
Mode16 = eModNone;
if ((Mode24 != eModNone) && !ModeInMask(Mask, Mode24))
Mode24 = eModNone;
Size = CutSizeSuffix(pArg);
switch (Size)
{
case eSymbolSize8Bit:
if (Mode8 == eModNone)
goto InvSize;
break;
case eSymbolSize16Bit:
if (Mode16 == eModNone)
goto InvSize;
break;
case eSymbolSize24Bit:
if (Mode24 == eModNone)
goto InvSize;
break;
default:
break;
InvSize:
WrStrErrorPos(ErrNum_InvAddrMode, pArg);
return;
}
if (IsCode)
SizeType = pCurrCPUProps->AddrIntType;
else switch (Size)
{
case eSymbolSize24Bit:
SizeType = Int24;
break;
case eSymbolSize16Bit:
SizeType = Int16;
break;
case eSymbolSize8Bit:
SizeType = Int8;
break;
default:
if (Mode24 != eModNone)
SizeType = Int24;
else if (Mode16 != eModNone)
SizeType = Int16;
else
SizeType = Int8;
break;
}
Value = EvalStrIntExpressionWithFlags(pArg, SizeType, &OK, &Flags);
if (OK)
{
LongWord SrcAddress = IsCode ? EProgCounter() + 3 : 0;
if (Size == eSymbolSizeUnknown)
{
if ((Value <= 0xff) && (Mode8 != eModNone))
Size = eSymbolSize8Bit;
else if (((Value >> 16) == (SrcAddress >> 16)) && (Mode16 != eModNone))
Size = eSymbolSize16Bit;
else
Size = eSymbolSize24Bit;
}
/* this may only happen if SizeTypes was forced to 24 Bit because of code addessing: */
if ((Size == eSymbolSize24Bit) && (Mode24 == eModNone) && !mSymbolQuestionable(Flags))
{
WrStrErrorPos(ErrNum_TargOnDiffSection, pArg);
return;
}
FillAdrVals(pAdrVals, Value, Size);
switch (Size)
{
case eSymbolSize8Bit:
pAdrVals->Part = Part8;
pAdrVals->Mode = Mode8;
break;
case eSymbolSize16Bit:
pAdrVals->Part = Part16;
pAdrVals->Mode = Mode16;
break;
case eSymbolSize24Bit:
pAdrVals->Part = Part24;
pAdrVals->Mode = Mode24;
break;
default:
}
}
}
/*!------------------------------------------------------------------------
* \fn DecideIndirectSize(LongWord Mask, const tStrComp *pArg,
tAdrMode Mode8_8, tAdrMode Mode8_16, tAdrMode Mode16_16, tAdrMode Mode16_24,
Byte Part8_8, Byte Part8_16, Byte Part16_16, Byte Part16_24,
tAdrVals *pAdrVals)
* \brief address mode decision for indirect operands []
* \param Mask bit mask of allowed modes
* \param pArg expression
* \param Mode8_8 requested mode for 8-bit pointer on 8-bit address
* \param Mode8_16 requested mode for 16-bit pointer on 8-bit address
* \param Mode16_16 requested mode for 16-bit pointer on 16-bit address
* \param Mode16_24 requested mode for 24-bit pointer on 16-bit address
* \param Part8_8 Address part for 8-bit pointer on 8-bit address
* \param Part8_16 Address part for 16-bit pointer on 8-bit address
* \param Part16_16 Address part for 16-bit pointer on 16-bit address
* \param Part16_24 Address part for 24-bit pointer on 16-bit address
* \param pAdrVals destination to fill out
* \return True if successfully parsed
* ------------------------------------------------------------------------ */
static Boolean DecideIndirectSize(LongWord Mask, const tStrComp *pArg,
tAdrMode Mode8_8, tAdrMode Mode8_16, tAdrMode Mode16_16, tAdrMode Mode16_24,
Byte Part8_8, Byte Part8_16, Byte Part16_16, Byte Part16_24,
tAdrVals *pAdrVals)
{
Boolean OK;
int Offset;
tSymbolSize AddrSize = eSymbolSizeUnknown,
PtrSize = eSymbolSizeUnknown;
IntType SizeType;
Word Address;
tSymbolFlags Flags;
if ((Mode8_8 != eModNone) && !ModeInMask(Mask, Mode8_8))
Mode8_8 = eModNone;
if ((Mode8_16 != eModNone) && !ModeInMask(Mask, Mode8_16))
Mode8_16 = eModNone;
if ((Mode16_16 != eModNone) && !ModeInMask(Mask, Mode16_16))
Mode16_16 = eModNone;
if ((Mode16_24 != eModNone) && !ModeInMask(Mask, Mode16_24))
Mode16_24 = eModNone;
/* Cut off address byte size, signified by leading '<' or '>': */
switch (*pArg->str.p_str)
{
case '>':
Offset = 1;
AddrSize = eSymbolSize16Bit;
break;
case '<':
Offset = 1;
AddrSize = eSymbolSize8Bit;
break;
default:
Offset = 0;
AddrSize = eSymbolSizeUnknown;
}
/* Cut off pointer size, signified by trailing '.w/.e' if 16/24 bit: */
PtrSize = CutSizeSuffix(pArg);
/* if no pointer size given, assume the smallest possible one: */
if (PtrSize == eSymbolSizeUnknown)
{
if (Mode8_8 != eModNone)
PtrSize = eSymbolSize8Bit;
else if ((Mode8_16 != eModNone) || (Mode16_16 != eModNone))
PtrSize = eSymbolSize16Bit;
else
PtrSize = eSymbolSize24Bit;
}
switch (AddrSize)
{
case eSymbolSize16Bit:
SizeType = Int16;
break;
case eSymbolSize8Bit:
SizeType = Int8;
break;
default:
if ((Mode16_16 != eModNone) || (Mode16_24 != eModNone))
SizeType = Int16;
else
SizeType = Int8;
break;
}
Address = EvalStrIntExpressionOffsWithFlags(pArg, Offset, SizeType, &OK, &Flags);
if (mFirstPassUnknown(Flags) && (Mode16_16 == eModNone) && (Mode16_24 == eModNone))
Address &= 0xff;
if (OK)
{
/* Finally decide about address size: */
if (eSymbolSizeUnknown == AddrSize)
{
if ((Address <= 0xff) && (PtrSize == eSymbolSize8Bit) && (Mode8_8 != eModNone))
AddrSize = eSymbolSize8Bit;
else if ((Address <= 0xff) && (PtrSize == eSymbolSize16Bit) && (Mode8_16 != eModNone))
AddrSize = eSymbolSize8Bit;
else
AddrSize = eSymbolSize16Bit;
}
FillAdrVals(pAdrVals, Address, AddrSize);
if (eSymbolSize16Bit == AddrSize)
{
if (PtrSize == eSymbolSize24Bit)
{
pAdrVals->Part = Part16_24;
pAdrVals->Mode = Mode16_24;
}
else
{
pAdrVals->Part = Part16_16;
pAdrVals->Mode = Mode16_16;
}
}
else
{
if (PtrSize == eSymbolSize16Bit)
{
pAdrVals->Part = Part8_16;
pAdrVals->Mode = Mode8_16;
}
else
{
pAdrVals->Part = Part8_8;
pAdrVals->Mode = Mode8_8;
}
}
}
return OK;
}
/*!------------------------------------------------------------------------
* \fn ChkAdrMode(tAdrMode *pAdrMode, LongWord Mask, tErrorNum ErrorNum, const tStrComp *pArg)
* \brief check for allowed addressing mode
* \param pAdrMode parsed addressing mode (in/out)
* \param Mask list of allowed modes
* \param ErrorNum error message to emit if not allowed
* \param pArg offending arg
* \return True if mode is OK
* ------------------------------------------------------------------------ */
static Boolean ChkAdrMode(tAdrMode *pAdrMode, LongWord Mask, tErrorNum ErrorNum, const tStrComp *pArg)
{
if ((*pAdrMode != eModNone) && (!(Mask & (1ul << *pAdrMode))))
{
WrStrErrorPos(ErrorNum, pArg);
*pAdrMode = eModNone;
return False;
}
return True;
}
/*!------------------------------------------------------------------------
* \fn ChkAdrValsMode(tAdrVals *pAdrVals, LongWord Mask, tErrorNum ErrorNum, const tStrComp *pArg)
* \brief check for allowed addressing mode
* \param pAdrVals parsed addressing mode (in/out)
* \param Mask list of allowed modes
* \param ErrorNum error message to emit if not allowed
* \param pArg offending arg
* \return True if mode is OK
* ------------------------------------------------------------------------ */
static Boolean ChkAdrValsMode(tAdrVals *pAdrVals, LongWord Mask, tErrorNum ErrorNum, const tStrComp *pArg)
{
if (!ChkAdrMode(&pAdrVals->Mode, Mask, ErrorNum, pArg))
{
pAdrVals->Cnt = 0;
return False;
}
return True;
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const tStrComp *pArg, tAdrMode *pResult)
* \brief check whether argument is a CPU register
* \param pArg argument to check
* \param pResult resulting mode if it is a register
* \return True if argument is a register
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore(const tStrComp *pArg, tAdrMode *pResult)
{
*pResult = eModNone;
if (!as_strcasecmp(pArg->str.p_str, "A"))
{
*pResult = eModA;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "X"))
{
*pResult = eModX;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "XL"))
{
*pResult = eModXL;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "XH"))
{
*pResult = eModXH;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "Y"))
{
*pResult = eModY;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "YL"))
{
*pResult = eModYL;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "YH"))
{
*pResult = eModYH;
return True;
}
if ((!as_strcasecmp(pArg->str.p_str, "S"))
|| ((pCurrCPUProps->Core == eCoreSTM8) && !as_strcasecmp(pArg->str.p_str, "SP")))
{
*pResult = eModS;
return True;
}
return False;
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, tAdrMode *pResult, LongWord Mask)
* \brief decode addressing expression, registers-only
* \param pArg argument
* \param pResult resulting mode
* \param Mask list of allowed modes
* \return True if argument is a CPU register
* ------------------------------------------------------------------------ */
static Boolean DecodeReg(const tStrComp *pArg, tAdrMode *pResult, LongWord Mask)
{
return DecodeRegCore(pArg, pResult)
&& ChkAdrMode(pResult, Mask, ErrNum_InvReg, pArg);
}
/*!------------------------------------------------------------------------
* \fn DecodeAdr(const tStrComp *pArg, LongWord Mask, Boolean IsCode, tAdrVals *pAdrVals)
* \brief decode addressing expression
* \param pArg argument
* \param Mask list of allowed masks
* \param IsCode is expression a jump/call address?
* \param pAdrVals destination to fill out
* \return True if successfully parsed
* ------------------------------------------------------------------------ */
static Boolean DecodeAdr(const tStrComp *pArg, LongWord Mask, Boolean IsCode, tAdrVals *pAdrVals)
{
Boolean OK;
int ArgLen;
ArgLen
= strlen(pArg
->str.
p_str);
ResetAdrVals(pAdrVals);
/* Register ? */
if (DecodeRegCore(pArg, &pAdrVals->Mode))
{
switch (pAdrVals->Mode)
{
case eModY:
case eModYL:
case eModYH:
AddPrefix(0x90);
break;
default:
break;
}
goto chk;
}
/* immediate ? */
if (*pArg->str.p_str == '#')
{
Word Value = EvalStrIntExpressionOffs(pArg, 1, (OpSize == eSymbolSize16Bit) ? Int16 : Int8, &OK);
if (OK)
{
pAdrVals->Mode = eModImm;
pAdrVals->Part = 0xa;
FillAdrVals(pAdrVals, Value, OpSize);
}
goto chk;
}
/* speicherindirekt ? */
if ((*pArg->str.p_str == '[') && (pArg->str.p_str[ArgLen - 1] == ']'))
{
tStrComp Comp;
Boolean OK;
StrCompRefRight(&Comp, pArg, 1);
Comp.str.p_str[ArgLen - 2] = '\0'; Comp.Pos.Len--;
OK = DecideIndirectSize(Mask, &Comp, eModIAbs8, eModIAbs16, eModI16Abs16, eModI16Abs24, 0xb, 0xc, 0xc, 0xb, pAdrVals);
Comp.str.p_str[ArgLen - 2] = ']';
if (OK)
AddPrefix((pAdrVals->Mode == eModI16Abs16) ? 0x72: 0x92);
goto chk;
}
/* sonstwie indirekt ? */
if (IsIndirect(pArg->str.p_str))
{
tStrComp Comp, Left, Right;
Boolean YReg = False, SPReg = False;
char *p;
StrCompRefRight(&Comp, pArg, 1);
StrCompShorten(&Comp, 1);
/* ein oder zwei Argumente ? */
p = QuotPos(Comp.str.p_str, ',');
if (!p)
{
pAdrVals->Part = 0xf;
if (!as_strcasecmp(Comp.str.p_str, "X")) pAdrVals->Mode = eModIX;
else if (!as_strcasecmp(Comp.str.p_str, "Y"))
{
pAdrVals->Mode = eModIY;
AddPrefix(0x90);
}
else WrStrErrorPos(ErrNum_InvReg, &Comp);
goto chk;
}
StrCompSplitRef(&Left, &Right, &Comp, p);
if (!as_strcasecmp(Left.str.p_str, "X"))
Left = Right;
else if (!as_strcasecmp(Right.str.p_str, "X"));
else if (!as_strcasecmp(Left.str.p_str, "Y"))
{
Left = Right;
YReg = True;
}
else if (!as_strcasecmp(Right.str.p_str, "Y"))
YReg = True;
else if (!as_strcasecmp(Left.str.p_str, "SP"))
{
Left = Right;
SPReg = True;
}
else if (!as_strcasecmp(Right.str.p_str, "SP"))
SPReg = True;
else
{
WrStrErrorPos(ErrNum_InvAddrMode, &Comp);
return False;
}
/* speicherindirekt ? */
ArgLen
= strlen(Left.
str.
p_str);
if ((*Left.str.p_str == '[') && (Left.str.p_str[ArgLen - 1] == ']'))
{
StrCompRefRight(&Right, &Left, 1);
StrCompShorten(&Right, 1);
if (YReg)
{
if (DecideIndirectSize(Mask, &Right, eModIYAbs8, eModIYAbs16, eModNone, eModI16YAbs24, 0xe, 0xd, 0x0, 0xa, pAdrVals))
AddPrefix(0x91);
}
else
{
if (DecideIndirectSize(Mask, &Right, eModIXAbs8, eModIXAbs16, eModI16XAbs16, eModI16YAbs24, 0xe, 0xd, 0xd, 0xa, pAdrVals))
AddPrefix((pAdrVals->Mode == eModI16XAbs16) ? 0x72 : 0x92);
}
}
else
{
if (YReg) DecideSize(Mask, &Left, eModIY8, eModIY16, eModIY24, 0xe, 0xd, 0xa, IsCode, pAdrVals);
else if (SPReg) DecideSize(Mask, &Left, eModISP8, eModNone, eModNone, 0x1, 0x0, 0x0, IsCode, pAdrVals);
else DecideSize(Mask, &Left, eModIX8, eModIX16, eModIX24, 0xe, 0xd, 0xa, IsCode, pAdrVals);
if ((pAdrVals->Mode != eModNone) && YReg) AddPrefix(0x90);
}
goto chk;
}
/* dann absolut */
DecideSize(Mask, pArg, eModAbs8, eModAbs16, eModAbs24, 0xb, 0xc, 0xb, IsCode, pAdrVals);
chk:
return ChkAdrValsMode(pAdrVals, Mask, ErrNum_InvAddrMode, pArg);
}
/*!------------------------------------------------------------------------
* \fn ConstructMask(LongWord TotMask, tSymbolSize OpSize)
* \brief construct actual bit mask of allowed addressing modes from overall list
* \param TotMask overall list
* \param OpSize operand size in use (8/16/unknown)
* \return actual mask
* ------------------------------------------------------------------------ */
static LongWord ConstructMask(LongWord TotMask, tSymbolSize OpSize)
{
if (pCurrCPUProps->Core == eCoreST7)
{
/* not present on ST7 */
TotMask &= ~(MModISP8 | MModI16Abs16 | MModI16XAbs16 | MModXL | MModYL | MModXH | MModYH);
/* SP/X/Y are 8 bits wide on ST7 */
if (OpSize == eSymbolSize16Bit)
TotMask &= ~(MModX | MModY | MModS);
}
if (pCurrCPUProps->Core == eCoreSTM8)
{
/* removed on STM8 */
TotMask &= ~(MModIAbs8 | MModIXAbs8 | MModIYAbs8);
/* SP/X/Y changed to 16 bits on STM8 */
if (OpSize == eSymbolSize8Bit)
TotMask &= ~(MModX | MModY | MModS);
}
return TotMask;
}
/*--------------------------------------------------------------------------*/
/* Bit Symbol Handling */
/*
* Compact representation of bits in symbol table:
* bits 0..2: bit position
* bits 3...10/18: register address in memory space (first 256/64K)
*/
/*!------------------------------------------------------------------------
* \fn EvalBitPosition(const tStrComp *pArg, Boolean *pOK)
* \brief evaluate bit position
* \param bit position argument (with or without #)
* \param pOK parsing OK?
* \return numeric bit position
* ------------------------------------------------------------------------ */
static LongWord EvalBitPosition(const tStrComp *pArg, Boolean *pOK)
{
return EvalStrIntExpressionOffs(pArg, !!(*pArg->str.p_str == '#'), UInt3, pOK);
}
/*!------------------------------------------------------------------------
* \fn AssembleBitSymbol(Byte BitPos, Word Address)
* \brief build the compact internal representation of a bit symbol
* \param BitPos bit position in word
* \param Address register address
* \return compact representation
* ------------------------------------------------------------------------ */
static LongWord AssembleBitSymbol(Byte BitPos, Word Address)
{
return (BitPos & 7)
| (((LongWord)Address & 0xffff) << 3);
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg)
* \brief encode a bit symbol, address & bit position separated
* \param pResult resulting encoded bit
* \param pRegArg register argument
* \param pBitArg bit argument
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg)
{
Boolean OK;
LongWord Addr;
Byte BitPos;
BitPos = EvalBitPosition(pBitArg, &OK);
if (!OK)
return False;
Addr = EvalStrIntExpression(pRegArg, (pCurrCPUProps->Core == eCoreSTM8) ? UInt16 : UInt8, &OK);
if (!OK)
return False;
*pResult = AssembleBitSymbol(BitPos, 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
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg(LongWord *pResult, int Start, int Stop)
{
*pResult = 0;
/* Just one argument -> parse as bit argument */
if (Start == Stop)
{
tEvalResult EvalResult;
*pResult = EvalStrIntExpressionWithResult(&ArgStr[Start], (pCurrCPUProps->Core == eCoreSTM8) ? UInt19 : UInt11, &EvalResult);
if (EvalResult.OK)
ChkSpace(SegBData, EvalResult.AddrSpaceMask);
return EvalResult.OK;
}
/* register & bit position are given as separate arguments */
else if (Stop == Start + 1)
return DecodeBitArg2(pResult, &ArgStr[Start], &ArgStr[Stop]);
/* other # of arguments not allowed */
else
{
WrError(ErrNum_WrongArgCnt);
return False;
}
}
/*!------------------------------------------------------------------------
* \fn DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos)
* \brief transform compact representation of bit (field) symbol into components
* \param BitSymbol compact storage
* \param pAddress (I/O) register address
* \param pBitPos (start) bit position
* \return constant True
* ------------------------------------------------------------------------ */
static Boolean DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos)
{
*pAddress = (BitSymbol >> 3) & 0xffff;
*pBitPos = BitSymbol & 7;
return True;
}
/*!------------------------------------------------------------------------
* \fn DissectBit_ST7(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_ST7(char *pDest, size_t DestSize, LargeWord Inp)
{
Byte BitPos;
Word Address;
DissectBitSymbol(Inp, &Address, &BitPos);
as_snprintf(pDest, DestSize, "$%x.%u", (unsigned)Address, (unsigned)BitPos);
}
/*!------------------------------------------------------------------------
* \fn ExpandST7Bit(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 ExpandST7Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
{
LongWord Address = Base + pStructElem->Offset;
if (pInnermostNamedStruct)
{
PStructElem pElem = CloneStructElem(pVarName, pStructElem);
if (!pElem)
return;
pElem->Offset = Address;
AddStructElem(pInnermostNamedStruct->StructRec, pElem);
}
else
{
if (!ChkRange(Address, 0, (pCurrCPUProps->Core == eCoreSTM8) ? 0xffff : 0xff)
|| !ChkRange(pStructElem->BitPos, 0, 7))
return;
PushLocHandle(-1);
EnterIntSymbol(pVarName, AssembleBitSymbol(pStructElem->BitPos, Address), SegBData, False);
PopLocHandle();
/* TODO: MakeUseList? */
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBitAdrWithIndir(int Start, int Stop, Byte *pBitPos, tAdrVals *pAdrVals)
* \brief decode bit expression, regarding indirect mode on ST7
* \param Start 1st argument of bit expression
* \param Stop 2nd argument of bit expression
* \param pAdrVals result to fill
* \return True if parsing OK
* ------------------------------------------------------------------------ */
static Boolean DecodeBitAdrWithIndir(int Start, int Stop, Byte *pBitPos, tAdrVals *pAdrVals)
{
Boolean OK;
if (Start == Stop)
{
LongWord BitSym;
Word Address;
if (!DecodeBitArg(&BitSym, Start, Stop))
return False;
DissectBitSymbol(BitSym, &Address, pBitPos);
if (pCurrCPUProps->Core == eCoreSTM8)
{
FillAdrVals(pAdrVals, Address, eSymbolSize16Bit);
pAdrVals->Mode = eModAbs16;
}
else
{
FillAdrVals(pAdrVals, Address, eSymbolSize8Bit);
pAdrVals->Mode = eModAbs8;
}
PrefixCnt = 0;
return True;
}
else if (Start + 1 == Stop)
{
*pBitPos = EvalBitPosition(&ArgStr[Stop], &OK);
if (!OK)
return False;
return DecodeAdr(&ArgStr[Start], (pCurrCPUProps->Core == eCoreSTM8) ? MModAbs16 : (MModAbs8 | MModIAbs8), False, pAdrVals);
}
else
return False;
}
/*!------------------------------------------------------------------------
* \fn CompleteCode(const tAdrVals *pAdrVals)
* \brief assemble instruction from prefixes, opcode and address values
* \param pAdrVals values to append to code
* ------------------------------------------------------------------------ */
static void CompleteCode(const tAdrVals *pAdrVals)
{
memcpy(BAsmCode
+ PrefixCnt
+ 1, pAdrVals
->Vals
, pAdrVals
->Cnt
);
CodeLen = PrefixCnt + 1 + pAdrVals->Cnt;
}
/*!------------------------------------------------------------------------
* \fn WriteMOV(tAdrVals *pDestAdrVals, tAdrVals *pSrcAdrVals)
* \brief core of writing code of MOV instruction
* \param pDestAdrVals parsed destination operand
* \param pSrcAdrVals parsed source operand
* ------------------------------------------------------------------------ */
static void WriteMOV(tAdrVals *pDestAdrVals, tAdrVals *pSrcAdrVals)
{
if ((pDestAdrVals->Mode == eModAbs16)
|| (pSrcAdrVals->Mode == eModAbs16)
|| (pSrcAdrVals->Mode == eModImm))
{
ExtendAdrVals(pSrcAdrVals);
ExtendAdrVals(pDestAdrVals);
}
switch (pSrcAdrVals->Mode)
{
case eModImm:
BAsmCode[0] = 0x35;
break;
case eModAbs8:
BAsmCode[0] = 0x45;
break;
case eModAbs16:
BAsmCode[0] = 0x55;
break;
default:
break;
}
memcpy(&BAsmCode
[1], pSrcAdrVals
->Vals
, pSrcAdrVals
->Cnt
);
memcpy(&BAsmCode
[1 + pSrcAdrVals
->Cnt
], pDestAdrVals
->Vals
, pDestAdrVals
->Cnt
);
CodeLen = 1 + pSrcAdrVals->Cnt + pDestAdrVals->Cnt;
}
/*--------------------------------------------------------------------------*/
/* Code Generators */
/*!------------------------------------------------------------------------
* \fn DecodeFixed(Word Code)
* \brief decode instructions without argument
* \param per-instruction context
* ------------------------------------------------------------------------ */
static void DecodeFixed(Word Code)
{
if (!ChkArgCnt(0, 0));
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (Hi(Code) && (pCurrCPUProps->Core != eCoreSTM8)) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else
{
if (Hi(Code) >= 2)
AddPrefix(Hi(Code));
BAsmCode[PrefixCnt] = Lo(Code);
CodeLen = PrefixCnt + 1;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeLD(Word Code)
* \brief decode LD instruction
* ------------------------------------------------------------------------ */
static void DecodeLD(Word Code)
{
LongWord Mask;
tAdrVals DestAdrVals, SrcAdrVals;
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
/* NOTE: Set eSymbolSizeUnknown so we get X/Y/S also in STM8 mode.
LD will work like LDW in thi case. */
Mask = ConstructMask(MModA | MModX | MModY | MModS | MModXL | MModYL | MModXH | MModYH
| MModImm | MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs8 | MModIAbs16 | MModI16Abs16
| MModIXAbs8 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs8 | MModIYAbs16, eSymbolSizeUnknown);
if (DecodeAdr(&ArgStr[1], Mask, False, &DestAdrVals))
switch (DestAdrVals.Mode)
{
case eModA:
Mask = ConstructMask(MModImm | MModX | MModY | MModS | MModXL | MModYL | MModXH | MModYH | MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs8 | MModIAbs16 | MModI16Abs16
| MModIXAbs8 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs8 | MModIYAbs16, eSymbolSize8Bit);
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModX: case eModXL:
case eModY: case eModYL:
BAsmCode[PrefixCnt] = 0x9f;
CodeLen = PrefixCnt + 1;
break;
case eModXH: case eModYH:
BAsmCode[PrefixCnt] = 0x9e;
CodeLen = PrefixCnt + 1;
break;
case eModS:
BAsmCode[PrefixCnt] = 0x9e;
CodeLen = PrefixCnt + 1;
break;
case eModISP8: /* irregular, cannot use default case */
BAsmCode[PrefixCnt] = 0x7b;
CompleteCode(&SrcAdrVals);
break;
default:
BAsmCode[PrefixCnt] = 0x06 + (SrcAdrVals.Part << 4);
CompleteCode(&SrcAdrVals);
}
break;
case eModX:
if (pCurrCPUProps->Core == eCoreSTM8)
OpSize = eSymbolSize16Bit;
Mask = ConstructMask(MModA | MModY | MModS | MModImm
| MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModISP8
| MModIAbs8 | MModIAbs16 | MModI16Abs16
| MModIXAbs8 | MModIXAbs16 | MModI16XAbs16, OpSize);
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModA:
BAsmCode[PrefixCnt] = 0x97;
CodeLen = PrefixCnt + 1;
break;
case eModY:
BAsmCode[0] = 0x93;
CodeLen = 1;
break;
case eModS:
BAsmCode[PrefixCnt] = 0x96;
CodeLen = PrefixCnt + 1;
break;
default:
BAsmCode[PrefixCnt] = 0x0e + (SrcAdrVals.Part << 4); /* ANSI :-O */
CompleteCode(&SrcAdrVals);
}
break;
case eModXL:
case eModYL:
if (DecodeAdr(&ArgStr[2], MModA, False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = 0x97;
CodeLen = PrefixCnt + 1;
}
break;
case eModXH:
case eModYH:
if (DecodeAdr(&ArgStr[2], MModA, False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = 0x95;
CodeLen = PrefixCnt + 1;
}
break;
case eModY:
PrefixCnt = 0;
if (pCurrCPUProps->Core == eCoreSTM8)
OpSize = eSymbolSize16Bit;
Mask = ConstructMask(MModA | MModX | MModS | MModImm
| MModAbs8 | MModAbs16
| MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs8 | MModIAbs16 | MModIYAbs8 | MModIYAbs16, OpSize);
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModA:
AddPrefix(0x90);
BAsmCode[PrefixCnt] = 0x97;
CodeLen = PrefixCnt + 1;
break;
case eModX:
AddPrefix(0x90);
BAsmCode[PrefixCnt] = 0x93;
CodeLen = PrefixCnt + 1;
break;
case eModS:
AddPrefix(0x90);
BAsmCode[PrefixCnt] = 0x96;
CodeLen = PrefixCnt + 1;
break;
case eModISP8:
BAsmCode[PrefixCnt] = 0x16;
goto common;
default:
if (PrefixCnt == 0) AddPrefix(0x90);
if (BAsmCode[0] == 0x92) BAsmCode[0]--;
BAsmCode[PrefixCnt] = 0x0e + (SrcAdrVals.Part << 4); /* ANSI :-O */
common:
CompleteCode(&SrcAdrVals);
}
break;
case eModS:
if (DecodeAdr(&ArgStr[2], MModA | MModX | MModY, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModA:
BAsmCode[PrefixCnt] = 0x95;
CodeLen = PrefixCnt + 1;
break;
case eModX:
case eModY:
BAsmCode[PrefixCnt] = 0x94;
CodeLen = PrefixCnt + 1;
break;
default:
break;
}
break;
default:
{
Boolean Result;
unsigned SavePrefixCnt = PrefixCnt;
/* set unknown size to allow X&Y also on STM8 if LD is written instead of LDW */
Mask = ConstructMask(MModA | MModX | MModY, eSymbolSizeUnknown);
/* aliases for MOV */
if (pCurrCPUProps->Core == eCoreSTM8)
switch (DestAdrVals.Mode)
{
case eModAbs16:
Mask |= MModAbs16 | MModImm;
break;
case eModAbs8:
Mask |= MModAbs8 | MModAbs16 | MModImm;
break;
default:
break;
}
Result = DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals);
PrefixCnt = SavePrefixCnt;
if (Result)
switch (SrcAdrVals.Mode)
{
case eModA:
Mask = ConstructMask(MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs8 | MModIAbs16 | MModI16Abs16 | MModIXAbs8 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs8 | MModIYAbs16, eSymbolSize8Bit);
if (ChkAdrValsMode(&DestAdrVals, Mask, ErrNum_InvAddrMode, &ArgStr[1]))
{
BAsmCode[PrefixCnt] = (DestAdrVals.Mode == eModISP8) ? 0x6b : (0x07 + (DestAdrVals.Part << 4));
CompleteCode(&DestAdrVals);
}
break;
case eModX:
Mask = MModAbs8 | MModAbs16 | MModIAbs16;
if (pCurrCPUProps->Core == eCoreST7)
Mask |= MModIX | MModIX8 | MModIX16 | MModIAbs8 | MModIXAbs8 | MModIXAbs16;
if (pCurrCPUProps->Core == eCoreSTM8)
Mask |= MModIY | MModIY8 | MModIY16 | MModIYAbs16 | MModISP8 | MModI16Abs16;
if (ChkAdrValsMode(&DestAdrVals, Mask, ErrNum_InvAddrMode, &ArgStr[1]))
{
BAsmCode[PrefixCnt] = 0x0f + (DestAdrVals.Part << 4);
CompleteCode(&DestAdrVals);
}
break;
case eModY:
Mask = MModAbs8 | MModAbs16 | MModIAbs16;
if (pCurrCPUProps->Core == eCoreST7)
Mask |= MModIY | MModIY8 | MModIY16 | MModIAbs8 | MModIYAbs8 | MModIYAbs16;
if (pCurrCPUProps->Core == eCoreSTM8)
Mask |= MModIX | MModIX8 | MModIX16 | MModIXAbs16 | MModI16XAbs16 | MModISP8;
if (ChkAdrValsMode(&DestAdrVals, Mask, ErrNum_InvAddrMode, &ArgStr[1]))
switch (DestAdrVals.Mode)
{
case eModISP8:
PrefixCnt = 0;
BAsmCode[PrefixCnt] = 0x07 + (DestAdrVals.Part << 4);
goto common_ysrc2;
case eModIX:
case eModIX8:
case eModIX16:
PrefixCnt = 0;
goto common_ysrc;
case eModIXAbs16:
goto common_ysrc;
default:
if (PrefixCnt == 0) AddPrefix(0x90);
if (BAsmCode[0] == 0x92) BAsmCode[0]--;
common_ysrc:
BAsmCode[PrefixCnt] = 0x0f + (DestAdrVals.Part << 4);
common_ysrc2:
CompleteCode(&DestAdrVals);
}
break;
case eModImm: /* MOV aliases: only possible if Dest = Abs8/16 */
case eModAbs8:
case eModAbs16:
WriteMOV(&DestAdrVals, &SrcAdrVals);
break;
default:
break;
}
}
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeLDW(Word Code)
* \brief decode LDW instruction
* ------------------------------------------------------------------------ */
static void DecodeLDW(Word Code)
{
tAdrVals DestAdrVals, SrcAdrVals;
LongWord Mask;
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
Mask = ConstructMask(MModX | MModY | MModS
| MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs16 | MModI16Abs16 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs16, OpSize = eSymbolSize16Bit);
if (DecodeAdr(&ArgStr[1], Mask, False, &DestAdrVals))
switch (DestAdrVals.Mode)
{
case eModX:
Mask = ConstructMask(MModY | MModS | MModImm
| MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModISP8
| MModIAbs16 | MModI16Abs16 | MModIXAbs16 | MModI16XAbs16, eSymbolSize16Bit);
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModY:
PrefixCnt = 0;
BAsmCode[PrefixCnt] = 0x93;
CodeLen = PrefixCnt + 1;
break;
case eModS:
BAsmCode[PrefixCnt] = 0x96;
CodeLen = PrefixCnt + 1;
break;
default:
BAsmCode[PrefixCnt] = 0x0e | (SrcAdrVals.Part << 4);
CompleteCode(&SrcAdrVals);
break;
}
break;
case eModY:
PrefixCnt = 0;
Mask = ConstructMask(MModX | MModS | MModImm
| MModAbs8 | MModAbs16
| MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs16 | MModIYAbs16, eSymbolSize16Bit);
DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals);
if (!PrefixCnt)
AddPrefix(0x90);
if (SrcAdrVals.Mode != eModNone)
switch (SrcAdrVals.Mode)
{
case eModX:
BAsmCode[PrefixCnt] = 0x93;
CodeLen = PrefixCnt + 1;
break;
case eModS:
BAsmCode[PrefixCnt] = 0x96;
CodeLen = PrefixCnt + 1;
break;
case eModISP8:
PrefixCnt = 0;
BAsmCode[PrefixCnt] = 0x16;
goto common_x;
case eModIAbs16:
PrefixCnt = 0;
AddPrefix(0x91);
/* fall-through */
default:
BAsmCode[PrefixCnt] = 0x0e | (SrcAdrVals.Part << 4);
common_x:
CompleteCode(&SrcAdrVals);
break;
}
break;
case eModS:
Mask = ConstructMask(MModX | MModY, eSymbolSize16Bit);
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = 0x94;
CodeLen = PrefixCnt + 1;
}
break;
default:
{
Mask = ConstructMask(MModX | MModY, eSymbolSize16Bit);
if (DecodeReg(&ArgStr[2], &SrcAdrVals.Mode, Mask))
switch (DestAdrVals.Mode)
{
case eModIAbs16:
if (eModY == SrcAdrVals.Mode)
{
PrefixCnt = 0;
AddPrefix(0x91);
}
goto common_y2;
case eModISP8:
BAsmCode[PrefixCnt] = (eModY == SrcAdrVals.Mode) ? 0x17 : 0x1f;
goto common_y;
case eModAbs8:
case eModAbs16:
if (eModY == SrcAdrVals.Mode)
AddPrefix(0x90);
/* fall-through */
default:
common_y2:
BAsmCode[PrefixCnt] = 0x0f | (DestAdrVals.Part << 4);
common_y:
CompleteCode(&DestAdrVals);
break;
}
break;
}
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeLDF(Word Code)
* \brief decode LDF instruction
* ------------------------------------------------------------------------ */
static void DecodeLDF(Word Code)
{
tAdrVals AdrVals;
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeAdr(&ArgStr[1], MModA | MModAbs24 | MModIX24 | MModIY24 | MModI16XAbs24 | MModI16YAbs24 | MModI16Abs24, False, &AdrVals))
switch (AdrVals.Mode)
{
case eModA:
if (DecodeAdr(&ArgStr[2], MModAbs24 | MModIX24 | MModIY24 | MModI16XAbs24 | MModI16YAbs24 | MModI16Abs24, False, &AdrVals))
{
switch (AdrVals.Mode)
{
case eModAbs24:
case eModI16Abs24:
BAsmCode[PrefixCnt] = 0x0c | (AdrVals.Part << 4);
break;
case eModIX24:
case eModIY24:
case eModI16XAbs24:
case eModI16YAbs24:
BAsmCode[PrefixCnt] = 0x0f | (AdrVals.Part << 4);
break;
default:
break;
}
CompleteCode(&AdrVals);
}
break;
default:
{
tAdrMode RegMode;
if (DecodeReg(&ArgStr[2], &RegMode, MModA))
{
switch (AdrVals.Mode)
{
case eModAbs24:
case eModI16Abs24:
BAsmCode[PrefixCnt] = 0x0d | (AdrVals.Part << 4);
break;
case eModIX24:
case eModIY24:
case eModI16XAbs24:
case eModI16YAbs24:
BAsmCode[PrefixCnt] = 0x07 | (AdrVals.Part << 4);
break;
default:
break;
}
CompleteCode(&AdrVals);
}
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMOV(Word Code)
* \brief decode MOV instruction
* ------------------------------------------------------------------------ */
static void DecodeMOV(Word Code)
{
tAdrVals SrcAdrVals, DestAdrVals;
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeAdr(&ArgStr[2], MModImm | MModAbs8 | MModAbs16, False, &SrcAdrVals))
{
if (DecodeAdr(&ArgStr[1], ((SrcAdrVals.Mode == eModAbs8) ? MModAbs8 : 0) | MModAbs16, False, &DestAdrVals))
WriteMOV(&DestAdrVals, &SrcAdrVals);
}
}
/*!------------------------------------------------------------------------
* \fn DecodePUSH_POP(Word Code)
* \brief decode PUSH(W)/POP(W) instructions
* \param Code instruction context
* ------------------------------------------------------------------------ */
static void DecodePUSH_POP(Word Code)
{
if (!ChkArgCnt(1, 1));
else if (Hi(Code) && (pCurrCPUProps->Core != eCoreSTM8)) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
LongWord Mask;
tAdrVals AdrVals;
Mask = MModX | MModY | (Hi(Code) ? 0 : MModA);
if (pCurrCPUProps->Core == eCoreSTM8)
{
Mask |= MModAbs16;
if (Lo(Code))
Mask |= MModImm;
}
if (!as_strcasecmp(ArgStr[1].str.p_str, "CC"))
{
BAsmCode[PrefixCnt] = 0x86 + Lo(Code);
CodeLen = PrefixCnt + 1;
}
else if (DecodeAdr(&ArgStr[1], Mask, False, &AdrVals))
{
switch (AdrVals.Mode)
{
case eModA:
BAsmCode[PrefixCnt] = 0x84 + Lo(Code);
break;
case eModX:
case eModY:
BAsmCode[PrefixCnt] = 0x85 + Lo(Code);
break;
case eModAbs16:
BAsmCode[PrefixCnt] = Lo(Code) ? 0x4b : 0x32;
break;
case eModImm:
BAsmCode[PrefixCnt] = 0x4b;
break;
default:
break;
}
CompleteCode(&AdrVals);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeCP(Word Code)
* \brief decode CP(W) instructions
* \param IsCPW 1 if CPW
* ------------------------------------------------------------------------ */
static void DecodeCP(Word IsCPW)
{
LongWord Mask;
if (!ChkArgCnt(2, 2));
else if (IsCPW && (pCurrCPUProps->Core != eCoreSTM8)) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
tAdrVals SrcAdrVals;
tAdrMode DestMode;
if (DecodeReg(&ArgStr[1], &DestMode, (IsCPW ? 0 : MModA) | MModX | MModY))
switch (DestMode)
{
case eModA:
Mask = ConstructMask(MModImm | MModAbs8 | MModAbs16
| MModIX | MModIX8 | MModIX16 | MModIY | MModIY8 | MModIY16 | MModISP8
| MModIAbs8 | MModIAbs16 | MModI16Abs16
| MModIXAbs8 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs8 | MModIYAbs16, eSymbolSize8Bit);
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = 0x01 + (SrcAdrVals.Part << 4);
CompleteCode(&SrcAdrVals);
}
break;
case eModX:
Mask = MModImm | MModAbs8 | MModAbs16 | MModIAbs16;
if (pCurrCPUProps->Core == eCoreST7)
Mask |= MModIAbs8 | MModIXAbs8 | MModIX | MModIX8 | MModIX16 | MModIXAbs16;
if (pCurrCPUProps->Core == eCoreSTM8)
{
Mask |= MModIY | MModIY8 | MModIY16 | MModISP8 | MModI16Abs16 | MModIYAbs16;
OpSize = eSymbolSize16Bit;
}
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = 0x03 + (SrcAdrVals.Part << 4);
CompleteCode(&SrcAdrVals);
}
break;
case eModY:
PrefixCnt = 0;
Mask = MModImm | MModAbs8 | MModAbs16 | MModIAbs16;
if (pCurrCPUProps->Core == eCoreST7)
Mask |= MModIAbs8 | MModIYAbs8 | MModIY | MModIY8 | MModIY16 | MModIYAbs16;
if (pCurrCPUProps->Core == eCoreSTM8)
{
Mask |= MModIX | MModIX8 | MModIX16 | MModIXAbs16 | MModI16XAbs16;
OpSize = eSymbolSize16Bit;
}
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModIXAbs16:
case eModIX:
case eModIX8:
case eModIX16:
goto common;
default:
if (PrefixCnt == 0) AddPrefix(0x90);
if (BAsmCode[0] == 0x92) BAsmCode[0]--;
common:
BAsmCode[PrefixCnt] = 0x03 + (SrcAdrVals.Part << 4);
CompleteCode(&SrcAdrVals);
}
break;
default:
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeAri16(Word Code)
* \brief decode 16-bit arithmetic/logic instructions with two operands
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeAri16(Word Code)
{
tAdrVals SrcAdrVals, DestAdrVals;
if (!ChkArgCnt(2, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeAdr(&ArgStr[1], MModX | MModY | MModS, False, &DestAdrVals))
switch (DestAdrVals.Mode)
{
case eModX:
case eModY:
OpSize = eSymbolSize16Bit;
if (DecodeAdr(&ArgStr[2], MModImm | MModAbs16 | MModISP8, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModImm:
if (PrefixCnt)
{
BAsmCode[PrefixCnt - 1] = 0x72;
BAsmCode[PrefixCnt] = 0xa0 | Hi(Code);
}
else
BAsmCode[PrefixCnt] = 0x1d - !!Lo(Code);
goto common;
case eModAbs16:
if (PrefixCnt)
{
BAsmCode[PrefixCnt - 1] = 0x72;
BAsmCode[PrefixCnt] = 0xb0 | Hi(Code);
}
else
{
BAsmCode[PrefixCnt++] = 0x72;
BAsmCode[PrefixCnt] = 0xb0 | Lo(Code);
}
goto common;
case eModISP8:
if (PrefixCnt)
{
BAsmCode[PrefixCnt - 1] = 0x72;
BAsmCode[PrefixCnt] = 0xf0 | Hi(Code);
}
else
{
BAsmCode[PrefixCnt++] = 0x72;
BAsmCode[PrefixCnt] = 0xf0 | Lo(Code);
}
goto common;
common:
CompleteCode(&SrcAdrVals);
break;
default:
break;
}
break;
case eModS:
OpSize = eSymbolSize8Bit;
if (DecodeAdr(&ArgStr[2], MModImm, False, &SrcAdrVals))
{
BAsmCode[0] = 0x52 | Lo(Code);
BAsmCode[1] = SrcAdrVals.Vals[0];
CodeLen = 2;
}
break;
default:
break;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeAri(Word Code)
* \brief decode 8-bit arithmetic/logic instructions with two operands
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeAri(Word Code)
{
tAdrVals SrcAdrVals, DestAdrVals;
LongWord Mask;
Word Code16 = 0;
if (!ChkArgCnt(2, 2));
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
Mask = MModA;
if (pCurrCPUProps->Core == eCoreSTM8)
switch (Lo(Code))
{
case 0x00: /* SUB->SUBW */
Code16 = 0x0200;
Mask |= MModS | MModX | MModY;
break;
case 0x0b: /* ADD->ADDW */
Code16 = 0x090b;
Mask |= MModS | MModX | MModY;
break;
}
if (DecodeAdr(&ArgStr[1], Mask, False, &DestAdrVals))
switch (DestAdrVals.Mode)
{
case eModA:
Mask = MModAbs8 | MModAbs16 | MModIX | MModIX8 | MModIX16 | MModIY |
MModIY8 | MModIY16 | MModIAbs16 | MModIXAbs16 | MModIYAbs16;
if (pCurrCPUProps->Core == eCoreST7)
Mask |= MModIAbs8 | MModIXAbs8 | MModIYAbs8;
if (pCurrCPUProps->Core == eCoreSTM8)
Mask |= MModISP8 | MModI16Abs16 | MModI16XAbs16;
if (Hi(Code)) Mask |= MModImm;
if (DecodeAdr(&ArgStr[2], Mask, False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = Lo(Code) + (SrcAdrVals.Part << 4);
CompleteCode(&SrcAdrVals);
}
break;
case eModS:
case eModX:
case eModY:
PrefixCnt = 0;
DecodeAri16(Code16);
default:
break;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRMW(Word Code)
* \brief decode 8-bit read/modify/write instructions with one operand
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeRMW(Word Code)
{
Boolean IsW = Hi(Code);
Code = Lo(Code);
if (!ChkArgCnt(1, 1));
else if (IsW && (pCurrCPUProps->Core != eCoreSTM8)) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
LongWord Mask;
tAdrVals AdrVals;
Mask = MModX | MModY;
if (!IsW)
{
Mask |= MModA | MModAbs8
| MModIX | MModIX8 | MModIY | MModIY8;
if (pCurrCPUProps->Core == eCoreST7)
Mask |= MModIAbs8 | MModIXAbs8 | MModIYAbs8;
if (pCurrCPUProps->Core == eCoreSTM8)
Mask |= MModAbs16 | MModIX16 | MModIY16 | MModISP8
| MModIAbs16 | MModI16Abs16 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs16;
}
if (DecodeAdr(&ArgStr[1], Mask, False, &AdrVals))
switch (AdrVals.Mode)
{
case eModA:
BAsmCode[PrefixCnt] = 0x40 + Code;
CodeLen = PrefixCnt + 1;
break;
case eModX:
case eModY:
BAsmCode[PrefixCnt] = 0x50 + Code;
CodeLen = PrefixCnt + 1;
break;
case eModAbs16:
BAsmCode[PrefixCnt++] = 0x72;
BAsmCode[PrefixCnt] = 0x50 | Code;
goto common;
case eModIX16:
BAsmCode[PrefixCnt++] = 0x72;
BAsmCode[PrefixCnt] = 0x40 | Code;
goto common;
case eModIY16:
BAsmCode[PrefixCnt] = 0x40 | Code;
goto common;
case eModISP8:
BAsmCode[PrefixCnt] = 0x00 | Code;
goto common;
case eModIAbs16:
case eModI16Abs16:
BAsmCode[PrefixCnt] = 0x30 | Code;
goto common;
case eModIXAbs16:
case eModI16XAbs16:
case eModIYAbs16:
BAsmCode[PrefixCnt] = 0x60 | Code;
goto common;
default:
BAsmCode[PrefixCnt] = Code + ((AdrVals.Part - 8) << 4);
/* fall-through */
common:
CompleteCode(&AdrVals);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMUL(Word Code)
* \brief decode MUL instruction
* ------------------------------------------------------------------------ */
static void DecodeMUL(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
tAdrMode SrcMode;
tAdrVals DestVals;
if (DecodeReg(&ArgStr[2], &SrcMode, MModA)
&& DecodeAdr(&ArgStr[1], MModX | MModY, False, &DestVals))
{
BAsmCode[PrefixCnt] = 0x42;
CodeLen = PrefixCnt + 1;
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeDIV(Word Code)
* \brief decode DIV(W) instructions
* \param IsW True if DIVW
* ------------------------------------------------------------------------ */
static void DecodeDIV(Word IsW)
{
tAdrVals DestAdrVals, SrcAdrVals;
if (!ChkArgCnt(2, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeAdr(&ArgStr[1], MModX | (IsW ? 0 : MModY), False, &DestAdrVals)
&& DecodeAdr(&ArgStr[2], MModY | (IsW ? 0 : MModA), False, &SrcAdrVals))
{
BAsmCode[PrefixCnt] = (SrcAdrVals.Mode == eModA) ? 0x62 : 0x65;
CodeLen = PrefixCnt + 1;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeEXG(Word Code)
* \brief decode EXG(W) instructions
* \param IsW True if EXGW
* ------------------------------------------------------------------------ */
static void DecodeEXG(Word IsW)
{
tAdrVals DestAdrVals, SrcAdrVals;
if (!ChkArgCnt(2, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeAdr(&ArgStr[1], (IsW ? 0 : (MModA | MModXL | MModYL | MModAbs16)) | MModX | MModY, False, &DestAdrVals))
switch (DestAdrVals.Mode)
{
case eModA:
if (DecodeAdr(&ArgStr[2], MModXL | MModYL | MModAbs16, False, &SrcAdrVals))
switch (SrcAdrVals.Mode)
{
case eModXL:
BAsmCode[0] = 0x41;
CodeLen = 1;
break;
case eModYL:
BAsmCode[0] = 0x61;
CodeLen = 1;
break;
case eModAbs16:
BAsmCode[0] = 0x31;
CompleteCode(&SrcAdrVals);
break;
default:
break;
}
break;
case eModXL:
if (DecodeAdr(&ArgStr[2], MModA, False, &SrcAdrVals))
{
BAsmCode[0] = 0x41;
CodeLen = 1;
}
break;
case eModYL:
if (DecodeAdr(&ArgStr[2], MModA, False, &SrcAdrVals))
{
BAsmCode[0] = 0x61;
CodeLen = 1;
}
break;
case eModAbs16:
if (DecodeAdr(&ArgStr[2], MModA, False, &SrcAdrVals))
{
BAsmCode[0] = 0x31;
memcpy(&BAsmCode
[1], SrcAdrVals.
Vals, SrcAdrVals.
Cnt);
CodeLen = 3;
}
break;
case eModX:
if (DecodeAdr(&ArgStr[2], MModY, False, &SrcAdrVals))
{
BAsmCode[0] = 0x51;
CodeLen = 1;
}
break;
case eModY:
if (DecodeAdr(&ArgStr[2], MModX, False, &SrcAdrVals))
{
BAsmCode[0] = 0x51;
CodeLen = 1;
}
break;
default:
break;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBitOp(Word Code)
* \brief decode bit operation instructions
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeBitOp(Word Code)
{
Byte BitPos;
tAdrVals AdrVals;
if (!ChkArgCnt(1, 2));
else if ((Hi(Code == 0x90)) && (pCurrCPUProps->Core != eCoreSTM8)) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeBitAdrWithIndir(1, ArgCnt, &BitPos, &AdrVals))
{
if (pCurrCPUProps->Core == eCoreSTM8)
{
PrefixCnt = 0;
AddPrefix(Hi(Code));
BAsmCode[PrefixCnt] = 0x10 | (BitPos << 1) | (Code & 1);
}
else
BAsmCode[PrefixCnt] = Lo(Code) + (BitPos << 1);
CompleteCode(&AdrVals);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBTJF_BTJT(Word Code)
* \brief decode BTJF/BTJT instructions
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeBTJF_BTJT(Word Code)
{
Byte BitPos;
tAdrVals AdrVals;
if (!ChkArgCnt(2, 3));
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeBitAdrWithIndir(1, ArgCnt - 1, &BitPos, &AdrVals))
{
Integer AdrInt;
Boolean OK;
tSymbolFlags Flags;
if (pCurrCPUProps->Core == eCoreSTM8)
{
PrefixCnt = 0;
AddPrefix(0x72);
}
BAsmCode[PrefixCnt] = Code + (BitPos << 1);
memcpy(BAsmCode
+ 1 + PrefixCnt
, AdrVals.
Vals, AdrVals.
Cnt);
AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[3], pCurrCPUProps->AddrIntType, &OK, &Flags) - (EProgCounter() + PrefixCnt + 1 + AdrVals.Cnt + 1);
if (OK)
{
if (!mSymbolQuestionable(Flags) && ((AdrInt < -128) || (AdrInt > 127))) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[3]);
else
{
BAsmCode[PrefixCnt + 1 + AdrVals.Cnt] = AdrInt & 0xff;
CodeLen = PrefixCnt + 1 + AdrVals.Cnt + 1;
}
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeJP_CALL(Word Code)
* \brief decode JP/CALL instructions
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeJP_CALL(Word Code)
{
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else
{
LongWord Mask;
tAdrVals AdrVals;
Mask = ConstructMask(MModAbs8 | MModAbs16 | MModIX | MModIX8 | MModIX16 | MModIY
| MModIY8 | MModIY16 | MModIAbs8 | MModIAbs16 | MModI16Abs16
| MModIXAbs8 | MModIXAbs16 | MModI16XAbs16 | MModIYAbs8 | MModIYAbs16,
eSymbolSizeUnknown);
if (DecodeAdr(&ArgStr[1], Mask, True, &AdrVals))
{
BAsmCode[PrefixCnt] = Code + (AdrVals.Part << 4);
CompleteCode(&AdrVals);
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeJPF_CALLF(Word Code)
* \brief decode JPF/CALLF instructions
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeJPF_CALLF(Word Code)
{
tAdrVals AdrVals;
if (!ChkArgCnt(1, 1));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (DecodeAdr(&ArgStr[1], MModAbs24 | MModI16Abs24, True, &AdrVals))
{
BAsmCode[PrefixCnt] = Code;
CompleteCode(&AdrVals);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRel(Word Code)
* \brief decode relative branch instructions
* \param instruction code
* ------------------------------------------------------------------------ */
static void DecodeRel(Word Code)
{
if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (!Code) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (!ChkArgCnt(1, 1));
else if (*ArgStr[1].str.p_str == '[')
{
if (pCurrCPUProps->Core != eCoreST7) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
else
{
tAdrVals AdrVals;
if (DecodeAdr(&ArgStr[1], MModIAbs8, False, &AdrVals))
{
BAsmCode[PrefixCnt] = Lo(Code);
CompleteCode(&AdrVals);
}
}
}
else
{
Boolean OK;
Integer AdrInt;
tSymbolFlags Flags;
if (Hi(Code))
BAsmCode[PrefixCnt++] = Hi(Code);
AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], pCurrCPUProps->AddrIntType, &OK, &Flags) - (EProgCounter() + 2 + PrefixCnt);
if (OK)
{
if (!mSymbolQuestionable(Flags) && ((AdrInt < -128) || (AdrInt > 127))) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
else
{
BAsmCode[PrefixCnt] = Lo(Code);
BAsmCode[PrefixCnt + 1] = AdrInt & 0xff;
CodeLen = PrefixCnt + 2;
}
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRxWA(Word Code)
* \brief decode RLWA/RRWA instructions
* \param Code instruction code
* ------------------------------------------------------------------------ */
static void DecodeRxWA(Word Code)
{
tAdrMode SrcMode;
tAdrVals DestAdrVals;
if (*AttrPart.str.p_str) WrStrErrorPos(ErrNum_UseLessAttr, &AttrPart);
else if (!ChkArgCnt(1, 2));
else if (pCurrCPUProps->Core != eCoreSTM8) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
else if (((ArgCnt == 1) || DecodeReg(&ArgStr[2], &SrcMode, MModA)) && DecodeAdr(&ArgStr[1], MModX | MModY, False, &DestAdrVals))
{
BAsmCode[PrefixCnt] = Code;
CodeLen = PrefixCnt + 1;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBIT(Word Code)
* \brief decode BIT 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[2], &OK);
if (!OK)
return;
pElement = CreateStructElem(&LabPart);
if (!pElement)
return;
pElement->pRefElemName = as_strdup(ArgStr[1].str.p_str);
pElement->OpSize = eSymbolSize8Bit;
pElement->BitPos = BitPos;
pElement->ExpandFnc = ExpandST7Bit;
AddStructElem(pInnermostNamedStruct->StructRec, pElement);
}
else
{
if (DecodeBitArg(&BitSpec, 1, ArgCnt))
{
*ListLine = '=';
DissectBit_ST7(ListLine + 1, STRINGSIZE - 3, BitSpec);
PushLocHandle(-1);
EnterIntSymbol(&LabPart, BitSpec, SegBData, False);
PopLocHandle();
/* TODO: MakeUseList? */
}
}
}
/*--------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn InitFields(void)
* \brief build up hash table of instructions
* ------------------------------------------------------------------------ */
static void AddFixed(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFixed);
}
static void AddAri(const char *NName, Word NCode, Boolean NMay)
{
AddInstTable(InstTable, NName, NCode | (NMay << 8), DecodeAri);
}
static void AddAri16(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeAri16);
}
static void AddRMW(const char *NName, Byte NCode)
{
char WName[10];
AddInstTable(InstTable, NName, NCode, DecodeRMW);
as_snprintf(WName, sizeof(WName), "%sW", NName);
AddInstTable(InstTable, WName, NCode | 0x100, DecodeRMW);
}
static void AddRel(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRel);
}
static void InitFields(void)
{
InstTable = CreateInstTable(201);
SetDynamicInstTable(InstTable);
AddInstTable(InstTable, "LD", 0, DecodeLD);
AddInstTable(InstTable, "LDF", 0, DecodeLDF);
AddInstTable(InstTable, "LDW", 0, DecodeLDW);
AddInstTable(InstTable, "MOV", 0, DecodeMOV);
AddInstTable(InstTable, "PUSH", 0x0004, DecodePUSH_POP);
AddInstTable(InstTable, "POP", 0x0000, DecodePUSH_POP);
AddInstTable(InstTable, "PUSHW", 0x0104, DecodePUSH_POP);
AddInstTable(InstTable, "POPW", 0x0100, DecodePUSH_POP);
AddInstTable(InstTable, "CP", 0, DecodeCP);
AddInstTable(InstTable, "CPW", 1, DecodeCP);
AddInstTable(InstTable, "MUL", 0, DecodeMUL);
AddInstTable(InstTable, "DIV", 0, DecodeDIV);
AddInstTable(InstTable, "DIVW", 1, DecodeDIV);
AddInstTable(InstTable, "EXG", 0, DecodeEXG);
AddInstTable(InstTable, "EXGW", 1, DecodeEXG);
AddInstTable(InstTable, "RLWA", 0x02, DecodeRxWA);
AddInstTable(InstTable, "RRWA", 0x01, DecodeRxWA);
AddInstTable(InstTable, "BCCM", 0x9001, DecodeBitOp);
AddInstTable(InstTable, "BCPL", 0x9000, DecodeBitOp);
AddInstTable(InstTable, "BRES", 0x7211, DecodeBitOp);
AddInstTable(InstTable, "BSET", 0x7210, DecodeBitOp);
AddInstTable(InstTable, "BTJF", 0x01, DecodeBTJF_BTJT);
AddInstTable(InstTable, "BTJT", 0x00, DecodeBTJF_BTJT);
AddInstTable(InstTable, "JP", 0x0c, DecodeJP_CALL);
AddInstTable(InstTable, "CALL", 0x0d, DecodeJP_CALL);
AddInstTable(InstTable, "JPF", 0xac, DecodeJPF_CALLF);
AddInstTable(InstTable, "CALLF", 0x8d, DecodeJPF_CALLF);
AddInstTable(InstTable, "BIT", 0, DecodeBIT);
AddFixed("HALT" , 0x8e); AddFixed("IRET" , 0x80); AddFixed("NOP" , 0x9d);
AddFixed("RCF" , 0x98); AddFixed("RET" , 0x81); AddFixed("RIM" , 0x9a);
AddFixed("RSP" , 0x9c); AddFixed("SCF" , 0x99); AddFixed("SIM" , 0x9b);
AddFixed("TRAP" , 0x83); AddFixed("WFI" , 0x8f); AddFixed("BREAK", 0x018b);
AddFixed("WFE" , 0x728f); AddFixed("RVF" , 0x019c); AddFixed("RETF", 0x0187);
AddFixed("CCF" , 0x018c);
AddAri("ADC" , 0x09, True ); AddAri("ADD" , 0x0b, True ); AddAri("AND" , 0x04, True );
AddAri("BCP" , 0x05, True ); AddAri("OR" , 0x0a, True ); AddAri("SBC" , 0x02, True );
AddAri("SUB" , 0x00, True ); AddAri("XOR" , 0x08, True );
AddAri16("ADDW", 0x090b); AddAri16("SUBW", 0x0200);
AddRMW("CLR" , 0x0f); AddRMW("CPL" , 0x03); AddRMW("DEC" , 0x0a);
AddRMW("INC" , 0x0c); AddRMW("NEG" , 0x00); AddRMW("RLC" , 0x09);
AddRMW("RRC" , 0x06); AddRMW("SLA" , 0x08); AddRMW("SLL" , 0x08);
AddRMW("SRA" , 0x07); AddRMW("SRL" , 0x04); AddRMW("SWAP", 0x0e);
AddRMW("TNZ" , 0x0d);
AddRel("CALLR", 0xad);
AddRel("JRA" , 0x20);
AddRel("JRC" , 0x25);
AddRel("JREQ" , 0x27);
AddRel("JRF" , 0x21);
AddRel("JRH" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x9029 : 0x29);
AddRel("JRIH" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x902f : 0x2f);
AddRel("JRIL" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x902e : 0x2e);
AddRel("JRM" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x902d : 0x2d);
AddRel("JRMI" , 0x2b);
AddRel("JRNC" , 0x24);
AddRel("JRNE" , 0x26);
AddRel("JRNH" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x9028 : 0x28);
AddRel("JRNM" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x902c : 0x2c);
AddRel("JRNV" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x28 : 0x00);
AddRel("JRPL" , 0x2a);
AddRel("JRSGE", (pCurrCPUProps->Core == eCoreSTM8) ? 0x2e : 0x00);
AddRel("JRSGT", (pCurrCPUProps->Core == eCoreSTM8) ? 0x2c : 0x00);
AddRel("JRSLE", (pCurrCPUProps->Core == eCoreSTM8) ? 0x2d : 0x00);
AddRel("JRSLT", (pCurrCPUProps->Core == eCoreSTM8) ? 0x2f : 0x00);
AddRel("JRT" , 0x20);
AddRel("JRUGE", 0x24);
AddRel("JRUGT", 0x22);
AddRel("JRULE", 0x23);
AddRel("JRULT", 0x25);
AddRel("JRV" , (pCurrCPUProps->Core == eCoreSTM8) ? 0x29 : 0x00);
init_moto8_pseudo(InstTable, e_moto_8_be);
}
/*!------------------------------------------------------------------------
* \fn DeinitFields(void)
* \brief tear down instruction hash table
* ------------------------------------------------------------------------ */
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
}
/*!------------------------------------------------------------------------
* \fn MakeCode_ST7(void)
* \brief entry point to decode machine instructions
* ------------------------------------------------------------------------ */
static Boolean DecodeAttrPart_ST7(void)
{
if (strlen(AttrPart.
str.
p_str) > 1)
{
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return False;
}
return DecodeMoto16AttrSize(*AttrPart.str.p_str, &AttrPartOpSize[0], False);
}
static void MakeCode_ST7(void)
{
CodeLen = 0;
DontPrint = False;
OpSize = (AttrPartOpSize[0] != eSymbolSizeUnknown) ? AttrPartOpSize[0] : eSymbolSize8Bit;
PrefixCnt = 0;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodeMoto16Pseudo(OpSize,True)) return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*!------------------------------------------------------------------------
* \fn IsDef_ST7(void)
* \brief does instruction consume label field?
* \return true if to be consumed
* ------------------------------------------------------------------------ */
static Boolean IsDef_ST7(void)
{
return Memo("BIT");
}
/*!------------------------------------------------------------------------
* \fn SwitchTo_ST7(void)
* \brief switch to target
* ------------------------------------------------------------------------ */
static void SwitchTo_ST7(void *pUser)
{
pCurrCPUProps = (const tCPUProps*)pUser;
TurnWords = False;
SetIntConstMode(eIntConstModeMoto);
PCSymbol = "PC"; HeaderID = 0x33; NOPCode = 0x9d;
DivideChars = ","; HasAttrs = True; AttrChars = ".";
ValidSegs = 1 << SegCode;
Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
SegLimits[SegCode] = IntTypeDefs[pCurrCPUProps->AddrIntType].Max;
DecodeAttrPart = DecodeAttrPart_ST7;
MakeCode = MakeCode_ST7;
IsDef = IsDef_ST7;
SwitchFrom = DeinitFields;
DissectBit = DissectBit_ST7;
InitFields();
AddMoto16PseudoONOFF(False);
}
/*!------------------------------------------------------------------------
* \fn codest7_init(void)
* \brief register ST7/STM8 target
* ------------------------------------------------------------------------ */
static const tCPUProps CPUProps[] =
{
{ "ST7" , Int16, eCoreST7 },
{ "ST7232AK1" , Int16, eCoreST7 },
{ "ST7232AK2" , Int16, eCoreST7 },
{ "ST7232AJ1" , Int16, eCoreST7 },
{ "ST7232AJ2" , Int16, eCoreST7 },
{ "ST72251G1" , Int16, eCoreST7 },
{ "ST72251G2" , Int16, eCoreST7 },
{ "ST72311J2" , Int16, eCoreST7 },
{ "ST72311J4" , Int16, eCoreST7 },
{ "ST72321BR6" , Int16, eCoreST7 },
{ "ST72321BR7" , Int16, eCoreST7 },
{ "ST72321BR9" , Int16, eCoreST7 },
{ "ST72324J6" , Int16, eCoreST7 },
{ "ST72324K6" , Int16, eCoreST7 },
{ "ST72324J4" , Int16, eCoreST7 },
{ "ST72324K4" , Int16, eCoreST7 },
{ "ST72324J2" , Int16, eCoreST7 },
{ "ST72324K2" , Int16, eCoreST7 },
{ "ST72325S4" , Int16, eCoreST7 },
{ "ST72325S6" , Int16, eCoreST7 },
{ "ST72325J7" , Int16, eCoreST7 },
{ "ST72325R9" , Int16, eCoreST7 },
{ "ST72344K2" , Int16, eCoreST7 },
{ "ST72344K4" , Int16, eCoreST7 },
{ "ST72345C4" , Int16, eCoreST7 },
{ "ST72521BR6" , Int16, eCoreST7 },
{ "ST72521BM9" , Int16, eCoreST7 },
{ "ST72361AR4" , Int16, eCoreST7 },
{ "ST72361AR6" , Int16, eCoreST7 },
{ "ST72361AR7" , Int16, eCoreST7 },
{ "ST72361AR9" , Int16, eCoreST7 },
{ "ST7FOXK1" , Int16, eCoreST7 },
{ "ST7FOXK2" , Int16, eCoreST7 },
{ "ST7LITES2Y0" , Int16, eCoreST7 },
{ "ST7LITES5Y0" , Int16, eCoreST7 },
{ "ST7LITE02Y0" , Int16, eCoreST7 },
{ "ST7LITE05Y0" , Int16, eCoreST7 },
{ "ST7LITE09Y0" , Int16, eCoreST7 },
{ "ST7LITE10F1" , Int16, eCoreST7 },
{ "ST7LITE15F1" , Int16, eCoreST7 },
{ "ST7LITE19F1" , Int16, eCoreST7 },
{ "ST7LITE10BF0", Int16, eCoreST7 },
{ "ST7LITE15BF0", Int16, eCoreST7 },
{ "ST7LITE15BF1", Int16, eCoreST7 },
{ "ST7LITE19BF0", Int16, eCoreST7 },
{ "ST7LITE19BF1", Int16, eCoreST7 },
{ "ST7LITE20F2" , Int16, eCoreST7 },
{ "ST7LITE25F2" , Int16, eCoreST7 },
{ "ST7LITE29F2" , Int16, eCoreST7 },
{ "ST7LITE30F2" , Int16, eCoreST7 },
{ "ST7LITE35F2" , Int16, eCoreST7 },
{ "ST7LITE39F2" , Int16, eCoreST7 },
{ "ST7LITE49K2" , Int16, eCoreST7 },
{ "ST7MC1K2" , Int16, eCoreST7 },
{ "ST7MC1K4" , Int16, eCoreST7 },
{ "ST7MC2N6" , Int16, eCoreST7 },
{ "ST7MC2S4" , Int16, eCoreST7 },
{ "ST7MC2S6" , Int16, eCoreST7 },
{ "ST7MC2S7" , Int16, eCoreST7 },
{ "ST7MC2S9" , Int16, eCoreST7 },
{ "ST7MC2R6" , Int16, eCoreST7 },
{ "ST7MC2R7" , Int16, eCoreST7 },
{ "ST7MC2R9" , Int16, eCoreST7 },
{ "ST7MC2M9" , Int16, eCoreST7 },
{ "STM8" , Int24, eCoreSTM8 },
{ "STM8S001J3" , Int16, eCoreSTM8 },
{ "STM8S003F3" , Int16, eCoreSTM8 },
{ "STM8S003K3" , Int16, eCoreSTM8 },
{ "STM8S005C6" , Int16, eCoreSTM8 },
{ "STM8S005K6" , Int16, eCoreSTM8 },
{ "STM8S007C8" , Int24, eCoreSTM8 },
{ "STM8S103F2" , Int16, eCoreSTM8 },
{ "STM8S103F3" , Int16, eCoreSTM8 },
{ "STM8S103K3" , Int16, eCoreSTM8 },
{ "STM8S105C4" , Int16, eCoreSTM8 },
{ "STM8S105C6" , Int16, eCoreSTM8 },
{ "STM8S105K4" , Int16, eCoreSTM8 },
{ "STM8S105K6" , Int16, eCoreSTM8 },
{ "STM8S105S4" , Int16, eCoreSTM8 },
{ "STM8S105S6" , Int16, eCoreSTM8 },
{ "STM8S207MB" , Int24, eCoreSTM8 },
{ "STM8S207M8" , Int24, eCoreSTM8 },
{ "STM8S207RB" , Int24, eCoreSTM8 },
{ "STM8S207R8" , Int24, eCoreSTM8 },
{ "STM8S207R6" , Int16, eCoreSTM8 },
{ "STM8S207CB" , Int24, eCoreSTM8 },
{ "STM8S207C8" , Int24, eCoreSTM8 },
{ "STM8S207C6" , Int16, eCoreSTM8 },
{ "STM8S207SB" , Int24, eCoreSTM8 },
{ "STM8S207S8" , Int24, eCoreSTM8 },
{ "STM8S207S6" , Int16, eCoreSTM8 },
{ "STM8S207K8" , Int24, eCoreSTM8 },
{ "STM8S207K6" , Int16, eCoreSTM8 },
{ "STM8S208MB" , Int24, eCoreSTM8 },
{ "STM8S208RB" , Int24, eCoreSTM8 },
{ "STM8S208R8" , Int24, eCoreSTM8 },
{ "STM8S208R6" , Int24, eCoreSTM8 },
{ "STM8S208CB" , Int24, eCoreSTM8 },
{ "STM8S208C8" , Int24, eCoreSTM8 },
{ "STM8S208C6" , Int16, eCoreSTM8 },
{ "STM8S208SB" , Int24, eCoreSTM8 },
{ "STM8S208S8" , Int24, eCoreSTM8 },
{ "STM8S208S6" , Int16, eCoreSTM8 },
{ "STM8S903K3" , Int16, eCoreSTM8 },
{ "STM8S903F3" , Int16, eCoreSTM8 },
{ "STM8L050J3" , Int16, eCoreSTM8 },
{ "STM8L051F3" , Int16, eCoreSTM8 },
{ "STM8L052C6" , Int16, eCoreSTM8 },
{ "STM8L052R8" , Int24, eCoreSTM8 },
{ "STM8L001J3" , Int16, eCoreSTM8 },
{ "STM8L101F1" , Int16, eCoreSTM8 },
{ "STM8L101F2" , Int16, eCoreSTM8 },
{ "STM8L101G2" , Int16, eCoreSTM8 },
{ "STM8L101F3" , Int16, eCoreSTM8 },
{ "STM8L101G3" , Int16, eCoreSTM8 },
{ "STM8L101K3" , Int16, eCoreSTM8 },
{ "STM8L151C2" , Int16, eCoreSTM8 },
{ "STM8L151K2" , Int16, eCoreSTM8 },
{ "STM8L151G2" , Int16, eCoreSTM8 },
{ "STM8L151F2" , Int16, eCoreSTM8 },
{ "STM8L151C3" , Int16, eCoreSTM8 },
{ "STM8L151K3" , Int16, eCoreSTM8 },
{ "STM8L151G3" , Int16, eCoreSTM8 },
{ "STM8L151F3" , Int16, eCoreSTM8 },
{ "STM8L151C4" , Int16, eCoreSTM8 },
{ "STM8L151C6" , Int16, eCoreSTM8 },
{ "STM8L151K4" , Int16, eCoreSTM8 },
{ "STM8L151K6" , Int16, eCoreSTM8 },
{ "STM8L151G4" , Int16, eCoreSTM8 },
{ "STM8L151G6" , Int16, eCoreSTM8 },
{ "STM8L152C4" , Int16, eCoreSTM8 },
{ "STM8L152C6" , Int16, eCoreSTM8 },
{ "STM8L152K4" , Int16, eCoreSTM8 },
{ "STM8L152K6" , Int16, eCoreSTM8 },
{ "STM8L151R6" , Int16, eCoreSTM8 },
{ "STM8L151C8" , Int24, eCoreSTM8 },
{ "STM8L151M8" , Int16, eCoreSTM8 },
{ "STM8L151R8" , Int24, eCoreSTM8 },
{ "STM8L152R6" , Int16, eCoreSTM8 },
{ "STM8L152C8" , Int24, eCoreSTM8 },
{ "STM8L152K8" , Int24, eCoreSTM8 },
{ "STM8L152M8" , Int24, eCoreSTM8 },
{ "STM8L152R8" , Int24, eCoreSTM8 },
{ "STM8L162M8" , Int24, eCoreSTM8 },
{ "STM8L162R8" , Int24, eCoreSTM8 },
{ "STM8AF6366" , Int16, eCoreSTM8 },
{ "STM8AF6388" , Int24, eCoreSTM8 },
{ "STM8AF6213" , Int16, eCoreSTM8 },
{ "STM8AF6223" , Int16, eCoreSTM8 },
{ "STM8AF6226" , Int16, eCoreSTM8 },
{ "STM8AF6246" , Int16, eCoreSTM8 },
{ "STM8AF6248" , Int16, eCoreSTM8 },
{ "STM8AF6266" , Int16, eCoreSTM8 },
{ "STM8AF6268" , Int16, eCoreSTM8 },
{ "STM8AF6269" , Int16, eCoreSTM8 },
{ "STM8AF6286" , Int24, eCoreSTM8 },
{ "STM8AF6288" , Int24, eCoreSTM8 },
{ "STM8AF6289" , Int24, eCoreSTM8 },
{ "STM8AF628A" , Int24, eCoreSTM8 },
{ "STM8AF62A6" , Int24, eCoreSTM8 },
{ "STM8AF62A8" , Int24, eCoreSTM8 },
{ "STM8AF62A9" , Int24, eCoreSTM8 },
{ "STM8AF62AA" , Int24, eCoreSTM8 },
{ "STM8AF5268" , Int16, eCoreSTM8 },
{ "STM8AF5269" , Int16, eCoreSTM8 },
{ "STM8AF5286" , Int24, eCoreSTM8 },
{ "STM8AF5288" , Int24, eCoreSTM8 },
{ "STM8AF5289" , Int24, eCoreSTM8 },
{ "STM8AF528A" , Int24, eCoreSTM8 },
{ "STM8AF52A6" , Int24, eCoreSTM8 },
{ "STM8AF52A8" , Int24, eCoreSTM8 },
{ "STM8AF52A9" , Int24, eCoreSTM8 },
{ "STM8AF52AA" , Int24, eCoreSTM8 },
{ "STM8AL3136" , Int16, eCoreSTM8 },
{ "STM8AL3138" , Int16, eCoreSTM8 },
{ "STM8AL3146" , Int16, eCoreSTM8 },
{ "STM8AL3148" , Int16, eCoreSTM8 },
{ "STM8AL3166" , Int16, eCoreSTM8 },
{ "STM8AL3168" , Int16, eCoreSTM8 },
{ "STM8AL3L46" , Int16, eCoreSTM8 },
{ "STM8AL3L48" , Int16, eCoreSTM8 },
{ "STM8AL3L66" , Int16, eCoreSTM8 },
{ "STM8AL3L68" , Int16, eCoreSTM8 },
{ "STM8AL3188" , Int24, eCoreSTM8 },
{ "STM8AL3189" , Int24, eCoreSTM8 },
{ "STM8AL318A" , Int24, eCoreSTM8 },
{ "STM8AL3L88" , Int24, eCoreSTM8 },
{ "STM8AL3L89" , Int24, eCoreSTM8 },
{ "STM8AL3L8A" , Int24, eCoreSTM8 },
{ "STM8TL52F4" , Int16, eCoreSTM8 },
{ "STM8TL52G4" , Int16, eCoreSTM8 },
{ "STM8TL53C4" , Int16, eCoreSTM8 },
{ "STM8TL53F4" , Int16, eCoreSTM8 },
{ "STM8TL53G4" , Int16, eCoreSTM8 },
{ NULL , UInt1, eCoreST7 },
};
void codest7_init(void)
{
const tCPUProps *pProp;
for (pProp = CPUProps; pProp->pName; pProp++)
(void)AddCPUUser(pProp->pName, SwitchTo_ST7, (void*)pProp, NULL);
}