/* code8x30x.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator Signetics 8X30x */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "nls.h"
#include "chunks.h"
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codevars.h"
#include "errmsg.h"
#include "code8x30x.h"
/*****************************************************************************/
static CPUVar CPU8x300, CPU8x305;
/*-------------------------------------------------------------------------*/
static Boolean DecodeReg(const tStrComp *pArg, Word *Erg, ShortInt *ErgLen)
{
Boolean OK;
Word Acc;
LongInt Adr;
char *z;
int Len
= strlen(pArg
->str.
p_str);
*ErgLen = -1;
if (!as_strcasecmp(pArg->str.p_str, "AUX"))
{
*Erg = 0;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "OVF"))
{
*Erg = 8;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "IVL"))
{
*Erg = 7;
return True;
}
if (!as_strcasecmp(pArg->str.p_str, "IVR"))
{
*Erg = 15;
return True;
}
if ((as_toupper(*pArg->str.p_str) == 'R') && (Len > 1) && (Len < 4))
{
Acc = 0;
OK = True;
for (z = pArg->str.p_str + 1; *z != '\0'; z++)
if (OK)
{
if ((*z < '0') || (*z > '7'))
OK = False;
else
Acc = (Acc << 3) + (*z - '0');
}
if ((OK) && (Acc < 32))
{
if ((MomCPU == CPU8x300) && (Acc > 9) && (Acc < 15))
{
WrStrErrorPos(ErrNum_InvReg, pArg);
return False;
}
else *Erg = Acc;
return True;
}
}
if ((Len == 4) && (as_strncasecmp(pArg->str.p_str + 1, "IV", 2) == 0) && (pArg->str.p_str[3] >= '0') && (pArg->str.p_str[3] <= '7'))
{
if (as_toupper(*pArg->str.p_str) == 'L')
{
*Erg = pArg->str.p_str[3]-'0' + 0x10;
return True;
}
else if (as_toupper(*pArg->str.p_str) == 'R')
{
*Erg = pArg->str.p_str[3] - '0' + 0x18;
return True;
}
}
/* IV - Objekte */
Adr = EvalStrIntExpression(pArg, UInt24, &OK);
if (OK)
{
*ErgLen = Adr & 7;
*Erg = 0x10 | ((Adr & 0x10) >> 1) | ((Adr & 0x700) >> 8);
return True;
}
else
return False;
}
static char *HasDisp(char *Asc)
{
int Lev;
char *z;
if (Asc[l - 1] == ')')
{
z = Asc + l - 2;
Lev = 0;
while ((z >= Asc) && (Lev != -1))
{
switch (*z)
{
case '(':
Lev--;
break;
case ')':
Lev++;
break;
}
if (Lev != -1)
z--;
}
if (Lev != -1)
{
WrError(ErrNum_BrackErr);
return NULL;
}
}
else
z = NULL;
return z;
}
static Boolean GetLen(const tStrComp *pArg, Word *Erg, tSymbolFlags *pFlags)
{
Boolean OK;
*Erg = EvalStrIntExpressionWithFlags(pArg, UInt4, &OK, pFlags);
if (!OK)
return False;
if (mFirstPassUnknown(*pFlags))
*Erg = 8;
if (!ChkRange(*Erg, 1, 8))
return False;
*Erg &= 7;
return True;
}
/*-------------------------------------------------------------------------*/
static void DecodeNOP(Word Code) /* NOP = MOVE AUX,AUX */
{
UNUSED(Code);
if (ChkArgCnt(0, 0))
{
WAsmCode[0] = 0x0000;
CodeLen = 1;
}
}
static void DecodeHALT(Word Code) /* HALT = JMP * */
{
UNUSED(Code);
if (ChkArgCnt(0, 0))
{
WAsmCode[0] = 0xe000 | (EProgCounter() & 0x1fff);
CodeLen = 1;
}
}
static void DecodeXML_XMR(Word Code)
{
if (ChkArgCnt(1, 1)
&& ChkMinCPU(CPU8x305))
{
Boolean OK;
Word Adr = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
if (OK)
{
WAsmCode[0] = Code | (Adr & 0xff);
CodeLen = 1;
}
}
}
static void DecodeSEL(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
Boolean OK;
LongInt Op = EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
if (OK)
{
WAsmCode[0] = 0xc700 | ((Op & 0x10) << 7) | ((Op >> 16) & 0xff);
CodeLen = 1;
}
}
}
static void DecodeXMIT(Word Code)
{
Word SrcReg, Rot;
ShortInt SrcLen;
Boolean OK;
tSymbolFlags Flags;
LongInt Adr;
UNUSED(Code);
if (ChkArgCnt(2, 3)
&& DecodeReg(&ArgStr[2], &SrcReg, &SrcLen))
{
if (SrcReg < 16)
{
if (ChkArgCnt(2, 2))
{
Adr = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
if (OK)
{
WAsmCode[0] = 0xc000 | (SrcReg << 8) | (Adr & 0xff);
CodeLen = 1;
}
}
}
else
{
if (ArgCnt == 2)
{
Rot = 0xffff; OK = True; Flags = eSymbolFlag_None;
}
else
OK = GetLen(&ArgStr[3], &Rot, &Flags);
if (OK)
{
if (Rot == 0xffff)
Rot = (SrcLen == -1) ? 0 : SrcLen;
if ((SrcLen != -1) && (Rot != SrcLen)) WrError(ErrNum_ConfOpSizes);
else
{
Adr = EvalStrIntExpression(&ArgStr[1], Int5, &OK);
if (OK)
{
WAsmCode[0] = 0xc000 | (SrcReg << 8) | (Rot << 5) | (Adr & 0x1f);
CodeLen = 1;
}
}
}
}
}
}
static void DecodeAri(Word Code)
{
Word SrcReg, DestReg, Rot;
ShortInt SrcLen, DestLen;
char *p;
Boolean OK;
if (ChkArgCnt(2, 3)
&& DecodeReg(&ArgStr[ArgCnt], &DestReg, &DestLen))
{
if (DestReg < 16) /* Ziel Register */
{
if (ArgCnt == 2) /* wenn nur zwei Operanden und Ziel Register... */
{
p = HasDisp(ArgStr[1].str.p_str); /* kann eine Rotation dabei sein */
if (p)
{ /* jau! */
tStrComp RegArg, RotArg;
StrCompSplitRef(&RegArg, &RotArg, &ArgStr[1], p);
StrCompShorten(&RotArg, 1);
Rot = EvalStrIntExpression(&RotArg, UInt3, &OK);
if (OK)
{
if (DecodeReg(&RegArg, &SrcReg, &SrcLen))
{
if (SrcReg >= 16) WrStrErrorPos(ErrNum_InvReg, &RegArg);
else
{
WAsmCode[0] = (Code << 13) | (SrcReg << 8) | (Rot << 5) | DestReg;
CodeLen = 1;
}
}
}
}
else /* noi! */
{
if (DecodeReg(&ArgStr[1], &SrcReg, &SrcLen))
{
WAsmCode[0] = (Code << 13) | (SrcReg << 8) | DestReg;
if ((SrcReg >= 16) && (SrcLen != -1)) WAsmCode[0] += SrcLen << 5;
CodeLen = 1;
}
}
}
else /* 3 Operanden --> Quelle ist I/O */
{
tSymbolFlags Flags;
if (GetLen(&ArgStr[2], &Rot, &Flags))
if (DecodeReg(&ArgStr[1], &SrcReg, &SrcLen))
{
if (SrcReg < 16) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
else if ((SrcLen != -1) && (SrcLen != Rot)) WrError(ErrNum_ConfOpSizes);
else
{
WAsmCode[0] = (Code << 13) | (SrcReg << 8) | (Rot << 5) | DestReg;
CodeLen = 1;
}
}
}
}
else /* Ziel I/O */
{
if (ArgCnt == 2) /* 2 Argumente: Laenge=Laenge Ziel */
{
Rot = DestLen; OK = True;
}
else /* 3 Argumente: Laenge=Laenge Ziel+Angabe */
{
tSymbolFlags Flags;
OK = GetLen(&ArgStr[2], &Rot, &Flags);
if (OK)
{
if (mFirstPassUnknown(Flags)) Rot = DestLen;
if (DestLen == -1) DestLen = Rot;
OK = Rot == DestLen;
if (!OK) WrError(ErrNum_ConfOpSizes);
}
}
if (OK)
if (DecodeReg(&ArgStr[1], &SrcReg, &SrcLen))
{
if (Rot == 0xffff)
Rot = ((SrcLen == -1)) ? 0 : SrcLen;
if ((DestReg >= 16) && (SrcLen != -1) && (SrcLen != Rot)) WrError(ErrNum_ConfOpSizes);
else
{
WAsmCode[0] = (Code << 13) | (SrcReg << 8) | (Rot << 5) | DestReg;
CodeLen = 1;
}
}
}
}
}
static void DecodeXEC(Word Code)
{
char *p;
Word SrcReg, Rot;
ShortInt SrcLen;
Boolean OK;
UNUSED(Code);
if (ChkArgCnt(1, 2))
{
p = HasDisp(ArgStr[1].str.p_str);
if (!p) WrError(ErrNum_InvAddrMode);
else
{
tStrComp DispArg, RegArg;
StrCompSplitRef(&DispArg, &RegArg, &ArgStr[1], p);
StrCompShorten(&RegArg, 1);
if (DecodeReg(&RegArg, &SrcReg, &SrcLen))
{
if (SrcReg < 16)
{
if (ChkArgCnt(1, 1))
{
WAsmCode[0] = EvalStrIntExpression(&DispArg, UInt8, &OK);
if (OK)
{
WAsmCode[0] |= 0x8000 | (SrcReg << 8);
CodeLen = 1;
}
}
}
else
{
tSymbolFlags Flags;
if (ArgCnt == 1)
{
Rot = 0xffff; OK = True; Flags = eSymbolFlag_None;
}
else OK = GetLen(&ArgStr[2], &Rot, &Flags);
if (OK)
{
if (Rot == 0xffff)
Rot = (SrcLen == -1) ? 0 : SrcLen;
if ((SrcLen != -1) && (Rot != SrcLen)) WrError(ErrNum_ConfOpSizes);
else
{
WAsmCode[0] = EvalStrIntExpression(&DispArg, UInt5, &OK);
if (OK)
{
WAsmCode[0] |= 0x8000 | (SrcReg << 8) | (Rot << 5);
CodeLen = 1;
}
}
}
}
}
}
}
}
static void DecodeJMP(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
Boolean OK;
WAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt13, &OK);
if (OK)
{
WAsmCode[0] |= 0xe000;
CodeLen = 1;
}
}
return;
}
static void DecodeNZT(Word Code)
{
Word SrcReg, Adr, Rot;
ShortInt SrcLen;
Boolean OK;
tSymbolFlags Flags;
UNUSED(Code);
if (ChkArgCnt(2, 3)
&& DecodeReg(&ArgStr[1], &SrcReg, &SrcLen))
{
if (SrcReg < 16)
{
if (ChkArgCnt(2, 2))
{
Adr = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt13, &OK, &Flags);
if (OK && ChkSamePage(Adr, EProgCounter(), 8, Flags))
{
WAsmCode[0] = 0xa000 | (SrcReg << 8) | (Adr & 0xff);
CodeLen = 1;
}
}
}
else
{
if (ArgCnt == 2)
{
Rot = 0xffff; OK = True; Flags = eSymbolFlag_None;
}
else OK = GetLen(&ArgStr[2], &Rot, &Flags);
if (OK)
{
if (Rot == 0xffff)
Rot = (SrcLen == -1) ? 0 : SrcLen;
if ((SrcLen != -1) && (Rot != SrcLen)) WrError(ErrNum_ConfOpSizes);
else
{
Adr = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], UInt13, &OK, &Flags);
if (OK && ChkSamePage(Adr, EProgCounter(), 5, Flags))
{
WAsmCode[0] = 0xa000 | (SrcReg << 8) | (Rot << 5) | (Adr & 0x1f);
CodeLen = 1;
}
}
}
}
}
}
/* Symbol: 00AA0ORL */
static void DecodeLIV_RIV(Word Code)
{
LongInt Adr, Ofs;
Word Len;
Boolean OK;
tSymbolFlags Flags;
if (ChkArgCnt(3, 3))
{
Adr = EvalStrIntExpression(&ArgStr[1], UInt8, &OK);
if (OK)
{
Ofs = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
if (OK)
if (GetLen(&ArgStr[3], &Len, &Flags))
{
PushLocHandle(-1);
EnterIntSymbol(&LabPart, Code | (Adr << 16) | (Ofs << 8) | (Len & 7), SegNone, False);
PopLocHandle();
}
}
}
}
/*-------------------------------------------------------------------------*/
static void AddAri(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeAri);
}
static void InitFields(void)
{
InstTable = CreateInstTable(103);
AddInstTable(InstTable, "NOP", 0, DecodeNOP);
AddInstTable(InstTable, "HALT", 0, DecodeHALT);
AddInstTable(InstTable, "XML", 0xca00, DecodeXML_XMR);
AddInstTable(InstTable, "XMR", 0xcb00, DecodeXML_XMR);
AddInstTable(InstTable, "SEL", 0, DecodeSEL);
AddInstTable(InstTable, "XMIT", 0, DecodeXMIT);
AddInstTable(InstTable, "XEC", 0, DecodeXEC);
AddInstTable(InstTable, "JMP", 0, DecodeJMP);
AddInstTable(InstTable, "NZT", 0, DecodeNZT);
AddInstTable(InstTable, "LIV", 0, DecodeLIV_RIV);
AddInstTable(InstTable, "RIV", 0x10, DecodeLIV_RIV);
AddAri("MOVE", 0); AddAri("ADD", 1); AddAri("AND", 2); AddAri("XOR", 3);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
static void MakeCode_8x30X(void)
{
CodeLen = 0; DontPrint = False;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_8x30X(void)
{
return (Memo("LIV") || Memo("RIV"));
}
static void SwitchFrom_8x30X(void)
{
DeinitFields();
}
static void SwitchTo_8x30X(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeMoto);
PCSymbol = "*";
HeaderID = 0x3a;
NOPCode = 0x0000;
DivideChars = ",";
HasAttrs = False;
ValidSegs = 1 << SegCode;
Grans[SegCode] = 2;
ListGrans[SegCode] = 2;
SegInits[SegCode] = 0;
SegLimits[SegCode] = 0x1fff;
MakeCode = MakeCode_8x30X;
IsDef = IsDef_8x30X;
SwitchFrom = SwitchFrom_8x30X;
InitFields();
}
void code8x30x_init(void)
{
CPU8x300 = AddCPU("8x300", SwitchTo_8x30X);
CPU8x305 = AddCPU("8x305", SwitchTo_8x30X);
}