/* codexa.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* AS-Codegenerator Philips XA */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "nls.h"
#include "strutil.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmitree.h"
#include "asmcode.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "motpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "codexa.h"
/*-------------------------------------------------------------------------*/
/* Definitionen */
#define ModNone (-1)
#define ModReg 0
#define MModReg (1 << ModReg)
#define ModMem 1
#define MModMem (1 << ModMem)
#define ModImm 2
#define MModImm (1 << ModImm)
#define ModAbs 3
#define MModAbs (1 << ModAbs)
#define REG_SP 7
#define RETICode 0xd690
#define eSymbolSize5Bit ((tSymbolSize)-4)
#define eSymbolSizeSigned4Bit ((tSymbolSize)-3)
#define eSymbolSize4Bit ((tSymbolSize)-2)
typedef struct
{
Byte SizeMask;
Byte Code;
} RegOrder;
typedef struct
{
const char *Name;
Byte SizeMask;
Byte Code;
Byte Inversion;
} InvOrder;
static CPUVar CPUXAG1,CPUXAG2,CPUXAG3;
static InvOrder *JBitOrders;
static RegOrder *RegOrders;
static InvOrder *RelOrders;
static LongInt Reg_DS;
static ShortInt AdrMode;
static Byte AdrPart,MemPart;
static Byte AdrVals[4];
static tSymbolSize OpSize;
static Boolean DoBranchExt; /* automatically extend branches */
#define ASSUMEXACount 1
static ASSUMERec ASSUMEXAs[ASSUMEXACount] =
{
{"DS", &Reg_DS, 0, 0xff, 0x100, NULL}
};
/*-------------------------------------------------------------------------*/
/* Hilfsroutinen */
static void SetOpSize(tSymbolSize NSize)
{
if (OpSize == eSymbolSizeUnknown) OpSize = NSize;
else if (OpSize != NSize)
{
AdrMode = ModNone; AdrCnt = 0; WrError(ErrNum_ConfOpSizes);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, tSymbolSize *pSize, Byte *pResult)
* \brief check whether argument is a CPU register
* \param pArg source argument
* \param pSize register size if yes
* \param pResult register number if yes
* \return Reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeRegCore(const char *pArg, tSymbolSize *pSize, Byte *pResult)
{
int len;
if (!as_strcasecmp(pArg, "SP"))
{
*pResult = REG_SP | REGSYM_FLAG_ALIAS;
*pSize = eSymbolSize16Bit;
return eIsReg;
}
if ((len >= 2) && (as_toupper(*pArg) == 'R') && (pArg[1] >= '0') && (pArg[1] <= '7'))
{
*pResult = pArg[1] - '0';
if (len == 2)
{
if (OpSize == eSymbolSize32Bit)
{
*pSize = eSymbolSize32Bit;
if (*pResult & 1)
{
WrError(ErrNum_InvRegPair);
(*pResult)--;
return eRegAbort;
}
else
return eIsReg;
}
else
{
*pSize = eSymbolSize16Bit;
return eIsReg;
}
}
else if ((len == 3) && (as_toupper(pArg[2]) == 'L'))
{
*pResult <<= 1;
*pSize = eSymbolSize8Bit;
return eIsReg;
}
else if ((len == 3) && (as_toupper(pArg[2]) == 'H'))
{
*pResult = (*pResult << 1) + 1;
*pSize = eSymbolSize8Bit;
return eIsReg;
}
else
return eIsNoReg;
}
return eIsNoReg;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_XA(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - XA variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_XA(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
{
switch (InpSize)
{
case eSymbolSize8Bit:
as_snprintf(pDest, DestSize, "R%u%c", (unsigned)(Value >> 1), "LH"[Value & 1]);
break;
case eSymbolSize16Bit:
as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
break;
case eSymbolSize32Bit:
as_snprintf(pDest, DestSize, "R%u.D", (unsigned)Value);
break;
default:
as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, tSymbolSize *pSize, Byte *pResult, Boolean MustBeReg)
* \brief check whether argument is a CPU register or register alias
* \param pArg source argument
* \param pSize register size if yes
* \param pResult register number if yes
* \param MustBeReg expecting register?
* \return Reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg(const tStrComp *pArg, tSymbolSize *pSize, Byte *pResult, Boolean MustBeReg)
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
RegEvalResult = DecodeRegCore(pArg->str.p_str, pSize, pResult);
if (RegEvalResult != eIsNoReg)
{
*pResult &= ~REGSYM_FLAG_ALIAS;
return RegEvalResult;
}
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
if (RegEvalResult == eIsReg)
{
*pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
*pSize = EvalResult.DataSize;
}
return RegEvalResult;
}
static Boolean ChkAdr(Word Mask, const tStrComp *pComp)
{
if ((AdrMode != ModNone) && (!(Mask & (1 << AdrMode))))
{
WrStrErrorPos(ErrNum_InvAddrMode, pComp);
AdrMode = ModNone;
AdrCnt = 0;
return False;
}
return True;
}
static Boolean DecodeAdrIndirect(tStrComp *pArg, Word Mask)
{
unsigned ArgLen;
Byte Reg;
tSymbolSize NSize;
ArgLen
= strlen(pArg
->str.
p_str);
if (pArg->str.p_str[ArgLen - 1] == '+')
{
StrCompShorten(pArg, 1); ArgLen--;
if (!DecodeReg(pArg, &NSize, &AdrPart, True));
else if (NSize != eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvAddrMode, pArg);
else
{
AdrMode = ModMem; MemPart = 3;
}
}
else
{
char *pSplit;
Boolean FirstFlag = False, NegFlag = False, NextNegFlag, ErrFlag = False;
tStrComp ThisComp = *pArg, RemComp;
LongInt DispAcc = 0;
AdrPart = 0xff;
do
{
KillPrefBlanksStrComp(&ThisComp);
pSplit = indir_split_pos(ThisComp.str.p_str);
NextNegFlag = (pSplit && (*pSplit == '-'));
if (pSplit)
StrCompSplitRef(&ThisComp, &RemComp, &ThisComp, pSplit);
KillPostBlanksStrComp(&ThisComp);
switch (DecodeReg(&ThisComp, &NSize, &Reg, False))
{
case eIsReg:
if ((NSize != eSymbolSize16Bit) || (AdrPart != 0xff) || NegFlag)
{
WrStrErrorPos(ErrNum_InvAddrMode, &ThisComp); ErrFlag = True;
}
else
AdrPart = Reg;
break;
case eRegAbort:
return False;
default:
{
LongInt DispPart;
tSymbolFlags Flags;
DispPart = EvalStrIntExpressionWithFlags(&ThisComp, Int32, &ErrFlag, &Flags);
ErrFlag = !ErrFlag;
if (!ErrFlag)
{
FirstFlag = FirstFlag || mFirstPassUnknown(Flags);
DispAcc += NegFlag ? -DispPart : DispPart;
}
}
}
NegFlag = NextNegFlag;
if (pSplit)
ThisComp = RemComp;
}
while (pSplit && !ErrFlag);
if (FirstFlag) DispAcc &= 0x7fff;
if (AdrPart == 0xff) WrStrErrorPos(ErrNum_InvAddrMode, pArg);
else if (DispAcc == 0)
{
AdrMode = ModMem; MemPart = 2;
}
else if ((DispAcc >= -128) && (DispAcc < 127))
{
AdrMode = ModMem; MemPart = 4;
AdrVals[0] = DispAcc & 0xff; AdrCnt = 1;
}
else if (ChkRange(DispAcc, -0x8000l, 0x7fffl))
{
AdrMode = ModMem; MemPart = 5;
AdrVals[0] = (DispAcc >> 8) & 0xff;
AdrVals[1] = DispAcc & 0xff;
AdrCnt = 2;
}
}
return ChkAdr(Mask, pArg);
}
static Boolean DecodeAdr(tStrComp *pArg, Word Mask)
{
tSymbolSize NSize;
LongInt AdrLong;
tEvalResult EvalResult;
Word AdrInt;
int ArgLen;
AdrMode = ModNone; AdrCnt = 0;
KillPrefBlanksStrComp(pArg);
KillPostBlanksStrComp(pArg);
switch (DecodeReg(pArg, &NSize, &AdrPart, False))
{
case eIsReg:
if (Mask & MModReg)
{
AdrMode = ModReg;
SetOpSize(NSize);
}
else
{
AdrMode = ModMem;
MemPart = 1;
SetOpSize(NSize);
}
return ChkAdr(Mask, pArg);
case eRegAbort:
return False;
default:
break;
}
if (*pArg->str.p_str == '#')
{
tStrComp ImmComp;
Boolean OK;
StrCompRefRight(&ImmComp, pArg, 1);
switch ((int)OpSize)
{
case eSymbolSize5Bit:
AdrVals[0] = EvalStrIntExpression(&ImmComp, UInt5, &OK);
if (OK)
{
AdrCnt = 1; AdrMode = ModImm;
}
break;
case eSymbolSizeSigned4Bit:
AdrVals[0] = EvalStrIntExpression(&ImmComp, SInt4, &OK);
if (OK)
{
AdrCnt = 1; AdrMode = ModImm;
}
break;
case eSymbolSize4Bit:
AdrVals[0] = EvalStrIntExpression(&ImmComp, UInt4, &OK);
if (OK)
{
AdrCnt = 1; AdrMode = ModImm;
}
break;
case eSymbolSizeUnknown:
WrError(ErrNum_UndefOpSizes);
break;
case eSymbolSize8Bit:
AdrVals[0] = EvalStrIntExpression(&ImmComp, Int8, &OK);
if (OK)
{
AdrCnt = 1; AdrMode = ModImm;
}
break;
case eSymbolSize16Bit:
AdrInt = EvalStrIntExpression(&ImmComp, Int16, &OK);
if (OK)
{
AdrVals[0] = Hi(AdrInt);
AdrVals[1] = Lo(AdrInt);
AdrCnt = 2;
AdrMode = ModImm;
}
break;
case eSymbolSize32Bit:
AdrLong = EvalStrIntExpression(&ImmComp, Int32, &OK);
if (OK)
{
AdrVals[0] = (AdrLong >> 24) & 0xff;
AdrVals[1] = (AdrLong >> 16) & 0xff;
AdrVals[2] = (AdrLong >> 8) & 0xff;
AdrVals[3] = AdrLong & 0xff;
AdrCnt = 4;
AdrMode = ModImm;
}
break;
default:
break;
}
return ChkAdr(Mask, pArg);
}
ArgLen
= strlen(pArg
->str.
p_str);
if ((*pArg->str.p_str == '[') && (pArg->str.p_str[ArgLen - 1] == ']'))
{
tStrComp IndirComp;
StrCompShorten(pArg, 1);
StrCompRefRight(&IndirComp, pArg, 1);
KillPrefBlanksStrComp(&IndirComp);
KillPostBlanksStrComp(&IndirComp);
return DecodeAdrIndirect(&IndirComp, Mask);
}
AdrLong = EvalStrIntExpressionWithResult(pArg, UInt24, &EvalResult);
if (EvalResult.OK)
{
if (mFirstPassUnknown(EvalResult.Flags))
{
if (!(Mask & MModAbs)) AdrLong &= 0x3ff;
}
if ((AdrLong & 0xffff) > 0x7ff) WrError(ErrNum_AdrOverflow);
else if ((AdrLong & 0xffff) <= 0x3ff)
{
if ((AdrLong >> 16) != Reg_DS) WrError(ErrNum_InAccPage);
ChkSpace(SegData, EvalResult.AddrSpaceMask);
AdrMode = ModMem; MemPart = 6;
AdrPart = Hi(AdrLong);
AdrVals[0] = Lo(AdrLong);
AdrCnt = 1;
}
else if (AdrLong > 0x7ff) WrError(ErrNum_AdrOverflow);
else
{
ChkSpace(SegIO, EvalResult.AddrSpaceMask);
AdrMode = ModMem; MemPart = 6;
AdrPart = Hi(AdrLong);
AdrVals[0] = Lo(AdrLong);
AdrCnt = 1;
}
}
return ChkAdr(Mask, pArg);
}
static Boolean DecodeBitAddr(tStrComp *pArg, LongInt *Erg)
{
char *p;
Byte BPos, Reg;
ShortInt Res;
tSymbolSize Size;
LongInt AdrLong;
tEvalResult EvalResult;
p = RQuotPos(pArg->str.p_str, '.'); Res = 0;
if (!p)
{
AdrLong = EvalStrIntExpressionWithResult(pArg, UInt24, &EvalResult);
if (mFirstPassUnknown(EvalResult.Flags)) AdrLong &= 0x3ff;
*Erg = AdrLong; Res = 1;
}
else
{
int l = p - pArg->str.p_str;
BPos = EvalStrIntExpressionOffsWithResult(pArg, l + 1, UInt4, &EvalResult);
if (mFirstPassUnknown(EvalResult.Flags)) BPos &= 7;
*p = '\0'; pArg->Pos.Len -= l + 1;
if (EvalResult.OK)
{
switch (DecodeReg(pArg, &Size, &Reg, False))
{
case eRegAbort:
return False;
case eIsReg:
if ((Size == eSymbolSize8Bit) && (BPos > 7)) WrError(ErrNum_OverRange);
else
{
if (Size == eSymbolSize8Bit) *Erg = (Reg << 3) + BPos;
else *Erg = (Reg << 4) + BPos;
Res = 1;
}
break;
default:
if (BPos > 7) WrError(ErrNum_OverRange);
else
{
AdrLong = EvalStrIntExpressionWithResult(pArg, UInt24, &EvalResult);
if (EvalResult.AddrSpaceMask & (1 << SegIO))
{
ChkSpace(SegIO, EvalResult.AddrSpaceMask);
if (mFirstPassUnknown(EvalResult.Flags)) AdrLong = (AdrLong & 0x3f) | 0x400;
if (ChkRange(AdrLong, 0x400, 0x43f))
{
*Erg = 0x200 + ((AdrLong & 0x3f) << 3) + BPos;
Res = 1;
}
else
Res = -1;
}
else
{
ChkSpace(SegData, EvalResult.AddrSpaceMask);
if (mFirstPassUnknown(EvalResult.Flags)) AdrLong = (AdrLong & 0x00ff003f) | 0x20;
if (ChkRange(AdrLong & 0xff, 0x20, 0x3f))
{
*Erg = 0x100 + ((AdrLong & 0x1f) << 3) + BPos + (AdrLong & 0xff0000);
Res = 1;
}
else
Res = -1;
}
}
break;
}
}
*p = '.';
}
if (Res == 0) WrError(ErrNum_InvAddrMode);
return (Res == 1);
}
static void ChkBitPage(LongInt Adr)
{
if ((Adr >> 16) != Reg_DS) WrError(ErrNum_InAccPage);
}
static LongWord MkEven24(LongWord Inp)
{
return Inp & 0xfffffeul;
}
static LongWord GetBranchDest(const tStrComp *pComp, tEvalResult *pEvalResult)
{
LongWord Result;
Result = EvalStrIntExpressionWithResult(pComp, UInt24, pEvalResult);
if (pEvalResult->OK)
{
if (mFirstPassUnknown(pEvalResult->Flags)) Result = MkEven24(Result);
ChkSpace(SegCode, pEvalResult->AddrSpaceMask);
if (Result & 1)
{
WrStrErrorPos(ErrNum_NotAligned, pComp);
pEvalResult->OK = False;
}
}
return Result;
}
static Boolean ChkShortEvenDist(LongInt *pDist, tSymbolFlags Flags)
{
if (!mSymbolQuestionable(Flags) && ((*pDist > 254) || (*pDist < -256)))
return False;
else
{
*pDist >>= 1;
return True;
}
}
static Boolean ChkLongEvenDist(LongInt *pDist, const tStrComp *pComp, tSymbolFlags Flags)
{
if (!mSymbolQuestionable(Flags) && ((*pDist > 65534) || (*pDist < -65536)))
{
WrStrErrorPos(ErrNum_JmpDistTooBig, pComp);
return False;
}
else
{
*pDist >>= 1;
return True;
}
}
/*-------------------------------------------------------------------------*/
/* Befehlsdekoder */
static void DecodePORT(Word Index)
{
UNUSED(Index);
CodeEquate(SegIO, 0x400, 0x7ff);
}
static void DecodeBIT(Word Index)
{
LongInt BAdr;
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (DecodeBitAddr(&ArgStr[1], &BAdr))
{
EnterIntSymbol(&LabPart, BAdr, SegNone, False);
switch ((BAdr & 0x3ff) >> 8)
{
case 0:
as_snprintf(ListLine, STRINGSIZE, "=R%d.%d",
(unsigned)((BAdr >> 4) & 15),
(unsigned) (BAdr & 15));
break;
case 1:
as_snprintf(ListLine, STRINGSIZE, "=%x:%x.%d",
(unsigned)((BAdr >> 16) & 255),
(unsigned)((BAdr & 0x1f8) >> 3), (unsigned)(BAdr & 7));
break;
default:
as_snprintf(ListLine, STRINGSIZE, "=S:%x.%d",
(unsigned)(((BAdr >> 3) & 0x3f) + 0x400),
(unsigned)(BAdr & 7));
break;
}
}
}
static void DecodeFixed(Word Code)
{
if (ChkArgCnt(0, 0))
{
if (Hi(Code) != 0) BAsmCode[CodeLen++] = Hi(Code);
BAsmCode[CodeLen++] = Lo(Code);
if ((Code == RETICode) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
}
}
static void DecodeStack(Word Code)
{
Byte HReg;
Boolean OK;
Word Mask;
int i;
if (ChkArgCnt(1, ArgCntMax))
{
HReg = 0xff; OK = True; Mask = 0;
for (i = 1; i <= ArgCnt; i++)
if (OK)
{
DecodeAdr(&ArgStr[i], MModMem);
if (AdrMode == ModNone) OK = False;
else switch (MemPart)
{
case 1:
if (HReg == 0)
{
WrError(ErrNum_InvAddrMode); OK = False;
}
else
{
HReg = 1; Mask |= (1 << AdrPart);
}
break;
case 6:
if (HReg != 0xff)
{
WrError(ErrNum_InvAddrMode); OK = False;
}
else
HReg = 0;
break;
default:
WrError(ErrNum_InvAddrMode); OK = False;
}
}
if (OK)
{
if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else if (HReg == 0)
{
BAsmCode[CodeLen++] = 0x87 + (OpSize << 3);
BAsmCode[CodeLen++] = Hi(Code) + AdrPart;
BAsmCode[CodeLen++] = AdrVals[0];
}
else if (Code < 0x2000) /* POP(U): obere Register zuerst */
{
if (Hi(Mask) != 0)
{
BAsmCode[CodeLen++] = Lo(Code) + (OpSize << 3) + 0x40;
BAsmCode[CodeLen++]=Hi(Mask);
}
if (Lo(Mask) != 0)
{
BAsmCode[CodeLen++] = Lo(Code) + (OpSize << 3);
BAsmCode[CodeLen++] = Lo(Mask);
}
if ((OpSize == eSymbolSize16Bit) && (Code == 0x1027) && (Mask & 0x80)) WrError(ErrNum_Unpredictable);
}
else /* PUSH(U): untere Register zuerst */
{
if (Lo(Mask) != 0)
{
BAsmCode[CodeLen++] = Lo(Code) + (OpSize << 3);
BAsmCode[CodeLen++] = Lo(Mask);
}
if (Hi(Mask) != 0)
{
BAsmCode[CodeLen++] = Lo(Code) + (OpSize << 3) + 0x40;
BAsmCode[CodeLen++] = Hi(Mask);
}
}
}
}
}
static void DecodeALU(Word Index)
{
Byte HReg, HCnt, HVals[3], HMem;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg | MModMem);
switch (AdrMode)
{
case ModReg:
if (OpSize >= eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModMem | MModImm);
switch (AdrMode)
{
case ModMem:
BAsmCode[CodeLen++] = (Index << 4) + (OpSize << 3) + MemPart;
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
if ((MemPart == 3) && ((HReg >> (1 - OpSize)) == AdrPart)) WrError(ErrNum_Unpredictable);
break;
case ModImm:
BAsmCode[CodeLen++] = 0x91 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + Index;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
}
}
break;
case ModMem:
HReg = AdrPart; HMem = MemPart; HCnt = AdrCnt;
memcpy(HVals
, AdrVals
, AdrCnt
);
DecodeAdr(&ArgStr[2], MModReg | MModImm);
switch (AdrMode)
{
case ModReg:
if (OpSize == eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else
{
BAsmCode[CodeLen++] = (Index << 4) + (OpSize << 3) + HMem;
BAsmCode[CodeLen++] = (AdrPart << 4) + 8 + HReg;
memcpy(BAsmCode
+ CodeLen
, HVals
, HCnt
);
CodeLen += HCnt;
if ((HMem == 3) && ((AdrPart >> (1 - OpSize)) == HReg)) WrError(ErrNum_Unpredictable);
}
break;
case ModImm:
if (OpSize == eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else
{
BAsmCode[CodeLen++] = 0x90 + HMem + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + Index;
memcpy(BAsmCode
+ CodeLen
, HVals
, HCnt
);
memcpy(BAsmCode
+ CodeLen
+ HCnt
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt + HCnt;
}
break;
}
break;
}
}
}
static void DecodeRegO(Word Index)
{
RegOrder *Op = RegOrders + Index;
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg);
switch (AdrMode)
{
case ModReg:
if ((Op->SizeMask & (1 << OpSize)) == 0) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0x90 + (OpSize << 3);
BAsmCode[CodeLen++] = (AdrPart << 4) + Op->Code;
}
break;
}
}
}
static void DecodeShift(Word Index)
{
Byte HReg, HMem;
if (!ChkArgCnt(2, 2));
else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else
{
DecodeAdr(&ArgStr[1], MModReg);
switch (AdrMode)
{
case ModReg:
HReg = AdrPart; HMem = OpSize;
if (*ArgStr[2].str.p_str == '#')
OpSize = (HMem == 2) ? eSymbolSize5Bit : eSymbolSize4Bit;
else
OpSize = eSymbolSize8Bit;
DecodeAdr(&ArgStr[2], MModReg | ((Index == 3) ? 0 : MModImm));
switch (AdrMode)
{
case ModReg:
BAsmCode[CodeLen++] = 0xc0 + ((HMem & 1) << 3) + Index;
if (HMem == 2) BAsmCode[CodeLen - 1] += 12;
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
if (Index == 3)
{
if (HMem == 2)
{
if ((AdrPart >> 2) == (HReg >> 1)) WrError(ErrNum_Unpredictable);
}
else if ((AdrPart >> HMem) == HReg) WrError(ErrNum_Unpredictable);
}
break;
case ModImm:
BAsmCode[CodeLen++] = 0xd0 + ((HMem & 1) << 3) + Index;
if (HMem == 2)
{
BAsmCode[CodeLen - 1] += 12;
BAsmCode[CodeLen++] = ((HReg & 14) << 4) + AdrVals[0];
}
else
BAsmCode[CodeLen++] = (HReg << 4) + AdrVals[0];
break;
}
break;
}
}
}
static void DecodeRotate(Word Code)
{
Byte HReg, HMem;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
switch (AdrMode)
{
case ModReg:
if (OpSize == eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart; HMem = OpSize; OpSize = eSymbolSize4Bit;
DecodeAdr(&ArgStr[2], MModImm);
switch (AdrMode)
{
case ModImm:
BAsmCode[CodeLen++] = Code + (HMem << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrVals[0];
break;
}
}
break;
}
}
}
static void DecodeRel(Word Index)
{
InvOrder *Op = RelOrders + Index;
LongWord Dest;
LongInt Dist;
tEvalResult EvalResult;
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
Dest = GetBranchDest(&ArgStr[1], &EvalResult);
if (EvalResult.OK)
{
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 2);
if (ChkShortEvenDist(&Dist, EvalResult.Flags))
{
BAsmCode[CodeLen++] = Op->Code;
BAsmCode[CodeLen++] = Dist & 0xff;
}
else if (!DoBranchExt) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
else if (Op->Inversion == 255) /* BR */
{
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 3);
if (ChkLongEvenDist(&Dist, &ArgStr[1], EvalResult.Flags))
{
Dist >>= 1;
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
}
}
else
{
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 5);
if (ChkLongEvenDist(&Dist, &ArgStr[1], EvalResult.Flags))
{
BAsmCode[CodeLen++] = RelOrders[Op->Inversion].Code;
BAsmCode[CodeLen++] = 2;
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
if (Odd(EProgCounter() + CodeLen)) BAsmCode[CodeLen++] = 0;
}
}
}
}
}
static void DecodeJBit(Word Index)
{
LongInt BitAdr, Dist, odd;
LongWord Dest;
tEvalResult EvalResult;
InvOrder *Op = JBitOrders + Index;
if (!ChkArgCnt(2, 2));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (DecodeBitAddr(&ArgStr[1], &BitAdr))
{
Dest = GetBranchDest(&ArgStr[2], &EvalResult);
if (EvalResult.OK)
{
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 4);
if (ChkShortEvenDist(&Dist, EvalResult.Flags))
{
BAsmCode[CodeLen++] = 0x97;
BAsmCode[CodeLen++] = Op->Code + Hi(BitAdr);
BAsmCode[CodeLen++] = Lo(BitAdr);
BAsmCode[CodeLen++] = Dist & 0xff;
}
else if (!DoBranchExt) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[2]);
else if (Op->Inversion == 255)
{
odd = EProgCounter() & 1;
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 9 + odd);
if (ChkLongEvenDist(&Dist, &ArgStr[2], EvalResult.Flags))
{
BAsmCode[CodeLen++] = 0x97;
BAsmCode[CodeLen++] = Op->Code + Hi(BitAdr);
BAsmCode[CodeLen++] = Lo(BitAdr);
BAsmCode[CodeLen++] = 1 + odd;
BAsmCode[CodeLen++] = 0xfe;
BAsmCode[CodeLen++] = 2 + odd;
if (odd) BAsmCode[CodeLen++] = 0;
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
BAsmCode[CodeLen++] = 0;
}
}
else
{
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 7);
if (ChkLongEvenDist(&Dist, &ArgStr[2], EvalResult.Flags))
{
BAsmCode[CodeLen++] = 0x97;
BAsmCode[CodeLen++] = JBitOrders[Op->Inversion].Code + Hi(BitAdr);
BAsmCode[CodeLen++] = Lo(BitAdr);
BAsmCode[CodeLen++] = 2;
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
if (Odd(EProgCounter() + CodeLen)) BAsmCode[CodeLen++] = 0;
}
}
}
}
}
static void DecodeMOV(Word Index)
{
LongInt AdrLong;
Byte HVals[3], HReg, HPart, HCnt;
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (!as_strcasecmp(ArgStr[1].str.p_str, "C"))
{
if (DecodeBitAddr(&ArgStr[2], &AdrLong))
{
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
ChkBitPage(AdrLong);
BAsmCode[CodeLen++] = 0x08;
BAsmCode[CodeLen++] = 0x20 + Hi(AdrLong);
BAsmCode[CodeLen++] = Lo(AdrLong);
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "C"))
{
if (DecodeBitAddr(&ArgStr[1], &AdrLong))
{
if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
ChkBitPage(AdrLong);
BAsmCode[CodeLen++] = 0x08;
BAsmCode[CodeLen++] = 0x30 + Hi(AdrLong);
BAsmCode[CodeLen++] = Lo(AdrLong);
}
}
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "USP"))
{
SetOpSize(eSymbolSize16Bit);
DecodeAdr(&ArgStr[2], MModReg);
if (AdrMode == ModReg)
{
BAsmCode[CodeLen++] = 0x98;
BAsmCode[CodeLen++] = (AdrPart << 4) + 0x0f;
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "USP"))
{
SetOpSize(eSymbolSize16Bit);
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
BAsmCode[CodeLen++] = 0x90;
BAsmCode[CodeLen++] = (AdrPart << 4)+0x0f;
}
}
else
{
DecodeAdr(&ArgStr[1], MModReg | MModMem);
switch (AdrMode)
{
case ModReg:
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModMem | MModImm);
switch (AdrMode)
{
case ModMem:
BAsmCode[CodeLen++] = 0x80 + (OpSize << 3) + MemPart;
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
if ((MemPart == 3) && ((HReg >> (1 - OpSize)) == AdrPart)) WrError(ErrNum_Unpredictable);
break;
case ModImm:
BAsmCode[CodeLen++] = 0x91 + (OpSize << 3);
BAsmCode[CodeLen++] = 0x08 + (HReg << 4);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
}
}
break;
case ModMem:
memcpy(HVals
, AdrVals
, AdrCnt
); HCnt
= AdrCnt
; HPart
= MemPart
; HReg
= AdrPart
;
DecodeAdr(&ArgStr[2], MModReg | MModMem | MModImm);
switch (AdrMode)
{
case ModReg:
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0x80 + (OpSize << 3) + HPart;
BAsmCode[CodeLen++] = (AdrPart << 4) + 0x08 + HReg;
memcpy(BAsmCode
+ CodeLen
, HVals
, HCnt
);
CodeLen += HCnt;
if ((HPart == 3) && ((AdrPart >> (1 - OpSize)) == HReg)) WrError(ErrNum_Unpredictable);
}
break;
case ModMem:
if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else if ((OpSize != eSymbolSize8Bit) & (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else if ((HPart == 6) && (MemPart == 6))
{
BAsmCode[CodeLen++] = 0x97 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4)+AdrPart;
BAsmCode[CodeLen++] = HVals[0];
BAsmCode[CodeLen++] = AdrVals[0];
}
else if ((HPart == 6) && (MemPart == 2))
{
BAsmCode[CodeLen++] = 0xa0 + (OpSize << 3);
BAsmCode[CodeLen++] = 0x80 + (AdrPart << 4) + HReg;
BAsmCode[CodeLen++] = HVals[0];
}
else if ((HPart == 2) && (MemPart == 6))
{
BAsmCode[CodeLen++] = 0xa0 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
BAsmCode[CodeLen++] = AdrVals[0];
}
else if ((HPart == 3) && (MemPart == 3))
{
BAsmCode[CodeLen++] = 0x90 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
if (HReg == AdrPart) WrError(ErrNum_Unpredictable);
}
else
WrError(ErrNum_InvAddrMode);
break;
case ModImm:
if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0x90 + (OpSize << 3) + HPart;
BAsmCode[CodeLen++] = 0x08 + (HReg << 4);
memcpy(BAsmCode
+ CodeLen
, HVals
, HCnt
);
memcpy(BAsmCode
+ CodeLen
+ HCnt
, AdrVals
, AdrCnt
);
CodeLen += HCnt + AdrCnt;
}
break;
}
break;
}
}
}
static void DecodeMOVC(Word Index)
{
Byte HReg;
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else
{
if (!*AttrPart.str.p_str && !as_strcasecmp(ArgStr[1].str.p_str, "A")) OpSize = eSymbolSize8Bit;
if (!as_strcasecmp(ArgStr[2].str.p_str, "[A+DPTR]"))
{
if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrError(ErrNum_InvAddrMode);
else if (OpSize != eSymbolSize8Bit) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0x90;
BAsmCode[CodeLen++] = 0x4e;
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "[A+PC]"))
{
if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrError(ErrNum_InvAddrMode);
else if (OpSize != eSymbolSize8Bit) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0x90;
BAsmCode[CodeLen++] = 0x4c;
}
}
else
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode != ModNone)
{
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModMem);
if (AdrMode != ModNone)
{
if (MemPart != 3) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[CodeLen++] = 0x80 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
if ((MemPart == 3) && ((HReg >> (1 - OpSize)) == AdrPart)) WrError(ErrNum_Unpredictable);
}
}
}
}
}
}
}
static void DecodeMOVX(Word Index)
{
Byte HReg;
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else
{
DecodeAdr(&ArgStr[1], MModMem);
if (AdrMode == ModMem)
{
switch (MemPart)
{
case 1:
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart; DecodeAdr(&ArgStr[2], MModMem);
if (AdrMode == ModMem)
{
if (MemPart != 2) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[CodeLen++] = 0xa7 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
}
}
}
break;
case 2:
HReg = AdrPart; DecodeAdr(&ArgStr[2], MModReg);
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0xa7 + (OpSize << 3);
BAsmCode[CodeLen++] = 0x08 + (AdrPart << 4) + HReg;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
}
}
static void DecodeXCH(Word Index)
{
Byte HReg, HPart, HVals[3];
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModMem);
if (AdrMode == ModMem)
{
switch (MemPart)
{
case 1:
HReg = AdrPart; DecodeAdr(&ArgStr[2], MModMem);
if (AdrMode == ModMem)
{
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
else switch (MemPart)
{
case 1:
BAsmCode[CodeLen++] = 0x60 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
if (HReg == AdrPart) WrError(ErrNum_Unpredictable);
break;
case 2:
BAsmCode[CodeLen++] = 0x50 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
break;
case 6:
BAsmCode[CodeLen++] = 0xa0 + (OpSize << 3);
BAsmCode[CodeLen++] = 0x08 + (HReg << 4) + AdrPart;
BAsmCode[CodeLen++] = AdrVals[0];
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
break;
case 2:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg);
if (AdrMode == ModReg)
{
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0x50 + (OpSize << 3);
BAsmCode[CodeLen++] = (AdrPart << 4) + HReg;
}
}
break;
case 6:
HPart = AdrPart; HVals[0] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg);
if (AdrMode == ModReg)
{
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen++] = 0xa0 + (OpSize << 3);
BAsmCode[CodeLen++] = 0x08 + (AdrPart << 4) + HPart;
BAsmCode[CodeLen++] = HVals[0];
}
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
}
}
static void DecodeADDSMOVS(Word Index)
{
Byte HReg;
tSymbolSize HSize;
if (ChkArgCnt(2, 2))
{
HSize = OpSize;
OpSize = eSymbolSizeSigned4Bit;
DecodeAdr(&ArgStr[2], MModImm);
switch (AdrMode)
{
case ModImm:
HReg = AdrVals[0]; OpSize = HSize;
DecodeAdr(&ArgStr[1], MModMem);
switch (AdrMode)
{
case ModMem:
if (OpSize == eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
else if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else
{
BAsmCode[CodeLen++] = 0xa0 + (Index << 4) + (OpSize << 3) + MemPart;
BAsmCode[CodeLen++] = (AdrPart << 4) + (HReg & 0x0f);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
}
break;
}
break;
}
}
}
static void DecodeDIV(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart; OpSize--; DecodeAdr(&ArgStr[2], MModReg | MModImm);
switch (AdrMode)
{
case ModReg:
BAsmCode[CodeLen++] = 0xe7 + (OpSize << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
break;
case ModImm:
BAsmCode[CodeLen++] = 0xe8 + OpSize;
BAsmCode[CodeLen++] = (HReg << 4) + 0x0b - (OpSize << 1);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
}
}
}
}
}
static void DecodeDIVU(Word Index)
{
Byte HReg;
int z;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
if ((OpSize == eSymbolSize8Bit) && (AdrPart & 1)) WrError(ErrNum_InvReg);
else
{
HReg = AdrPart; z = OpSize; if (OpSize != eSymbolSize8Bit) OpSize--;
DecodeAdr(&ArgStr[2], MModReg | MModImm);
switch (AdrMode)
{
case ModReg:
BAsmCode[CodeLen++] = 0xe1 + (z << 2);
if (z == 2) BAsmCode[CodeLen - 1] += 4;
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
break;
case ModImm:
BAsmCode[CodeLen++] = 0xe8 + Ord(z == 2);
BAsmCode[CodeLen++] = (HReg << 4) + 0x01 + (Ord(z == 1) << 1);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
}
}
}
}
}
static void DecodeMUL(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else if (AdrPart & 1) WrError(ErrNum_InvReg);
else
{
HReg = AdrPart; DecodeAdr(&ArgStr[2], MModReg | MModImm);
switch (AdrMode)
{
case ModReg:
BAsmCode[CodeLen++] = 0xe6;
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
break;
case ModImm:
BAsmCode[CodeLen++] = 0xe9;
BAsmCode[CodeLen++] = (HReg << 4) + 0x08;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
}
}
}
}
}
static void DecodeMULU(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
if (AdrPart & 1) WrError(ErrNum_InvReg);
else
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg | MModImm);
switch (AdrMode)
{
case ModReg:
BAsmCode[CodeLen++] = 0xe0 + (OpSize << 2);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
break;
case ModImm:
BAsmCode[CodeLen++] = 0xe8 + OpSize;
BAsmCode[CodeLen++] = (HReg << 4);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
}
}
}
}
}
static void DecodeLEA(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart;
DecodeAdrIndirect(&ArgStr[2], MModMem);
if (AdrMode == ModMem)
switch (MemPart)
{
case 4:
case 5:
BAsmCode[CodeLen++] = 0x20 + (MemPart << 3);
BAsmCode[CodeLen++] = (HReg << 4) + AdrPart;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen += AdrCnt;
break;
default:
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
}
}
}
}
static void DecodeANLORL(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (as_strcasecmp(ArgStr[1].str.p_str, "C")) WrError(ErrNum_InvAddrMode);
else
{
Byte Invert = 0;
LongInt AdrLong;
Boolean Result;
if (*ArgStr[2].str.p_str == '/')
{
tStrComp Comp;
StrCompRefRight(&Comp, &ArgStr[2], 1);
Result = DecodeBitAddr(&Comp, &AdrLong);
Invert = 1;
}
else
Result = DecodeBitAddr(&ArgStr[2], &AdrLong);
if (Result)
{
ChkBitPage(AdrLong);
BAsmCode[CodeLen++] = 0x08;
BAsmCode[CodeLen++] = 0x40 | (Index << 5) | (Ord(Invert) << 4) | (Hi(AdrLong) & 3);
BAsmCode[CodeLen++] = Lo(AdrLong);
}
}
}
static void DecodeCLRSETB(Word Index)
{
LongInt AdrLong;
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (DecodeBitAddr(&ArgStr[1], &AdrLong))
{
ChkBitPage(AdrLong);
BAsmCode[CodeLen++] = 0x08;
BAsmCode[CodeLen++] = (Index << 4) + (Hi(AdrLong) & 3);
BAsmCode[CodeLen++] = Lo(AdrLong);
}
}
static void DecodeTRAP(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
OpSize = eSymbolSize4Bit;
DecodeAdr(&ArgStr[1], MModImm);
switch (AdrMode)
{
case ModImm:
BAsmCode[CodeLen++] = 0xd6;
BAsmCode[CodeLen++] = 0x30 + AdrVals[0];
break;
}
}
}
static void DecodeCALL(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (*ArgStr[1].str.p_str == '[')
{
DecodeAdr(&ArgStr[1], MModMem);
if (AdrMode != ModNone)
{
if (MemPart != 2) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[CodeLen++] = 0xc6;
BAsmCode[CodeLen++] = AdrPart;
}
}
}
else
{
tEvalResult EvalResult;
LongWord Dest = GetBranchDest(&ArgStr[1], &EvalResult);
if (EvalResult.OK)
{
LongInt Dist = Dest - MkEven24(EProgCounter() + CodeLen + 3);
if (ChkLongEvenDist(&Dist, &ArgStr[1], EvalResult.Flags))
{
BAsmCode[CodeLen++] = 0xc5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
}
}
}
}
static void DecodeJMP(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else if (!as_strcasecmp(ArgStr[1].str.p_str, "[A+DPTR]"))
{
BAsmCode[CodeLen++] = 0xd6;
BAsmCode[CodeLen++] = 0x46;
}
else if (!strncmp(ArgStr
[1].
str.
p_str, "[[", 2))
{
tStrComp Comp;
ArgStr
[1].
str.
p_str[strlen(ArgStr
[1].
str.
p_str) - 1] = '\0';
ArgStr[1].Pos.Len--;
StrCompRefRight(&Comp, &ArgStr[1], 1);
DecodeAdr(&Comp, MModMem);
if (AdrMode == ModMem)
switch (MemPart)
{
case 3:
BAsmCode[CodeLen++] = 0xd6;
BAsmCode[CodeLen++] = 0x60 + AdrPart;
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
else if (*ArgStr[1].str.p_str == '[')
{
DecodeAdr(&ArgStr[1], MModMem);
if (AdrMode == ModMem)
switch (MemPart)
{
case 2:
BAsmCode[CodeLen++] = 0xd6;
BAsmCode[CodeLen++] = 0x70 + AdrPart;
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
else
{
tEvalResult EvalResult;
LongWord Dest = GetBranchDest(&ArgStr[1], &EvalResult);
if (EvalResult.OK)
{
LongInt Dist = Dest - MkEven24(EProgCounter() + CodeLen + 3);
if (ChkLongEvenDist(&Dist, &ArgStr[1], EvalResult.Flags))
{
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
}
}
}
}
static void DecodeCJNE(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(3, 3))
{
tEvalResult EvalResult;
LongWord Dest = GetBranchDest(&ArgStr[3], &EvalResult);
if (EvalResult.OK)
{
EvalResult.OK = False; HReg = 0;
DecodeAdr(&ArgStr[1], MModMem);
if (AdrMode == ModMem)
{
switch (MemPart)
{
case 1:
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart; DecodeAdr(&ArgStr[2], MModMem | MModImm);
switch (AdrMode)
{
case ModMem:
if (MemPart != 6) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[CodeLen] = 0xe2 + (OpSize << 3);
BAsmCode[CodeLen + 1] = (HReg << 4) + AdrPart;
BAsmCode[CodeLen + 2] = AdrVals[0];
HReg=CodeLen + 3;
CodeLen += 4; EvalResult.OK = True;
}
break;
case ModImm:
BAsmCode[CodeLen] = 0xe3 + (OpSize << 3);
BAsmCode[CodeLen + 1] = HReg << 4;
HReg=CodeLen + 2;
memcpy(BAsmCode
+ CodeLen
+ 3, AdrVals
, AdrCnt
);
CodeLen += 3 + AdrCnt; EvalResult.OK = True;
break;
}
}
break;
case 2:
if ((OpSize != eSymbolSizeUnknown) && (OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrPart; DecodeAdr(&ArgStr[2], MModImm);
if (AdrMode == ModImm)
{
BAsmCode[CodeLen] = 0xe3 + (OpSize << 3);
BAsmCode[CodeLen + 1] = (HReg << 4)+8;
HReg = CodeLen + 2;
memcpy(BAsmCode
+ CodeLen
+ 3, AdrVals
, AdrCnt
);
CodeLen += 3 + AdrCnt; EvalResult.OK = True;
}
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
if (EvalResult.OK)
{
LongInt Dist = Dest - MkEven24(EProgCounter() + CodeLen);
EvalResult.OK = False;
if (ChkShortEvenDist(&Dist, EvalResult.Flags))
{
BAsmCode[HReg] = Dist & 0xff;
EvalResult.OK = True;
}
else if (!DoBranchExt) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[3]);
else
{
LongWord odd = (EProgCounter() + CodeLen) & 1;
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 5 + odd);
if (ChkLongEvenDist(&Dist, &ArgStr[3], EvalResult.Flags))
{
BAsmCode[HReg] = 1 + odd;
BAsmCode[CodeLen++] = 0xfe;
BAsmCode[CodeLen++] = 2 + odd;
if (odd) BAsmCode[CodeLen++] = 0;
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
BAsmCode[CodeLen++] = 0;
EvalResult.OK = True;
}
}
}
if (!EvalResult.OK)
CodeLen = 0;
}
}
}
static void DecodeDJNZ(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
tEvalResult EvalResult;
LongInt Dest = GetBranchDest(&ArgStr[2], &EvalResult);
if (EvalResult.OK)
{
HReg = 0;
DecodeAdr(&ArgStr[1], MModMem);
EvalResult.OK = False; DecodeAdr(&ArgStr[1], MModMem);
if (AdrMode == ModMem)
switch (MemPart)
{
case 1:
if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen] = 0x87 + (OpSize << 3);
BAsmCode[CodeLen + 1] = (AdrPart << 4) + 0x08;
HReg=CodeLen + 2;
CodeLen += 3; EvalResult.OK = True;
}
break;
case 6:
if (OpSize == eSymbolSizeUnknown) WrError(ErrNum_UndefOpSizes);
else if ((OpSize != eSymbolSize8Bit) && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
else
{
BAsmCode[CodeLen] = 0xe2 + (OpSize << 3);
BAsmCode[CodeLen+1] = 0x08 + AdrPart;
BAsmCode[CodeLen+2] = AdrVals[0];
HReg=CodeLen + 3;
CodeLen += 4; EvalResult.OK = True;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
if (EvalResult.OK)
{
LongInt Dist = Dest - MkEven24(EProgCounter() + CodeLen);
EvalResult.OK = False;
if (ChkShortEvenDist(&Dist, EvalResult.Flags))
{
BAsmCode[HReg] = Dist & 0xff;
EvalResult.OK = True;
}
else if (!DoBranchExt) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[2]);
else
{
LongWord odd = (EProgCounter() + CodeLen) & 1;
Dist = Dest - MkEven24(EProgCounter() + CodeLen + 5 + odd);
if (ChkLongEvenDist(&Dist, &ArgStr[2], EvalResult.Flags))
{
BAsmCode[HReg] = 1 + odd;
BAsmCode[CodeLen++] = 0xfe;
BAsmCode[CodeLen++] = 2 + odd;
if (odd) BAsmCode[CodeLen++] = 0;
BAsmCode[CodeLen++] = 0xd5;
BAsmCode[CodeLen++] = (Dist >> 8) & 0xff;
BAsmCode[CodeLen++] = Dist & 0xff;
BAsmCode[CodeLen++] = 0;
EvalResult.OK = True;
}
}
}
if (!EvalResult.OK)
CodeLen = 0;
}
}
}
static void DecodeFCALLJMP(Word Index)
{
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
tEvalResult EvalResult;
LongInt AdrLong = GetBranchDest(&ArgStr[1], &EvalResult);
if (EvalResult.OK)
{
BAsmCode[CodeLen++] = 0xc4 | (Index << 4);
BAsmCode[CodeLen++] = (AdrLong >> 8) & 0xff;
BAsmCode[CodeLen++] = AdrLong & 0xff;
BAsmCode[CodeLen++] = (AdrLong >> 16) & 0xff;
}
}
}
static Boolean IsRealDef(void)
{
switch (*OpPart.str.p_str)
{
case 'P':
return Memo("PORT");
case 'B':
return Memo("BIT");
case 'R':
return Memo("REG");
default:
return FALSE;
}
}
static void ForceAlign(void)
{
if (EProgCounter() & 1)
{
BAsmCode[0] = NOPCode; CodeLen = 1;
}
}
static Boolean DecodeAttrPart_XA(void)
{
if (strlen(AttrPart.
str.
p_str) > 1)
{
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return False;
}
if (*AttrPart.str.p_str)
switch (as_toupper(*AttrPart.str.p_str))
{
case 'B': AttrPartOpSize[0] = eSymbolSize8Bit; break;
case 'W': AttrPartOpSize[0] = eSymbolSize16Bit; break;
case 'D': AttrPartOpSize[0] = eSymbolSize32Bit; break;
default : WrStrErrorPos(ErrNum_UndefAttr, &AttrPart); return False;
}
return True;
}
static void MakeCode_XA(void)
{
CodeLen = 0; DontPrint = False; OpSize = eSymbolSizeUnknown;
/* Operandengroesse */
if (*AttrPart.str.p_str)
SetOpSize(AttrPartOpSize[0]);
/* Labels muessen auf geraden Adressen liegen */
if ( (ActPC == SegCode) && (!IsRealDef()) &&
((*LabPart.
str.
p_str != '\0') ||((ArgCnt
== 1) && (!strcmp(ArgStr
[1].
str.
p_str, "$")))) )
{
ForceAlign();
if (*LabPart.str.p_str != '\0')
EnterIntSymbol(&LabPart, EProgCounter() + CodeLen, (as_addrspace_t)ActPC, False);
}
if (DecodeMoto16Pseudo(OpSize, False)) return;
if (DecodeIntelPseudo(False)) return;
/* zu ignorierendes */
if (Memo("")) return;
/* via Tabelle suchen */
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*-------------------------------------------------------------------------*/
/* Codetabellenverwaltung */
static void AddFixed(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFixed);
}
static void AddJBit(const char *NName, Word NCode)
{
order_array_rsv_end(JBitOrders, InvOrder);
JBitOrders[InstrZ].Name = NName;
JBitOrders[InstrZ].Inversion = 255;
JBitOrders[InstrZ].Code = NCode;
AddInstTable(InstTable, NName, InstrZ++, DecodeJBit);
}
static void AddStack(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeStack);
}
static void AddReg(const char *NName, Byte NMask, Byte NCode)
{
order_array_rsv_end(RegOrders, RegOrder);
RegOrders[InstrZ].Code = NCode;
RegOrders[InstrZ].SizeMask = NMask;
AddInstTable(InstTable, NName, InstrZ++, DecodeRegO);
}
static void AddRotate(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRotate);
}
static void AddRel(const char *NName, Word NCode)
{
order_array_rsv_end(RelOrders, InvOrder);
RelOrders[InstrZ].Name = NName;
RelOrders[InstrZ].Inversion = 255;
RelOrders[InstrZ].Code = NCode;
AddInstTable(InstTable, NName, InstrZ++, DecodeRel);
}
static void SetInv(const char *Name1, const char *Name2, InvOrder *Orders)
{
InvOrder *Order1, *Order2;
for (Order1
= Orders
; strcmp(Order1
->Name
, Name1
); Order1
++);
for (Order2
= Orders
; strcmp(Order2
->Name
, Name2
); Order2
++);
Order1->Inversion = Order2 - Orders;
Order2->Inversion = Order1 - Orders;
}
static void InitFields(void)
{
InstTable = CreateInstTable(201);
AddInstTable(InstTable, "MOV" , 0, DecodeMOV);
AddInstTable(InstTable, "MOVC" , 0, DecodeMOVC);
AddInstTable(InstTable, "MOVX" , 0, DecodeMOVX);
AddInstTable(InstTable, "XCH" , 0, DecodeXCH);
AddInstTable(InstTable, "ADDS" , 0, DecodeADDSMOVS);
AddInstTable(InstTable, "MOVS" , 1, DecodeADDSMOVS);
AddInstTable(InstTable, "DIV" , 0, DecodeDIV);
AddInstTable(InstTable, "DIVU" , 0, DecodeDIVU);
AddInstTable(InstTable, "MUL" , 0, DecodeMUL);
AddInstTable(InstTable, "MULU" , 0, DecodeMULU);
AddInstTable(InstTable, "LEA" , 0, DecodeLEA);
AddInstTable(InstTable, "ANL" , 0, DecodeANLORL);
AddInstTable(InstTable, "ORL" , 1, DecodeANLORL);
AddInstTable(InstTable, "CLR" , 0, DecodeCLRSETB);
AddInstTable(InstTable, "SETB" , 1, DecodeCLRSETB);
AddInstTable(InstTable, "TRAP" , 0, DecodeTRAP);
AddInstTable(InstTable, "CALL" , 0, DecodeCALL);
AddInstTable(InstTable, "JMP" , 0, DecodeJMP);
AddInstTable(InstTable, "CJNE" , 0, DecodeCJNE);
AddInstTable(InstTable, "DJNZ" , 0, DecodeDJNZ);
AddInstTable(InstTable, "FCALL", 0, DecodeFCALLJMP);
AddInstTable(InstTable, "FJMP" , 1, DecodeFCALLJMP);
AddInstTable(InstTable, "PORT" , 0, DecodePORT);
AddInstTable(InstTable, "BIT" , 0, DecodeBIT);
AddInstTable(InstTable, "REG" , 0, CodeREG);
AddFixed("NOP" , 0x0000);
AddFixed("RET" , 0xd680);
AddFixed("RETI" , RETICode);
AddFixed("BKPT" , 0x00ff);
AddFixed("RESET", 0xd610);
InstrZ = 0;
AddJBit("JB" , 0x80);
AddJBit("JBC" , 0xc0);
AddJBit("JNB" , 0xa0);
SetInv("JB", "JNB", JBitOrders);
AddStack("POP" , 0x1027);
AddStack("POPU" , 0x0037);
AddStack("PUSH" , 0x3007);
AddStack("PUSHU", 0x2017);
InstrZ = 0;
AddInstTable(InstTable, "ADD" , InstrZ++, DecodeALU);
AddInstTable(InstTable, "ADDC", InstrZ++, DecodeALU);
AddInstTable(InstTable, "SUB" , InstrZ++, DecodeALU);
AddInstTable(InstTable, "SUBB", InstrZ++, DecodeALU);
AddInstTable(InstTable, "CMP" , InstrZ++, DecodeALU);
AddInstTable(InstTable, "AND" , InstrZ++, DecodeALU);
AddInstTable(InstTable, "OR" , InstrZ++, DecodeALU);
AddInstTable(InstTable, "XOR" , InstrZ++, DecodeALU);
InstrZ = 0;
AddReg("NEG" , 3, 0x0b);
AddReg("CPL" , 3, 0x0a);
AddReg("SEXT", 3, 0x09);
AddReg("DA" , 1, 0x08);
AddInstTable(InstTable, "LSR" , 0, DecodeShift);
AddInstTable(InstTable, "ASL" , 1, DecodeShift);
AddInstTable(InstTable, "ASR" , 2, DecodeShift);
AddInstTable(InstTable, "NORM", 3, DecodeShift);
AddRotate("RR" , 0xb0); AddRotate("RL" , 0xd3);
AddRotate("RRC", 0xb7); AddRotate("RLC", 0xd7);
InstrZ = 0;
AddRel("BCC", 0xf0); AddRel("BCS", 0xf1); AddRel("BNE", 0xf2);
AddRel("BEQ", 0xf3); AddRel("BNV", 0xf4); AddRel("BOV", 0xf5);
AddRel("BPL", 0xf6); AddRel("BMI", 0xf7); AddRel("BG" , 0xf8);
AddRel("BL" , 0xf9); AddRel("BGE", 0xfa); AddRel("BLT", 0xfb);
AddRel("BGT", 0xfc); AddRel("BLE", 0xfd); AddRel("BR" , 0xfe);
AddRel("JZ" , 0xec); AddRel("JNZ", 0xee);
SetInv("BCC", "BCS", RelOrders);
SetInv("BNE", "BEQ", RelOrders);
SetInv("BNV", "BOV", RelOrders);
SetInv("BPL", "BMI", RelOrders);
SetInv("BG" , "BL" , RelOrders);
SetInv("BGE", "BLT", RelOrders);
SetInv("BGT", "BLE", RelOrders);
SetInv("JZ" , "JNZ", RelOrders);
}
static void DeinitFields(void)
{
order_array_free(JBitOrders);
order_array_free(RegOrders);
order_array_free(RelOrders);
DestroyInstTable(InstTable);
}
/*-------------------------------------------------------------------------*/
/* Callbacks */
/*!------------------------------------------------------------------------
* \fn InternSymbol_XA(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on XA
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_XA(char *pArg, TempResult *pResult)
{
Byte Reg;
tSymbolSize Size;
if (*AttrPart.str.p_str)
OpSize = AttrPartOpSize[0];
if (DecodeRegCore(pArg, &Size, &Reg))
{
pResult->Typ = TempReg;
pResult->DataSize = Size;
pResult->Contents.RegDescr.Reg = Reg;
pResult->Contents.RegDescr.Dissect = DissectReg_XA;
pResult->Contents.RegDescr.compare = NULL;
}
}
static void InitCode_XA(void)
{
Reg_DS = 0;
}
static Boolean ChkPC_XA(LargeWord Addr)
{
switch (ActPC)
{
case SegCode:
case SegData:
return (Addr<0x1000000);
case SegIO:
return ((Addr > 0x3ff) && (Addr < 0x800));
default:
return False;
}
}
static Boolean IsDef_XA(void)
{
return (ActPC == SegCode) || IsRealDef();
}
static void SwitchTo_XA(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "$"; HeaderID = 0x3c; NOPCode = 0x00;
DivideChars = ","; HasAttrs = True; AttrChars = ".";
ValidSegs =(1 << SegCode) | (1 << SegData) | (1 << SegIO);
Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
Grans[SegData ] = 1; ListGrans[SegData ] = 1; SegInits[SegData ] = 0;
Grans[SegIO ] = 1; ListGrans[SegIO ] = 1; SegInits[SegIO ] = 0x400;
DecodeAttrPart = DecodeAttrPart_XA;
MakeCode = MakeCode_XA;
ChkPC = ChkPC_XA;
IsDef = IsDef_XA;
InternSymbol = InternSymbol_XA;
DissectReg = DissectReg_XA;
SwitchFrom = DeinitFields; InitFields();
onoff_supmode_add();
if (!onoff_test_and_set(e_onoff_reg_branchext))
SetFlag(&DoBranchExt, BranchExtSymName, False);
AddONOFF(BranchExtCmdName, &DoBranchExt, BranchExtSymName , False);
AddMoto16PseudoONOFF(False);
pASSUMERecs = ASSUMEXAs;
ASSUMERecCnt = ASSUMEXACount;
}
void codexa_init(void)
{
CPUXAG1 = AddCPU("XAG1", SwitchTo_XA);
CPUXAG2 = AddCPU("XAG2", SwitchTo_XA);
CPUXAG3 = AddCPU("XAG3", SwitchTo_XA);
AddInitPassProc(InitCode_XA);
}