/* code3254x.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* Macro Assembler AS */
/* */
/* Code Generator for TI C54x DSP devices */
/* */
/*****************************************************************************/
/*-------------------------------------------------------------------------*/
/* Includes */
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "asmrelocs.h"
#include "asmcode.h"
#include "codepseudo.h"
#include "tipseudo.h"
#include "asmitree.h"
#include "codevars.h"
#include "fileformat.h"
#include "headids.h"
#include "errmsg.h"
#include "code3254x.h"
/*-------------------------------------------------------------------------*/
/* Data Structures */
#define FixedOrderCnt 12
#define AccOrderCnt 16
#define Acc2OrderCnt 5
#define MemOrderCnt 9
#define XYOrderCnt 4
#define MemAccOrderCnt 17
#define MemConstOrderCnt 5
#define MacOrderCnt 3
#define ConditionCnt 23
typedef struct
{
Word Code;
Boolean IsRepeatable;
} FixedOrder;
typedef struct
{
Word Code;
Boolean IsRepeatable, Swap;
IntType ConstType;
} MemConstOrder;
typedef struct
{
const char *Name;
Word Class, Code, Mask;
} Condition;
typedef enum {ModNone = - 1, ModAcc, ModMem, ModImm, ModAReg} ModType;
#define MModAcc (1 << ModAcc)
#define MModMem (1 << ModMem)
#define MModImm (1 << ModImm)
#define MModAReg (1 << ModAReg)
static LongInt Reg_CPL, Reg_DP, Reg_SP;
static Boolean ThisRep, LastRep, ForcePageZero;
static FixedOrder *FixedOrders, *AccOrders, *Acc2Orders, *MemOrders, *XYOrders,
*MemAccOrders, *MacOrders;
static MemConstOrder *MemConstOrders;
static Condition *Conditions;
static CPUVar CPU320C541;
static IntType OpSize;
static ShortInt AdrMode;
static Word AdrVals[3];
static Boolean ThisPar;
static Word LastOpCode;
/*-------------------------------------------------------------------------*/
/* Address Decoder */
static const char ShortConds[4][4] =
{
"EQ", "LT", "GT", "NEQ"
};
static Boolean IsAcc(char *Asc)
{
return ((Asc[1] == '\0') && (as_toupper(*Asc) >= 'A') && (as_toupper(*Asc) <= 'B'));
}
static Boolean DecodeAdr(const tStrComp *pArg, int Mask)
{
#define IndirCnt 16
static const char Patterns[IndirCnt][9] = /* leading asterisk is omitted since constant */
{
"ARx", "ARx-", "ARx+", "+ARx",
"ARx-0B", "ARx-0", "ARx+0", "ARx+0B",
"ARx-%", "ARx-0%", "ARx+%", "ARx+0%",
"ARx(n)", "+ARx(n)", "+ARx(n)%", "(n)"
};
Boolean OK;
AdrMode = ModNone;
AdrCnt = 0;
/* accumulators */
if (IsAcc(pArg->str.p_str))
{
AdrMode = ModAcc;
*AdrVals = as_toupper(*pArg->str.p_str) - 'A';
goto done;
}
/* aux registers */
if ((strlen(pArg
->str.
p_str) == 3) && (!as_strncasecmp
(pArg
->str.
p_str, "AR", 2)) && (pArg
->str.
p_str[2] >= '0') && (pArg
->str.
p_str[2] <= '7'))
{
AdrMode = ModAReg;
*AdrVals = pArg->str.p_str[2] - '0';
goto done;
}
/* immediate */
if (*pArg->str.p_str == '#')
{
*AdrVals = EvalStrIntExpressionOffs(pArg, 1, OpSize, &OK);
if (OK)
AdrMode = ModImm;
goto done;
}
/* indirect */
if (*pArg->str.p_str == '*')
{
int z;
Word RegNum;
char *pConstStart, *pConstEnd;
/* check all possible patterns */
for (z = 0; z < IndirCnt; z++)
{
const char *pPattern = Patterns[z];
char *pComp = pArg->str.p_str + 1;
/* pattern comparison */
RegNum = 0;
pConstStart = pConstEnd = NULL;
OK = TRUE;
while ((*pPattern) && (*pComp) && (OK))
{
switch (*pPattern)
{
case 'x': /* embedded number */
RegNum = *pComp - '0';
OK = RegNum < 8;
break;
case 'n': /* constant */
pConstStart = pComp;
pConstEnd = QuotPos(pComp, pPattern[1]);
if (pConstEnd)
pComp = pConstEnd - 1;
else
OK = False;
break;
default: /* compare verbatim */
if (as_toupper(*pPattern) != as_toupper(*pComp))
OK = False;
}
if (OK)
{
pPattern++;
pComp++;
}
}
/* for a successful comparison, we must have reached the end of both strings
simultaneously. */
OK = OK && (!*pPattern) && (!*pComp);
if (OK)
break;
}
if (!OK) WrError(ErrNum_InvAddrMode);
else
{
/* decode offset ? pConst... /must/ be set if such a pattern was successfully
decoded! */
{
/* MMR-style instructions do not allow an extension word */
if (ForcePageZero)
{
WrError(ErrNum_InvAddrMode);
OK = False;
}
else
{
tStrComp Start, Remainder;
char Save;
StrCompRefRight(&Start, pArg, pConstStart - pArg->str.p_str);
Save = StrCompSplitRef(&Start, &Remainder, &Start, pConstEnd);
AdrVals[1] = EvalStrIntExpression(&Start, Int16, &OK);
*pConstEnd = Save;
if (OK)
AdrCnt = 1;
}
}
/* all fine until now? Then do the rest... */
if (OK)
{
AdrMode = ModMem;
AdrVals[0] = 0x80 | (z << 3) | RegNum;
}
}
goto done;
}
/* then try absolute resp. immediate if absolute not allowed */
if (Mask & MModMem)
{
tSymbolFlags Flags;
*AdrVals = EvalStrIntExpressionWithFlags(pArg, UInt16, &OK, &Flags);
if (OK)
{
if (Reg_CPL) /* short address rel. to SP? */
{
*AdrVals -= Reg_SP;
if (!mFirstPassUnknown(Flags) && (*AdrVals > 127))
WrError(ErrNum_InAccPage);
}
else /* on DP page ? */
{
if (!mFirstPassUnknown(Flags) && ((*AdrVals >> 7) != (Reg_DP)))
WrError(ErrNum_InAccPage);
}
AdrVals[0] &= 127;
AdrMode = ModMem;
}
}
else
{
*AdrVals = EvalStrIntExpression(pArg, OpSize, &OK);
if (OK)
AdrMode = ModImm;
}
done:
if ((AdrMode != ModNone) && (!(Mask & (1 << AdrMode))))
{
AdrMode = ModNone; AdrCnt = 0;
WrError(ErrNum_InvAddrMode);
}
return (AdrMode != ModNone);
}
static Boolean MakeXY(Word *Dest, Boolean Quarrel)
{
Boolean Result = False;
if (AdrMode != ModMem); /* should never occur, if address mask specified correctly before */
else
{
Word Mode = (*AdrVals >> 3) & 15, Reg = *AdrVals & 7;
if ((Reg < 2) || (Reg > 5));
else if ((Mode != 0) && (Mode != 1) && (Mode != 2) && (Mode != 11));
else
{
*Dest = (Reg - 2) | ((Mode & 3) << 2);
Result = True;
}
}
if ((Quarrel) && (!Result))
WrError(ErrNum_InvAddrMode);
return Result;
}
static Boolean DecodeCondition(int StartIndex, Word *Result, int *errindex, Boolean *ErrUnknown)
{
int z, z2;
Word CurrClass, CurrMask;
*Result = CurrMask = 0; CurrClass = 0xffff; *ErrUnknown = False;
for (z = StartIndex; z <= ArgCnt; z++)
{
for (z2 = 0; z2 < ConditionCnt; z2++)
if (!as_strcasecmp(ArgStr[z].str.p_str, Conditions[z2].Name))
break;
if (z2 >= ConditionCnt)
{
*ErrUnknown = True;
break;
}
if (CurrClass == 0xffff)
CurrClass = Conditions[z2].Class;
else if (CurrClass != Conditions[z2].Class)
break;
if (Conditions[z2].Mask & CurrMask)
break;
CurrMask |= Conditions[z2].Mask;
*Result |= Conditions[z2].Code;
}
*errindex = z;
return (CurrClass != 0xffff) && (z > ArgCnt);
}
/*-------------------------------------------------------------------------*/
/* Decoders */
static void DecodeFixed(Word Index)
{
const FixedOrder *POrder = FixedOrders + Index;
if (!ChkArgCnt(0, 0));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else
{
WAsmCode[0] = POrder->Code;
CodeLen = 1;
}
}
static void DecodeAcc(Word Index)
{
const FixedOrder *POrder = AccOrders + Index;
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else
{
if (DecodeAdr(&ArgStr[1], MModAcc))
{
WAsmCode[0] = POrder->Code | (AdrVals[0] << 8);
CodeLen = 1;
}
}
}
static void DecodeAcc2(Word Index)
{
const FixedOrder *POrder = Acc2Orders + Index;
Boolean OK;
if (!ChkArgCnt(1, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else
{
OK = DecodeAdr(&ArgStr[1], MModAcc);
if (OK)
{
WAsmCode[0] = POrder->Code | (AdrVals[0] << 9);
if (ArgCnt == 2)
OK = DecodeAdr(&ArgStr[2], MModAcc);
if (OK)
{
WAsmCode[0] |= (AdrVals[0] << 8);
CodeLen = 1;
}
}
}
}
static void DecodeMem(Word Index)
{
const FixedOrder *POrder = MemOrders + Index;
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else if (DecodeAdr(&ArgStr[1], MModMem))
{
memcpy(WAsmCode
, AdrVals
, (AdrCnt
+ 1) << 1);
WAsmCode[0] |= POrder->Code;
CodeLen = 1 + AdrCnt;
}
}
static void DecodeXY(Word Index)
{
const FixedOrder *POrder = XYOrders + Index;
Word TmpX, TmpY;
if (ArgCnt != 2) WrError(ErrNum_InvAddrMode);
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else
{
if (DecodeAdr(&ArgStr[1], MModMem))
if (MakeXY(&TmpX, True))
if (DecodeAdr(&ArgStr[2], MModMem))
if (MakeXY(&TmpY, True))
{
WAsmCode[0] = POrder->Code | (TmpX << 4) | TmpY;
CodeLen = 1;
}
}
}
static void DecodeADDSUB(Word Index)
{
Boolean OK;
Integer Shift;
Word DestAcc;
if (ChkArgCnt(2, 4))
{
OpSize = SInt16;
DecodeAdr(&ArgStr[1], MModAcc | MModMem | MModImm);
switch (AdrMode)
{
case ModAcc: /* ADD src, SHIFT|ASM [,dst] */
if (!ChkArgCnt(2, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
Word SrcAcc = *AdrVals;
/* SrcAcc remains in AdrVals[0] if no 3rd operand, therefore
no extra assignment needed! */
if (ArgCnt == 3)
{
if (!DecodeAdr(&ArgStr[3], MModAcc))
break;
}
/* distinguish variants of shift specification: */
if (!as_strcasecmp(ArgStr[2].str.p_str, "ASM"))
{
WAsmCode[0] = 0xf480 | Index | (SrcAcc << 9) | (*AdrVals << 8);
CodeLen = 1;
}
else
{
WAsmCode[0] = EvalStrIntExpression(&ArgStr[2], SInt5, &OK);
if (OK)
{
WAsmCode[0] = (WAsmCode[0] & 0x1f) | 0xf400 | (Index << 5) | (SrcAcc << 9) | (*AdrVals << 8);
CodeLen = 1;
}
}
}
break;
case ModMem: /* ADD mem[, TS | SHIFT | Ymem], src[, dst] */
{
int HCnt;
/* rescue decoded address values */
memcpy(WAsmCode
, AdrVals
, (AdrCnt
+ 1) << 1);
HCnt = AdrCnt;
/* no shift? this is the case for two operands or three operands and the second is an accumulator */
if (ArgCnt == 2)
Shift = 0;
else if ((ArgCnt == 3) && (IsAcc(ArgStr[2].str.p_str)))
Shift = 0;
/* special shift value ? */
else if (!as_strcasecmp(ArgStr[2].str.p_str, "TS"))
Shift = 255;
/* shift address operand ? */
else if (*ArgStr[2].str.p_str == '*')
{
Word Tmp;
/* break down source operand to reduced variant */
if (!MakeXY(WAsmCode, True))
break;
WAsmCode[0] = WAsmCode[0] << 4;
/* merge in second operand */
if (!DecodeAdr(&ArgStr[2], MModMem))
break;
if (!MakeXY(&Tmp, True))
break;
WAsmCode[0] |= Tmp;
Shift = 254;
}
/* normal immediate shift */
else
{
tSymbolFlags Flags;
Shift = EvalStrIntExpressionWithFlags(&ArgStr[2], SInt6, &OK, &Flags);
if (!OK)
break;
if (mFirstPassUnknown(Flags) && (Shift > 16))
Shift &= 15;
if (!ChkRange(Shift, -16 ,16))
break;
}
/* decode destination accumulator */
if (!DecodeAdr(&ArgStr[ArgCnt], MModAcc))
break;
DestAcc = *AdrVals;
/* optionally decode source accumulator. If no second accumulator, result
again remains in AdrVals */
if ((ArgCnt == 4) || ((ArgCnt == 3) && (IsAcc(ArgStr[2].str.p_str))))
{
if (!DecodeAdr(&ArgStr[ArgCnt - 1], MModAcc))
break;
}
/* now start applying the variants */
if (Shift == 255) /* TS case */
{
if (*AdrVals != DestAcc) WrError(ErrNum_InvAddrMode);
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[0] |= 0x0400 | (Index << 11) | (DestAcc << 8);
CodeLen = 1 + HCnt;
}
}
else if (Shift == 254) /* XY case */
{
if (*AdrVals != DestAcc) WrError(ErrNum_InvAddrMode);
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[0] |= 0xa000 | (Index << 9) | (DestAcc << 8);
CodeLen = 1;
}
}
else if (Shift == 16) /* optimization for 16 shifts */
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[0] |= (0x3c00 + (Index << 10)) | (*AdrVals << 9) | (DestAcc << 8);
CodeLen = 1 + HCnt;
}
}
else if ((DestAcc == *AdrVals) && (Shift == 0)) /* shortform without shift and with one accu only */
{
if (ThisPar)
{
AdrMode = ModMem; AdrVals[0] = WAsmCode[0];
if (MakeXY(AdrVals, True))
{
/* prev. operation must be STH src,0,Xmem */
if ((LastOpCode & 0xfe0f) != 0x9a00) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
WAsmCode[0] = 0xc000 | (Index << 10) | (DestAcc << 8) | ((LastOpCode & 0x0100) << 1) | ((LastOpCode & 0x00f0) >> 4) | (*AdrVals << 4);
CodeLen = 1;
}
}
}
else
{
WAsmCode[0] |= 0x0000 | (Index << 11) | (DestAcc << 8);
CodeLen = 1 + HCnt;
}
}
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
Word SrcAcc = *AdrVals;
/* fool MakeXY a bit */
AdrMode = ModMem; AdrVals[0] = WAsmCode[0];
if ((Shift >= 0) && (DestAcc == SrcAcc) && (MakeXY(WAsmCode, False))) /* X-Addr and positive shift */
{
WAsmCode[0] = 0x9000 | (Index << 9) | (WAsmCode[0] << 4) | (DestAcc << 8) | Shift;
CodeLen = 1;
}
else /* last resort... */
{
WAsmCode[0] |= 0x6f00;
WAsmCode[2] = WAsmCode[1]; /* shift optional address offset */
WAsmCode[1] = 0x0c00 | (Index << 5) | (SrcAcc << 9) | (DestAcc << 8) | (Shift & 0x1f);
CodeLen = 2 + HCnt;
}
}
break;
}
case ModImm: /* ADD #lk[, SHIFT|16], src[, dst] */
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
{
/* store away constant */
WAsmCode[1] = *AdrVals;
/* no shift? this is the case for two operands or three operands and the second is an accumulator */
if (ArgCnt == 2)
Shift = 0;
else if ((ArgCnt == 3) && (IsAcc(ArgStr[2].str.p_str)))
Shift = 0;
/* otherwise shift is second argument */
else
{
tSymbolFlags Flags;
Shift = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt5, &OK, &Flags);
if (!OK)
break;
if (mFirstPassUnknown(Flags) && (Shift > 16))
Shift &= 15;
if (!ChkRange(Shift, 0 ,16))
break;
}
/* decode destination accumulator */
if (!DecodeAdr(&ArgStr[ArgCnt], MModAcc))
break;
DestAcc = *AdrVals;
/* optionally decode source accumulator. If no second accumulator, result
again remains in AdrVals */
if ((ArgCnt == 4) || ((ArgCnt == 3) && (IsAcc(ArgStr[2].str.p_str))))
{
if (!DecodeAdr(&ArgStr[ArgCnt - 1], MModAcc))
break;
}
/* distinguish according to shift count */
if (Shift == 16)
{
WAsmCode[0] = 0xf060 | Index | (DestAcc << 8) | (*AdrVals << 9);
CodeLen = 2;
}
else
{
WAsmCode[0] = 0xf000 | (Index << 5) | (DestAcc << 8) | (*AdrVals << 9) | (Shift & 15);
CodeLen = 2;
}
}
break;
}
}
}
}
static void DecodeMemAcc(Word Index)
{
FixedOrder *POrder = MemAccOrders + Index;
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else if (DecodeAdr(&ArgStr[2], MModAcc))
{
WAsmCode[0] = POrder->Code | (AdrVals[0] << 8);
if (DecodeAdr(&ArgStr[1], MModMem))
{
WAsmCode[0] |= *AdrVals;
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
}
static void DecodeMemConst(Word Index)
{
MemConstOrder *POrder = MemConstOrders + Index;
int HCnt;
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((LastRep) && (!POrder->IsRepeatable)) WrError(ErrNum_NotRepeatable);
else if (DecodeAdr(&ArgStr[2 - POrder->Swap], MModMem))
{
WAsmCode[0] = POrder->Code | 0[AdrVals];
HCnt = AdrCnt;
if (HCnt)
WAsmCode[1] = AdrVals[1];
OpSize = POrder->ConstType;
if (DecodeAdr(&ArgStr[1 + POrder->Swap], MModImm))
{
WAsmCode[1 + HCnt] = *AdrVals;
CodeLen = 2 + HCnt;
}
}
}
static void DecodeMPY(Word Index)
{
Word DestAcc;
(void)Index;
if (!ChkArgCnt(2, 3));
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
DestAcc = (*AdrVals) << 8;
if (ArgCnt == 3)
{
Word XMode;
if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModMem))
if (MakeXY(&XMode, True))
if (DecodeAdr(&ArgStr[2], MModMem))
if (MakeXY(WAsmCode, True))
{
*WAsmCode |= 0xa400 | DestAcc | (XMode << 4);
CodeLen = 1;
}
}
else
{
OpSize = SInt16;
DecodeAdr(&ArgStr[1], MModImm | MModMem);
switch (AdrMode)
{
case ModImm:
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[0] = 0xf066 | DestAcc;
WAsmCode[1] = *AdrVals;
CodeLen = 2;
}
break;
case ModMem:
if (ThisPar)
{
if (MakeXY(AdrVals, True))
{
/* previous op ST src, Ym */
if ((LastOpCode & 0xfe0f) != 0x9a00) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
*WAsmCode = 0xcc00 | DestAcc | ((LastOpCode & 0x0100) << 1) | ((LastOpCode & 0x00f0) >> 4) | (*AdrVals);
CodeLen = 1;
}
}
}
else
{
WAsmCode[0] = 0x2000 | DestAcc | 0[AdrVals];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
break;
}
}
}
}
static void DecodeMPYA(Word Index)
{
(void) Index;
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
DecodeAdr(&ArgStr[1], MModAcc | MModMem);
switch (AdrMode)
{
case ModMem:
WAsmCode[0] = 0x3100 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
break;
case ModAcc:
WAsmCode[0] = 0xf48c | (*AdrVals << 8);
CodeLen = 1;
break;
}
}
}
static void DecodeSQUR(Word Index)
{
(void)Index;
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[2], MModAcc))
{
0[WAsmCode] = *AdrVals << 8;
DecodeAdr(&ArgStr[1], MModAcc | MModMem);
switch (AdrMode)
{
case ModAcc:
if (*AdrVals) WrError(ErrNum_InvAddrMode);
else
{
WAsmCode[0] |= 0xf48d;
CodeLen = 1;
}
break;
case ModMem:
WAsmCode[0] |= 0x2600 | *AdrVals;
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
break;
}
}
}
static void DecodeMAC(Word Index)
{
(void) Index;
if (!ChkArgCnt(2, 4));
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
*WAsmCode = (*AdrVals) << 8;
OpSize = SInt16;
DecodeAdr(&ArgStr[1], MModImm | MModMem);
/* handle syntax 3: immediate op first */
if (AdrMode == ModImm)
{
if (!ChkArgCnt(2, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
*WAsmCode |= 0xf067; WAsmCode[1] = *AdrVals;
if (ArgCnt == 2)
{
*WAsmCode |= ((*WAsmCode & 0x100) << 1);
CodeLen = 2;
}
else if (DecodeAdr(&ArgStr[2], MModAcc))
{
*WAsmCode |= ((*AdrVals) << 9);
CodeLen = 2;
}
}
}
/* syntax 1/2/4 have memory operand in front */
else if (AdrMode == ModMem)
{
/* save [first] memory operand */
Word HMode = *AdrVals, HCnt = AdrCnt;
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
/* syntax 2+4 have at least 3 operands, handle syntax 1 */
if (ArgCnt == 2)
{
if (ThisPar)
{
if (MakeXY(AdrVals, True))
{
if ((LastOpCode & 0xfe0f) == 0x9400) /* previous op LD Xmem, src */
{
if ((LastOpCode & 0x0100) == (*WAsmCode & 0x0100)) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
*WAsmCode = 0xa800 | (LastOpCode & 0x01f0) | (*AdrVals);
CodeLen = 1;
}
}
else if ((LastOpCode & 0xfe0f) == 0x9a00) /* previous op ST src, Ymem */
{
RetractWords(1);
*WAsmCode |= 0xd000 | ((LastOpCode & 0x0100) << 1) | ((LastOpCode & 0x00f0) >> 4) | (*AdrVals << 4);
CodeLen = 1;
}
else WrError(ErrNum_ParNotPossible);
}
}
else
{
*WAsmCode |= 0x2800 | HMode;
CodeLen = 1 + AdrCnt;
}
}
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
/* both syntax 2+4 have optional second accumulator */
if (ArgCnt == 3)
*WAsmCode |= ((*WAsmCode & 0x100) << 1);
else if (DecodeAdr(&ArgStr[3], MModAcc))
*WAsmCode |= ((*AdrVals) << 9);
/* if no second accu, AdrMode is still set from previous decode */
if (AdrMode != ModNone)
{
/* differentiate & handle syntax 2 & 4. OpSize still set from above! */
DecodeAdr(&ArgStr[2], MModMem | MModImm);
switch (AdrMode)
{
case ModMem:
if (MakeXY(AdrVals, TRUE))
{
WAsmCode[0] |= (*AdrVals);
*AdrVals = HMode;
if (MakeXY(&HMode, TRUE))
{
WAsmCode[0] |= 0xb000 | (HMode << 4);
CodeLen = 1;
}
}
break;
case ModImm:
WAsmCode[1 + HCnt] = *AdrVals;
WAsmCode[0] |= 0x6400 | HMode;
CodeLen = 2 + HCnt;
break;
}
}
}
}
}
}
static void DecodeMACDP(Word Index)
{
if (!ChkArgCnt(3, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[3], MModAcc))
{
*WAsmCode = Index | (0[AdrVals] << 8);
if (DecodeAdr(&ArgStr[1], MModMem))
{
tEvalResult EvalResult;
*WAsmCode |= *AdrVals;
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
WAsmCode[1 + AdrCnt] = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(Index & 0x200 ? SegData : SegCode, EvalResult.AddrSpaceMask);
CodeLen = 2 + AdrCnt;
}
}
}
}
static void DecodeFIRS(Word Index)
{
(void)Index;
if (!ChkArgCnt(3, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModMem))
if (MakeXY(WAsmCode, TRUE))
{
0[WAsmCode] = 0xe000 | ((*WAsmCode) << 4);
if (DecodeAdr(&ArgStr[2], MModMem))
if (MakeXY(AdrVals, TRUE))
{
tEvalResult EvalResult;
0[WAsmCode] |= *AdrVals;
WAsmCode[1] = EvalStrIntExpressionWithResult(&ArgStr[3], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
CodeLen = 2;
}
}
}
}
static void DecodeBIT(Word Index)
{
Boolean OK;
(void)Index;
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModMem))
if (MakeXY(AdrVals, TRUE))
{
WAsmCode[0] = EvalStrIntExpression(&ArgStr[2], UInt4, &OK);
if (OK)
{
WAsmCode[0] |= 0x9600 | (AdrVals[0] << 4);
CodeLen = 1;
}
}
}
static void DecodeBITF(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
OpSize = UInt16;
if (DecodeAdr(&ArgStr[2], MModImm))
{
WAsmCode[1] = *AdrVals;
if (DecodeAdr(&ArgStr[1], MModMem))
{
*WAsmCode = 0x6100 | *AdrVals;
if (AdrCnt)
{
WAsmCode[2] = WAsmCode[1];
WAsmCode[1] = AdrVals[1];
}
CodeLen = 2 + AdrCnt;
}
}
}
}
static void DecodeMACR(Word Index)
{
(void) Index;
if (!ChkArgCnt(2, 4));
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
*WAsmCode = *AdrVals << 8;
if (DecodeAdr(&ArgStr[1], MModMem))
{
if (ArgCnt == 2)
{
if (ThisPar)
{
if (MakeXY(AdrVals, True))
{
if ((LastOpCode & 0xfe0f) == 0x9400) /* previous op LD Xmem, src */
{
if ((LastOpCode & 0x0100) == (*WAsmCode & 0x0100)) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
*WAsmCode = 0xaa00 | (LastOpCode & 0x01f0) | (*AdrVals);
CodeLen = 1;
}
}
else if ((LastOpCode & 0xfe0f) == 0x9a00) /* previous op ST src, Ymem */
{
RetractWords(1);
*WAsmCode |= 0xd400 | ((LastOpCode & 0x0100) << 1) | ((LastOpCode & 0x00f0) >> 4) | (*AdrVals << 4);
CodeLen = 1;
}
else WrError(ErrNum_ParNotPossible);
}
}
else
{
WAsmCode[0] |= 0x2a00 | *AdrVals;
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
if (MakeXY(AdrVals, True))
{
WAsmCode[0] |= 0xb400 | ((*AdrVals) << 4);
if (DecodeAdr(&ArgStr[2], MModMem))
if (MakeXY(AdrVals, True))
{
WAsmCode[0] |= *AdrVals;
if (ArgCnt == 4)
{
if (DecodeAdr(&ArgStr[3], MModAcc))
WAsmCode[0] |= (*AdrVals) << 9;
}
else
*WAsmCode |= ((*WAsmCode & 0x100) << 1);
if (AdrMode != ModNone)
CodeLen = 1;
}
}
}
}
}
}
static void DecodeMac(Word Index)
{
FixedOrder *POrder = MacOrders + Index;
if (!ChkArgCnt(1, ArgCntMax));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (!as_strcasecmp(ArgStr[1].str.p_str, "T"))
{
if (!ChkArgCnt(1, 3));
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
WAsmCode[0] = 0xf480 | (POrder->Code & 0xff) | ((*AdrVals) << 8);
if (ArgCnt == 3)
DecodeAdr(&ArgStr[2], MModAcc);
if (AdrMode != ModNone)
{
WAsmCode[0] |= ((*AdrVals) << 9);
CodeLen = 1;
}
}
}
else if (!ChkArgCnt(1, 2));
else
{
if ((ArgCnt == 2) && (as_strcasecmp(ArgStr[2].str.p_str, "B"))) WrError(ErrNum_InvAddrMode);
else if (DecodeAdr(&ArgStr[1], MModMem))
{
WAsmCode[0] = (POrder->Code & 0xff00) | (*AdrVals);
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
}
static void DecodeMACSU(Word Index)
{
(void)Index;
if (!ChkArgCnt(3, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[3], MModAcc))
{
*WAsmCode = 0xa600 | ((*AdrVals) << 8);
if ((DecodeAdr(&ArgStr[1], MModMem))
&& (MakeXY(AdrVals, TRUE)))
{
*WAsmCode |= ((*AdrVals) << 4);
if ((DecodeAdr(&ArgStr[2], MModMem))
&& (MakeXY(AdrVals, TRUE)))
{
*WAsmCode |= *AdrVals;
CodeLen = 1;
}
}
}
}
static void DecodeMAS(Word Index)
{
if (!ChkArgCnt(2, 4));
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
*WAsmCode = ((*AdrVals) << 8);
if (DecodeAdr(&ArgStr[1], MModMem))
{
if (ArgCnt == 2)
{
if (ThisPar)
{
if (MakeXY(AdrVals, True))
{
if ((LastOpCode & 0xfe0f) == 0x9400) /* previous op LD Xmem, src */
{
if ((LastOpCode & 0x0100) == (*WAsmCode & 0x0100)) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
*WAsmCode = 0xac00 | Index | (LastOpCode & 0x01f0) | (*AdrVals);
CodeLen = 1;
}
}
else if ((LastOpCode & 0xfe0f) == 0x9a00) /* previous op ST src, Ymem */
{
RetractWords(1);
*WAsmCode |= 0xd800 | (Index << 1) | ((LastOpCode & 0x0100) << 1) | ((LastOpCode & 0x00f0) >> 4) | (*AdrVals << 4);
CodeLen = 1;
}
else WrError(ErrNum_ParNotPossible);
}
}
else
{
*WAsmCode |= 0x2c00 | Index | *AdrVals;
if (AdrCnt)
1[WAsmCode] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (MakeXY(AdrVals, TRUE))
{
*WAsmCode |= 0xb800 | (Index << 1) | ((*AdrVals) << 4);
if (DecodeAdr(&ArgStr[2], MModMem))
if (MakeXY(AdrVals, TRUE))
{
*WAsmCode |= *AdrVals;
if (ArgCnt == 4)
{
if (DecodeAdr(&ArgStr[3], MModAcc))
*WAsmCode |= ((*AdrVals) << 9);
}
else
*WAsmCode |= ((*WAsmCode & 0x100) << 1);
if (AdrMode != ModNone)
CodeLen = 1;
}
}
}
}
}
static void DecodeMASAR(Word Index)
{
(void)Index;
if (!ChkArgCnt(2, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (as_strcasecmp(ArgStr[1].str.p_str, "T")) WrError(ErrNum_InvAddrMode);
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
WAsmCode[0] = (*AdrVals << 8);
if (ArgCnt == 3)
DecodeAdr(&ArgStr[2], MModAcc);
if (AdrMode != ModNone)
{
*WAsmCode |= 0xf48b | ((*AdrVals) << 9);
CodeLen = 1;
}
}
}
static void DecodeDADD(Word Index)
{
(void)Index;
if (!ChkArgCnt(2, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
WAsmCode[0] = 0x5000 | (AdrVals[0] << 8);
if (ArgCnt == 3)
DecodeAdr(&ArgStr[2], MModAcc);
if (AdrMode != ModNone)
{
WAsmCode[0] |= (AdrVals[0] << 9);
if (DecodeAdr(&ArgStr[1], MModMem))
{
WAsmCode[0] |= AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
}
}
static void DecodeLog(Word Index)
{
Word Acc, Shift;
Boolean OK;
if (!ChkArgCnt(1, 4));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
OpSize = UInt16;
DecodeAdr(&ArgStr[1], MModAcc | MModMem | MModImm);
switch (AdrMode)
{
case ModAcc: /* Variant 4 */
if (ChkArgCnt(1, 3))
{
Acc = *AdrVals << 9;
*WAsmCode = 0xf080 | Acc | (Index << 5);
Shift = 0; OK = True;
if (((ArgCnt == 2) && IsAcc(ArgStr[2].str.p_str)) || (ArgCnt == 3))
{
OK = DecodeAdr(&ArgStr[ArgCnt], MModAcc);
if (OK)
Acc = *AdrVals << 8;
}
else
Acc = Acc >> 1;
if (OK)
if (((ArgCnt == 2) && (!IsAcc(ArgStr[2].str.p_str))) || (ArgCnt == 3))
{
Shift = EvalStrIntExpression(&ArgStr[2], SInt5, &OK);
}
if (OK)
{
*WAsmCode |= Acc | (Shift & 0x1f);
CodeLen = 1;
}
}
break;
case ModMem: /* Variant 1 */
if (ChkArgCnt(2, 2))
{
*WAsmCode = 0x1800 | (*AdrVals) | (Index << 9);
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = AdrCnt + 1;
if (DecodeAdr(&ArgStr[2], MModAcc))
*WAsmCode |= (*AdrVals) << 8;
else
CodeLen = 0;
}
break;
case ModImm: /* Variant 2,3 */
if (ChkArgCnt(2, 4))
{
WAsmCode[1] = *AdrVals;
if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
*WAsmCode = Acc = *AdrVals << 8;
Shift = 0;
OK = True;
if (((ArgCnt == 3) && IsAcc(ArgStr[2].str.p_str)) || (ArgCnt == 4))
{
OK = DecodeAdr(&ArgStr[ArgCnt - 1], MModAcc);
if (OK)
Acc = (*AdrVals) << 9;
}
else
Acc = Acc << 1;
if (OK)
{
if (((ArgCnt == 3) && (!IsAcc(ArgStr[2].str.p_str))) || (ArgCnt == 4))
{
tSymbolFlags Flags;
Shift = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt5, &OK, &Flags);
if (mFirstPassUnknown(Flags))
Shift &= 15;
OK = ChkRange(Shift, 0, 16);
}
}
if (OK)
{
*WAsmCode |= Acc;
if (Shift == 16) /* Variant 3 */
{
*WAsmCode |= 0xf063 + Index;
}
else /* Variant 2 */
{
*WAsmCode |= 0xf000 | ((Index + 3) << 4) | Shift;
}
CodeLen = 2;
}
}
}
break;
}
}
}
static void DecodeSFT(Word Index)
{
Boolean OK;
int Shift;
if (!ChkArgCnt(2, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
0[WAsmCode] = Index | ((*AdrVals) << 9);
if (ArgCnt == 3)
DecodeAdr(&ArgStr[3], MModAcc);
if (AdrMode != ModNone)
{
0[WAsmCode] |= ((*AdrVals) << 8);
Shift = EvalStrIntExpression(&ArgStr[2], SInt5, &OK);
if (OK)
{
0[WAsmCode] |= (Shift & 0x1f);
CodeLen = 1;
}
}
}
}
static void DecodeCMPR(Word Index)
{
Word z;
Boolean OK;
(void) Index;
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[2], MModAReg))
{
OK = False;
for (z = 0; z < 4; z++)
if (!as_strcasecmp(ArgStr[1].str.p_str, ShortConds[z]))
{
OK = True;
break;
}
if (!OK)
z = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
if (OK)
{
0[WAsmCode] = 0xf4a8 | (*AdrVals) | (z << 8);
CodeLen = 1;
}
}
}
static void DecodePMAD(Word Index)
{
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else
{
tEvalResult EvalResult;
WAsmCode[1] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
0[WAsmCode] = Index;
CodeLen = 2;
}
}
}
static void DecodeBANZ(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else if (DecodeAdr(&ArgStr[2], MModMem))
{
tEvalResult EvalResult;
if (CodeLen)
WAsmCode[1] = 1[AdrVals];
WAsmCode[1 + CodeLen] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
0[WAsmCode] = Index | (*AdrVals);
CodeLen = 2 + AdrCnt;
}
}
}
static void DecodePMADCond(Word Index)
{
int index;
Boolean OK;
if (!ChkArgCnt(2, ArgCntMax));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else if (!DecodeCondition(2, WAsmCode, &index, &OK))
WrStrErrorPos(OK ? ErrNum_UndefCond : ErrNum_IncompCond, &ArgStr[index]);
else
{
tEvalResult EvalResult;
WAsmCode[1] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
0[WAsmCode] |= Index;
CodeLen = 2;
}
}
}
static void DecodeFPMAD(Word Index)
{
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else
{
tEvalResult EvalResult;
LongWord Addr = EvalStrIntExpressionWithResult(&ArgStr[1], UInt23, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
0[WAsmCode] = Index | (Addr >> 16);
1[WAsmCode] = Addr & 0xffff;
CodeLen = 2;
}
}
}
static void DecodeINTR(Word Index)
{
Boolean OK;
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else
{
*WAsmCode = Index | EvalStrIntExpression(&ArgStr[1], UInt5, &OK);
if (OK)
CodeLen = 1;
}
}
static void DecodeRPT(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else
{
OpSize = UInt16;
DecodeAdr(&ArgStr[1], MModImm | MModMem);
switch (AdrMode)
{
case ModImm:
if (!Hi(*AdrVals))
{
*WAsmCode = 0xec00 | (*AdrVals);
CodeLen = 1;
}
else
{
*WAsmCode = 0xf070;
WAsmCode[1] = *AdrVals;
CodeLen = 2;
}
ThisRep = True;
break;
case ModMem:
WAsmCode[0] = 0x4700 | (*AdrVals);
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
ThisRep = True;
break;
}
}
}
static void DecodeRPTZ(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
*WAsmCode = 0xf071 | (AdrVals[0] << 8);
OpSize = UInt16;
if (DecodeAdr(&ArgStr[2], MModImm))
{
WAsmCode[1] = *AdrVals;
CodeLen = 2;
ThisRep = True;
}
}
}
static void DecodeFRAME(Word Index)
{
Boolean OK;
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
*WAsmCode = 0xee00 | (EvalStrIntExpression(&ArgStr[1], SInt8, &OK) & 0xff);
if (OK)
CodeLen = 1;
}
}
static void DecodeIDLE(Word Index)
{
Boolean OK;
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else
{
tSymbolFlags Flags;
*WAsmCode = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt2, &OK, &Flags);
if (mFirstPassUnknown(Flags))
*WAsmCode = 1;
if ((OK) && (ChkRange(*WAsmCode, 1, 3)))
{
if (*WAsmCode != 2)
*WAsmCode = (*WAsmCode) >> 1;
*WAsmCode = 0xf4e1 | (*WAsmCode << 8);
CodeLen = 1;
}
}
}
static void DecodeSBIT(Word Index)
{
Boolean OK;
Word Bit;
if (!ChkArgCnt(1, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else
{
if (ArgCnt == 1)
Bit = EvalStrIntExpression(&ArgStr[1], UInt5, &OK);
else
{
Bit = EvalStrIntExpression(&ArgStr[1], UInt1, &OK) << 4;
if (OK)
Bit |= EvalStrIntExpression(&ArgStr[2], UInt4, &OK);
}
if (OK)
{
*WAsmCode = Index | ((Bit & 16) << 5) | (Bit & 15);
CodeLen = 1;
}
}
}
static void DecodeXC(Word Index)
{
Boolean OK;
int errindex;
UNUSED(Index);
if (!ChkArgCnt(2, ArgCntMax));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (LastRep) WrError(ErrNum_NotRepeatable);
else if (!DecodeCondition(2, WAsmCode, &errindex, &OK))
WrStrErrorPos(OK ? ErrNum_UndefCond : ErrNum_IncompCond, &ArgStr[errindex]);
else
{
tSymbolFlags Flags;
errindex = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt2, &OK, &Flags);
if (mFirstPassUnknown(Flags))
errindex = 1;
if ((OK) && (ChkRange(errindex, 1, 2)))
{
errindex--;
0[WAsmCode] |= 0xfd00 | (errindex << 9);
CodeLen = 1;
}
}
}
static void DecodeLD(Word Index)
{
Integer Shift;
Boolean OK;
UNUSED(Index);
if (!ChkArgCnt(2, 3));
else if (!as_strcasecmp(ArgStr[ArgCnt].str.p_str, "T"))
{
if (!ChkArgCnt(2, 2));
else if (DecodeAdr(&ArgStr[1], MModMem))
{
if (ThisPar)
{
if (MakeXY(AdrVals, TRUE))
{
/* prev. operation must be STH src,0,Xmem */
if ((LastOpCode & 0xfe0f) != 0x9a00) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
*WAsmCode = 0xe400 | ((LastOpCode & 0x0100) << 1)
| ((LastOpCode & 0x00f0) >> 4) | ((*AdrVals) << 4);
CodeLen = 1;
}
}
}
else
{
WAsmCode[0] = 0x3000 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
}
else if (!as_strcasecmp(ArgStr[ArgCnt].str.p_str, "DP"))
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
OpSize = UInt9;
DecodeAdr(&ArgStr[1], MModMem | MModImm);
switch (AdrMode)
{
case ModMem:
WAsmCode[0] = 0x2600 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
break;
case ModImm:
WAsmCode[0] = 0xea00 | (AdrVals[0] & 0x1ff);
CodeLen = 1;
break;
}
}
}
else if (!as_strcasecmp(ArgStr[ArgCnt].str.p_str, "ARP"))
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
OpSize = UInt3;
if (DecodeAdr(&ArgStr[1], MModImm))
{
WAsmCode[0] = 0xf4a0 | (AdrVals[0] & 7);
CodeLen = 1;
}
}
}
else if (!as_strcasecmp(ArgStr[2].str.p_str, "ASM"))
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
OpSize = SInt5;
DecodeAdr(&ArgStr[1], MModAcc | MModMem | MModImm);
switch (AdrMode)
{
case ModAcc:
WAsmCode[0] = *AdrVals << 9;
if (ArgCnt == 3)
DecodeAdr(&ArgStr[3], MModAcc);
if (AdrMode == ModAcc)
{
WAsmCode[0] |= 0xf482 | (AdrVals[0] << 8);
CodeLen = 1;
}
break;
case ModMem:
if (ChkArgCnt(2, 2))
{
WAsmCode[0] = 0x3200 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
break;
case ModImm:
if (ChkArgCnt(2, 2))
{
WAsmCode[0] = 0xed00 | (AdrVals[0] & 0x1f);
CodeLen = 1;
}
break;
}
}
}
else if (DecodeAdr(&ArgStr[ArgCnt], MModAcc))
{
*WAsmCode = *AdrVals << 8;
if (ArgCnt == 3)
{
if (!as_strcasecmp(ArgStr[2].str.p_str, "TS"))
{
Shift = 0xff;
OK = True;
}
else
{
tSymbolFlags Flags;
Shift = EvalStrIntExpressionWithFlags(&ArgStr[2], SInt6, &OK, &Flags);
if (mFirstPassUnknown(Flags))
Shift = 0;
if (OK)
OK = ChkRange(Shift, -16, 16);
}
}
else
{
Shift = 0;
OK = True;
}
if (OK)
{
OpSize = UInt16;
DecodeAdr(&ArgStr[1], MModAcc | MModMem | MModImm);
switch (AdrMode)
{
case ModAcc:
if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (ChkRange(Shift, -16, 15))
{
*WAsmCode |= 0xf440 | (AdrVals[0] << 9) | (Shift & 0x1f);
CodeLen = 1;
}
break;
case ModMem:
if (Shift == 0xff) /* TS ? */
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
*WAsmCode |= 0x1400 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
else if ((Shift >= 0) && (MakeXY(WAsmCode + 1, False)))
{
if (ThisPar)
{
if (Shift) WrError(ErrNum_ParNotPossible);
/* prev. operation must be STH src,0,Xmem */
else if ((LastOpCode & 0xfe0f) != 0x9a00) WrError(ErrNum_ParNotPossible);
else
{
RetractWords(1);
*WAsmCode |= 0xc800 | ((LastOpCode & 0x0100) << 1)
| ((LastOpCode & 0x00f0) >> 4) | (WAsmCode[1] << 4);
CodeLen = 1;
}
}
else
{
WAsmCode[0] |= 0x9400 | (WAsmCode[1] << 4) | Shift;
CodeLen = 1;
}
}
else if (Shift == 16)
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[0] |= 0x4400 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
else if (!Shift)
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[0] |= 0x1000 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 1 + AdrCnt;
}
}
else
{
if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
WAsmCode[1 + AdrCnt] = 0x0c40 | WAsmCode[0] | (Shift & 0x1f);
WAsmCode[0] = 0x6f00 | AdrVals[0];
if (AdrCnt)
WAsmCode[1] = AdrVals[1];
CodeLen = 2 + AdrCnt;
}
}
break;
case ModImm:
if (Shift == 0xff) WrError(ErrNum_InvAddrMode);
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (ChkRange(Shift, 0, 16))
{
if ((Hi(AdrVals[0]) == 0) && (!Shift))
{
WAsmCode[0] |= 0xe800 | Lo(AdrVals[0]);
CodeLen = 1;
}
else if (Shift == 16)
{
WAsmCode[0] |= 0xf062;
WAsmCode[1] = AdrVals[0];
CodeLen = 2;
}
else
{
WAsmCode[0] |= 0xf020 | (Shift & 15);
WAsmCode[1] = AdrVals[0];
CodeLen = 2;
}
}
break;
}
}
}
}
static void DecodePSHM(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
ForcePageZero = True;
if (DecodeAdr(&ArgStr[1], MModMem))
{
*WAsmCode = 0x4a00 | (*AdrVals);
CodeLen = 1;
}
}
}
static void DecodeLDM(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[2], MModAcc))
{
*WAsmCode = 0x4800 | (*AdrVals << 8);
ForcePageZero = True;
if (DecodeAdr(&ArgStr[1], MModMem))
{
*WAsmCode |= *AdrVals;
CodeLen = 1;
}
}
}
static void DecodeSTLM(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
*WAsmCode = 0x8800 | (*AdrVals << 8);
ForcePageZero = True;
if (DecodeAdr(&ArgStr[2], MModMem))
{
*WAsmCode |= *AdrVals;
CodeLen = 1;
}
}
}
static void DecodeSTM(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModImm))
{
WAsmCode[1] = *AdrVals;
ForcePageZero = True;
if (DecodeAdr(&ArgStr[2], MModMem))
{
*WAsmCode = 0x7700 | (*AdrVals);
CodeLen = 2;
}
}
}
static void DecodeDST(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
*WAsmCode = 0x4e00 | (*AdrVals << 8);
if (DecodeAdr(&ArgStr[2], MModMem))
{
*WAsmCode |= *AdrVals;
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
CodeLen = 1 + AdrCnt;
}
}
}
static void DecodeST(Word Index)
{
Word Acc;
UNUSED(Index);
/* NOTE: we also allow the form 'ST src,Xmem' as an alias
for 'STH src,Ymem' since the first form is used in parallel
load-store instructions. */
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[2], MModMem))
{
*WAsmCode = *AdrVals;
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
CodeLen = 1 + AdrCnt;
OpSize = SInt16;
if (!as_strcasecmp(ArgStr[1].str.p_str, "T"))
*WAsmCode |= 0x8c00;
else if (!as_strcasecmp(ArgStr[1].str.p_str, "TRN"))
*WAsmCode |= 0x8d00;
else
{
DecodeAdr(&ArgStr[1], MModImm | MModAcc);
switch (AdrMode)
{
case ModImm:
*WAsmCode |= 0x7600;
(CodeLen++)[WAsmCode] = *AdrVals;
break;
case ModAcc:
Acc = *AdrVals;
*AdrVals = *WAsmCode;
AdrMode = ModMem;
if (MakeXY(AdrVals, True))
{
*WAsmCode = 0x9a00 | (Acc << 8) | (*AdrVals << 4);
CodeLen = 1;
}
else
CodeLen = 0;
break;
default:
CodeLen = 0;
}
}
}
}
static void DecodeSTLH(Word Index)
{
Integer Shift;
Boolean OK;
if (!ChkArgCnt(2, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
*WAsmCode = Index | (*AdrVals << 8);
OK = True;
if (ArgCnt == 2)
Shift = 0;
else if (!as_strcasecmp(ArgStr[2].str.p_str, "ASM"))
Shift = 0xff;
else
Shift = EvalStrIntExpression(&ArgStr[2], SInt5, &OK);
if ((OK) && (DecodeAdr(&ArgStr[ArgCnt], MModMem)))
{
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
CodeLen = 1 + AdrCnt;
if (!Shift)
*WAsmCode |= 0x8000 | *AdrVals;
else if (Shift == 0xff)
*WAsmCode |= 0x8400 | *AdrVals;
else if ((MakeXY(WAsmCode + 2, False)) && (Shift > 0))
*WAsmCode |= 0x9800 | (2[WAsmCode] << 4) | Shift;
else
{
CodeLen[WAsmCode] = (0x0c80 | ((*WAsmCode) & 0x100) | (Shift & 0x1f)) - (Index >> 4);
*WAsmCode = 0x6f00 | *AdrVals;
CodeLen++;
}
}
}
}
static void DecodeCMPS(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
*WAsmCode = 0x8e00 | (*AdrVals << 8);
if (DecodeAdr(&ArgStr[2], MModMem))
{
*WAsmCode |= *AdrVals;
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
CodeLen = 1 + AdrCnt;
}
}
}
static void DecodeSACCD(Word Index)
{
int index;
Boolean OK;
UNUSED(Index);
if (!ChkArgCnt(3, 3));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModAcc))
{
*WAsmCode = 0x9e00 | ((*AdrVals) << 8);
if ((DecodeAdr(&ArgStr[2], MModMem))
&& (MakeXY(AdrVals, True)))
{
*WAsmCode |= ((*AdrVals) << 4);
if (!DecodeCondition(3, WAsmCode + 1, &index, &OK)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[index]);
else if ((WAsmCode[1] & 0xf0) != 0x40) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[index]);
else
{
*WAsmCode |= WAsmCode[1] & 15;
CodeLen = 1;
}
}
}
}
static void DecodeStoreCC(Word Index)
{
int index;
Boolean OK;
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((DecodeAdr(&ArgStr[1], MModMem)) && (MakeXY(AdrVals, True)))
{
*WAsmCode = Index | ((*AdrVals) << 4);
if (!DecodeCondition(2, WAsmCode + 1, &index, &OK)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[index]);
else if ((WAsmCode[1] & 0xf0) != 0x40) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[index]);
else
{
*WAsmCode |= WAsmCode[1] & 15;
CodeLen = 1;
}
}
}
static void DecodeMVDabs(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[1], MModMem))
{
tEvalResult EvalResult;
*WAsmCode = Index | *AdrVals;
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
WAsmCode[1 + AdrCnt] = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace((Index == 0x7100) ? SegData : SegCode, EvalResult.AddrSpaceMask);
CodeLen = 2 + AdrCnt;
}
}
}
static void DecodeMVabsD(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if (DecodeAdr(&ArgStr[2], MModMem))
{
tEvalResult EvalResult;
*WAsmCode = Index | *AdrVals;
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
WAsmCode[1 + AdrCnt] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace((Index == 0x7000) ? SegData : SegCode, EvalResult.AddrSpaceMask);
CodeLen = 2 + AdrCnt;
}
}
}
static void DecodeMVdmadmmr(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
const tStrComp *pArg1 = (Index & 0x0100) ? &ArgStr[2] : &ArgStr[1],
*pArg2 = (Index & 0x0100) ? &ArgStr[1] : &ArgStr[2];
ForcePageZero = True;
if (DecodeAdr(pArg2, MModMem))
{
tEvalResult EvalResult;
*WAsmCode = Index | *AdrVals;
WAsmCode[1] = EvalStrIntExpressionWithResult(pArg1, UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegData, EvalResult.AddrSpaceMask);
CodeLen = 2;
}
}
}
}
static Boolean GetReg(const tStrComp *pArg, Word *Res)
{
tEvalResult EvalResult;
*Res = EvalStrIntExpressionWithResult(pArg, UInt8, &EvalResult);
if (EvalResult.OK)
{
if (mFirstPassUnknown(EvalResult.Flags))
*Res = 0x10;
ChkSpace(SegData, EvalResult.AddrSpaceMask);
EvalResult.OK = ChkRange(*Res, 0x10, 0x1f);
if (EvalResult.OK)
*Res -= 0x10;
}
return EvalResult.OK;
}
static void DecodeMVMM(Word Index)
{
Word XReg, YReg;
UNUSED(Index);
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else if ((GetReg(&ArgStr[1], &XReg)) && (GetReg(&ArgStr[2], &YReg)))
{
*WAsmCode = 0xe700 | (XReg << 4) | YReg;
CodeLen = 1;
}
}
static void DecodePort(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (ThisPar) WrError(ErrNum_ParNotPossible);
else
{
const tStrComp *pArg1 = (Index & 0x0100) ? &ArgStr[2] : &ArgStr[1],
*pArg2 = (Index & 0x0100) ? &ArgStr[1] : &ArgStr[2];
if (DecodeAdr(pArg2, MModMem))
{
tEvalResult EvalResult;
*WAsmCode = Index | *AdrVals;
if (AdrCnt)
1[WAsmCode] = 1[AdrVals];
WAsmCode[1 + AdrCnt] = EvalStrIntExpressionWithResult(pArg1, UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegIO, EvalResult.AddrSpaceMask);
CodeLen = 2 + AdrCnt;
}
}
}
}
/*-------------------------------------------------------------------------*/
/* Pseudo Instructions */
static Boolean DecodePseudo(void)
{
if (Memo("PORT"))
{
CodeEquate(SegIO, 0, 65535);
return True;
}
return False;
}
/*-------------------------------------------------------------------------*/
/* Code Table Handling */
static void AddFixed(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= FixedOrderCnt)
FixedOrders[InstrZ].Code = Code;
FixedOrders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeFixed);
}
static void AddAcc(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= AccOrderCnt)
AccOrders[InstrZ].Code = Code;
AccOrders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeAcc);
}
static void AddAcc2(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= Acc2OrderCnt)
Acc2Orders[InstrZ].Code = Code;
Acc2Orders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeAcc2);
}
static void AddMem(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= MemOrderCnt)
MemOrders[InstrZ].Code = Code;
MemOrders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeMem);
}
static void AddXY(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= XYOrderCnt)
XYOrders[InstrZ].Code = Code;
XYOrders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeXY);
}
static void AddMemAcc(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= MemAccOrderCnt)
MemAccOrders[InstrZ].Code = Code;
MemAccOrders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeMemAcc);
}
static void AddMemConst(const char *Name, Word Code, Boolean IsRepeatable, Boolean Swap, IntType ConstType)
{
if (InstrZ >= MemConstOrderCnt)
MemConstOrders[InstrZ].Code = Code;
MemConstOrders[InstrZ].IsRepeatable = IsRepeatable;
MemConstOrders[InstrZ].Swap = Swap;
MemConstOrders[InstrZ].ConstType = ConstType;
AddInstTable(InstTable, Name, InstrZ++, DecodeMemConst);
}
static void AddMac(const char *Name, Word Code, Boolean IsRepeatable)
{
if (InstrZ >= MacOrderCnt)
MacOrders[InstrZ].Code = Code;
MacOrders[InstrZ].IsRepeatable = IsRepeatable;
AddInstTable(InstTable, Name, InstrZ++, DecodeMac);
}
static void AddCondition(const char *NName, Word NClass, Word NCode, Word NMask)
{
if (InstrZ >= ConditionCnt)
Conditions[InstrZ ].Name = NName;
Conditions[InstrZ ].Class = NClass;
Conditions[InstrZ ].Code = NCode;
Conditions[InstrZ++].Mask = NMask;
}
static void InitFields(void)
{
InstTable = CreateInstTable(203);
AddInstTable(InstTable, "LD", 0, DecodeLD);
AddInstTable(InstTable, "ST", 0, DecodeST);
AddInstTable(InstTable, "STH", 0x200, DecodeSTLH);
AddInstTable(InstTable, "STL", 0x000, DecodeSTLH);
FixedOrders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * FixedOrderCnt
); InstrZ
= 0;
AddFixed("FRET" , 0xf4e4, FALSE);
AddFixed("FRETD" , 0xf6e4, FALSE);
AddFixed("FRETE" , 0xf4e5, FALSE);
AddFixed("FRETED", 0xf6e5, FALSE);
AddFixed("NOP" , NOPCode, TRUE);
AddFixed("RESET" , 0xf7e0, FALSE);
AddFixed("RET" , 0xfc00, FALSE);
AddFixed("RETD" , 0xfe00, FALSE);
AddFixed("RETE" , 0xf4eb, FALSE);
AddFixed("RETED" , 0xf6eb, FALSE);
AddFixed("RETF" , 0xf49b, FALSE);
AddFixed("RETFD" , 0xf69b, FALSE);
AccOrders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * AccOrderCnt
); InstrZ
= 0;
AddAcc ("EXP" , 0xf48e, TRUE );
AddAcc ("MAX" , 0xf486, TRUE );
AddAcc ("MIN" , 0xf487, TRUE );
AddAcc ("SAT" , 0xf483, TRUE );
AddAcc ("ROL" , 0xf491, TRUE );
AddAcc ("ROLTC" , 0xf492, TRUE );
AddAcc ("ROR" , 0xf490, TRUE );
AddAcc ("SFTC" , 0xf494, TRUE );
AddAcc ("CALA" , 0xf4e3, FALSE);
AddAcc ("CALAD" , 0xf6e3, FALSE);
AddAcc ("FCALA" , 0xf4e7, FALSE);
AddAcc ("FCALAD", 0xf6e7, FALSE);
AddAcc ("BACC" , 0xf4e2, FALSE);
AddAcc ("BACCD" , 0xf6e2, FALSE);
AddAcc ("FBACC" , 0xf4e6, FALSE);
AddAcc ("FBACCD", 0xf6e6, FALSE);
Acc2Orders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * Acc2OrderCnt
); InstrZ
= 0;
AddAcc2 ("NEG" , 0xf484, TRUE );
AddAcc2 ("NORM" , 0xf48f, TRUE );
AddAcc2 ("RND" , 0xf49f, TRUE );
AddAcc2 ("ABS" , 0xf485, TRUE );
AddAcc2 ("CMPL" , 0xf493, TRUE );
MemOrders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * MemOrderCnt
); InstrZ
= 0;
AddMem ("DELAY" , 0x4d00, TRUE );
AddMem ("POLY" , 0x3600, TRUE );
AddMem ("BITT" , 0x3400, TRUE );
AddMem ("POPD" , 0x8b00, TRUE );
AddMem ("PSHD" , 0x4b00, TRUE );
AddMem ("MAR" , 0x6d00, TRUE );
AddMem ("LTD" , 0x4c00, TRUE );
AddMem ("READA" , 0x7e00, TRUE );
AddMem ("WRITA" , 0x7f00, TRUE );
XYOrders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * XYOrderCnt
); InstrZ
= 0;
AddXY ("ABDST" , 0xe300, TRUE );
AddXY ("LMS" , 0xe100, TRUE );
AddXY ("SQDST" , 0xe200, TRUE );
AddXY ("MVDD" , 0xe500, TRUE );
AddInstTable(InstTable, "ADD", 0, DecodeADDSUB);
AddInstTable(InstTable, "SUB", 1, DecodeADDSUB);
MemAccOrders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * MemAccOrderCnt
); InstrZ
= 0;
AddMemAcc("ADDC" , 0x0600, TRUE );
AddMemAcc("ADDS" , 0x0200, TRUE );
AddMemAcc("SUBB" , 0x0e00, TRUE );
AddMemAcc("SUBC" , 0x1e00, TRUE );
AddMemAcc("SUBS" , 0x0a00, TRUE );
AddMemAcc("MPYR" , 0x2200, TRUE );
AddMemAcc("MPYU" , 0x2400, TRUE );
AddMemAcc("SQURA", 0x3800, TRUE );
AddMemAcc("SQURS", 0x3a00, TRUE );
AddMemAcc("DADST", 0x5a00, TRUE );
AddMemAcc("DRSUB", 0x5800, TRUE );
AddMemAcc("DSADT", 0x5e00, TRUE );
AddMemAcc("DSUB" , 0x5400, TRUE );
AddMemAcc("DSUBT", 0x5c00, TRUE );
AddMemAcc("DLD" , 0x5600, TRUE );
AddMemAcc("LDR" , 0x1600, TRUE );
AddMemAcc("LDU" , 0x1200, TRUE );
MacOrders
= (FixedOrder
*) malloc(sizeof(FixedOrder
) * MacOrderCnt
); InstrZ
= 0;
AddMac("MACA" , 0x3508, TRUE );
AddMac("MACAR" , 0x3709, TRUE );
AddMac("MASA" , 0x330a, TRUE );
MemConstOrders
= (MemConstOrder
*) malloc(sizeof(MemConstOrder
) * MemConstOrderCnt
); InstrZ
= 0;
AddMemConst("ADDM", 0x6b00, FALSE, FALSE, SInt16);
AddMemConst("ANDM", 0x6800, FALSE, FALSE, UInt16);
AddMemConst("CMPM", 0x6000, TRUE , TRUE , SInt16);
AddMemConst("ORM" , 0x6900, FALSE, FALSE, UInt16);
AddMemConst("XORM", 0x6a00, FALSE, FALSE, UInt16);
AddInstTable(InstTable, "AND" , 0, DecodeLog);
AddInstTable(InstTable, "OR" , 1, DecodeLog);
AddInstTable(InstTable, "XOR" , 2, DecodeLog);
AddInstTable(InstTable, "MPY" , 0, DecodeMPY);
AddInstTable(InstTable, "MPYA" , 0, DecodeMPYA);
AddInstTable(InstTable, "SQUR" , 0, DecodeSQUR);
AddInstTable(InstTable, "MAC" , 0, DecodeMAC);
AddInstTable(InstTable, "MACR" , 0, DecodeMACR);
AddInstTable(InstTable, "MACD" , 0x7a00, DecodeMACDP);
AddInstTable(InstTable, "MACP" , 0x7800, DecodeMACDP);
AddInstTable(InstTable, "MACSU", 0, DecodeMACSU);
AddInstTable(InstTable, "MAS" , 0x000, DecodeMAS);
AddInstTable(InstTable, "MASR" , 0x200, DecodeMAS);
AddInstTable(InstTable, "MASAR", 0, DecodeMASAR);
AddInstTable(InstTable, "DADD" , 0, DecodeDADD);
AddInstTable(InstTable, "FIRS" , 0, DecodeFIRS);
AddInstTable(InstTable, "SFTA" , 0xf460, DecodeSFT);
AddInstTable(InstTable, "SFTL" , 0xf0e0, DecodeSFT);
AddInstTable(InstTable, "BIT" , 0, DecodeBIT);
AddInstTable(InstTable, "BITF" , 0, DecodeBITF);
AddInstTable(InstTable, "CMPR" , 0, DecodeCMPR);
AddInstTable(InstTable, "B" , 0xf073, DecodePMAD);
AddInstTable(InstTable, "BD" , 0xf273, DecodePMAD);
AddInstTable(InstTable, "CALL" , 0xf074, DecodePMAD);
AddInstTable(InstTable, "CALLD", 0xf274, DecodePMAD);
AddInstTable(InstTable, "RPTB" , 0xf072, DecodePMAD);
AddInstTable(InstTable, "RPTBD", 0xf272, DecodePMAD);
AddInstTable(InstTable, "BC" , 0xf800, DecodePMADCond);
AddInstTable(InstTable, "BCD" , 0xfa00, DecodePMADCond);
AddInstTable(InstTable, "CC" , 0xf900, DecodePMADCond);
AddInstTable(InstTable, "CCD" , 0xfb00, DecodePMADCond);
AddInstTable(InstTable, "FB" , 0xf880, DecodeFPMAD);
AddInstTable(InstTable, "FBD" , 0xfa80, DecodeFPMAD);
AddInstTable(InstTable, "FCALL" , 0xf980, DecodeFPMAD);
AddInstTable(InstTable, "FCALLD", 0xfb80, DecodeFPMAD);
AddInstTable(InstTable, "BANZ" , 0x6c00, DecodeBANZ);
AddInstTable(InstTable, "BANZD", 0x6e00, DecodeBANZ);
AddInstTable(InstTable, "INTR" , 0xf7c0, DecodeINTR);
AddInstTable(InstTable, "TRAP" , 0xf4c0, DecodeINTR);
AddInstTable(InstTable, "PSHM" , 0 , DecodePSHM);
AddInstTable(InstTable, "LDM" , 0 , DecodeLDM);
AddInstTable(InstTable, "STLM" , 0 , DecodeSTLM);
AddInstTable(InstTable, "STM" , 0 , DecodeSTM);
AddInstTable(InstTable, "CMPS" , 0 , DecodeCMPS);
AddInstTable(InstTable, "RPT" , 0 , DecodeRPT);
AddInstTable(InstTable, "RPTZ" , 0 , DecodeRPTZ);
AddInstTable(InstTable, "FRAME", 0 , DecodeFRAME);
AddInstTable(InstTable, "IDLE" , 0 , DecodeIDLE);
AddInstTable(InstTable, "RSBX" , 0xf4b0, DecodeSBIT);
AddInstTable(InstTable, "SSBX" , 0xf5b0, DecodeSBIT);
AddInstTable(InstTable, "XC" , 0 , DecodeXC);
AddInstTable(InstTable, "DST" , 0 , DecodeDST);
AddInstTable(InstTable, "SACCD", 0 , DecodeSACCD);
AddInstTable(InstTable, "SRCCD", 0x9d00, DecodeStoreCC);
AddInstTable(InstTable, "STRCD", 0x9c00, DecodeStoreCC);
AddInstTable(InstTable, "MVDK" , 0x7100, DecodeMVDabs);
AddInstTable(InstTable, "MVDP" , 0x7d00, DecodeMVDabs);
AddInstTable(InstTable, "MVKD" , 0x7000, DecodeMVabsD);
AddInstTable(InstTable, "MVPD" , 0x7c00, DecodeMVabsD);
AddInstTable(InstTable, "MVDM" , 0x7200, DecodeMVdmadmmr);
AddInstTable(InstTable, "MVMD" , 0x7300, DecodeMVdmadmmr);
AddInstTable(InstTable, "MVMM" , 0x7300, DecodeMVMM);
AddInstTable(InstTable, "PORTR", 0x7400, DecodePort);
AddInstTable(InstTable, "PORTW", 0x7500, DecodePort);
Conditions
= (Condition
*) malloc(sizeof(Condition
) * ConditionCnt
); InstrZ
= 0;
AddCondition("BIO" , 0, 0x0003, 0x0003);
AddCondition("NBIO" , 0, 0x0002, 0x0003);
AddCondition("C" , 0, 0x000c, 0x000c);
AddCondition("NC" , 0, 0x0008, 0x000c);
AddCondition("TC" , 0, 0x0030, 0x0030);
AddCondition("NTC" , 0, 0x0020, 0x0030);
AddCondition("AEQ" , 1, 0x0045, 0x000f);
AddCondition("ANEQ" , 1, 0x0044, 0x000f);
AddCondition("AGT" , 1, 0x0046, 0x000f);
AddCondition("AGEQ" , 1, 0x0042, 0x000f);
AddCondition("ALT" , 1, 0x0043, 0x000f);
AddCondition("ALEQ" , 1, 0x0047, 0x000f);
AddCondition("AOV" , 1, 0x0070, 0x00f0);
AddCondition("ANOV" , 1, 0x0060, 0x00f0);
AddCondition("BEQ" , 2, 0x004d, 0x000f);
AddCondition("BNEQ" , 2, 0x004c, 0x000f);
AddCondition("BGT" , 2, 0x004e, 0x000f);
AddCondition("BGEQ" , 2, 0x004a, 0x000f);
AddCondition("BLT" , 2, 0x004b, 0x000f);
AddCondition("BLEQ" , 2, 0x004f, 0x000f);
AddCondition("BOV" , 2, 0x0078, 0x00f0);
AddCondition("BNOV" , 2, 0x0068, 0x00f0);
AddCondition("UNC" , 3, 0x0000, 0x00ff);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
}
/*-------------------------------------------------------------------------*/
/* Linking Routines */
static void MakeCode_32054x(void)
{
CodeLen = 0;
DontPrint = False;
ThisPar
= !strcmp(LabPart.
str.
p_str, "||");
if ((strlen(OpPart.
str.
p_str) > 2) && (!strncmp(OpPart.
str.
p_str, "||", 2)))
{
ThisPar = True; strmov(OpPart.str.p_str, OpPart.str.p_str + 2);
}
/* zu ignorierendes */
if (*OpPart.str.p_str == '\0')
return;
if (DecodePseudo())
return;
if (DecodeTIPseudo())
return;
/* search */
ThisRep = False;
ForcePageZero = False;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
else
LastOpCode = *WAsmCode;
LastRep = ThisRep;
}
static void InitCode_32054x(void)
{
Reg_CPL = 0;
Reg_DP = 0;
Reg_SP = 0;
}
static Boolean IsDef_32054x(void)
{
return (!strcmp(LabPart.
str.
p_str, "||"));
}
static void SwitchFrom_32054x(void)
{
DeinitFields();
}
static void SwitchTo_32054x(void)
{
#define ASSUME3254xCount (sizeof(ASSUME3254xs) / sizeof(*ASSUME3254xs))
static ASSUMERec ASSUME3254xs[] =
{
{"CPL", &Reg_CPL, 0, 1, 0, NULL},
{"DP" , &Reg_DP , 0, 0x1ff, 0x200, NULL},
{"SP" , &Reg_SP , 0, 0xffff, 0x10000, NULL}
};
const TFamilyDescr *FoundDescr;
FoundDescr = FindFamilyByName("TMS320C54x");
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "$";
HeaderID = FoundDescr->Id;
NOPCode = 0xf495;
DivideChars = ",";
HasAttrs = False;
ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 2; SegLimits[SegCode] = 0xffff;
Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 2; SegLimits[SegData] = 0xffff;
Grans[SegIO ] = 2; ListGrans[SegIO ] = 2; SegInits[SegIO ] = 2; SegLimits[SegIO ] = 0xffff;
MakeCode = MakeCode_32054x;
IsDef = IsDef_32054x;
pASSUMERecs = ASSUME3254xs;
ASSUMERecCnt = ASSUME3254xCount;
InitFields();
SwitchFrom = SwitchFrom_32054x;
ThisRep = LastRep = False;
LastOpCode = 0;
}
/*-------------------------------------------------------------------------*/
/* Global Interface */
void code32054x_init(void)
{
CPU320C541 = AddCPU("320C541", SwitchTo_32054x);
AddInitPassProc(InitCode_32054x);
}