/* code97c241.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator TLCS-9000 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "nls.h"
#include "strutil.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "asmitree.h"
#include "asmcode.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code97c241.h"
typedef struct
{
Byte Code;
Byte Mask; /* B0..2=OpSizes, B4=-MayImm, B5=-MayReg */
} RMWOrder;
static CPUVar CPU97C241;
static int OpSize, OpSize2;
static Integer LowLim4, LowLim8;
static Boolean AdrOK;
static Word AdrMode, AdrMode2;
static Byte AdrCnt2;
static Word AdrVals[2], AdrVals2[2];
static int AdrInc;
static Word Prefs[2];
static Boolean PrefUsed[2];
static char Format;
static Boolean MinOneIs0;
static RMWOrder *RMWOrders;
static const char Conditions[][4] =
{
"C", "NC",
"Z", "NZ",
"OV", "NOV",
"MI", "PL",
"LE", "GT",
"LT", "GE",
"ULE", "UGT",
"N", "A",
"ULT", "UGE",
"EQ", "NE"
};
/*--------------------------------------------------------------------------*/
static int CheckForcePrefix(const char *pArg, Boolean *pForce)
{
if (*pArg == '>')
{
*pForce = True;
return 1;
}
return 0;
}
static void AddSignedPrefix(Byte Index, Byte MaxBits, LongInt Value, Boolean Force)
{
LongInt Max;
Max = 1l << (MaxBits -1);
if (Force || ((Value < -Max) || (Value >= Max)))
{
PrefUsed[Index] = True;
Prefs[Index] = (Value >> MaxBits) & 0x7ff;
}
}
static Boolean AddRelPrefix(Byte Index, Byte MaxBits, LongInt *Value, Boolean Force)
{
LongInt Max1,Max2;
Max1 = 1l << (MaxBits - 1);
Max2 = 1l << (MaxBits + 10);
if ((*Value < -Max2) || (*Value >= Max2)) WrError(ErrNum_JmpDistTooBig);
else
{
if (Force || ((*Value < -Max1) || (*Value >= Max1)))
{
PrefUsed[Index] = True;
Prefs[Index] = ((*Value) >> MaxBits) & 0x7ff;
}
return True;
}
return False;
}
static void AddAbsPrefix(Byte Index, Byte MaxBits, LongInt Value, Boolean Force)
{
LongInt Dist;
Dist = 1l << (MaxBits - 1);
if (Force || ((Value >= Dist) && (Value < 0x1000000 - Dist)))
{
PrefUsed[Index] = True;
Prefs[Index] = (Value >> MaxBits) & 0x7ff;
}
}
static void InsertSinglePrefix(Byte Index)
{
if (PrefUsed[Index])
{
memmove(WAsmCode
+ 1, WAsmCode
+ 0, CodeLen
);
WAsmCode[0] = Prefs[Index] + 0xd000 + (((Word)Index) << 11);
CodeLen += 2;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, Byte *pResult, tSymbolSize *pSize)
* \brief check whether argument is a CPU register
* \param pArg source argument
* \param pResult register number if yes
* \param pSize register size if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore(const char *pArg, Byte *pResult, tSymbolSize *pSize)
{
Boolean OK;
if (as_toupper(*pArg) != 'R')
return False;
if ((l > 4) || (l < 3))
return False;
switch (as_toupper(pArg[1]))
{
case 'B':
*pSize = eSymbolSize8Bit;
break;
case 'W':
*pSize = eSymbolSize16Bit;
break;
case 'D':
*pSize = eSymbolSize32Bit;
break;
default:
return False;
}
*pResult = ConstLongInt(pArg + 2, &OK, 10);
if (!OK || (*pResult > 15))
return False;
if ((*pSize == eSymbolSize32Bit) && Odd(*pResult))
return False;
return True;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_97C241(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - TLCS-9000 variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_97C241(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
{
switch (InpSize)
{
case eSymbolSize8Bit:
as_snprintf(pDest, DestSize, "RB%u", (unsigned)Value);
break;
case eSymbolSize16Bit:
as_snprintf(pDest, DestSize, "RW%u", (unsigned)Value);
break;
case eSymbolSize32Bit:
as_snprintf(pDest, DestSize, "RD%u", (unsigned)Value);
break;
default:
as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
}
}
/*!------------------------------------------------------------------------
* \fn tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pResult, tSymbolSize *pSize, Boolean MustBeReg)
* \brief check whether argument is a CPU register or register alias
* \param pArg source argument
* \param pResult register number if yes
* \param pSize register size if yes
* \param MustBeReg True if register is expected
* \return True if yes
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pResult, tSymbolSize *pSize, Boolean MustBeReg)
{
tRegEvalResult RegEvalResult;
tEvalResult EvalResult;
tRegDescr RegDescr;
if (DecodeRegCore(pArg->str.p_str, pResult, pSize))
return eIsReg;
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
if (eIsReg == RegEvalResult)
{
*pResult = RegDescr.Reg;
*pSize = EvalResult.DataSize;
}
return RegEvalResult;
}
static Boolean DecodeSpecReg(char *Asc, Byte *Result)
{
if (!as_strcasecmp(Asc, "SP")) *Result = 0x8c;
else if (!as_strcasecmp(Asc, "ISP")) *Result = 0x81;
else if (!as_strcasecmp(Asc, "ESP")) *Result = 0x83;
else if (!as_strcasecmp(Asc, "PBP")) *Result = 0x05;
else if (!as_strcasecmp(Asc, "CBP")) *Result = 0x07;
else if (!as_strcasecmp(Asc, "PSW")) *Result = 0x89;
else if (!as_strcasecmp(Asc, "IMC")) *Result = 0x0b;
else if (!as_strcasecmp(Asc, "CC")) *Result = 0x0e;
else return False;
return True;
}
static Boolean DecodeRegAdr(const tStrComp *pArg, Byte *pResult)
{
tSymbolSize Size;
if (DecodeReg(pArg, pResult, &Size, True) != eIsReg)
return False;
if (OpSize == eSymbolSizeUnknown)
OpSize = Size;
if (Size != OpSize)
{
WrError(ErrNum_ConfOpSizes);
return False;
}
*pResult &= 0x3f;
return True;
}
typedef enum
{
eImmNo,
eImmYes,
eImmAsAbs
} tImmAllow;
static void DecodeAdr(const tStrComp *pArg, Byte PrefInd, tImmAllow MayImm, Boolean MayReg)
{
#define FreeReg 0xff
#define SPReg 0xfe
#define PCReg 0xfd
Byte Reg;
String AdrPartStr;
tStrComp AdrPart, Remainder;
Boolean OK;
int ArgLen;
tSymbolSize Size;
tRegEvalResult RegEvalResult;
AdrCnt = 0; AdrOK = False;
StrCompMkTemp(&AdrPart, AdrPartStr, sizeof(AdrPartStr));
/* I. Speicheradresse */
if (IsIndirect(pArg->str.p_str))
{
Boolean ForcePrefix = False, MinFlag, NMinFlag;
tStrComp Arg, TmpComp;
String Tmp;
char *PMPos, *EPos;
Byte BaseReg, IndReg, ScaleFact;
tSymbolSize BaseRegSize, IndRegSize;
LongInt DispAcc;
StrCompMkTemp(&TmpComp, Tmp, sizeof(Tmp));
/* I.1. vorkonditionieren */
StrCompRefRight(&Arg, pArg, 1);
StrCompShorten(&Arg, 1);
KillPrefBlanksStrCompRef(&Arg);
KillPostBlanksStrComp(&Arg);
/* I.2. Predekrement */
if ((*Arg.str.p_str == '-') && (Arg.str.p_str[1] == '-'))
{
tStrComp RegComp;
StrCompRefRight(&RegComp, &Arg, 2);
if (DecodeReg(&RegComp, &Reg, &Size, True) == eIsReg)
{
switch (Size)
{
case eSymbolSize16Bit:
AdrMode = 0x50 + (Reg & 15);
AdrOK = True;
break;
case eSymbolSize32Bit:
AdrMode = 0x71 + (Reg & 14);
AdrOK = True;
break;
default:
WrStrErrorPos(ErrNum_InvAddrMode, &Arg);
break;
}
}
return;
}
/* I.3. Postinkrement */
ArgLen
= strlen(Arg.
str.
p_str);
if ((Arg.str.p_str[ArgLen - 1] == '+') && (Arg.str.p_str[ArgLen - 2] == '+'))
{
StrCompCopySub(&AdrPart, &Arg, 0, Arg.Pos.Len - 2);
if (DecodeReg(&AdrPart, &Reg, &Size, True) == eIsReg)
{
switch (Size)
{
case eSymbolSize16Bit:
AdrMode = 0x40 + (Reg & 15);
AdrOK = True;
break;
case eSymbolSize32Bit:
AdrMode = 0x70 + (Reg & 14);
AdrOK = True;
break;
default:
WrError(ErrNum_InvAddrMode);
break;
}
return;
}
}
/* I.4. Adresskomponenten zerlegen */
BaseReg = IndReg = FreeReg;
BaseRegSize = IndRegSize = eSymbolSizeUnknown;
ScaleFact = 0;
DispAcc = AdrInc;
MinFlag = False;
do
{
/* I.4.a. Trennzeichen suchen */
KillPrefBlanksStrCompRef(&Arg);
PMPos = indir_split_pos(Arg.str.p_str);
NMinFlag = (PMPos && (*PMPos == '-'));
if (PMPos)
{
StrCompSplitRef(&Arg, &Remainder, &Arg, PMPos);
KillPostBlanksStrComp(&Arg);
}
/* I.4.b. Indexregister mit Skalierung */
EPos = QuotPos(Arg.str.p_str, '*');
if (EPos)
{
StrCompCopySub(&TmpComp, &Arg, 0, EPos - Arg.str.p_str);
KillPostBlanksStrComp(&TmpComp);
}
ArgLen
= strlen(Arg.
str.
p_str);
if ((EPos == Arg.str.p_str + ArgLen - 2)
&& ((Arg.str.p_str[ArgLen - 1] == '1') || (Arg.str.p_str[ArgLen - 1] == '2') || (Arg.str.p_str[ArgLen - 1] == '4') || (Arg.str.p_str[ArgLen - 1] == '8'))
&& ((RegEvalResult = DecodeReg(&TmpComp, &Reg, &Size, False)) != eIsNoReg))
{
if (RegEvalResult == eRegAbort)
return;
if ((Size == eSymbolSize8Bit) || MinFlag || (IndReg != FreeReg))
{
WrError(ErrNum_InvAddrMode);
return;
}
IndReg = Reg;
IndRegSize = Size;
switch (Arg.str.p_str[ArgLen - 1])
{
case '1':
ScaleFact = 0;
break;
case '2':
ScaleFact = 1;
break;
case '4':
ScaleFact = 2;
break;
case '8':
ScaleFact = 3;
break;
}
}
/* I.4.c. Basisregister */
else if ((RegEvalResult = DecodeReg(&Arg, &Reg, &Size, False)) != eIsNoReg)
{
if (RegEvalResult == eRegAbort)
return;
if ((Size == eSymbolSize8Bit) || (MinFlag))
{
WrError(ErrNum_InvAddrMode);
return;
}
if (BaseReg == FreeReg)
{
BaseReg = Reg;
BaseRegSize = Size;
}
else if (IndReg == FreeReg)
{
IndReg = Reg;
IndRegSize = Size;
ScaleFact = 0;
}
else
{
WrStrErrorPos(ErrNum_InvAddrMode, &Arg);
return;
}
}
/* I.4.d. Sonderregister */
else if ((!as_strcasecmp(Arg.str.p_str, "PC")) || (!as_strcasecmp(Arg.str.p_str, "SP")))
{
if ((BaseReg != FreeReg) && (IndReg == FreeReg))
{
IndReg = BaseReg;
IndRegSize = BaseRegSize;
BaseReg = FreeReg;
ScaleFact = 0;
};
if ((BaseReg != FreeReg) || (MinFlag))
{
WrError(ErrNum_InvAddrMode);
return;
}
/*#warning here*/
BaseReg = as_strcasecmp(Arg.str.p_str, "SP") ? PCReg : SPReg;
}
/* I.4.e. Displacement */
else
{
LongInt DispPart;
tSymbolFlags Flags;
DispPart = EvalStrIntExpressionOffsWithFlags(&Arg, CheckForcePrefix(Arg.str.p_str, &ForcePrefix), Int32, &OK, &Flags);
if (!OK)
return;
if (mFirstPassUnknown(Flags))
DispPart = 1;
DispAcc = MinFlag ? DispAcc - DispPart : DispAcc + DispPart;
}
if (PMPos)
Arg = Remainder;
MinFlag = NMinFlag;
}
while (PMPos);
/* I.5. Indexregister mit Skalierung 1 als Basis behandeln */
if ((BaseReg == FreeReg) && (IndReg != FreeReg) && (ScaleFact == 0))
{
BaseReg = IndReg;
BaseRegSize = IndRegSize;
IndReg = FreeReg;
}
/* I.6. absolut */
if ((BaseReg == FreeReg) && (IndReg == FreeReg))
{
AdrMode = 0x20; /* 0x60 should be equivalent: adding 0 as RW0 or RD0 is irrelvant */
AdrVals[0] = 0xe000 + (DispAcc & 0x1fff); AdrCnt = 2;
AddAbsPrefix(PrefInd, 13, DispAcc, ForcePrefix);
AdrOK = True;
return;
}
/* I.7. Basis [mit Displacement] */
if ((BaseReg != FreeReg) && (IndReg == FreeReg))
{
/* I.7.a. Basis ohne Displacement */
if (DispAcc == 0)
{
if (BaseRegSize == eSymbolSize16Bit)
AdrMode = 0x10 + (BaseReg & 15);
else
AdrMode = 0x61 + (BaseReg & 14);
AdrOK = True;
return;
}
/* I.7.b. Nullregister mit Displacement muss in Erweiterungswort */
else if (BaseReg == 0)
{
if (DispAcc > 0x7ffff) WrError(ErrNum_OverRange);
else if (DispAcc < -0x80000) WrError(ErrNum_UnderRange);
else
{
AdrMode = 0x20;
if (BaseRegSize == eSymbolSize16Bit)
AdrVals[0] = ((Word)BaseReg & 15) << 11;
else
AdrVals[0] = (((Word)BaseReg & 14) << 11) + 0x8000;
AdrVals[0] += DispAcc & 0x1ff;
AdrCnt = 2;
AddSignedPrefix(PrefInd, 9, DispAcc, ForcePrefix);
AdrOK = True;
}
return;
}
/* I.7.c. Stack mit Displacement: Optimierung moeglich */
else if (BaseReg == SPReg)
{
if (DispAcc > 0x7ffff) WrError(ErrNum_OverRange);
else if (DispAcc < -0x80000) WrError(ErrNum_UnderRange);
else if ((DispAcc >= 0) && (DispAcc <= 127))
{
AdrMode = 0x80 + (DispAcc & 0x7f);
AdrOK = True;
}
else
{
AdrMode = 0x20;
AdrVals[0] = 0xd000 + (DispAcc & 0x1ff); AdrCnt = 2;
AddSignedPrefix(PrefInd, 9, DispAcc, ForcePrefix);
AdrOK = True;
}
return;
}
/* I.7.d. Programmzaehler mit Displacement: keine Optimierung */
else if (BaseReg == PCReg)
{
if (DispAcc > 0x7ffff) WrError(ErrNum_OverRange);
else if (DispAcc < -0x80000) WrError(ErrNum_UnderRange);
else
{
AdrMode = 0x20;
AdrVals[0] = 0xd800 + (DispAcc & 0x1ff);
AdrCnt = 2;
AddSignedPrefix(PrefInd, 9, DispAcc, ForcePrefix);
AdrOK = True;
}
return;
}
/* I.7.e. einfaches Basisregister mit Displacement */
else
{
if (DispAcc > 0x7fffff) WrError(ErrNum_OverRange);
else if (DispAcc < -0x800000) WrError(ErrNum_UnderRange);
else
{
if (BaseRegSize == eSymbolSize16Bit)
AdrMode = 0x20 + (BaseReg & 15);
else
AdrMode = 0x60 + (BaseReg & 14);
AdrVals[0] = 0xe000 + (DispAcc & 0x1fff);
AdrCnt = 2;
AddSignedPrefix(PrefInd, 13, DispAcc, ForcePrefix);
AdrOK = True;
}
return;
}
}
/* I.8. Index- [und Basisregister] */
else
{
if (DispAcc > 0x7ffff) WrError(ErrNum_OverRange);
else if (DispAcc < -0x80000) WrError(ErrNum_UnderRange);
else if ((IndReg & 15) == 0) WrError(ErrNum_InvAddrMode);
else
{
if (IndRegSize == eSymbolSize16Bit)
AdrMode = 0x20 + (IndReg & 15);
else
AdrMode = 0x60 + (IndReg & 14);
switch (BaseReg)
{
case FreeReg:
AdrVals[0] = 0xc000; break;
case SPReg:
AdrVals[0] = 0xd000; break;
case PCReg:
AdrVals[0] = 0xd800; break;
default:
if (BaseRegSize == eSymbolSize16Bit)
AdrVals[0] = ((Word)BaseReg & 15) << 11;
else
AdrVals[0] = 0x8000 + (((Word)BaseReg & 14) << 10);
}
AdrVals[0] += (((Word)ScaleFact) << 9) + (DispAcc & 0x1ff);
AdrCnt = 2;
AddSignedPrefix(PrefInd, 9, DispAcc, ForcePrefix);
AdrOK = True;
}
return;
}
}
/* II. Arbeitsregister */
else if ((RegEvalResult = DecodeReg(pArg, &Reg, &Size, False)) != eIsNoReg)
{
if (RegEvalResult == eRegAbort)
return;
if (!MayReg) WrStrErrorPos(ErrNum_InvAddrMode, pArg);
else
{
if (OpSize == eSymbolSizeUnknown)
OpSize = Size;
if (Size != OpSize) WrError(ErrNum_ConfOpSizes);
else
{
AdrMode = Reg & 15;
AdrOK = True;
}
}
return;
}
/* III. Spezialregister */
else if (DecodeSpecReg(pArg->str.p_str, &Reg))
{
if (!MayReg) WrError(ErrNum_InvAddrMode);
else
{
if (OpSize == -1)
OpSize=Reg >> 6;
if ((Reg >> 6) != OpSize) WrError(ErrNum_ConfOpSizes);
else
{
AdrMode = 0x30 + (Reg & 15);
AdrOK = True;
}
}
return;
}
else switch (MayImm)
{
case eImmNo:
WrError(ErrNum_InvAddrMode);
break;
case eImmAsAbs:
{
Boolean ForcePrefix = False;
LongInt DispAcc = EvalStrIntExpressionOffs(pArg, CheckForcePrefix(pArg->str.p_str, &ForcePrefix), Int32, &AdrOK);
if (AdrOK)
{
AdrMode = 0x20; /* 0x60 should be equivalent: adding 0 as RW0 or RD0 is irrelvant */
AdrVals[0] = 0xe000 + (DispAcc & 0x1fff); AdrCnt = 2;
AddAbsPrefix(PrefInd, 13, DispAcc, ForcePrefix);
AdrOK = True;
}
break;
}
case eImmYes:
if ((OpSize == -1) && (MinOneIs0))
OpSize = 0;
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
AdrMode = 0x30;
switch (OpSize)
{
case 0:
AdrVals[0] = EvalStrIntExpression(pArg, Int8, &OK) & 0xff;
if (OK)
{
AdrCnt = 2;
AdrOK = True;
}
break;
case 1:
AdrVals[0] = EvalStrIntExpression(pArg, Int16, &OK);
if (OK)
{
AdrCnt = 2;
AdrOK = True;
}
break;
case 2:
{
LongInt DispAcc = EvalStrIntExpression(pArg, Int32, &OK);
if (OK)
{
AdrVals[0] = DispAcc & 0xffff;
AdrVals[1] = DispAcc >> 16;
AdrCnt = 4;
AdrOK = True;
}
break;
}
}
}
break;
}
}
static void CopyAdr(void)
{
OpSize2 = OpSize;
AdrMode2 = AdrMode;
AdrCnt2 = AdrCnt;
memcpy(AdrVals2
, AdrVals
, AdrCnt
);
}
static Boolean IsReg(void)
{
return (AdrMode <= 15);
}
static Boolean Is2Reg(void)
{
return (AdrMode2 <= 15);
}
static Boolean IsImmediate(void)
{
return (AdrMode == 0x30);
}
static Boolean Is2Immediate(void)
{
return (AdrMode2 == 0x30);
}
static LongInt ImmVal(void)
{
LongInt Tmp1;
Integer Tmp2;
ShortInt Tmp3;
switch (OpSize)
{
case 0:
Tmp3 = AdrVals[0] & 0xff;
return Tmp3;
case 1:
Tmp2 = AdrVals[0];
return Tmp2;
case 2:
Tmp1 = (((LongInt)AdrVals[1]) << 16) + AdrVals[0];
return Tmp1;
default:
WrError(ErrNum_InternalError);
return 0;
}
}
static LongInt ImmVal2(void)
{
LongInt Tmp1;
Integer Tmp2;
ShortInt Tmp3;
switch (OpSize)
{
case 0:
Tmp3 = AdrVals2[0] & 0xff;
return Tmp3;
case 1:
Tmp2 = AdrVals2[0];
return Tmp2;
case 2:
Tmp1 = (((LongInt)AdrVals2[1]) << 16) + AdrVals2[0];
return Tmp1;
default:
WrError(ErrNum_InternalError);
return 0;
}
}
static Boolean IsAbsolute(void)
{
return (((AdrMode == 0x20) || (AdrMode == 0x60))
&& (AdrCnt == 2)
&& ((AdrVals[0] & 0xe000) == 0xe000));
}
static Boolean Is2Absolute(void)
{
return (((AdrMode2 == 0x20) || (AdrMode2 == 0x60))
&& (AdrCnt2 == 2)
&& ((AdrVals2[0] & 0xe000) == 0xe000));
}
static Boolean IsShort(void)
{
if (AdrMode < 0x30)
return True;
else if (AdrMode == 0x30)
{
LongInt ImmValue = ImmVal();
return ((ImmValue >= LowLim4) && (ImmValue <= 7));
}
else
return False;
}
static Boolean Is2Short(void)
{
if (AdrMode2 < 0x30)
return True;
else if (AdrMode2 == 0x30)
{
LongInt ImmValue = ImmVal2();
return ((ImmValue >= LowLim4) && (ImmValue <= 7));
}
else
return False;
}
static void ConvertShort(void)
{
if (AdrMode == 0x30)
{
AdrMode += ImmVal() & 15;
AdrCnt = 0;
}
}
static void Convert2Short(void)
{
if (AdrMode2 == 0x30)
{
AdrMode2 += ImmVal2() & 15;
AdrCnt2 = 0;
}
}
static void SetULowLims(void)
{
LowLim4 = 0;
LowLim8 = 0;
}
static Boolean DecodePseudo(void)
{
return False;
}
static void AddPrefixes(void)
{
if (CodeLen != 0)
{
InsertSinglePrefix(1);
InsertSinglePrefix(0);
}
}
static Boolean DecodeCondition(const char *pAsc, Word *pCondition)
{
size_t z;
for (z = 0; z < as_array_size(Conditions); z++)
if (!as_strcasecmp(pAsc, Conditions[z]))
{
*pCondition = z;
return True;
}
return False;
}
static char DecideGA(void)
{
if (((IsShort()) && (Is2Absolute()))
|| ((Is2Short()) && (IsAbsolute())))
return 'A';
else
return 'G';
}
/*--------------------------------------------------------------------------*/
static void DecodeFixed(Word Code)
{
if (!ChkArgCnt(0, 0));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
WAsmCode[0] = Code;
CodeLen = 2;
}
}
static void DecodeRMW(Word Index)
{
const RMWOrder *pOrder = RMWOrders + Index;
if ((OpSize == -1) && (pOrder->Mask & 0x20))
OpSize = 2;
if (ChkArgCnt(1, 1))
{
tImmAllow AllowImm = (pOrder->Mask & 0x10) ? eImmNo : eImmYes;
if (!IsIndirect(ArgStr[1].str.p_str) && (pOrder->Mask & 0x20))
AllowImm = eImmAsAbs;
DecodeAdr(&ArgStr[1], 0, AllowImm, !(pOrder->Mask & 0x20));
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else if (!(pOrder->Mask & (1 << OpSize))) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] = (((Word)OpSize + 1) << 14) + (((Word)pOrder->Code) << 8) + AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
}
}
}
}
static void DecodeGASI1(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
CopyAdr();
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
if (Format == ' ')
{
if (((IsReg()) && (Is2Short()))
|| ((Is2Reg()) && (IsShort())))
Format = 'S';
else if ((IsImmediate()) && (OpSize > 0) && ((ImmValue > 127) || (ImmValue < -128)))
Format = 'I';
else
Format = DecideGA();
}
switch (Format)
{
case 'G':
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue <= 127) && (ImmValue >= -128))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0x8400 + (Code << 8) + AdrMode2;
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsShort()) && (Is2Absolute()))
{
ConvertShort();
WAsmCode[0] = 0x3900
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt;
}
else if ((Is2Short()) && (IsAbsolute()))
{
Convert2Short();
WAsmCode[0] = 0x3980
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt2;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'S':
if ((IsShort()) && (Is2Reg()))
{
ConvertShort();
WAsmCode[0] = 0x0000
+ (((Word)OpSize + 1) << 14)
+ (AdrMode & 15)
+ ((AdrMode & 0xf0) << 5)
+ ((AdrMode2 & 1) << 12)
+ ((AdrMode2 & 14) << 4)
+ ((Code & 1) << 4)
+ ((Code & 2) << 10);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
}
else if ((Is2Short()) && (IsReg()))
{
Convert2Short();
WAsmCode[0] = 0x0100
+ (((Word)OpSize + 1) << 14)
+ (AdrMode2 & 15)
+ ((AdrMode2 & 0xf0) << 5)
+ ((AdrMode & 1) << 12)
+ ((AdrMode & 14) << 4)
+ ((Code & 1) << 4)
+ ((Code & 2) << 11);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
CodeLen = 2 + AdrCnt2;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'I':
if ((!IsImmediate()) || (OpSize == 0)) WrError(ErrNum_InvAddrMode);
else
{
WAsmCode[0] = AdrMode2 + (((Word)OpSize-1) << 11) + (Code << 8);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
memcpy(WAsmCode
+ 1 + (AdrCnt2
>> 1), AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt + AdrCnt2;
}
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeGASI2(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
CopyAdr();
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
if (Format == ' ')
{
if ((IsReg()) && (Is2Reg()))
Format = 'S';
else if ((IsImmediate()) && (OpSize > 0) && ((ImmValue > 127) || (ImmValue < -128)))
Format = 'I';
else
Format = DecideGA();
}
switch (Format)
{
case 'G':
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue <= 127) && (ImmValue >= -128))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0xc400 + (Code << 8) + AdrMode2;
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsShort()) && (Is2Absolute()))
{
ConvertShort();
WAsmCode[0] = 0x3940
+ (((Word)OpSize+1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt;
}
else if ((Is2Short()) && (IsAbsolute()))
{
Convert2Short();
WAsmCode[0] = 0x39c0
+ (((Word)OpSize+1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt2;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'S':
if ((IsReg()) && (Is2Reg()))
{
WAsmCode[0] = 0x3800
+ (((Word)OpSize+1) << 14)
+ (AdrMode & 15)
+ (AdrMode2 << 4)
+ (Code << 9);
CodeLen = 2;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'I':
if ((!IsImmediate()) || (OpSize == 0)) WrError(ErrNum_InvAddrMode);
else
{
WAsmCode[0] = 0x400 + AdrMode2 + (((Word)OpSize-1) << 11) + (Code << 8);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
memcpy(WAsmCode
+ 1 + (AdrCnt2
>> 1), AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt + AdrCnt2;
}
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeTrinom(Word Code)
{
int Cnt;
Byte Reg;
if (Code == 2) /* MAC */
LowLim8 = 0;
if (!ChkArgCnt(3, 3));
else if (DecodeRegAdr(&ArgStr[1], &Reg))
{
if (Code >= 2)
OpSize--;
if (OpSize < 0) WrError(ErrNum_InvOpSize);
else
{
DecodeAdr(&ArgStr[3], 0, eImmYes, True);
if (AdrOK)
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
WAsmCode[0] = 0x700;
if ((IsImmediate()) && (ImmValue < 127) && (ImmValue > LowLim8))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += (((Word)OpSize + 1) << 14) + AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
Cnt = AdrCnt;
DecodeAdr(&ArgStr[2], 1, eImmNo, True);
if (AdrOK)
{
WAsmCode[1 + (Cnt >> 1)] = AdrMode + (Code << 8) + (((Word)Reg) << 11);
memcpy(WAsmCode
+ 2 + (Cnt
>> 1), AdrVals
, AdrCnt
);
CodeLen = 4 + Cnt + AdrCnt;
}
}
}
}
}
static void DecodeRLM_RRM(Word Code)
{
int Cnt;
Byte Reg;
tSymbolSize Size;
if (!ChkArgCnt(3, 3));
else if (!DecodeReg(&ArgStr[2], &Reg, &Size, True));
else if (Size != eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[2]);
else
{
Reg &= 0x3f;
DecodeAdr(&ArgStr[3], 0, eImmYes, True);
if (AdrOK)
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
WAsmCode[0] = 0x700;
if ((IsImmediate()) && (ImmValue < 127) && (ImmValue > -128))
{
AdrMode = ImmValue & 0xff; AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
Cnt = AdrCnt;
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
WAsmCode[0] += ((Word)OpSize + 1) << 14;
WAsmCode[1 + (Cnt >> 1)] = Code + (((Word)Reg) << 11)+AdrMode;
memcpy(WAsmCode
+ 2 + (Cnt
>> 1), AdrVals
, AdrCnt
);
CodeLen = 4 + AdrCnt + Cnt;
}
}
}
}
}
static void DecodeBit(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
CopyAdr();
OpSize = -1;
MinOneIs0 = True;
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
OpSize = OpSize2;
if (Format==' ')
{
if ((Is2Reg()) && (IsImmediate())
&& (ImmValue > 0)
&& (ImmValue < (1 << (OpSize + 3))))
Format = 'S';
else
Format = DecideGA();
}
switch (Format)
{
case 'G':
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue >= LowLim8) && (ImmValue < 127))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0xd400 + (Code << 8) + AdrMode2;
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x39d0
+ (((Word)OpSize+1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3950
+ (((Word)OpSize+1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'S':
if ((Is2Reg())
&& (IsImmediate())
&& (ImmVal() >= 0)
&& (ImmVal() < (1 << (3 + OpSize))))
{
if (OpSize == 2)
{
if (ImmVal() >= 16)
{
AdrVals[0] -= 16;
AdrMode2++;
}
OpSize = 1;
}
if (OpSize == 1)
{
if (ImmVal() < 8)
OpSize=0;
else
AdrVals[0] -= 8;
}
WAsmCode[0] = 0x1700
+ (((Word)OpSize + 1) << 14)
+ ((Code & 1) << 7)
+ ((Code & 2) << 10)
+ (ImmVal() << 4)
+ AdrMode2;
CodeLen = 2;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeShift(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
CopyAdr();
OpSize = -1;
MinOneIs0 = True;
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
OpSize = OpSize2;
if (Format==' ')
{
if ((IsImmediate()) && (ImmValue == 1))
Format = 'S';
else
Format = DecideGA();
}
switch (Format)
{
case 'G':
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue >= LowLim8) && (ImmVal() < 127))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0xb400
+ ((Code & 3) << 8)
+ ((Code & 4) << 9)
+ AdrMode2;
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x39b0
+ (((Word)OpSize+1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff) + (Code << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3930
+ (((Word)OpSize+1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff)+ (Code << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'S':
if ((IsImmediate()) && (ImmValue == 1))
{
WAsmCode[0] = 0x2400
+ (((Word)OpSize+1) << 14)
+ AdrMode2
+ ((Code & 3) << 8)
+ ((Code & 4) << 9);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
CodeLen =2 + AdrCnt2;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeBField(Word Code)
{
Byte Reg, Num1, Num2;
Boolean OK;
tSymbolFlags Flags;
tSymbolSize Size;
if (ChkArgCnt(4, 4))
{
tStrComp *pArg1 = (Code == 2) ? &ArgStr[2] : &ArgStr[1],
*pArg2 = (Code == 2) ? &ArgStr[1] : &ArgStr[2];
if (!DecodeReg(pArg1, &Reg, &Size, True));
else if (Size != eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, pArg1);
else
{
Reg &= 0x3f;
Num2 = EvalStrIntExpressionWithFlags(&ArgStr[4], Int5, &OK, &Flags);
if (OK)
{
if (mFirstPassUnknown(Flags))
Num2 &= 15;
Num2--;
if (Num2 > 15) WrError(ErrNum_OverRange);
else if ((OpSize == -1) && (!DecodeRegAdr(pArg2, &Num1)));
else
{
switch (OpSize)
{
case 0: Num1 = EvalStrIntExpression(&ArgStr[3], UInt3, &OK) & 7; break;
case 1: Num1 = EvalStrIntExpression(&ArgStr[3], Int4, &OK) & 15; break;
case 2: Num1 = EvalStrIntExpression(&ArgStr[3], Int5, &OK) & 31; break;
}
if (OK)
{
if ((OpSize == 2) && (Num1 > 15))
AdrInc = 2;
DecodeAdr(pArg2, 1, eImmNo, True);
if (AdrOK)
{
if ((OpSize == 2) && (Num1 > 15))
{
Num1 -= 16;
OpSize--;
if (!(AdrMode & 0xf0))
AdrMode++;
}
WAsmCode[0] = 0x7000 + (((Word)OpSize + 1) << 8) + AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (((Word)Reg) << 11)
+ Num2
+ (((Word)Num1) << 5)
+ ((Code & 1) << 10)
+ ((Code & 2) << 14);
CodeLen = 4 + AdrCnt;
}
}
}
}
}
}
}
static void DecodeGAEq(Word Code)
{
if (Hi(Code))
SetULowLims();
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
CopyAdr();
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
if (OpSize == 0)
LowLim8 = -128;
if (Format == ' ')
Format = DecideGA();
switch (Format)
{
case 'G':
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue < 127) && (ImmValue > LowLim8))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0x8400
+ AdrMode2
+ ((Code & 0xf0) << 8)
+ ((Code & 4) << 9)
+ ((Code & 3) << 8);
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
}
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x3980
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3900
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeGAHalf(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
if (OpSize == 0) WrError(ErrNum_InvOpSize);
else
{
if (OpSize != -1)
OpSize--;
CopyAdr();
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
if (OpSize == 2) WrError(ErrNum_InvOpSize);
else if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
if (Format == ' ')
Format = DecideGA();
switch (Format)
{
case 'G':
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue < 127) && (ImmValue > LowLim8))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0x8400
+ AdrMode2
+ ((Code & 0xf0) << 8)
+ ((Code & 4) << 9)
+ ((Code & 3) << 8);
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
}
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x3980
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3900
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
}
static void DecodeGAFirst(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, (Memo("STCF") || Memo("TSET")) ? eImmNo : eImmYes, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
CopyAdr();
OpSize = -1;
MinOneIs0 = True;
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
OpSize = OpSize2;
if (AdrOK)
{
if (Format == ' ')
Format = DecideGA();
switch (Format)
{
case 'G':
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
WAsmCode[0] = 0x700
+ (((Word)OpSize + 1) << 14);
if ((IsImmediate()) && (ImmValue < 127) && (ImmValue > LowLim8))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0x8400
+ AdrMode2
+ ((Code & 0xf0) << 8)
+ ((Code & 4) << 9)
+ ((Code & 3) << 8);
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
}
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x3980
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3900
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeGASecond(Word Code)
{
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
CopyAdr();
OpSize = -1;
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
OpSize = OpSize2;
if (AdrOK)
{
if (Format == ' ')
Format = DecideGA();
switch (Format)
{
case 'G':
WAsmCode[0] = 0x700 + (((Word)OpSize + 1) << 14);
if ((Is2Immediate()) && (ImmVal2() < 127) && (ImmVal2() > LowLim8))
{
AdrMode2 = ImmVal2() & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode2;
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = 0x8400
+ AdrMode
+ ((Code & 0xf0) << 8)
+ ((Code & 4) << 9)
+ ((Code & 3) << 8);
memcpy(WAsmCode
+ 2 + (AdrCnt2
>> 1), AdrVals
, AdrCnt
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x3900
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = (AdrVals[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3980 + (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15)
+ (Code & 0xf0);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = (AdrVals2[0] & 0x1fff)
+ ((Code & 15) << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeCHK_CHKS(Word IsSigned)
{
if (!IsSigned)
SetULowLims();
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[2], 1, eImmNo, True);
if (AdrOK)
{
if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
else if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
CopyAdr();
DecodeAdr(&ArgStr[1], 0, eImmNo, False);
if (AdrOK)
{
if (OpSize == 0)
LowLim8 = -128;
if (Format == ' ')
Format = DecideGA();
switch (Format)
{
case 'G':
WAsmCode[0] = 0xf00 + (((Word)OpSize + 1) << 14) + AdrMode2;
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = 0xa600 + AdrMode
+ (IsSigned << 8);
memcpy(WAsmCode
+ 2 + (AdrCnt2
>> 1), AdrVals
, AdrCnt
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x3920
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = 0x4000
+ (AdrVals[0] & 0x1fff)
+ (IsSigned << 13);
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x39a0
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0x4000
+ (AdrVals2[0] & 0x1fff)
+ (IsSigned << 13);
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeString(Word Code)
{
Byte Reg;
int Cnt;
tSymbolSize Size;
if (!ChkArgCnt(3, 3));
else if (!DecodeReg(&ArgStr[3], &Reg, &Size, True));
else if (Size != eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[3]);
else
{
Reg &= 0x3f;
DecodeAdr(&ArgStr[2], 0, eImmYes, True);
if (AdrOK)
{
LongInt ImmValue = IsImmediate() ? ImmVal() : 0;
WAsmCode[0] = 0x700;
if ((IsImmediate()) && (ImmValue < 127) && (ImmValue > LowLim8))
{
AdrMode = ImmValue & 0xff;
AdrCnt = 0;
}
else
WAsmCode[0] += 0x800;
WAsmCode[0] += AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
Cnt = AdrCnt;
DecodeAdr(&ArgStr[1], 1, eImmYes, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
WAsmCode[0] += ((Word)OpSize + 1) << 14;
WAsmCode[1 + (Cnt >> 1)] = 0x8000 + AdrMode + (Code << 8) + (((Word)Reg) << 11);
memcpy(WAsmCode
+ 2 + (Cnt
>> 1), AdrVals
, AdrCnt
);
CodeLen = 4 + AdrCnt + Cnt;
}
}
}
}
}
static void DecodeEX(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
CopyAdr();
DecodeAdr(&ArgStr[2], 0, eImmNo, True);
if (AdrOK)
{
if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
else
{
if (Format == ' ')
{
if ((IsReg()) && (Is2Reg()))
Format = 'S';
else
Format = DecideGA();
}
switch (Format)
{
case 'G':
WAsmCode[0] = 0x0f00 + (((Word)OpSize + 1) << 14) + AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0x8f00 + AdrMode2;
memcpy(WAsmCode
+ 2 + (AdrCnt
>> 1), AdrVals2
, AdrCnt2
);
CodeLen = 4 + AdrCnt + AdrCnt2;
break;
case 'A':
if ((IsAbsolute()) && (Is2Short()))
{
Convert2Short();
WAsmCode[0] = 0x3980
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode2 & 0xf0) << 5)
+ (AdrMode2 & 15);
memcpy(WAsmCode
+ 1, AdrVals2
, AdrCnt2
);
WAsmCode[1 + (AdrCnt2 >> 1)] = AdrVals[0];
CodeLen = 4 + AdrCnt2;
}
else if ((Is2Absolute()) && (IsShort()))
{
ConvertShort();
WAsmCode[0] = 0x3900
+ (((Word)OpSize + 1) << 14)
+ ((AdrMode & 0xf0) << 5)
+ (AdrMode & 15);
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = AdrVals2[0];
CodeLen = 4 + AdrCnt;
}
else WrError(ErrNum_InvAddrMode);
break;
case 'S':
if ((IsReg()) && (Is2Reg()))
{
WAsmCode[0] = 0x3e00
+ (((Word)OpSize + 1) << 14)
+ (AdrMode2 << 4)
+ AdrMode;
CodeLen = 2;
}
else WrError(ErrNum_InvAddrMode);
break;
default:
WrError(ErrNum_InvFormat);
}
}
}
}
}
}
static void DecodeCALR_JR(Word Code)
{
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
LongInt AdrInt;
Boolean OK, ForcePrefix = False;
AdrInt = EvalStrIntExpressionOffs(&ArgStr[1], CheckForcePrefix(ArgStr[1].str.p_str, &ForcePrefix), Int32, &OK) - EProgCounter();
if ((OK) && (AddRelPrefix(0, 13, &AdrInt, ForcePrefix)))
{
if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
else
{
WAsmCode[0] = Code + (AdrInt & 0x1ffe);
CodeLen = 2;
}
}
}
}
static void DecodeJRC(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
Word Condition;
if (!DecodeCondition(ArgStr[1].str.p_str, &Condition)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
else
{
LongInt AdrInt;
Boolean OK, ForcePrefix = False;
Condition %= 16;
AdrInt = EvalStrIntExpressionOffs(&ArgStr[2], CheckForcePrefix(ArgStr[2].str.p_str, &ForcePrefix), Int32, &OK) - EProgCounter();
if ((OK) && (AddRelPrefix(0, 9, &AdrInt, ForcePrefix)))
{
if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
else
{
WAsmCode[0] = 0x1000 + ((Condition & 14) << 8) + (AdrInt & 0x1fe) + (Condition & 1);
CodeLen = 2;
}
}
}
}
}
static void DecodeJRBC_JRBS(Word Code)
{
if (!ChkArgCnt(3, 3));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
int z;
Boolean OK;
z = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
if (OK)
{
Boolean AdrLongPrefix = False;
LongInt AdrLong;
AdrLong = EvalStrIntExpressionOffs(&ArgStr[2], CheckForcePrefix(ArgStr[2].str.p_str, &AdrLongPrefix), Int24, &OK);
if (OK)
{
LongInt AdrInt;
Boolean AdrIntPrefix = False;
AddAbsPrefix(1, 13, AdrLong, AdrLongPrefix);
AdrInt = EvalStrIntExpressionOffs(&ArgStr[3], CheckForcePrefix(ArgStr[3].str.p_str, &AdrIntPrefix), Int32, &OK) - EProgCounter();
if ((OK) && (AddRelPrefix(0, 9, &AdrInt, AdrIntPrefix)))
{
if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
else
{
CodeLen = 4;
WAsmCode[1] = (z << 13) + (AdrLong & 0x1fff);
WAsmCode[0] = Code + (AdrInt & 0x1fe);
}
}
}
}
}
}
static void DecodeDJNZ(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], 0, eImmNo, True);
if (AdrOK)
{
if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
else
{
LongInt AdrInt;
Boolean OK, ForcePrefix = False;
AdrInt = EvalStrIntExpressionOffs(&ArgStr[2], CheckForcePrefix(ArgStr[2].str.p_str, &ForcePrefix), Int32, &OK) - (EProgCounter() + 4 + AdrCnt +2 * Ord(PrefUsed[0]));
if ((OK) && (AddRelPrefix(1, 13, &AdrInt, ForcePrefix)))
{
if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
else
{
WAsmCode[0] = 0x3700 + (((Word)OpSize + 1) << 14) + AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = 0xe000 + (AdrInt & 0x1ffe);
CodeLen = 4 + AdrCnt;
}
}
}
}
}
}
static void DecodeDJNZC(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(3, 3))
{
Word Condition;
if (!DecodeCondition(ArgStr[2].str.p_str, &Condition)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[2]);
else
{
Condition %= 16;
DecodeAdr(&ArgStr[1], 0, eImmNo, True);
if (AdrOK)
{
if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
else
{
Boolean OK, ForcePrefix = False;
LongInt AdrInt;
AdrInt = EvalStrIntExpressionOffs(&ArgStr[3], CheckForcePrefix(ArgStr[3].str.p_str, &ForcePrefix), Int32, &OK) - EProgCounter();
if ((OK) && (AddRelPrefix(1, 13, &AdrInt, ForcePrefix)))
{
if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
else
{
WAsmCode[0] = 0x3700 + (((Word)OpSize+1) << 14) + AdrMode;
memcpy(WAsmCode
+ 1, AdrVals
, AdrCnt
);
WAsmCode[1 + (AdrCnt >> 1)] = ((Condition & 14) << 12) + (AdrInt & 0x1ffe) + (Condition & 1);
CodeLen =4 + AdrCnt;
}
}
}
}
}
}
}
static void DecodeLINK_RETD(Word Code)
{
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
LongInt AdrInt;
Boolean OK, ForcePrefix = False;
tSymbolFlags Flags;
AdrInt = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], CheckForcePrefix(ArgStr[1].str.p_str, &ForcePrefix), Int32, &OK, &Flags);
if (mFirstPassUnknown(Flags))
AdrInt &= 0x1fe;
if (ChkRange(AdrInt, -0x80000, 0x7ffff))
{
if (Odd(AdrInt)) WrError(ErrNum_NotAligned);
else
{
WAsmCode[0] = Code + (AdrInt & 0x1fe);
AddSignedPrefix(0, 9, AdrInt, ForcePrefix);
CodeLen = 2;
}
}
}
}
static void DecodeSWI(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
else
{
Boolean OK;
WAsmCode[0] = EvalStrIntExpression(&ArgStr[1], Int4, &OK) + 0x7f90;
if (OK)
CodeLen = 2;
}
}
static void DecodeLDA(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[2], 0, eImmNo, False);
if (AdrOK)
{
int z;
WAsmCode[0] = 0x3000 + AdrMode;
z = AdrCnt;
memcpy(WAsmCode
+ 1, AdrVals
, z
);
DecodeAdr(&ArgStr[1], 1, eImmNo, True);
if (AdrOK)
{
if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
else
{
WAsmCode[0] += ((Word)OpSize) << 14;
WAsmCode[1 + (z >> 1)] = 0x9700 + AdrMode;
memcpy(WAsmCode
+ 2 + (z
>> 1), AdrVals
, AdrCnt
);
CodeLen = 4 + z + AdrCnt;
}
}
}
}
}
/*--------------------------------------------------------------------------*/
static void AddFixed(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFixed);
}
static void AddRMW(const char *NName, Byte NCode, Byte NMask)
{
order_array_rsv_end(RMWOrders, RMWOrder);
RMWOrders[InstrZ].Mask = NMask;
RMWOrders[InstrZ].Code = NCode;
AddInstTable(InstTable, NName, InstrZ++, DecodeRMW);
}
static void AddGAEq(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeGAEq);
}
static void AddGAHalf(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeGAHalf);
}
static void AddGAFirst(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeGAFirst);
}
static void AddGASecond(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeGASecond);
}
static void InitFields(void)
{
InstTable = CreateInstTable(301);
AddInstTable(InstTable, "RLM", 0x0400, DecodeRLM_RRM);
AddInstTable(InstTable, "RRM", 0x0500, DecodeRLM_RRM);
AddInstTable(InstTable, "CHK", 0, DecodeCHK_CHKS);
AddInstTable(InstTable, "CHKS", 1, DecodeCHK_CHKS);
AddInstTable(InstTable, "EX", 0, DecodeEX);
AddInstTable(InstTable, "CALR", 0x2001, DecodeCALR_JR);
AddInstTable(InstTable, "JR", 0x2000, DecodeCALR_JR);
AddInstTable(InstTable, "JRC", 0, DecodeJRC);
AddInstTable(InstTable, "JRBC", 0x1e00, DecodeJRBC_JRBS);
AddInstTable(InstTable, "JRBS", 0x1e01, DecodeJRBC_JRBS);
AddInstTable(InstTable, "DJNZ", 0, DecodeDJNZ);
AddInstTable(InstTable, "DJNZC", 0, DecodeDJNZC);
AddInstTable(InstTable, "LINK", 0xc001, DecodeLINK_RETD);
AddInstTable(InstTable, "RETD", 0xc801, DecodeLINK_RETD);
AddInstTable(InstTable, "SWI", 0, DecodeSWI);
AddInstTable(InstTable, "LDA", 0, DecodeLDA);
AddInstTable(InstTable, "REG", 0, CodeREG);
AddFixed("CCF" , 0x7f82);
AddFixed("CSF" , 0x7f8a);
AddFixed("CVF" , 0x7f86);
AddFixed("CZF" , 0x7f8e);
AddFixed("DI" , 0x7fa1);
AddFixed("EI" , 0x7fa3);
AddFixed("HALT", 0x7fa5);
AddFixed("NOP" , 0x7fa0);
AddFixed("RCF" , 0x7f80);
AddFixed("RET" , 0x7fa4);
AddFixed("RETI", 0x7fa9);
AddFixed("RETS", 0x7fab);
AddFixed("RSF" , 0x7f88);
AddFixed("RVF" , 0x7f84);
AddFixed("RZF" , 0x7f8c);
AddFixed("SCF" , 0x7f81);
AddFixed("SSF" , 0x7f89);
AddFixed("SVF" , 0x7f85);
AddFixed("SZF" , 0x7f8b);
AddFixed("UNLK", 0x7fa2);
InstrZ = 0;
AddRMW("CALL" , 0x35, 0x36);
AddRMW("CLR" , 0x2b, 0x17);
AddRMW("CPL" , 0x28, 0x17);
AddRMW("EXTS" , 0x33, 0x16);
AddRMW("EXTZ" , 0x32, 0x16);
AddRMW("JP" , 0x34, 0x36);
AddRMW("MIRR" , 0x23, 0x17);
AddRMW("NEG" , 0x29, 0x17);
AddRMW("POP" , 0x20, 0x17);
AddRMW("PUSH" , 0x21, 0x07);
AddRMW("PUSHA", 0x31, 0x36);
AddRMW("RVBY" , 0x22, 0x17);
AddRMW("TJP" , 0x36, 0x16);
AddRMW("TST" , 0x2a, 0x17);
InstrZ = 0;
AddInstTable(InstTable, "ADD", InstrZ++, DecodeGASI1);
AddInstTable(InstTable, "SUB", InstrZ++, DecodeGASI1);
AddInstTable(InstTable, "CP" , InstrZ++, DecodeGASI1);
AddInstTable(InstTable, "LD" , InstrZ++, DecodeGASI1);
InstrZ = 0;
AddInstTable(InstTable, "AND", InstrZ++, DecodeGASI2);
AddInstTable(InstTable, "OR" , InstrZ++, DecodeGASI2);
AddInstTable(InstTable, "XOR", InstrZ++, DecodeGASI2);
InstrZ = 0;
AddInstTable(InstTable, "ADD3", InstrZ++, DecodeTrinom);
AddInstTable(InstTable, "SUB3", InstrZ++, DecodeTrinom);
AddInstTable(InstTable, "MAC" , InstrZ++, DecodeTrinom);
AddInstTable(InstTable, "MACS", InstrZ++, DecodeTrinom);
InstrZ = 0;
AddInstTable(InstTable, "BRES", InstrZ++, DecodeBit);
AddInstTable(InstTable, "BSET", InstrZ++, DecodeBit);
AddInstTable(InstTable, "BCHG", InstrZ++, DecodeBit);
AddInstTable(InstTable, "BTST", InstrZ++, DecodeBit);
InstrZ = 0;
AddInstTable(InstTable, "SLL", InstrZ++, DecodeShift);
AddInstTable(InstTable, "SRL", InstrZ++, DecodeShift);
AddInstTable(InstTable, "SLA", InstrZ++, DecodeShift);
AddInstTable(InstTable, "SRA", InstrZ++, DecodeShift);
AddInstTable(InstTable, "RL" , InstrZ++, DecodeShift);
AddInstTable(InstTable, "RR" , InstrZ++, DecodeShift);
AddInstTable(InstTable, "RLC", InstrZ++, DecodeShift);
AddInstTable(InstTable, "RRC", InstrZ++, DecodeShift);
InstrZ = 0;
AddInstTable(InstTable, "BFEX" , InstrZ++, DecodeBField);
AddInstTable(InstTable, "BFEXS", InstrZ++, DecodeBField);
AddInstTable(InstTable, "BFIN" , InstrZ++, DecodeBField);
AddGAEq("ABCD" , 0x0110);
AddGAEq("ADC" , 0x0004);
AddGAEq("CBCD" , 0x0112);
AddGAEq("CPC" , 0x0006);
AddGAEq("MAX" , 0x0116);
AddGAEq("MAXS" , 0x0017);
AddGAEq("MIN" , 0x0114);
AddGAEq("MINS" , 0x0015);
AddGAEq("SBC" , 0x0105);
AddGAEq("SBCD" , 0x0111);
AddGAHalf("DIV" , 0x26);
AddGAHalf("DIVS" , 0x27);
AddGAHalf("MUL" , 0x24);
AddGAHalf("MULS" , 0x25);
AddGAFirst("ANDCF", 0x44);
AddGAFirst("LDCF" , 0x47);
AddGAFirst("ORCF" , 0x45);
AddGAFirst("STCF" , 0x43);
AddGAFirst("TSET" , 0x70);
AddGAFirst("XORCF", 0x46);
AddGASecond("BS0B" , 0x54);
AddGASecond("BS0F" , 0x55);
AddGASecond("BS1B" , 0x56);
AddGASecond("BS1F" , 0x57);
AddInstTable(InstTable, "CPSZ", 0, DecodeString);
AddInstTable(InstTable, "CPSN", 1, DecodeString);
AddInstTable(InstTable, "LDS" , 3, DecodeString);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
order_array_free(RMWOrders);
}
static Boolean DecodeAttrPart_97C241(void)
{
char *p;
switch (AttrSplit)
{
case '.':
p
= strchr(AttrPart.
str.
p_str, ':');
if (p)
{
Format
= (p
< AttrPart.
str.
p_str + strlen(AttrPart.
str.
p_str) - 1) ? p
[1] : ' ';
*p = '\0';
}
else
Format = ' ';
break;
case ':':
p
= strchr(AttrPart.
str.
p_str, '.');
if (!p)
{
Format = (*AttrPart.str.p_str);
*AttrPart.str.p_str = '\0';
}
else
{
Format = (p == AttrPart.str.p_str) ? ' ' : *AttrPart.str.p_str;
strmov(AttrPart.str.p_str, p + 1);
}
break;
default:
Format = ' ';
}
Format = as_toupper(Format);
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_97C241(void)
{
CodeLen = 0;
DontPrint = False;
PrefUsed[0] = False;
PrefUsed[1] = False;
AdrInc = 0;
MinOneIs0 = False;
LowLim4 = -8; LowLim8 = -128;
/* zu ignorierendes */
if (Memo(""))
return;
OpSize = AttrPartOpSize[0];
/* Pseudoanweisungen */
if (DecodePseudo()) return;
if (DecodeIntelPseudo(False)) return;
if (LookupInstTable(InstTable, OpPart.str.p_str))
{
AddPrefixes();
return;
}
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_97C241(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on TLCS-9000
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_97C241(char *pArg, TempResult *pResult)
{
Byte Reg;
tSymbolSize Size;
if (DecodeRegCore(pArg, &Reg, &Size))
{
pResult->Typ = TempReg;
pResult->DataSize = Size;
pResult->Contents.RegDescr.Reg = Reg;
pResult->Contents.RegDescr.Dissect = DissectReg_97C241;
pResult->Contents.RegDescr.compare = NULL;
}
}
static Boolean IsDef_97C241(void)
{
return Memo("REG");
}
static void SwitchFrom_97C241(void)
{
DeinitFields();
}
static void SwitchTo_97C241(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "$";
HeaderID = 0x56;
NOPCode = 0x7fa0;
DivideChars = ",";
HasAttrs = True;
AttrChars = ".:";
ValidSegs = 1 << SegCode;
Grans[SegCode] = 1;
ListGrans[SegCode] = 2;
SegInits[SegCode] = 0;
SegLimits[SegCode] = 0xffffffl;
DecodeAttrPart = DecodeAttrPart_97C241;
MakeCode = MakeCode_97C241;
IsDef = IsDef_97C241;
InternSymbol = InternSymbol_97C241;
DissectReg = DissectReg_97C241;
SwitchFrom = SwitchFrom_97C241;
InitFields();
}
void code97c241_init(void)
{
CPU97C241 = AddCPU("97C241", SwitchTo_97C241);
}