/* code166.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* AS-Codegenerator Siemens 80C16x */
/* */
/*****************************************************************************/
#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 "asmitree.h"
#include "asmcode.h"
#include "asmallg.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code166.h"
typedef struct
{
CPUVar MinCPU;
Word Code1, Code2;
} BaseOrder;
typedef struct
{
const char *Name;
Byte Code;
} Condition;
#define COND_CODE_TRUE 0x0
#define DPPCount 4
static const char RegNames[6][5] = { "DPP0", "DPP1", "DPP2", "DPP3", "CP", "SP" };
static CPUVar CPU80C166, CPU80C167, CPU80C167CS;
static BaseOrder *FixedOrders;
static Condition *Conditions;
static int TrueCond;
static LongInt DPPAssumes[DPPCount];
static IntType MemInt, MemInt2;
static tSymbolSize OpSize;
static Boolean DPPChanged[DPPCount], N_DPPChanged[DPPCount];
static Boolean SPChanged, CPChanged, N_SPChanged, N_CPChanged;
static ShortInt ExtCounter;
static enum
{
MemModeStd, /* normal */
MemModeNoCheck, /* EXTS Rn */
MemModeZeroPage, /* EXTP Rn */
MemModeFixedBank, /* EXTS nn */
MemModeFixedPage /* EXTP nn */
} MemMode;
static Word MemPage;
static Boolean ExtSFRs;
#define ASSUME166Count 4
static ASSUMERec ASSUME166s[ASSUME166Count] =
{
{ "DPP0", DPPAssumes + 0, 0, 15, -1, NULL },
{ "DPP1", DPPAssumes + 1, 0, 15, -1, NULL },
{ "DPP2", DPPAssumes + 2, 0, 15, -1, NULL },
{ "DPP3", DPPAssumes + 3, 0, 15, -1, NULL }
};
/*-------------------------------------------------------------------------*/
enum
{
ModNone = -1,
ModReg = 0,
ModImm = 1,
ModIReg = 2,
ModPreDec = 3,
ModPostInc = 4,
ModIndex = 5,
ModAbs = 6,
ModMReg = 7,
ModLAbs = 8
};
typedef enum
{
eForceNone = 0,
eForceShort = 1,
eForceLong = 2
} tForceSize;
#define MModReg (1 << ModReg)
#define MModImm (1 << ModImm)
#define MModIReg (1 << ModIReg)
#define MModPreDec (1 << ModPreDec)
#define MModPostInc (1 << ModPostInc)
#define MModIndex (1 << ModIndex)
#define MModAbs (1 << ModAbs)
#define MModMReg (1 << ModMReg)
#define MModLAbs (1 << ModLAbs)
#define M_InCode (1 << 14)
#define M_Dest (1 << 13)
typedef struct
{
Byte Mode;
Byte Vals[2];
ShortInt Type;
tSymbolFlags SymFlags;
tForceSize ForceSize;
int Cnt;
} tAdrResult;
/*!------------------------------------------------------------------------
* \fn IsRegCore(const char *pArg, tRegInt *pValue, tSymbolSize *pSize)
* \brief check whether argument describes a CPU (general purpose) register
* \param pArg argument
* \param pValue resulting register # if yes
* \param pSize resulting register size if yes
* \return true if yes
* ------------------------------------------------------------------------ */
static Boolean IsRegCore(const char *pArg, tRegInt *pValue, tSymbolSize *pSize)
{
Boolean OK;
if ((l < 2) || (as_toupper(*pArg) != 'R'))
return False;
else if ((l > 2) && (as_toupper(pArg[1]) == 'L'))
{
*pValue = ConstLongInt(pArg + 2, &OK, 10) << 1;
*pSize = eSymbolSize8Bit;
return (OK && (*pValue <= 15));
}
else if ((l > 2) && (as_toupper(pArg[1]) == 'H'))
{
*pValue = (ConstLongInt(pArg + 2, &OK, 10) << 1) + 1;
*pSize = eSymbolSize8Bit;
return (OK && (*pValue <= 15));
}
else
{
*pValue = ConstLongInt(pArg + 1, &OK, 10);
*pSize = eSymbolSize16Bit;
return (OK && (*pValue <= 15));
}
}
/*!------------------------------------------------------------------------
* \fn DissectReg_166(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - C16x variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_166(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
{
switch (InpSize)
{
case eSymbolSize8Bit:
as_snprintf(pDest, DestSize, "R%c%u", Value & 1 ? 'H' : 'L', (unsigned)(Value >> 1));
break;
case eSymbolSize16Bit:
as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
break;
default:
as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
}
}
/*!------------------------------------------------------------------------
* \fn IsReg(const tStrComp *pArg, Byte *pValue, tSymbolSize *pSize, tSymbolSize ReqSize, Boolean MustBeReg)
* \brief check whether argument is a CPU register or user-defined register alias
* \param pArg argument
* \param pValue resulting register # if yes
* \param pSize resulting register size if yes
* \param ReqSize requested register size
* \param MustBeReg expecting register or maybe not?
* \return reg eval result
* ------------------------------------------------------------------------ */
/* NOTE: If requester register size is 8 bits, R0..R15 is allowed as
alias for R0L,R0H,R1L,...,R7H: */
static Boolean ChkRegSize(tSymbolSize ReqSize, tSymbolSize ActSize)
{
return (ReqSize == eSymbolSizeUnknown)
|| (ReqSize == ActSize)
|| ((ReqSize == eSymbolSize8Bit) && (ActSize == eSymbolSize16Bit));
}
static tRegEvalResult IsReg(const tStrComp *pArg, Byte *pValue, tSymbolSize *pSize, tSymbolSize ReqSize, Boolean MustBeReg)
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
if (IsRegCore(pArg->str.p_str, &RegDescr.Reg, &EvalResult.DataSize))
RegEvalResult = eIsReg;
else
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
if (RegEvalResult == eIsReg)
{
if (!ChkRegSize(ReqSize, EvalResult.DataSize))
{
WrStrErrorPos(ErrNum_InvOpSize, pArg);
RegEvalResult = MustBeReg ? eIsNoReg : eRegAbort;
}
}
*pValue = RegDescr.Reg;
if (pSize) *pSize = EvalResult.DataSize;
return RegEvalResult;
}
static tRegEvalResult IsRegM1(const tStrComp *pArg, Byte *pValue, tSymbolSize ReqSize, Boolean MustBeReg)
{
if (*pArg->str.p_str)
{
int l;
char tmp
= pArg
->str.
p_str[l
= (strlen(pArg
->str.
p_str) - 1)];
tRegEvalResult b;
pArg->str.p_str[l] = '\0';
b = IsReg(pArg, pValue, NULL, ReqSize, MustBeReg);
pArg->str.p_str[l] = tmp;
return b;
}
else
return eIsNoReg;
}
static tRegEvalResult IsRegP1(const tStrComp *pArg, Byte *pValue, tSymbolSize ReqSize, Boolean MustBeReg)
{
tStrComp Arg;
StrCompRefRight(&Arg, pArg, 1);
return IsReg(&Arg, pValue, NULL, ReqSize, MustBeReg);
}
static LongInt SFRStart(void)
{
return (ExtSFRs) ? 0xf000 : 0xfe00;
}
static LongInt SFREnd(void)
{
return (ExtSFRs) ? 0xf1de : 0xffde;
}
static Boolean CalcPage(LongInt *Adr, Boolean DoAnyway)
{
int z;
Word Bank;
switch (MemMode)
{
case MemModeStd:
z = 0;
while ((z <= 3) && (((*Adr) >> 14) != DPPAssumes[z]))
z++;
if (z > 3)
{
WrError(ErrNum_InAccPage);
(*Adr) &= 0xffff;
return DoAnyway;
}
else
{
*Adr = ((*Adr) & 0x3fff) + (z << 14);
if (DPPChanged[z])
WrXError(ErrNum_Pipeline, RegNames[z]);
return True;
}
case MemModeZeroPage:
(*Adr) &= 0x3fff;
return True;
case MemModeFixedPage:
Bank = (*Adr) >> 14;
(*Adr) &= 0x3fff;
if (Bank != MemPage)
{
WrError(ErrNum_InAccPage);
return (DoAnyway);
}
else
return True;
case MemModeNoCheck:
(*Adr) &= 0xffff;
return True;
case MemModeFixedBank:
Bank = (*Adr) >> 16; (*Adr) &= 0xffff;
if (Bank != MemPage)
{
WrError(ErrNum_InAccPage);
return (DoAnyway);
}
else
return True;
default:
return False;
}
}
static void DecideAbsolute(LongInt DispAcc, Word Mask, tAdrResult *pResult)
{
#define DPPAdr 0xfe00
#define SPAdr 0xfe12
#define CPAdr 0xfe10
int z;
if (Mask & M_InCode)
{
if ((HiWord(EProgCounter()) == HiWord(DispAcc)) && (Mask & MModAbs))
{
pResult->Type = ModAbs;
pResult->Cnt = 2;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc);
}
else
{
pResult->Type = ModLAbs;
pResult->Cnt = 2;
pResult->Mode = DispAcc >> 16;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc);
}
}
else if (((Mask & MModMReg) != 0) && (DispAcc >= SFRStart()) && (DispAcc <= SFREnd()) && (!(DispAcc & 1)))
{
pResult->Type = ModMReg;
pResult->Cnt = 1;
pResult->Vals[0] = (DispAcc - SFRStart()) >> 1;
}
else switch (MemMode)
{
case MemModeStd:
z = 0;
while ((z <= 3) && ((DispAcc >> 14) != DPPAssumes[z]))
z++;
if (z > 3)
{
WrError(ErrNum_InAccPage);
z = (DispAcc >> 14) & 3;
}
pResult->Type = ModAbs;
pResult->Cnt = 2;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = (Hi(DispAcc) & 0x3f) + (z << 6);
if (DPPChanged[z])
WrXError(ErrNum_Pipeline, RegNames[z]);
break;
case MemModeZeroPage:
pResult->Type = ModAbs;
pResult->Cnt = 2;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc) & 0x3f;
break;
case MemModeFixedPage:
if ((DispAcc >> 14) != MemPage)
WrError(ErrNum_InAccPage);
pResult->Type = ModAbs;
pResult->Cnt = 2;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc) & 0x3f;
break;
case MemModeNoCheck:
pResult->Type = ModAbs;
pResult->Cnt = 2;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc);
break;
case MemModeFixedBank:
if ((DispAcc >> 16) != MemPage)
WrError(ErrNum_InAccPage);
pResult->Type = ModAbs;
pResult->Cnt = 2;
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc);
break;
}
if ((pResult->Type != ModNone) && (Mask & M_Dest))
{
switch ((Word)DispAcc)
{
case SPAdr : N_SPChanged = True; break;
case CPAdr : N_CPChanged = True; break;
case DPPAdr :
case DPPAdr + 1 : N_DPPChanged[0] = True; break;
case DPPAdr + 2 :
case DPPAdr + 3 : N_DPPChanged[1] = True; break;
case DPPAdr + 4 :
case DPPAdr + 5 : N_DPPChanged[2] = True; break;
case DPPAdr + 6 :
case DPPAdr + 7 : N_DPPChanged[3] = True; break;
}
}
}
static int SplitForceSize(const char *pArg, tForceSize *pForceSize)
{
switch (*pArg)
{
case '>': *pForceSize = eForceLong; return 1;
case '<': *pForceSize = eForceShort; return 1;
default: return 0;
}
}
static ShortInt DecodeAdr(const tStrComp *pArg, Word Mask, tAdrResult *pResult)
{
LongInt HDisp, DispAcc;
Boolean OK, NegFlag, NNegFlag;
Byte HReg;
int Offs;
tRegEvalResult RegEvalResult;
pResult->Type = ModNone;
pResult->Cnt = 0;
pResult->ForceSize = eForceNone;
/* immediate ? */
if (*pArg->str.p_str == '#')
{
Offs = SplitForceSize(pArg->str.p_str + 1, &pResult->ForceSize);
switch (OpSize)
{
case eSymbolSize8Bit:
pResult->Vals[0] = EvalStrIntExpressionOffsWithFlags(pArg, 1 + Offs, Int8, &OK, &pResult->SymFlags);
pResult->Vals[1] = 0;
break;
case eSymbolSize16Bit:
HDisp = EvalStrIntExpressionOffsWithFlags(pArg, 1 + Offs, Int16, &OK, &pResult->SymFlags);
pResult->Vals[0] = Lo(HDisp);
pResult->Vals[1] = Hi(HDisp);
break;
default:
OK = False;
break;
}
if (OK)
{
pResult->Type = ModImm;
AdrCnt = OpSize + 1;
}
}
/* Register ? */
else if ((RegEvalResult = IsReg(pArg, &pResult->Mode, NULL, OpSize, False)) != eIsNoReg)
{
if (RegEvalResult == eRegAbort)
return pResult->Type;
if ((Mask & MModReg) != 0)
pResult->Type = ModReg;
else
{
pResult->Type = ModMReg;
pResult->Vals[0] = 0xf0 + pResult->Mode;
AdrCnt = 1;
}
if (CPChanged)
WrXError(ErrNum_Pipeline, RegNames[4]);
}
/* indirekt ? */
else if ((*pArg
->str.
p_str == '[') && (pArg
->str.
p_str[strlen(pArg
->str.
p_str) - 1] == ']'))
{
tStrComp Arg;
int ArgLen;
StrCompRefRight(&Arg, pArg, 1);
StrCompShorten(&Arg, 1);
KillPrefBlanksStrCompRef(&Arg);
KillPostBlanksStrComp(&Arg);
ArgLen
= strlen(Arg.
str.
p_str);
/* Predekrement ? */
if ((ArgLen > 2) && (*Arg.str.p_str == '-') && ((RegEvalResult = IsRegP1(&Arg, &pResult->Mode, eSymbolSize16Bit, False)) != eIsNoReg))
{
if (eRegAbort == RegEvalResult)
return pResult->Type;
pResult->Type = ModPreDec;
}
/* Postinkrement ? */
else if ((ArgLen > 2) && (Arg.str.p_str[ArgLen - 1] == '+') && ((RegEvalResult = IsRegM1(&Arg, &pResult->Mode, eSymbolSize16Bit, False)) != eIsNoReg))
{
if (eRegAbort == RegEvalResult)
return pResult->Type;
pResult->Type = ModPostInc;
}
/* indiziert ? */
else
{
tStrComp Remainder;
char *pSplitPos;
NNegFlag = NegFlag = False;
DispAcc = 0;
pResult->Mode = 0xff;
do
{
pSplitPos = indir_split_pos(Arg.str.p_str);
if (pSplitPos)
{
NNegFlag = *pSplitPos == '-';
StrCompSplitRef(&Arg, &Remainder, &Arg, pSplitPos);
}
if ((RegEvalResult = IsReg(&Arg, &HReg, NULL, eSymbolSize16Bit, False)) != eIsNoReg)
{
if (RegEvalResult == eRegAbort)
return pResult->Type;
if (NegFlag || (pResult->Mode != 0xff))
WrError(ErrNum_InvAddrMode);
else
pResult->Mode = HReg;
}
else
{
HDisp = EvalStrIntExpressionOffs(&Arg, !!(*Arg.str.p_str == '#'), Int32, &OK);
if (OK)
DispAcc = NegFlag ? DispAcc - HDisp : DispAcc + HDisp;
}
if (pSplitPos)
{
NegFlag = NNegFlag;
Arg = Remainder;
}
}
while (pSplitPos);
if (pResult->Mode == 0xff)
DecideAbsolute(DispAcc, Mask, pResult);
else if (DispAcc == 0)
pResult->Type = ModIReg;
else if (DispAcc > 0xffff)
WrError(ErrNum_OverRange);
else if (DispAcc < -0x8000l)
WrError(ErrNum_UnderRange);
else
{
pResult->Vals[0] = Lo(DispAcc);
pResult->Vals[1] = Hi(DispAcc);
pResult->Type = ModIndex;
pResult->Cnt = 2;
}
}
}
else
{
int Offset = SplitForceSize(pArg->str.p_str, &pResult->ForceSize);
DispAcc = EvalStrIntExpressionOffsWithFlags(pArg, Offset, MemInt, &OK, &pResult->SymFlags);
if (OK)
DecideAbsolute(DispAcc, Mask, pResult);
}
if ((pResult->Type != ModNone) && (!((1 << pResult->Type) & Mask)))
{
WrError(ErrNum_InvAddrMode);
pResult->Type = ModNone;
pResult->Cnt = 0;
}
return pResult->Type;
}
static Boolean DecodeCondition(const char *Name, Byte *p_cond_code)
{
int z;
for (z = 0; Conditions[z].Name; z++)
if (!as_strcasecmp(Conditions[z].Name, Name))
{
*p_cond_code = Conditions[z].Code;
return True;
}
return False;
}
static Boolean DecodeBitAddr(const tStrComp *pArg, Word *Adr, Byte *Bit, Boolean MayBeOut)
{
char *p;
Word LAdr;
Byte Reg;
Boolean OK;
p = QuotPos(pArg->str.p_str, '.');
if (!p)
{
LAdr = EvalStrIntExpression(pArg, UInt16, &OK) & 0x1fff;
if (OK)
{
if ((!MayBeOut) && ((LAdr >> 12) != Ord(ExtSFRs)))
{
WrError(ErrNum_InAccReg);
return False;
}
*Adr = LAdr >> 4;
*Bit = LAdr & 15;
if (!MayBeOut)
*Adr = Lo(*Adr);
return True;
}
else return False;
}
else if (p == pArg->str.p_str)
{
WrError(ErrNum_InvAddrMode);
return False;
}
else
{
tStrComp AddrComp, BitComp;
StrCompSplitRef(&AddrComp, &BitComp, pArg, p);
switch (IsReg(&AddrComp, &Reg, NULL, eSymbolSize16Bit, False))
{
case eIsReg:
*Adr = 0xf0 + Reg;
break;
case eRegAbort:
return False;
case eIsNoReg:
{
tSymbolFlags Flags;
LAdr = EvalStrIntExpressionWithFlags(&AddrComp, UInt16, &OK, &Flags);
if (!OK)
return False;
if (mFirstPassUnknown(Flags))
LAdr = 0xfd00;
/* full addresses must be even, since bitfields in memory are 16 bit: */
if ((LAdr > 0xff) && (LAdr & 1))
{
WrStrErrorPos(ErrNum_NotAligned, &AddrComp);
return False;
}
/* coded bit address: */
if (LAdr <= 0xff)
*Adr = LAdr;
/* 1st RAM bank: */
else if ((LAdr >= 0xfd00) && (LAdr <= 0xfdfe))
*Adr = (LAdr - 0xfd00)/2;
/* SFR space: */
else if ((LAdr >= 0xff00) && (LAdr <= 0xffde))
{
if ((ExtSFRs) && (!MayBeOut))
{
WrStrErrorPos(ErrNum_InAccReg, &AddrComp);
return False;
}
*Adr = 0x80 + ((LAdr - 0xff00) / 2);
}
/* extended SFR space: */
else if ((LAdr >= 0xf100) && (LAdr <= 0xf1de))
{
if ((!ExtSFRs) && (!MayBeOut))
{
WrStrErrorPos(ErrNum_InAccReg, &AddrComp);
return False;
}
*Adr = 0x80 + ((LAdr - 0xf100) / 2);
if (MayBeOut)
(*Adr) += 0x100;
}
else
{
WrStrErrorPos(ErrNum_OverRange, &AddrComp);
return False;
}
}
}
*Bit = EvalStrIntExpression(&BitComp, UInt4, &OK);
return OK;
}
}
static Word WordVal(const tAdrResult *pResult)
{
return pResult->Vals[0] + (((Word)pResult->Vals[1]) << 8);
}
static Boolean DecodePref(const tStrComp *pArg, Byte *Erg)
{
Boolean OK;
tSymbolFlags Flags;
if (*pArg->str.p_str != '#')
{
WrError(ErrNum_InvAddrMode);
return False;
}
*Erg = EvalStrIntExpressionOffsWithFlags(pArg, 1, UInt3, &OK, &Flags);
if (mFirstPassUnknown(Flags))
*Erg = 1;
if (!OK)
return False;
if (*Erg < 1)
WrError(ErrNum_UnderRange);
else if (*Erg > 4)
WrError(ErrNum_OverRange);
else
{
(*Erg)--;
return True;
}
return False;
}
/*-------------------------------------------------------------------------*/
static void DecodeFixed(Word Index)
{
const BaseOrder *pOrder = FixedOrders + Index;
if (ChkArgCnt(0, 0))
{
CodeLen = 2;
BAsmCode[0] = Lo(pOrder->Code1);
BAsmCode[1] = Hi(pOrder->Code1);
if (pOrder->Code2 != 0)
{
CodeLen = 4;
BAsmCode[2] = Lo(pOrder->Code2);
BAsmCode[3] = Hi(pOrder->Code2);
if ((!strncmp(OpPart.
str.
p_str, "RET", 3)) && (SPChanged
))
WrXError(ErrNum_Pipeline, RegNames[5]);
}
}
}
static void DecodeMOV(Word Code)
{
LongInt AdrLong;
OpSize = (tSymbolSize)Hi(Code);
Code = 1 - OpSize;
if (ChkArgCnt(2, 2))
{
tAdrResult DestResult;
switch (DecodeAdr(&ArgStr[1], MModReg | MModMReg | MModIReg | MModPreDec | MModPostInc | MModIndex | MModAbs | M_Dest, &DestResult))
{
case ModReg:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | MModIReg | MModPostInc | MModIndex | MModAbs, &SrcResult))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xf0 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
case ModImm:
{
Boolean IsShort = WordVal(&SrcResult) <= 15;
if (!SrcResult.ForceSize)
SrcResult.ForceSize = IsShort ? eForceShort : eForceLong;
if (SrcResult.ForceSize == eForceShort)
{
if (!IsShort && !mSymbolQuestionable(SrcResult.SymFlags)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
else
{
CodeLen = 2;
BAsmCode[0] = 0xe0 + Code;
BAsmCode[1] = (WordVal(&SrcResult) << 4) + DestResult.Mode;
}
}
else
{
CodeLen = 4;
BAsmCode[0] = 0xe6 + Code;
BAsmCode[1] = DestResult.Mode + 0xf0;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, 2);
}
break;
}
case ModIReg:
CodeLen = 2;
BAsmCode[0] = 0xa8 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
case ModPostInc:
CodeLen = 2;
BAsmCode[0] = 0x98 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
case ModIndex:
CodeLen = 2 + SrcResult.Cnt;
BAsmCode[0] = 0xd4 + (Code << 5);
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
case ModAbs:
CodeLen = 2 + SrcResult.Cnt;
BAsmCode[0] = 0xf2 + Code;
BAsmCode[1] = 0xf0 + DestResult.Mode;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
}
break;
}
case ModMReg:
{
tAdrResult SrcResult;
BAsmCode[1] = DestResult.Vals[0];
switch (DecodeAdr(&ArgStr[2], MModImm | MModMReg | ((DPPAssumes[3] == 3) ? MModIReg : 0) | MModAbs, &SrcResult))
{
case ModImm:
CodeLen = 4;
BAsmCode[0] = 0xe6 + Code;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, 2);
break;
case ModMReg: /* BAsmCode[1] sicher absolut darstellbar, da Rn vorher */
/* abgefangen wird! */
BAsmCode[0] = 0xf6 + Code;
AdrLong = SFRStart() + (((Word)BAsmCode[1]) << 1);
CalcPage(&AdrLong, True);
BAsmCode[2] = Lo(AdrLong);
BAsmCode[3] = Hi(AdrLong);
BAsmCode[1] = SrcResult.Vals[0];
CodeLen = 4;
break;
case ModIReg:
CodeLen = 4; BAsmCode[0] = 0x94 + (Code << 5);
BAsmCode[2] = BAsmCode[1] << 1;
BAsmCode[3] = 0xfe + (BAsmCode[1] >> 7); /* ANSI :-0 */
BAsmCode[1] = SrcResult.Mode;
break;
case ModAbs:
CodeLen = 2 + SrcResult.Cnt;
BAsmCode[0] = 0xf2 + Code;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
}
break;
}
case ModIReg:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModReg | MModIReg | MModPostInc | MModAbs, &SrcResult))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xb8 + Code;
BAsmCode[1] = DestResult.Mode + (SrcResult.Mode << 4);
break;
case ModIReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
case ModPostInc:
CodeLen = 2;
BAsmCode[0] = 0xe8 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
case ModAbs:
CodeLen = 2 + SrcResult.Cnt;
BAsmCode[0] = 0x84 + (Code << 5);
BAsmCode[1] = DestResult.Mode;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
}
break;
}
case ModPreDec:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModReg, &SrcResult))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0x88 + Code;
BAsmCode[1] = DestResult.Mode + (SrcResult.Mode << 4);
break;
}
break;
}
case ModPostInc:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModIReg, &SrcResult))
{
case ModIReg:
CodeLen = 2;
BAsmCode[0] = 0xd8 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
}
break;
}
case ModIndex:
{
tAdrResult SrcResult;
BAsmCode[1] = DestResult.Mode;
memcpy(BAsmCode
+ 2, DestResult.
Vals, DestResult.
Cnt);
switch (DecodeAdr(&ArgStr[2], MModReg, &SrcResult))
{
case ModReg:
BAsmCode[0] = 0xc4 + (Code << 5);
CodeLen = 4;
BAsmCode[1] += SrcResult.Mode << 4;
break;
}
break;
}
case ModAbs:
{
tAdrResult SrcResult;
memcpy(BAsmCode
+ 2, DestResult.
Vals, DestResult.
Cnt);
switch (DecodeAdr(&ArgStr[2], MModIReg | MModMReg, &SrcResult))
{
case ModIReg:
CodeLen = 4;
BAsmCode[0] = 0x94 + (Code << 5);
BAsmCode[1] = SrcResult.Mode;
break;
case ModMReg:
CodeLen = 4;
BAsmCode[0] = 0xf6 + Code;
BAsmCode[1] = SrcResult.Vals[0];
break;
}
break;
}
}
}
}
static void DecodeMOVBS_MOVBZ(Word Code)
{
LongInt AdrLong;
if (ChkArgCnt(2, 2))
{
tAdrResult DestResult;
OpSize = eSymbolSize16Bit;
switch (DecodeAdr(&ArgStr[1], MModReg | MModMReg | MModAbs | M_Dest, &DestResult))
{
case ModReg:
{
tAdrResult SrcResult;
OpSize = eSymbolSize8Bit;
switch (DecodeAdr(&ArgStr[2], MModReg | MModAbs, &SrcResult))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc0 + Code;
BAsmCode[1] = DestResult.Mode + (SrcResult.Mode << 4);
break;
case ModAbs:
CodeLen = 4;
BAsmCode[0] = 0xc2 + Code;
BAsmCode[1] = 0xf0 + DestResult.Mode;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, 2);
break;
}
break;
}
case ModMReg:
{
tAdrResult SrcResult;
BAsmCode[1] = DestResult.Vals[0];
OpSize = eSymbolSize8Bit;
switch (DecodeAdr(&ArgStr[2], MModAbs | MModMReg, &SrcResult))
{
case ModMReg: /* BAsmCode[1] sicher absolut darstellbar, da Rn vorher */
/* abgefangen wird! */
BAsmCode[0] = 0xc5 + Code;
AdrLong = SFRStart() + (((Word)BAsmCode[1]) << 1);
CalcPage(&AdrLong, True);
BAsmCode[2] = Lo(AdrLong);
BAsmCode[3] = Hi(AdrLong);
BAsmCode[1] = SrcResult.Vals[0];
CodeLen = 4;
break;
case ModAbs:
CodeLen = 2 + SrcResult.Cnt;
BAsmCode[0] = 0xc2 + Code;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
}
break;
}
case ModAbs:
{
tAdrResult SrcResult;
OpSize = eSymbolSize8Bit;
memcpy(BAsmCode
+ 2, DestResult.
Vals, DestResult.
Cnt);
switch (DecodeAdr(&ArgStr[2], MModMReg, &SrcResult))
{
case ModMReg:
CodeLen = 4;
BAsmCode[0] = 0xc5 + Code;
BAsmCode[1] = SrcResult.Vals[0];
break;
}
break;
}
}
}
}
static void DecodePUSH_POP(Word Code)
{
if (ChkArgCnt(1, 1))
{
tAdrResult Result;
switch (DecodeAdr(&ArgStr[1], MModMReg | ((Code & 0x10) ? M_Dest : 0), &Result))
{
case ModMReg:
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] = Result.Vals[0];
if (SPChanged) WrXError(ErrNum_Pipeline, RegNames[5]);
break;
}
}
}
static void DecodeSCXT(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
tAdrResult Result;
switch (DecodeAdr(&ArgStr[1], MModMReg | M_Dest, &Result))
{
case ModMReg:
BAsmCode[1] = Result.Vals[0];
if (DecodeAdr(&ArgStr[2], MModAbs | MModImm, &Result) != ModNone)
{
CodeLen = 4; BAsmCode[0] = 0xc6 + (Ord(Result.Type == ModAbs) << 4);
memcpy(BAsmCode
+ 2, Result.
Vals, 2);
}
break;
}
}
}
static void DecodeALU2(Word Code)
{
LongInt AdrLong;
OpSize = (tSymbolSize)Hi(Code);
Code = (1 - OpSize) + (Lo(Code) << 4);
if (ChkArgCnt(2, 2))
{
tAdrResult DestResult;
switch (DecodeAdr(&ArgStr[1], MModReg | MModMReg | MModAbs | M_Dest, &DestResult))
{
case ModReg:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModReg | MModIReg | MModPostInc | MModAbs | MModImm, &SrcResult))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
case ModIReg:
if (SrcResult.Mode > 3) WrError(ErrNum_InvAddrMode);
else
{
CodeLen = 2;
BAsmCode[0] = 0x08 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + 8 + SrcResult.Mode;
}
break;
case ModPostInc:
if (SrcResult.Mode > 3) WrError(ErrNum_InvAddrMode);
else
{
CodeLen = 2;
BAsmCode[0] = 0x08 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + 12 + SrcResult.Mode;
}
break;
case ModAbs:
CodeLen = 4;
BAsmCode[0] = 0x02 + Code;
BAsmCode[1] = 0xf0 + DestResult.Mode;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
case ModImm:
{
Boolean IsShort = WordVal(&SrcResult) <= 7;
if (!SrcResult.ForceSize)
SrcResult.ForceSize = IsShort ? eForceShort : eForceLong;
if (SrcResult.ForceSize == eForceShort)
{
if (!IsShort && !mSymbolQuestionable(SrcResult.SymFlags)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
else
{
CodeLen = 2;
BAsmCode[0] = 0x08 + Code;
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Vals[0];
}
}
else
{
CodeLen = 4;
BAsmCode[0] = 0x06 + Code;
BAsmCode[1] = 0xf0 + DestResult.Mode;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, 2);
}
break;
}
}
break;
}
case ModMReg:
{
tAdrResult SrcResult;
BAsmCode[1] = DestResult.Vals[0];
switch (DecodeAdr(&ArgStr[2], MModAbs | MModMReg | MModImm, &SrcResult))
{
case ModAbs:
CodeLen = 4;
BAsmCode[0] = 0x02 + Code;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, SrcResult.
Cnt);
break;
case ModMReg: /* BAsmCode[1] sicher absolut darstellbar, da Rn vorher */
/* abgefangen wird! */
BAsmCode[0] = 0x04 + Code;
AdrLong = SFRStart() + (((Word)BAsmCode[1]) << 1);
CalcPage(&AdrLong, True);
BAsmCode[2] = Lo(AdrLong);
BAsmCode[3] = Hi(AdrLong);
BAsmCode[1] = SrcResult.Vals[0];
CodeLen = 4;
break;
case ModImm:
CodeLen = 4;
BAsmCode[0] = 0x06 + Code;
memcpy(BAsmCode
+ 2, SrcResult.
Vals, 2);
break;
}
break;
}
case ModAbs:
{
tAdrResult SrcResult;
memcpy(BAsmCode
+ 2, DestResult.
Vals, DestResult.
Cnt);
switch (DecodeAdr(&ArgStr[2], MModMReg, &SrcResult))
{
case ModMReg:
CodeLen = 4;
BAsmCode[0] = 0x04 + Code;
BAsmCode[1] = SrcResult.Vals[0];
break;
}
break;
}
}
}
}
static void DecodeCPL_NEG(Word Code)
{
OpSize = (tSymbolSize)Hi(Code);
Code = Lo(Code) + ((1 - OpSize) << 5);
if (ChkArgCnt(1, 1))
{
tAdrResult Result;
if (DecodeAdr(&ArgStr[1], MModReg | M_Dest, &Result) == ModReg)
{
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] = Result.Mode << 4;
}
}
}
static void DecodeDiv(Word Code)
{
if (ChkArgCnt(1, 1))
{
tAdrResult Result;
if (DecodeAdr(&ArgStr[1], MModReg, &Result) == ModReg)
{
CodeLen = 2;
BAsmCode[0] = 0x4b + (Code << 4);
BAsmCode[1] = Result.Mode * 0x11;
}
}
}
static void DecodeLoop(Word Code)
{
if (ChkArgCnt(2, 2))
{
tAdrResult Result;
if (DecodeAdr(&ArgStr[1], MModReg | M_Dest, &Result) == ModReg)
{
BAsmCode[1] = Result.Mode;
switch (DecodeAdr(&ArgStr[2], MModAbs | MModImm, &Result))
{
case ModAbs:
CodeLen = 4;
BAsmCode[0] = Code + 2;
BAsmCode[1] += 0xf0;
memcpy(BAsmCode
+ 2, Result.
Vals, 2);
break;
case ModImm:
{
Boolean IsShort = WordVal(&Result) < 16;
if (!Result.ForceSize)
Result.ForceSize = IsShort ? eForceShort : eForceLong;
if (Result.ForceSize == eForceShort)
{
if (!IsShort && !mSymbolQuestionable(Result.SymFlags)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
else
{
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] += (WordVal(&Result) << 4);
}
}
else
{
CodeLen = 4;
BAsmCode[0] = Code + 6;
BAsmCode[1] += 0xf0;
memcpy(BAsmCode
+ 2, Result.
Vals, 2);
}
break;
}
}
}
}
}
static void DecodeMul(Word Code)
{
if (ChkArgCnt(2, 2))
{
tAdrResult DestResult;
switch (DecodeAdr(&ArgStr[1], MModReg, &DestResult))
{
case ModReg:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModReg, &SrcResult))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0x0b + (Code << 4);
BAsmCode[1] = (DestResult.Mode << 4) + SrcResult.Mode;
break;
}
break;
}
}
}
}
static void DecodeShift(Word Code)
{
if (ChkArgCnt(2, 2))
{
tAdrResult DestResult;
OpSize = eSymbolSize16Bit;
switch (DecodeAdr(&ArgStr[1], MModReg | M_Dest, &DestResult))
{
case ModReg:
{
tAdrResult SrcResult;
switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | M_Dest, &SrcResult))
{
case ModReg:
BAsmCode[0] = Code;
BAsmCode[1] = SrcResult.Mode + (DestResult.Mode << 4);
CodeLen = 2;
break;
case ModImm:
if ((WordVal(&SrcResult) > 15) && !mSymbolQuestionable(SrcResult.SymFlags)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
else
{
BAsmCode[0] = Code + 0x10;
BAsmCode[1] = (WordVal(&SrcResult) << 4) + DestResult.Mode;
CodeLen = 2;
}
break;
}
break;
}
}
}
}
static void DecodeBit2(Word Code)
{
Byte BOfs1, BOfs2;
Word BAdr1, BAdr2;
if (ChkArgCnt(2, 2)
&& DecodeBitAddr(&ArgStr[1], &BAdr1, &BOfs1, False)
&& DecodeBitAddr(&ArgStr[2], &BAdr2, &BOfs2, False))
{
CodeLen = 4;
BAsmCode[0] = Code;
BAsmCode[1] = BAdr2;
BAsmCode[2] = BAdr1;
BAsmCode[3] = (BOfs2 << 4) + BOfs1;
}
}
static void DecodeBCLR_BSET(Word Code)
{
Byte BOfs;
Word BAdr;
if (ChkArgCnt(1, 1)
&& DecodeBitAddr(&ArgStr[1], &BAdr, &BOfs, False))
{
CodeLen = 2;
BAsmCode[0] = (BOfs << 4) + Code;
BAsmCode[1] = BAdr;
}
}
static void DecodeBFLDH_BFLDL(Word Code)
{
Byte BOfs;
Word BAdr;
if (ChkArgCnt(3, 3))
{
strmaxcat(ArgStr[1].str.p_str, ".0", STRINGSIZE);
if (DecodeBitAddr(&ArgStr[1], &BAdr, &BOfs, False))
{
tAdrResult Result;
OpSize = eSymbolSize8Bit;
BAsmCode[1] = BAdr;
if (DecodeAdr(&ArgStr[2], MModImm, &Result) == ModImm)
{
BAsmCode[2] = Result.Vals[0];
if (DecodeAdr(&ArgStr[3], MModImm, &Result) == ModImm)
{
BAsmCode[3] = Result.Vals[0];
CodeLen = 4;
BAsmCode[0] = Code;
if (Code & 0x10)
{
BAdr = BAsmCode[2];
BAsmCode[2] = BAsmCode[3];
BAsmCode[3] = BAdr;
}
}
}
}
}
}
static void DecodeJMP(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 2))
{
Byte cond_code;
tAdrResult Result;
if (ArgCnt == 1)
cond_code = TrueCond;
else if (!DecodeCondition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
switch (DecodeAdr(&ArgStr[ArgCnt], MModAbs | MModLAbs | MModIReg | M_InCode, &Result))
{
case ModLAbs:
if (cond_code != COND_CODE_TRUE) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
else
{
CodeLen = 2 + Result.Cnt;
BAsmCode[0] = 0xfa;
BAsmCode[1] = Result.Mode;
memcpy(BAsmCode
+ 2, Result.
Vals, Result.
Cnt);
}
break;
case ModAbs:
{
LongInt AdrDist = WordVal(&Result) - (EProgCounter() + 2);
Boolean IsShort = (AdrDist <= 254) && (AdrDist >= -256) && ((AdrDist & 1) == 0);
if (!Result.ForceSize)
Result.ForceSize = IsShort ? eForceShort : eForceLong;
if (Result.ForceSize == eForceShort)
{
if (!IsShort && !mSymbolQuestionable(Result.SymFlags)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[ArgCnt]);
else
{
CodeLen = 2;
BAsmCode[0] = 0x0d + (cond_code << 4);
BAsmCode[1] = (AdrDist / 2) & 0xff;
}
}
else
{
CodeLen = 2 + Result.Cnt;
BAsmCode[0] = 0xea;
BAsmCode[1] = cond_code << 4;
memcpy(BAsmCode
+ 2, Result.
Vals, Result.
Cnt);
}
break;
}
case ModIReg:
CodeLen = 2; BAsmCode[0] = 0x9c;
BAsmCode[1] = (cond_code << 4) + Result.Mode;
break;
}
}
}
static void DecodeCALL(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 2))
{
Byte cond_code;
tAdrResult Result;
if (ArgCnt == 1)
cond_code = COND_CODE_TRUE;
else if (!DecodeCondition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
switch (DecodeAdr(&ArgStr[ArgCnt], MModAbs | MModLAbs | MModIReg | M_InCode, &Result))
{
case ModLAbs:
if (cond_code != COND_CODE_TRUE) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
else
{
CodeLen = 2 + Result.Cnt;
BAsmCode[0] = 0xda;
BAsmCode[1] = Result.Mode;
memcpy(BAsmCode
+ 2, Result.
Vals, Result.
Cnt);
}
break;
case ModAbs:
{
LongInt AdrLong = WordVal(&Result) - (EProgCounter() + 2);
Boolean IsShort = (AdrLong <= 254) && (AdrLong >= -256) && ((AdrLong & 1) == 0);
if (!Result.ForceSize && (cond_code == COND_CODE_TRUE))
Result.ForceSize = IsShort ? eForceShort : eForceLong;
if (Result.ForceSize == eForceShort)
{
if (!IsShort && !mSymbolQuestionable(Result.SymFlags)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[ArgCnt]);
else
{
CodeLen = 2;
BAsmCode[0] = 0xbb;
BAsmCode[1] = (AdrLong / 2) & 0xff;
}
}
else
{
CodeLen = 2 + Result.Cnt;
BAsmCode[0] = 0xca;
BAsmCode[1] = 0x00 + (cond_code << 4);
memcpy(BAsmCode
+ 2, Result.
Vals, Result.
Cnt);
}
break;
}
case ModIReg:
CodeLen = 2;
BAsmCode[0] = 0xab;
BAsmCode[1] = (cond_code << 4) + Result.Mode;
break;
}
}
}
static void DecodeJMPR(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 2))
{
Byte cond_code;
Boolean OK;
tSymbolFlags Flags;
LongInt AdrLong;
if (ArgCnt == 1)
cond_code = COND_CODE_TRUE;
else if (!DecodeCondition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], MemInt, &OK, &Flags) - (EProgCounter() + 2);
if (OK)
{
if (AdrLong & 1) WrError(ErrNum_DistIsOdd);
else if (!mSymbolQuestionable(Flags) && ((AdrLong > 254) || (AdrLong < -256))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 2;
BAsmCode[0] = 0x0d + (cond_code << 4);
BAsmCode[1] = (AdrLong / 2) & 0xff;
}
}
}
}
static void DecodeCALLR(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
Boolean OK;
tSymbolFlags Flags;
LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], MemInt, &OK, &Flags) - (EProgCounter() + 2);
if (OK)
{
if (AdrLong & 1) WrError(ErrNum_DistIsOdd);
else if (!mSymbolQuestionable(Flags) && ((AdrLong > 254) || (AdrLong < -256))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 2;
BAsmCode[0] = 0xbb;
BAsmCode[1] = (AdrLong / 2) & 0xff;
}
}
}
}
static void DecodeJMPA_CALLA(Word Code)
{
if (ChkArgCnt(1, 2))
{
Byte cond_code;
Boolean OK;
LongInt AdrLong;
tSymbolFlags Flags;
if (ArgCnt == 1)
cond_code = COND_CODE_TRUE;
else if (!DecodeCondition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], MemInt, &OK, &Flags);
if (OK && ChkSamePage(AdrLong, EProgCounter(), 16, Flags))
{
CodeLen = 4;
BAsmCode[0] = Code;
BAsmCode[1] = 0x00 + (cond_code << 4);
BAsmCode[2] = Lo(AdrLong);
BAsmCode[3] = Hi(AdrLong);
}
}
}
static void DecodeJMPS_CALLS(Word Code)
{
if (ChkArgCnt(1, 2))
{
Boolean OK;
Word AdrWord;
Byte AdrBank;
LongInt AdrLong;
if (ArgCnt == 1)
{
AdrLong = EvalStrIntExpression(&ArgStr[1], MemInt, &OK);
AdrWord = AdrLong & 0xffff;
AdrBank = AdrLong >> 16;
}
else
{
AdrWord = EvalStrIntExpression(&ArgStr[2], UInt16, &OK);
AdrBank = OK ? EvalStrIntExpression(&ArgStr[1], MemInt2, &OK) : 0;
}
if (OK)
{
CodeLen = 4;
BAsmCode[0] = Code;
BAsmCode[1] = AdrBank;
BAsmCode[2] = Lo(AdrWord);
BAsmCode[3] = Hi(AdrWord);
}
}
}
static void DecodeJMPI_CALLI(Word Code)
{
if (ChkArgCnt(1, 2))
{
Byte cond_code;
tAdrResult Result;
if (ArgCnt == 1)
cond_code = COND_CODE_TRUE;
else if (!DecodeCondition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
switch (DecodeAdr(&ArgStr[ArgCnt], MModIReg | M_InCode, &Result))
{
case ModIReg:
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] = Result.Mode + (cond_code << 4);
break;
}
}
}
static void DecodeBJmp(Word Code)
{
Byte BOfs;
Word BAdr;
if (ChkArgCnt(2, 2)
&& DecodeBitAddr(&ArgStr[1], &BAdr, &BOfs, False))
{
Boolean OK;
tSymbolFlags Flags;
LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[2], MemInt, &OK, &Flags) - (EProgCounter() + 4);
if (OK)
{
if (AdrLong & 1) WrError(ErrNum_DistIsOdd);
else if (!mSymbolQuestionable(Flags) && ((AdrLong < -256) || (AdrLong > 254))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 4; BAsmCode[0] = 0x8a + (Code << 4);
BAsmCode[1] = BAdr;
BAsmCode[2] = (AdrLong / 2) & 0xff;
BAsmCode[3] = BOfs << 4;
}
}
}
}
static void DecodePCALL(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
tAdrResult Result;
switch (DecodeAdr(&ArgStr[1], MModMReg, &Result))
{
case ModMReg:
BAsmCode[1] = Result.Vals[0];
switch (DecodeAdr(&ArgStr[2], MModAbs | M_InCode, &Result))
{
case ModAbs:
CodeLen = 4;
BAsmCode[0] = 0xe2;
memcpy(BAsmCode
+ 2, Result.
Vals, 2);
break;
}
break;
}
}
}
static void DecodeRETP(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
tAdrResult Result;
switch (DecodeAdr(&ArgStr[1], MModMReg, &Result))
{
case ModMReg:
BAsmCode[1] = Result.Vals[0];
BAsmCode[0] = 0xeb;
CodeLen = 2;
if (SPChanged)
WrXError(ErrNum_Pipeline, RegNames[5]);
break;
}
}
}
static void DecodeTRAP(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_InvAddrMode);
else
{
Boolean OK;
BAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt7, &OK) << 1;
if (OK)
{
BAsmCode[0] = 0x9b;
CodeLen = 2;
}
}
}
static void DecodeATOMIC(Word Code)
{
Byte HReg;
UNUSED(Code);
if (ChkArgCnt(1, 1)
&& ChkMinCPU(CPU80C167)
&& DecodePref(&ArgStr[1], &HReg))
{
CodeLen = 2;
BAsmCode[0] = 0xd1;
BAsmCode[1] = HReg << 4;
}
}
static void DecodeEXTR(Word Code)
{
Byte HReg;
UNUSED(Code);
if (ChkArgCnt(1, 1)
&& ChkMinCPU(CPU80C167)
&& DecodePref(&ArgStr[1], &HReg))
{
CodeLen = 2;
BAsmCode[0] = 0xd1;
BAsmCode[1] = 0x80 + (HReg << 4);
ExtCounter = HReg + 1;
ExtSFRs = True;
}
}
static void DecodeEXTP_EXTPR(Word Code)
{
Byte HReg;
if (ChkArgCnt(2, 2)
&& ChkMinCPU(CPU80C167)
&& DecodePref(&ArgStr[2], &HReg))
{
tAdrResult Result;
switch (DecodeAdr(&ArgStr[1], MModReg | MModImm, &Result))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xdc;
BAsmCode[1] = Code + 0x40 + (HReg << 4) + Result.Mode;
ExtCounter = HReg + 1;
MemMode = MemModeZeroPage;
break;
case ModImm:
CodeLen = 4;
BAsmCode[0] = 0xd7;
BAsmCode[1] = Code + 0x40 + (HReg << 4);
BAsmCode[2] = WordVal(&Result) & 0xff;
BAsmCode[3] = (WordVal(&Result) >> 8) & 3;
ExtCounter = HReg + 1;
MemMode = MemModeFixedPage;
MemPage = WordVal(&Result) & 0x3ff;
break;
}
}
}
static void DecodeEXTS_EXTSR(Word Code)
{
Byte HReg;
OpSize = eSymbolSize8Bit;
if (ChkArgCnt(2, 2)
&& ChkMinCPU(CPU80C167)
&& DecodePref(&ArgStr[2], &HReg))
{
tAdrResult Result;
switch (DecodeAdr(&ArgStr[1], MModReg | MModImm, &Result))
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xdc;
BAsmCode[1] = Code + 0x00 + (HReg << 4) + Result.Mode;
ExtCounter = HReg + 1;
MemMode = MemModeNoCheck;
break;
case ModImm:
CodeLen = 4;
BAsmCode[0] = 0xd7;
BAsmCode[1] = Code + 0x00 + (HReg << 4);
BAsmCode[2] = Result.Vals[0];
BAsmCode[3] = 0;
ExtCounter = HReg + 1;
MemMode = MemModeFixedBank;
MemPage = Result.Vals[0];
break;
}
}
}
static void DecodeBIT(Word Code)
{
Word Adr;
Byte Bit;
UNUSED(Code);
if (ChkArgCnt(1, 1)
&& DecodeBitAddr(&ArgStr[1], &Adr, &Bit, True))
{
PushLocHandle(-1);
EnterIntSymbol(&LabPart, (Adr << 4) + Bit, SegNone, False);
PopLocHandle();
as_snprintf(ListLine, STRINGSIZE, "=%02xH.%1x", (unsigned)Adr, (unsigned)Bit);
}
}
/*-------------------------------------------------------------------------*/
static void AddBInstTable(const char *NName, Word NCode, InstProc Proc)
{
char BName[30];
AddInstTable(InstTable, NName, NCode | (eSymbolSize16Bit << 8), Proc);
as_snprintf(BName, sizeof(BName), "%sB", NName);
AddInstTable(InstTable, BName, NCode | (eSymbolSize8Bit << 8), Proc);
}
static void AddFixed(const char *NName, CPUVar NMin, Word NCode1, Word NCode2)
{
order_array_rsv_end(FixedOrders, BaseOrder);
FixedOrders[InstrZ].MinCPU = NMin;
FixedOrders[InstrZ].Code1 = NCode1;
FixedOrders[InstrZ].Code2 = NCode2;
AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
}
static void AddShift(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeShift);
}
static void AddBit2(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBit2);
}
static void AddLoop(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeLoop);
}
static void AddCondition(const char *NName, Byte NCode)
{
order_array_rsv_end(Conditions, Condition);
Conditions[InstrZ].Name = NName;
Conditions[InstrZ++].Code = NCode;
}
static void InitFields(void)
{
InstTable = CreateInstTable(201);
SetDynamicInstTable(InstTable);
AddBInstTable("MOV", 0, DecodeMOV);
AddInstTable(InstTable, "MOVBS", 0x10, DecodeMOVBS_MOVBZ);
AddInstTable(InstTable, "MOVBZ", 0x00, DecodeMOVBS_MOVBZ);
AddInstTable(InstTable, "PUSH", 0xec, DecodePUSH_POP);
AddInstTable(InstTable, "POP", 0xfc, DecodePUSH_POP);
AddInstTable(InstTable, "SCXT", 0, DecodeSCXT);
AddBInstTable("CPL", 0x91, DecodeCPL_NEG);
AddBInstTable("NEG", 0x81, DecodeCPL_NEG);
AddInstTable(InstTable, "BCLR", 0x0e, DecodeBCLR_BSET);
AddInstTable(InstTable, "BSET", 0x0f, DecodeBCLR_BSET);
AddInstTable(InstTable, "BFLDL", 0x0a, DecodeBFLDH_BFLDL);
AddInstTable(InstTable, "BFLDH", 0x1a, DecodeBFLDH_BFLDL);
AddInstTable(InstTable, "JMP", 0, DecodeJMP);
AddInstTable(InstTable, "CALL", 0, DecodeCALL);
AddInstTable(InstTable, "JMPR", 0, DecodeJMPR);
AddInstTable(InstTable, "CALLR", 0, DecodeCALLR);
AddInstTable(InstTable, "JMPA", 0xea, DecodeJMPA_CALLA);
AddInstTable(InstTable, "CALLA", 0xca, DecodeJMPA_CALLA);
AddInstTable(InstTable, "JMPS", 0xfa, DecodeJMPS_CALLS);
AddInstTable(InstTable, "CALLS", 0xda, DecodeJMPS_CALLS);
AddInstTable(InstTable, "JMPI", 0x9c, DecodeJMPI_CALLI);
AddInstTable(InstTable, "CALLI", 0xab, DecodeJMPI_CALLI);
AddInstTable(InstTable, "PCALL", 0, DecodePCALL);
AddInstTable(InstTable, "RETP", 0, DecodeRETP);
AddInstTable(InstTable, "TRAP", 0, DecodeTRAP);
AddInstTable(InstTable, "ATOMIC", 0, DecodeATOMIC);
AddInstTable(InstTable, "EXTR", 0, DecodeEXTR);
AddInstTable(InstTable, "EXTP", 0x00, DecodeEXTP_EXTPR);
AddInstTable(InstTable, "EXTPR", 0x80, DecodeEXTP_EXTPR);
AddInstTable(InstTable, "EXTS", 0x00, DecodeEXTS_EXTSR);
AddInstTable(InstTable, "EXTSR", 0x80, DecodeEXTS_EXTSR);
InstrZ = 0;
AddFixed("DISWDT", CPU80C166, 0x5aa5, 0xa5a5);
AddFixed("EINIT" , CPU80C166, 0x4ab5, 0xb5b5);
AddFixed("IDLE" , CPU80C166, 0x7887, 0x8787);
AddFixed("NOP" , CPU80C166, 0x00cc, 0x0000);
AddFixed("PWRDN" , CPU80C166, 0x6897, 0x9797);
AddFixed("RET" , CPU80C166, 0x00cb, 0x0000);
AddFixed("RETI" , CPU80C166, 0x88fb, 0x0000);
AddFixed("RETS" , CPU80C166, 0x00db, 0x0000);
AddFixed("SRST" , CPU80C166, 0x48b7, 0xb7b7);
AddFixed("SRVWDT", CPU80C166, 0x58a7, 0xa7a7);
InstrZ = 0;
AddCondition("UC" , COND_CODE_TRUE); AddCondition("Z" , 0x2);
AddCondition("NZ" , 0x3); AddCondition("V" , 0x4);
AddCondition("NV" , 0x5); AddCondition("N" , 0x6);
AddCondition("NN" , 0x7); AddCondition("C" , 0x8);
AddCondition("NC" , 0x9); AddCondition("EQ" , 0x2);
AddCondition("NE" , 0x3); AddCondition("ULT", 0x8);
AddCondition("ULE", 0xf); AddCondition("UGE", 0x9);
AddCondition("UGT", 0xe); AddCondition("SLT", 0xc);
AddCondition("SLE", 0xb); AddCondition("SGE", 0xd);
AddCondition("SGT", 0xa); AddCondition("NET", 0x1);
AddCondition(NULL, 0);
InstrZ = 0;
AddBInstTable("ADD" , InstrZ++, DecodeALU2);
AddBInstTable("ADDC", InstrZ++, DecodeALU2);
AddBInstTable("SUB" , InstrZ++, DecodeALU2);
AddBInstTable("SUBC", InstrZ++, DecodeALU2);
AddBInstTable("CMP" , InstrZ++, DecodeALU2);
AddBInstTable("XOR" , InstrZ++, DecodeALU2);
AddBInstTable("AND" , InstrZ++, DecodeALU2);
AddBInstTable("OR" , InstrZ++, DecodeALU2);
AddShift("ASHR", 0xac); AddShift("ROL" , 0x0c);
AddShift("ROR" , 0x2c); AddShift("SHL" , 0x4c);
AddShift("SHR" , 0x6c);
AddBit2("BAND", 0x6a); AddBit2("BCMP" , 0x2a);
AddBit2("BMOV", 0x4a); AddBit2("BMOVN", 0x3a);
AddBit2("BOR" , 0x5a); AddBit2("BXOR" , 0x7a);
AddLoop("CMPD1", 0xa0); AddLoop("CMPD2", 0xb0);
AddLoop("CMPI1", 0x80); AddLoop("CMPI2", 0x90);
InstrZ = 0;
AddInstTable(InstTable, "DIV" , InstrZ++, DecodeDiv);
AddInstTable(InstTable, "DIVU" , InstrZ++, DecodeDiv);
AddInstTable(InstTable, "DIVL" , InstrZ++, DecodeDiv);
AddInstTable(InstTable, "DIVLU", InstrZ++, DecodeDiv);
InstrZ = 0;
AddInstTable(InstTable, "JB" , InstrZ++, DecodeBJmp);
AddInstTable(InstTable, "JNB" , InstrZ++, DecodeBJmp);
AddInstTable(InstTable, "JBC" , InstrZ++, DecodeBJmp);
AddInstTable(InstTable, "JNBS" , InstrZ++, DecodeBJmp);
InstrZ = 0;
AddInstTable(InstTable, "MUL" , InstrZ++, DecodeMul);
AddInstTable(InstTable, "MULU" , InstrZ++, DecodeMul);
AddInstTable(InstTable, "PRIOR", InstrZ++, DecodeMul);
AddInstTable(InstTable, "BIT" , 0, DecodeBIT);
AddInstTable(InstTable, "REG" , 0, CodeREG);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
order_array_free(FixedOrders);
order_array_free(Conditions);
}
static void MakeCode_166(void)
{
int z;
CodeLen = 0;
DontPrint = False;
OpSize = eSymbolSize16Bit;
/* zu ignorierendes */
if (Memo(""))
return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(False))
return;
/* Pipeline-Flags weiterschalten */
SPChanged = N_SPChanged; N_SPChanged = False;
CPChanged = N_CPChanged; N_CPChanged = False;
for (z = 0; z < DPPCount; z++)
{
DPPChanged[z] = N_DPPChanged[z];
N_DPPChanged[z] = False;
}
/* Praefixe herunterzaehlen */
if (ExtCounter >= 0)
if (--ExtCounter < 0)
{
MemMode = MemModeStd;
ExtSFRs = False;
}
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_166(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on C16x
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_166(char *pArg, TempResult *pResult)
{
tRegInt Erg;
tSymbolSize Size;
if (IsRegCore(pArg, &Erg, &Size))
{
pResult->Typ = TempReg;
pResult->DataSize = Size;
pResult->Contents.RegDescr.Reg = Erg;
pResult->Contents.RegDescr.Dissect = DissectReg_166;
pResult->Contents.RegDescr.compare = NULL;
}
}
static void InitCode_166(void)
{
int z;
for (z = 0; z < DPPCount; z++)
{
DPPAssumes[z] = z;
N_DPPChanged[z] = False;
}
N_CPChanged = False;
N_SPChanged = False;
MemMode = MemModeStd;
ExtSFRs = False;
ExtCounter = (-1);
}
static Boolean IsDef_166(void)
{
return (Memo("BIT")) || (Memo("REG"));
}
static void SwitchFrom_166(void)
{
DeinitFields();
}
static void SwitchTo_166(void)
{
Byte z;
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
OpSize = eSymbolSize16Bit;
PCSymbol = "$";
HeaderID = 0x4c;
NOPCode = 0xcc00;
DivideChars = ",";
HasAttrs = False;
ValidSegs = (1 << SegCode);
Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
MakeCode = MakeCode_166;
IsDef = IsDef_166;
InternSymbol = InternSymbol_166;
DissectReg = DissectReg_166;
SwitchFrom = SwitchFrom_166;
if (MomCPU == CPU80C166)
{
MemInt = UInt18;
MemInt2 = UInt2;
ASSUME166s[0].Max = 15;
SegLimits[SegCode] = 0x3ffffl;
}
else
{
MemInt = UInt24;
MemInt2 = UInt8;
ASSUME166s[0].Max = 1023;
SegLimits[SegCode] = 0xffffffl;
}
for (z = 1; z < 4; z++)
ASSUME166s[z].Max = ASSUME166s[0].Max;
pASSUMERecs = ASSUME166s;
ASSUMERecCnt = ASSUME166Count;
InitFields();
}
void code166_init(void)
{
CPU80C166 = AddCPU("80C166", SwitchTo_166);
CPU80C167 = AddCPU("80C167", SwitchTo_166);
CPU80C167CS = AddCPU("80C167CS", SwitchTo_166);
AddInitPassProc(InitCode_166);
}