/* code53c8xx.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* Makroassembler AS */
/* */
/* Codegenerator SYM53C8xx */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "headids.h"
#include "strutil.h"
#include "codevars.h"
#include "intpseudo.h"
#include "errmsg.h"
#include "code53c8xx.h"
/*---------------------------------------------------------------------------*/
typedef struct
{
const char *Name;
LongWord Code;
Word Mask;
} TReg, *PReg;
static CPUVar CPU53C810, CPU53C860, CPU53C815, CPU53C825, CPU53C875,
CPU53C895;
#define M_53C810 0x0001
#define M_53C860 0x0002
#define M_53C815 0x0004
#define M_53C825 0x0008
#define M_53C875 0x0010
#define M_53C895 0x0020
static PReg Regs;
/*---------------------------------------------------------------------------*/
static Boolean IsInToken(char Inp)
{
return ((Inp
== '_') || (isalnum(((usint
) Inp
) & 0xff)));
}
static void GetToken(tStrComp *pSrc, tStrComp *pDest)
{
char *p;
/* search token start, by skipping spaces */
for (p = pSrc->str.p_str; as_isspace(*p); p++)
if (*p == '\0') break;
StrCompCutLeft(pSrc, p - pSrc->str.p_str);
if (*p == '\0')
{
StrCompReset(pDest);
return;
}
pDest->Pos.StartCol = pSrc->Pos.StartCol;
/* geklammerter Ausdruck ? */
if (*pSrc->str.p_str == '(')
{
p = QuotPos(pSrc->str.p_str, ')');
/* no closing ) -> copy all up to end */
if (!p)
{
StrCompCopy(pDest, pSrc);
StrCompCutLeft
(pSrc
, strlen(pSrc
->str.
p_str));
}
/* otherwise, copy (...) */
else
{
pDest->Pos.Len = strmemcpy(pDest->str.p_str, STRINGSIZE, pSrc->str.p_str, p + 1 - pSrc->str.p_str);
StrCompCutLeft(pSrc, p + 1 - pSrc->str.p_str);
}
}
/* Spezialtoken ? */
else if (!IsInToken(*pSrc->str.p_str))
{
pDest->str.p_str[0] = *pSrc->str.p_str;
pDest->str.p_str[1] = '\0';
pDest->Pos.Len = 1;
StrCompCutLeft(pSrc, 1);
}
/* Wort ? */
else
{
for (; IsInToken(*p); p++)
if (*p == '\0')
break;
pDest->Pos.Len = strmemcpy(pDest->str.p_str, STRINGSIZE, pSrc->str.p_str, p - pSrc->str.p_str);
StrCompCutLeft(pSrc, p - pSrc->str.p_str);
}
}
static Boolean DecodePhase(char *Name, LongWord *Result)
{
*Result = 8;
if (!as_strcasecmp(Name, "DATA_OUT")) *Result = 0;
else if (!as_strcasecmp(Name, "DATA_IN")) *Result = 1;
else if (!as_strcasecmp(Name, "CMD")) *Result = 2;
else if (!as_strcasecmp(Name, "COMMAND")) *Result = 2;
else if (!as_strcasecmp(Name, "STATUS")) *Result = 3;
else if (!as_strcasecmp(Name, "RES4")) *Result = 4;
else if (!as_strcasecmp(Name, "RES5")) *Result = 5;
else if (!as_strcasecmp(Name, "MSG_OUT")) *Result = 6;
else if (!as_strcasecmp(Name, "MSG_IN")) *Result = 7;
else if (!as_strcasecmp(Name, "MESSAGE_OUT")) *Result = 6;
else if (!as_strcasecmp(Name, "MESSAGE_IN")) *Result = 7;
return (*Result < 8);
}
static Boolean DecodeReg(char *Name, LongWord *Result)
{
Integer Mask = 1 << (MomCPU - CPU53C810);
PReg Reg;
for (Reg = Regs; Reg->Name; Reg++)
if (!(as_strcasecmp(Reg->Name, Name)) && (Mask & Reg->Mask))
{
*Result = Reg->Code;
return True;
}
return False;
}
static Boolean Err(tErrorNum Num, const char *Msg)
{
WrXError(Num, Msg);
return False;
}
static Boolean DecodeCond(tStrComp *pSrc, LongWord *Dest)
{
String TokStr;
tStrComp Tok;
Boolean PhaseATNUsed, DataUsed, CarryUsed, MaskUsed;
LongWord Tmp;
Boolean OK;
/* IF/WHEN/Nix-Unterscheidung - TRUE fuer Nix setzen */
StrCompMkTemp(&Tok, TokStr, sizeof(TokStr));
GetToken(pSrc, &Tok);
if (*Tok.str.p_str == '\0')
{
*Dest |= 0x00080000;
return True;
}
if (as_strcasecmp(Tok.str.p_str, "WHEN") == 0)
*Dest |= 0x00010000;
else if (as_strcasecmp(Tok.str.p_str, "IF") != 0)
return Err(ErrNum_OpTypeMismatch, Tok.str.p_str);
/* Negierung? */
GetToken(pSrc, &Tok);
if (as_strcasecmp(Tok.str.p_str, "NOT") == 0)
GetToken(pSrc, &Tok);
else
*Dest |= 0x00080000;
/* Bedingungen durchgehen */
PhaseATNUsed = DataUsed = MaskUsed = CarryUsed = False;
do
{
if (!as_strcasecmp(Tok.str.p_str, "ATN"))
{
if (PhaseATNUsed)
return Err(ErrNum_InvAddrMode, "2 x ATN/Phase");
if (CarryUsed)
return Err(ErrNum_InvAddrMode, "Carry + ATN/Phase");
if ((*Dest & 0x00010000) != 0)
return Err(ErrNum_InvAddrMode, "WHEN + ATN");
PhaseATNUsed = True;
*Dest |= 0x00020000;
}
else if (DecodePhase(Tok.str.p_str, &Tmp))
{
if (PhaseATNUsed)
return Err(ErrNum_InvAddrMode, "2 x ATN/Phase");
if (CarryUsed)
return Err(ErrNum_InvAddrMode, "Carry + ATN/Phase");
PhaseATNUsed = True;
*Dest |= 0x00020000 + (Tmp << 24);
}
else if (!as_strcasecmp(Tok.str.p_str, "CARRY"))
{
if (CarryUsed)
return Err(ErrNum_InvAddrMode, "2 x Carry");
if ((PhaseATNUsed) || (DataUsed))
return Err(ErrNum_InvAddrMode, "Carry + ...");
CarryUsed = True;
*Dest |= 0x00200000;
}
else if (!as_strcasecmp(Tok.str.p_str, "MASK"))
{
if (CarryUsed)
return Err(ErrNum_InvAddrMode, "Carry + Data");
if (MaskUsed)
return Err(ErrNum_InvAddrMode, "2 x Mask");
if (!DataUsed)
return Err(ErrNum_InvAddrMode, "Mask + !Data");
GetToken(pSrc, &Tok);
Tmp = EvalStrIntExpression(&Tok, UInt8, &OK);
if (!OK)
return False;
MaskUsed = True;
*Dest |= (Tmp << 8);
}
else
{
if (CarryUsed)
return Err(ErrNum_InvAddrMode, "Carry + Data");
if (DataUsed)
return Err(ErrNum_InvAddrMode, "2 x Data");
Tmp = EvalStrIntExpression(&Tok, UInt8, &OK);
if (!OK)
return False;
DataUsed = True;
*Dest |= 0x00040000 + Tmp;
}
GetToken(pSrc, &Tok);
if (*Tok.str.p_str != '\0')
{
if (as_strcasecmp(Tok.str.p_str, "AND"))
return Err(ErrNum_InvAddrMode, Tok.str.p_str);
GetToken(pSrc, &Tok);
}
}
while (*Tok.str.p_str != '\0');
return True;
}
typedef enum
{
NONE, SFBR, REGISTER, IMM8
} CompType;
static CompType DecodeComp(const tStrComp *pInp, LongWord *Outp)
{
Boolean OK;
if (!as_strcasecmp(pInp->str.p_str, "SFBR"))
return SFBR;
else if (DecodeReg(pInp->str.p_str, Outp))
return REGISTER;
else
{
*Outp = EvalStrIntExpression(pInp, Int8, &OK) & 0xff;
return (OK) ? IMM8 : NONE;
}
}
/*---------------------------------------------------------------------------*/
static void DecodeFixed(Word Index)
{
if (ChkArgCnt(0, 0))
{
DAsmCode[0] = ((LongWord) Index) << 24;
DAsmCode[1] = 0x00000000;
CodeLen = 8;
}
}
static void DecodeJmps(Word Index)
{
LongWord Buf;
LongInt Adr;
int l;
Boolean OK;
tSymbolFlags Flags;
if (ArgCnt == 0)
{
if (Memo("INTFLY"))
{
ArgCnt = 1;
strcpy(ArgStr
[1].
str.
p_str, "0");
}
else if (Memo("RETURN"))
{
ArgCnt = 1;
*ArgStr[1].str.p_str = '\0';
}
}
if (ChkArgCnt(1, 2))
{
if (ArgCnt == 1)
{
if (Memo("RETURN"))
StrCompCopy(&ArgStr[2], &ArgStr[1]);
else
StrCompReset(&ArgStr[2]);
}
Buf = 0;
if (Memo("RETURN"))
{
Adr = 0;
OK = True;
}
else
{
l
= strlen(ArgStr
[1].
str.
p_str);
if ((!as_strncasecmp(ArgStr[1].str.p_str, "REL(", 4)) && (ArgStr[1].str.p_str[l - 1] == ')'))
{
if (*OpPart.str.p_str == 'I')
{
WrError(ErrNum_InvAddrMode);
OK = False;
}
Buf |= 0x00800000;
strmov(ArgStr[1].str.p_str, ArgStr[1].str.p_str + 4);
ArgStr[1].str.p_str[l - 5] = '\0';
}
Adr = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags);
if ((OK) && (Buf != 0))
{
Adr -= EProgCounter() + 8;
if (!mSymbolQuestionable(Flags) && ((Adr > 0x7fffff) || (Adr < -0x800000)))
{
WrError(ErrNum_JmpDistTooBig);
OK = False;
}
}
}
if ((OK) && (DecodeCond(&ArgStr[2], &Buf)))
{
DAsmCode[0] = 0x80000000 + (((LongWord) Index) << 27) + Buf;
if (Memo("INTFLY")) DAsmCode[0] |= 0x00100000;
DAsmCode[1] = Adr;
CodeLen = 8;
}
}
}
static void DecodeCHMOV(Word Index)
{
String TokenStr;
tStrComp Token, *pAdrArg = NULL;
LongWord Phase;
Boolean OK;
UNUSED(Index);
StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
if ((ChkExactCPUList(ErrNum_InstructionNotSupported, CPU53C825, CPU53C875, CPU53C895, CPUNone) >= 0)
&& ChkArgCnt(2, 3))
{
GetToken(&ArgStr[ArgCnt], &Token);
if (!as_strcasecmp(Token.str.p_str, "WITH"))
DAsmCode[0] = 0x08000000;
else if (!as_strcasecmp(Token.str.p_str, "WHEN"))
DAsmCode[0] = 0x00000000;
else
{
WrStrErrorPos(ErrNum_InvAddrMode, &Token);
return;
}
KillPrefBlanksStrComp(&ArgStr[ArgCnt]);
KillPostBlanksStrComp(&ArgStr[ArgCnt]);
if (!DecodePhase(ArgStr[ArgCnt].str.p_str, &Phase)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[ArgCnt]);
else
{
DAsmCode[0] |= Phase << 24;
OK = False;
if (ArgCnt == 2)
{
GetToken(&ArgStr[1], &Token);
if (as_strcasecmp(Token.str.p_str, "FROM")) WrError(ErrNum_InvAddrMode);
else
{
pAdrArg = &ArgStr[1];
DAsmCode[0] |= 0x10000000;
OK = True;
}
}
else
{
Phase = EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
if (OK)
{
DAsmCode[0] |= Phase;
if (!as_strncasecmp(ArgStr[2].str.p_str,"PTR", 3))
{
StrCompCutLeft(&ArgStr[2], 4);
DAsmCode[0] |= 0x20000000;
}
pAdrArg = &ArgStr[2];
}
}
if (OK)
{
KillPrefBlanksStrComp(pAdrArg);
DAsmCode[1] = EvalStrIntExpression(pAdrArg, UInt32, &OK);
if (OK)
CodeLen = 8;
}
}
}
}
static Boolean TrueFnc(void)
{
return True;
}
static void DecodeFlags(Word Index)
{
Boolean OK;
String TokenStr;
tStrComp Token;
StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
if (ChkArgCnt(1, 1))
{
OK = True;
DAsmCode[0] = ((LongWord) Index) << 24;
DAsmCode[1] = 0;
while ((OK) && (*ArgStr[1].str.p_str != '\0'))
{
GetToken(&ArgStr[1], &Token);
if (!as_strcasecmp(Token.str.p_str, "ACK"))
DAsmCode[0] |= 0x00000040;
else if (!as_strcasecmp(Token.str.p_str, "ATN"))
DAsmCode[0] |= 0x00000008;
else if (!as_strcasecmp(Token.str.p_str, "TARGET"))
DAsmCode[0] |= 0x00000200;
else if (!as_strcasecmp(Token.str.p_str, "CARRY"))
DAsmCode[0] |= 0x00000400;
else
{
OK = False;
WrStrErrorPos(ErrNum_InvAddrMode, &Token);
}
if (OK && (*ArgStr[1].str.p_str != '\0'))
{
GetToken(&ArgStr[1], &Token);
if (as_strcasecmp(Token.str.p_str, "AND"))
{
OK = False;
WrStrErrorPos(ErrNum_InvAddrMode, &Token);
}
}
}
if (OK)
CodeLen = 8;
}
}
static void DecodeRegTrans(Word Index)
{
LongWord Reg, Cnt;
Boolean OK;
if (!ChkArgCnt(3, 3));
else if (!ChkExcludeCPU(CPU53C815));
else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
else
{
tSymbolFlags Flags;
Cnt = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt3, &OK, &Flags);
if (mFirstPassUnknown(Flags))
Cnt = 1;
if ((OK) && (ChkRange(Cnt, 1, 4)))
{
int l
= strlen(ArgStr
[3].
str.
p_str);
DAsmCode[0] = 0xe0000000 + (((LongInt) Index) << 24) + (Reg << 16) + Cnt;
if ((!as_strncasecmp(ArgStr[3].str.p_str, "DSAREL(", 7))
&& (ArgStr[3].str.p_str[l - 1] == ')'))
{
ArgStr[3].str.p_str[--l] = '\0';
DAsmCode[0] |= 0x10000000;
DAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[3], 6, SInt24, &OK) & 0xffffff;
}
else
DAsmCode[1] = EvalStrIntExpression(&ArgStr[3], UInt32, &OK);
if (OK)
CodeLen = 8;
}
}
}
static void DecodeMOVE(Word Index)
{
#define MAXPARTS 8
Boolean WithCarry;
String TokenStr;
tStrComp Token;
LongWord Tmp, DReg , AriOp = 0xff, ImmVal = 0x100;
Boolean OK;
int z;
Word BigCPUMask = (1 << (CPU53C825 - CPU53C810))
| (1 << (CPU53C875 - CPU53C810))
| (1 << (CPU53C895 - CPU53C810));
UNUSED(Index);
StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
if (!ChkArgCnt(1, 3));
else if (ArgCnt == 1) /* MOVE Register */
{
String PartStr[MAXPARTS];
tStrComp Parts[MAXPARTS];
int PartCnt = 0;
for (z = 0; z < MAXPARTS; z++)
StrCompMkTemp(&Parts[z], PartStr[z], sizeof(PartStr[z]));
do
{
GetToken(&ArgStr[1], &Parts[PartCnt++]);
}
while ((*ArgStr[1].str.p_str != '\0') && (PartCnt < MAXPARTS));
if ((PartCnt > 1) && (!as_strcasecmp(Parts[PartCnt - 1].str.p_str, "CARRY")) && (!as_strcasecmp(Parts[PartCnt - 1].str.p_str, "TO")))
{
WithCarry = True;
PartCnt -= 2;
}
else
WithCarry = False;
DAsmCode[0] = 0x40000000;
DAsmCode[1] = 0;
if (PartCnt == 3)
{
if (WithCarry) WrError(ErrNum_InvAddrMode);
else if (!as_strcasecmp(Parts[1].str.p_str, "TO")) /* MOVE */
{
switch (DecodeComp(&Parts[0], &ImmVal))
{
case SFBR:
switch (DecodeComp(&Parts[2], &ImmVal))
{
case SFBR:
ImmVal = 8;
/* fall-through */
case REGISTER: /* --> 0x00 OR SFBR to reg */
DAsmCode[0] += 0x2a000000 + (ImmVal << 16);
CodeLen = 8;
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
case REGISTER:
DReg = ImmVal;
switch (DecodeComp(&Parts[2], &ImmVal))
{
case SFBR: /* --> 0x00 OR reg to SFBR */
DAsmCode[0] += 0x32000000 + (DReg << 16);
CodeLen = 8;
break;
case REGISTER:
if (ImmVal != DReg) WrError(ErrNum_InvAddrMode);
else
{
DAsmCode[0] += 0x3a000000 + (DReg << 16);
CodeLen = 8;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
case IMM8:
switch (DecodeComp(&Parts[2], &DReg))
{
case SFBR:
DReg = 8;
/* fall-through */
case REGISTER: /* --> imm to reg */
DAsmCode[0] += 0x38000000 + (DReg << 16) + (ImmVal << 8);
CodeLen = 8;
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
default:
WrError(ErrNum_InvAddrMode);
break;
}
} /* ... TO ... */
else if ((!as_strcasecmp(Parts[1].str.p_str, "SHL")) || (!as_strcasecmp(Parts[1].str.p_str, "SHR")))
{
AriOp = 1 + (Ord(as_toupper(Parts[1].str.p_str[2]) == 'R') << 2);
switch (DecodeComp(&Parts[0], &DReg))
{
case SFBR:
switch (DecodeComp(&Parts[2], &DReg))
{
case SFBR:
DReg = 8;
/* fall-through */
case REGISTER:
DAsmCode[0] += 0x28000000 + (AriOp << 24) + (DReg << 16);
CodeLen = 8;
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
case REGISTER:
ImmVal = DReg;
switch (DecodeComp(&Parts[2], &DReg))
{
case SFBR:
DAsmCode[0] += 0x30000000 + (AriOp << 24) + (ImmVal << 16);
CodeLen = 8;
break;
case REGISTER:
if (DReg != ImmVal) WrError(ErrNum_InvAddrMode);
else
{
DAsmCode[0] += 0x38000000 + (AriOp << 24) + (ImmVal << 16);
CodeLen = 8;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
} /* ... SHx ... */
} /* PartCnt == 3 */
else if (PartCnt == 5)
{
if (as_strcasecmp(Parts[3].str.p_str, "TO")) WrError(ErrNum_InvAddrMode);
else
{
if ((!as_strcasecmp(Parts[1].str.p_str, "XOR"))
|| (!as_strcasecmp(Parts[1].str.p_str, "^")))
AriOp = 3;
else if ((!as_strcasecmp(Parts[1].str.p_str, "OR"))
|| (!as_strcasecmp(Parts[1].str.p_str, "|")))
AriOp = 2;
else if ((!as_strcasecmp(Parts[1].str.p_str, "AND"))
|| (!as_strcasecmp(Parts[1].str.p_str, "&")))
AriOp = 4;
else if (!strcmp(Parts
[1].
str.
p_str, "+"))
AriOp = 6;
if (WithCarry)
AriOp = (AriOp == 6) ? 7 : 0xff;
if (AriOp == 0xff) WrError(ErrNum_InvAddrMode);
else
{
DAsmCode[0] |= (AriOp << 24);
switch (DecodeComp(&Parts[0], &ImmVal))
{
case SFBR:
switch (DecodeComp(&Parts[2], &ImmVal))
{
case SFBR:
switch (DecodeComp(&Parts[4], &ImmVal))
{
case SFBR:
ImmVal = 8;
/* fall-through */
case REGISTER:
if (ChkExactCPUMask(BigCPUMask, CPU53C810) >= 0)
{
DAsmCode[0] |= 0x28800000 + (ImmVal << 16);
CodeLen = 8;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
case IMM8:
switch (DecodeComp(&Parts[4], &DReg))
{
case SFBR:
DReg = 8;
/* fall-through */
case REGISTER:
DAsmCode[0] |= 0x28000000 + (DReg << 16) + (ImmVal << 8);
CodeLen = 8;
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
case REGISTER:
DAsmCode[0] |= ImmVal << 16;
DReg = ImmVal;
switch (DecodeComp(&Parts[2], &ImmVal))
{
case SFBR:
switch (DecodeComp(&Parts[4], &ImmVal))
{
case SFBR:
if (ChkExactCPUMask(BigCPUMask, CPU53C810) >= 0)
{
DAsmCode[0] |= 0x30800000;
CodeLen = 8;
}
break;
case REGISTER:
if (DReg != ImmVal) WrError(ErrNum_InvAddrMode);
else if (ChkExactCPUMask(BigCPUMask, CPU53C810) >= 0)
{
DAsmCode[0] |= 0x38800000;
CodeLen = 8;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
case IMM8:
DAsmCode[0] |= (ImmVal << 8);
switch (DecodeComp(&Parts[4], &Tmp))
{
case SFBR:
DAsmCode[0] |= 0x30000000;
CodeLen = 8;
break;
case REGISTER:
if (DReg != Tmp) WrError(ErrNum_InvAddrMode);
else
{
DAsmCode[0] |= 0x38000000;
CodeLen = 8;
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
break;
default:
WrError(ErrNum_InvAddrMode);
}
}
}
} /* PartCnt == 5 */
else
WrError(ErrNum_InvAddrMode);
}
else if (ArgCnt == 2)
{
GetToken(&ArgStr[1], &Token);
if (as_strcasecmp(Token.str.p_str, "FROM")) WrError(ErrNum_InvAddrMode);
else
{
DAsmCode[0] = 0x00000000;
DAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int32, &OK);
if (OK)
{
GetToken(&ArgStr[2], &Token);
OK = True;
if (!as_strcasecmp(Token.str.p_str, "WHEN"))
DAsmCode[0] |= 0x08000000;
else if (as_strcasecmp(Token.str.p_str, "WITH"))
OK = False;
if (!OK) WrError(ErrNum_InvAddrMode);
else
{
KillPrefBlanksStrComp(&ArgStr[2]);
KillPostBlanksStrComp(&ArgStr[2]);
if (!DecodePhase(ArgStr[2].str.p_str, &ImmVal)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
else
{
DAsmCode[0] |= ImmVal << 24;
CodeLen = 8;
}
}
}
}
}
else if (ArgCnt == 3)
{
if (!as_strncasecmp(ArgStr[1].str.p_str, "MEMORY", 6))
{
StrCompCutLeft(&ArgStr[1], 7);
if (!as_strncasecmp(ArgStr[1].str.p_str, "NO FLUSH", 8))
{
DAsmCode[0] = 0xc1000000;
StrCompCutLeft(&ArgStr[1], 9);
}
else DAsmCode[0] = 0xc0000000;
DAsmCode[0] |= EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
if (OK)
{
DAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int32, &OK);
if (OK)
{
DAsmCode[2] = EvalStrIntExpression(&ArgStr[3], Int32, &OK);
if (OK) CodeLen = 12;
}
}
}
else
{
DAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
if (OK)
{
GetToken(&ArgStr[3], &Token);
OK = True;
if (!as_strcasecmp(Token.str.p_str, "WHEN")) DAsmCode[0] |= 0x08000000;
else if (as_strcasecmp(Token.str.p_str, "WITH")) OK = False;
if (!OK) WrError(ErrNum_InvAddrMode);
else
{
KillPrefBlanksStrComp(&ArgStr[3]);
KillPostBlanksStrComp(&ArgStr[3]);
if (!DecodePhase(ArgStr[3].str.p_str, &ImmVal)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[3]);
else
{
DAsmCode[0] |= ImmVal << 24;
if (!as_strncasecmp(ArgStr[2].str.p_str, "PTR", 3))
{
StrCompCutLeft(&ArgStr[2], 4);
DAsmCode[0] |= 0x20000000;
}
DAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt32, &OK);
if (OK) CodeLen = 8;
}
}
}
}
}
}
static void DecodeSELECT(Word MayATN)
{
Boolean OK;
LongInt Dist;
tSymbolFlags Flags;
int l;
if (ChkArgCnt(2, 2))
{
DAsmCode[0] = 0x40000000;
OK = True;
if (!as_strncasecmp(ArgStr[1].str.p_str, "ATN ", 4))
{
strmov(ArgStr[1].str.p_str, ArgStr[1].str.p_str + 4);
ArgStr[1].Pos.StartCol += 4;
ArgStr[1].Pos.Len -= 4;
KillPrefBlanksStrComp(&ArgStr[1]);
if (!MayATN)
OK = False;
else
DAsmCode[0] |= 0x01000000;
}
if (!OK) WrError(ErrNum_InvAddrMode);
else
{
if (!as_strncasecmp(ArgStr[1].str.p_str, "FROM ", 5))
{
strmov(ArgStr[1].str.p_str, ArgStr[1].str.p_str + 5);
ArgStr[1].Pos.StartCol += 5;
ArgStr[1].Pos.Len -= 5;
KillPrefBlanksStrComp(&ArgStr[1]);
DAsmCode[0] |= 0x02000000 + EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
}
else
DAsmCode[0] |= EvalStrIntExpression(&ArgStr[1], UInt4, &OK) << 16;
if (OK)
{
l
= strlen(ArgStr
[2].
str.
p_str);
if ((!as_strncasecmp(ArgStr[2].str.p_str, "REL(", 4)) && (ArgStr[2].str.p_str[l - 1] == ')'))
{
DAsmCode[0] |= 0x04000000;
ArgStr[2].str.p_str[l - 1] = '\0';
Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], 4, UInt32, &OK, &Flags) - (EProgCounter() + 8);
if (OK)
{
if (!mSymbolQuestionable(Flags) && ((Dist > 0x7fffff) || (Dist < -0x800000))) WrError(ErrNum_JmpDistTooBig);
else DAsmCode[1] = Dist & 0xffffff;
}
}
else DAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt32, &OK);
if (OK) CodeLen = 8;
}
}
}
}
static void DecodeWAIT(Word Index)
{
String TokenStr;
tStrComp Token;
Boolean OK;
LongInt Dist;
tSymbolFlags Flags;
UNUSED(Index);
StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
if (ChkArgCnt(1, 1))
{
GetToken(&ArgStr[1], &Token);
KillPrefBlanksStrComp(&ArgStr[1]);
if (!as_strcasecmp(Token.str.p_str, "DISCONNECT"))
{
if (*ArgStr[1].str.p_str != '\0') WrError(ErrNum_InvAddrMode);
else
{
DAsmCode[0] = 0x48000000;
DAsmCode[1] = 0;
CodeLen = 8;
}
}
else if ((!as_strcasecmp(Token.str.p_str, "RESELECT")) || (!as_strcasecmp(Token.str.p_str, "SELECT")))
{
if ((!as_strncasecmp
(ArgStr
[1].
str.
p_str, "REL(", 4)) && (ArgStr
[1].
str.
p_str[strlen(ArgStr
[1].
str.
p_str) - 1] == ')'))
{
StrCompShorten(&ArgStr[1], 1);
DAsmCode[0] = 0x54000000;
Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 4, UInt32, &OK, &Flags) - (EProgCounter() + 8);
if (OK)
{
if (mSymbolQuestionable(Flags) && ((Dist > 0x7fffff) || (Dist < -0x800000))) WrError(ErrNum_JmpDistTooBig);
else
DAsmCode[1] = Dist & 0xffffff;
}
}
else
{
DAsmCode[0] = 0x50000000;
DAsmCode[1] = EvalStrIntExpression(&ArgStr[1], UInt32, &OK);
}
if (OK)
{
if (as_toupper(*Token.str.p_str) == 'S')
DAsmCode[0] |= 0x00000200;
CodeLen = 8;
}
}
}
}
/*---------------------------------------------------------------------------*/
static void AddReg(const char *NName, LargeWord Adr, Word Mask)
{
order_array_rsv_end(Regs, TReg);
Regs[InstrZ].Name = NName;
Regs[InstrZ].Code = Adr;
Regs[InstrZ++].Mask = Mask;
}
static void InitFields(void)
{
InstTable = CreateInstTable(51);
AddInstTable(InstTable, "NOP" , 0x80, DecodeFixed);
AddInstTable(InstTable, "DISCONNECT" , 0x48, DecodeFixed);
AddInstTable(InstTable, "JUMP" , 0, DecodeJmps);
AddInstTable(InstTable, "CALL" , 1, DecodeJmps);
AddInstTable(InstTable, "RETURN" , 2, DecodeJmps);
AddInstTable(InstTable, "INT" , 3, DecodeJmps);
AddInstTable(InstTable, "INTFLY" , 3, DecodeJmps);
AddInstTable(InstTable, "CHMOV" , 0, DecodeCHMOV);
AddInstTable(InstTable, "CLEAR" , 0x60, DecodeFlags);
AddInstTable(InstTable, "SET" , 0x58, DecodeFlags);
AddInstTable(InstTable, "LOAD" , 1, DecodeRegTrans);
AddInstTable(InstTable, "STORE" , 0, DecodeRegTrans);
AddInstTable(InstTable, "MOVE" , 0, DecodeMOVE);
AddInstTable(InstTable, "RESELECT", 0, DecodeSELECT);
AddInstTable(InstTable, "SELECT" , 1, DecodeSELECT);
AddInstTable(InstTable, "WAIT" , 0, DecodeWAIT);
InstrZ = 0;
AddReg("SCNTL0" , 0x00, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCNTL1" , 0x01, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCNTL2" , 0x02, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCNTL3" , 0x03, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCID" , 0x04, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SXFER" , 0x05, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SDID" , 0x06, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("GPREG" , 0x07, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SFBR" , 0x08, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SOCL" , 0x09, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SSID" , 0x0a, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SBCL" , 0x0b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DSTAT" , 0x0c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SSTAT0" , 0x0d, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SSTAT1" , 0x0e, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SSTAT2" , 0x0f, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DSA" , 0x10, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("ISTAT" , 0x14, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST0" , 0x18, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST1" , 0x19, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST2" , 0x1a, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST3" , 0x1b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("TEMP" , 0x1c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DFIFO" , 0x20, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST4" , 0x21, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST5" , 0x22, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("CTEST6" , 0x23, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DBC" , 0x24, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DCMD" , 0x27, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DNAD" , 0x28, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DSP" , 0x2c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DSPS" , 0x30, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCRATCHA" , 0x34, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DMODE" , 0x38, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("DIEN" , 0x39, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SBR" , 0x3a, M_53C810 + M_53C860 + M_53C875 + M_53C895);
AddReg("DWT" , 0x3a, M_53C815 );
AddReg("DCNTL" , 0x3b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("ADDER" , 0x3c, M_53C810 + M_53C825 + M_53C860 + M_53C895);
AddReg("SIEN0" , 0x40, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SIEN1" , 0x41, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SIST0" , 0x42, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SIST1" , 0x43, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SLPAR" , 0x44, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SWIDE" , 0x45, M_53C825 + M_53C875 + M_53C895);
AddReg("MACNTL" , 0x46, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("GPCNTL" , 0x47, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("STIME0" , 0x48, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("STIME1" , 0x49, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("RESPID" , 0x4a, M_53C810 + M_53C815 + M_53C825 + M_53C860 );
AddReg("RESPID0" , 0x4a, M_53C875 + M_53C895);
AddReg("RESPID1" , 0x4b, M_53C875 + M_53C895);
AddReg("STEST0" , 0x4c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("STEST1" , 0x4d, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("STEST2" , 0x4e, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("STEST3" , 0x4f, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SIDL" , 0x50, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("STEST4" , 0x52, + M_53C895);
AddReg("SODL" , 0x54, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SBDL" , 0x58, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCRATCHB" , 0x5c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
AddReg("SCRATCHC" , 0x60, M_53C875 + M_53C895);
AddReg("SCRATCHD" , 0x64, M_53C875 + M_53C895);
AddReg("SCRATCHE" , 0x68, M_53C875 + M_53C895);
AddReg("SCRATCHF" , 0x6c, M_53C875 + M_53C895);
AddReg("SCRATCHG" , 0x70, M_53C875 + M_53C895);
AddReg("SCRATCHH" , 0x74, M_53C875 + M_53C895);
AddReg("SCRATCHI" , 0x78, M_53C875 + M_53C895);
AddReg("SCRATCHJ" , 0x7c, M_53C875 + M_53C895);
AddReg(NULL , 0x00, 0);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
order_array_free(Regs);
}
/*---------------------------------------------------------------------------*/
static void MakeCode_53c8xx(void)
{
CodeLen = 0;
DontPrint = False;
/* zu ignorierendes */
if (Memo(""))
return;
if (DecodeIntelPseudo(False))
return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_53c8xx(void)
{
return False;
}
static void SwitchFrom_53c8xx(void)
{
DeinitFields();
}
static void SwitchTo_53c8xx(void)
{
const TFamilyDescr *FoundDescr;
FoundDescr = FindFamilyByName("SYM53C8xx");
TurnWords = False;
SetIntConstMode(eIntConstModeC);
SetIsOccupiedFnc = TrueFnc;
PCSymbol="$";
HeaderID = FoundDescr->Id;
NOPCode = 0;
DivideChars = ",";
HasAttrs = False;
ValidSegs = (1 << SegCode);
Grans[SegCode ] = 1; ListGrans[SegCode ] = 4; SegInits[SegCode ] = 0;
SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
MakeCode = MakeCode_53c8xx;
IsDef = IsDef_53c8xx;
SwitchFrom = SwitchFrom_53c8xx;
InitFields();
}
/*---------------------------------------------------------------------------*/
void code53c8xx_init(void)
{
CPU53C810 = AddCPU("SYM53C810", SwitchTo_53c8xx);
CPU53C860 = AddCPU("SYM53C860", SwitchTo_53c8xx);
CPU53C815 = AddCPU("SYM53C815", SwitchTo_53c8xx);
CPU53C825 = AddCPU("SYM53C825", SwitchTo_53c8xx);
CPU53C875 = AddCPU("SYM53C875", SwitchTo_53c8xx);
CPU53C895 = AddCPU("SYM53C895", SwitchTo_53c8xx);
}