/* code1802.c */
/****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS */
/* Code Generator for Intersil 1802 */
/* */
/****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "codevars.h"
#include "intpseudo.h"
#include "headids.h"
#include "errmsg.h"
#include "code1802.h"
/*-------------------------------------------------------------------------*/
/* Variables */
typedef struct
{
Word Code;
CPUVar MinCPU;
} tOrder;
static tOrder *FixedOrders, *RegOrders, *RegNoZeroOrders,
*RegImm16Orders, *RegLBranchOrders, *ImmOrders,
*SBranchOrders, *LBranchOrders, *IOOrders;
static CPUVar CPU1802,
CPU1804, CPU1805, CPU1806,
CPU1804A, CPU1805A, CPU1806A;
/*-------------------------------------------------------------------------*/
/* Subroutines */
static Boolean PutCode(const tOrder *pOrder)
{
if (ChkMinCPU(pOrder->MinCPU))
{
if (Hi(pOrder->Code))
BAsmCode[CodeLen++] = Hi(pOrder->Code);
BAsmCode[CodeLen++] = Lo(pOrder->Code);
return True;
}
else
return False;
}
/*-------------------------------------------------------------------------*/
/* Coders */
static void DecodePORT(Word Opcode)
{
UNUSED(Opcode);
CodeEquate(SegIO, 1, 0x7);
}
static void DecodeFixed(Word Index)
{
const tOrder *pOrder = FixedOrders + Index;
if (ChkArgCnt(0, 0))
PutCode(pOrder);
}
static void DecodeReg(Word Index)
{
const tOrder *pOrder = RegOrders + Index;
Boolean OK;
if (ChkArgCnt(1, 1)
&& PutCode(pOrder))
{
BAsmCode[CodeLen - 1] |= EvalStrIntExpression(&ArgStr[1], UInt4, &OK);
if (!OK)
CodeLen = 0;
}
}
static void DecodeRegNoZero(Word Index)
{
const tOrder *pOrder = RegNoZeroOrders + Index;
if (ChkArgCnt(1, 1)
&& PutCode(pOrder))
{
Boolean OK;
Byte Reg;
tSymbolFlags Flags;
Reg = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt4, &OK, &Flags);
if (!OK) CodeLen = 0;
else if (!mFirstPassUnknown(Flags) && (0 == Reg))
{
WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
CodeLen = 0;
}
else
BAsmCode[CodeLen - 1] |= Reg;
}
}
static void DecodeRegImm16(Word Index)
{
const tOrder *pOrder = RegImm16Orders + Index;
Boolean OK;
if (ChkArgCnt(2, 2)
&& PutCode(pOrder))
{
BAsmCode[CodeLen - 1] |= EvalStrIntExpression(&ArgStr[1], UInt4, &OK);
if (!OK) CodeLen = 0;
else
{
Word Arg = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
if (!OK) CodeLen = 0;
else
{
BAsmCode[CodeLen++] = Hi(Arg);
BAsmCode[CodeLen++] = Lo(Arg);
}
}
}
}
static void DecodeRegLBranch(Word Index)
{
const tOrder *pOrder = RegLBranchOrders + Index;
if (ChkArgCnt(2, 2)
&& PutCode(pOrder))
{
tEvalResult EvalResult;
BAsmCode[CodeLen - 1] |= EvalStrIntExpressionWithResult(&ArgStr[1], UInt4, &EvalResult);
if (!EvalResult.OK) CodeLen = 0;
else
{
Word Addr = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &EvalResult);
if (!EvalResult.OK)
CodeLen = 0;
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[CodeLen++] = Hi(Addr);
BAsmCode[CodeLen++] = Lo(Addr);
}
}
}
}
static void DecodeImm(Word Index)
{
const tOrder *pOrder = ImmOrders + Index;
Boolean OK;
if (ChkArgCnt(1, 1)
&& PutCode(pOrder))
{
BAsmCode[CodeLen++] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
if (!OK) CodeLen = 0;
}
}
static void DecodeSBranch(Word Index)
{
const tOrder *pOrder = SBranchOrders + Index;
if (ChkArgCnt(1, 1)
&& PutCode(pOrder))
{
tEvalResult EvalResult;
Word Addr = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (!EvalResult.OK || !ChkSamePage(EProgCounter() + 1, Addr, 8, EvalResult.Flags))
CodeLen = 0;
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[CodeLen++] = Lo(Addr);
}
}
}
static void DecodeLBranch(Word Index)
{
const tOrder *pOrder = LBranchOrders + Index;
if (ChkArgCnt(1, 1)
&& PutCode(pOrder))
{
tEvalResult EvalResult;
Word Addr = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (!EvalResult.OK) CodeLen = 0;
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[CodeLen++] = Hi(Addr);
BAsmCode[CodeLen++] = Lo(Addr);
}
}
}
static void DecodeJump(Word Index)
{
const tOrder *pOrder = LBranchOrders + Index;
if (ChkArgCnt(1, 1) && ChkMinCPU(pOrder->MinCPU))
{
tEvalResult EvalResult;
Word Addr = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
if (Hi(EProgCounter() + 1) == Hi(Addr))
BAsmCode[CodeLen++] = pOrder->Code ^ 0xf0;
else
{
BAsmCode[CodeLen++] = pOrder->Code;
BAsmCode[CodeLen++] = Hi(Addr);
}
BAsmCode[CodeLen++] = Lo(Addr);
}
}
}
static void DecodeIO(Word Index)
{
const tOrder *pOrder = IOOrders + Index;
Boolean OK;
if (ChkArgCnt(1, 1))
{
tSymbolFlags Flags;
BAsmCode[0] = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt3, &OK, &Flags);
if (OK)
{
if (mFirstPassUnknown(Flags)) BAsmCode[0] = 1;
if (BAsmCode[0] == 0) WrError(ErrNum_UnderRange);
else
{
BAsmCode[0] |= pOrder->Code;
CodeLen = 1;
}
}
}
}
/*-------------------------------------------------------------------------*/
/* Instruction Hash Table Handling */
static void AddFixed(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(FixedOrders, tOrder);
FixedOrders[InstrZ].Code = Code;
FixedOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeFixed);
}
static void AddReg(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(RegOrders, tOrder);
RegOrders[InstrZ].Code = Code;
RegOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeReg);
}
static void AddRegNoZero(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(RegNoZeroOrders, tOrder);
RegNoZeroOrders[InstrZ].Code = Code;
RegNoZeroOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeRegNoZero);
}
static void AddRegImm16(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(RegImm16Orders, tOrder);
RegImm16Orders[InstrZ].Code = Code;
RegImm16Orders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeRegImm16);
}
static void AddImm(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(ImmOrders, tOrder);
ImmOrders[InstrZ].Code = Code;
ImmOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeImm);
}
static void AddRegLBranch(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(RegLBranchOrders, tOrder);
RegLBranchOrders[InstrZ].Code = Code;
RegLBranchOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeRegLBranch);
}
static void AddLBranch(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(LBranchOrders, tOrder);
LBranchOrders[InstrZ].Code = Code;
LBranchOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ, DecodeLBranch);
AddInstTable(InstTable, "JMP", InstrZ, DecodeJump);
else if (!strcmp(pName
, "NLBR"));
else
{
char JName[10];
as_snprintf(JName, sizeof(JName), "J%s", pName + 2);
AddInstTable(InstTable, JName, InstrZ, DecodeJump);
}
InstrZ++;
}
static void AddSBranch(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(SBranchOrders, tOrder);
SBranchOrders[InstrZ].Code = Code;
SBranchOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeSBranch);
}
static void AddIO(const char *pName, Word Code, CPUVar MinCPU)
{
order_array_rsv_end(IOOrders, tOrder);
IOOrders[InstrZ].Code = Code;
IOOrders[InstrZ].MinCPU = MinCPU;
AddInstTable(InstTable, pName, InstrZ++, DecodeIO);
}
static void InitFields(void)
{
SetDynamicInstTable((InstTable = CreateInstTable(203)));
AddInstTable(InstTable, "PORT", 0, DecodePORT);
InstrZ = 0;
AddFixed("LDX" , 0x00f0, CPU1802);
AddFixed("LDXA" , 0x0072, CPU1802);
AddFixed("STXD" , 0x0073, CPU1802);
AddFixed("IRX" , 0x0060, CPU1802);
AddFixed("OR" , 0x00f1, CPU1802);
AddFixed("XOR" , 0x00f3, CPU1802);
AddFixed("AND" , 0x00f2, CPU1802);
AddFixed("SHR" , 0x00f6, CPU1802);
AddFixed("SHRC" , 0x0076, CPU1802);
AddFixed("RSHR" , 0x0076, CPU1802);
AddFixed("SHL" , 0x00fe, CPU1802);
AddFixed("SHLC" , 0x007e, CPU1802);
AddFixed("RSHL" , 0x007e, CPU1802);
AddFixed("ADD" , 0x00f4, CPU1802);
AddFixed("ADC" , 0x0074, CPU1802);
AddFixed("SD" , 0x00f5, CPU1802);
AddFixed("SDB" , 0x0075, CPU1802);
AddFixed("SM" , 0x00f7, CPU1802);
AddFixed("SMB" , 0x0077, CPU1802);
AddFixed("DADD" , 0x68f4, CPU1804A);
AddFixed("DADC" , 0x6874, CPU1804A);
AddFixed("DSM" , 0x68f7, CPU1804A);
AddFixed("DSMB" , 0x6877, CPU1804A);
AddFixed("SKP" , 0x0038, CPU1802);
AddFixed("LSKP" , 0x00c8, CPU1802);
AddFixed("LSZ" , 0x00ce, CPU1802);
AddFixed("LSNZ" , 0x00c6, CPU1802);
AddFixed("LSDF" , 0x00cf, CPU1802);
AddFixed("LSNF" , 0x00c7, CPU1802);
AddFixed("LSQ" , 0x00cd, CPU1802);
AddFixed("LSNQ" , 0x00c5, CPU1802);
AddFixed("LSIE" , 0x00cc, CPU1802);
AddFixed("IDL" , 0x0000, CPU1802);
AddFixed("NOP" , 0x00c4, CPU1802);
AddFixed("SEQ" , 0x007b, CPU1802);
AddFixed("REQ" , 0x007a, CPU1802);
AddFixed("SAV" , 0x0078, CPU1802);
AddFixed("MARK" , 0x0079, CPU1802);
AddFixed("RET" , 0x0070, CPU1802);
AddFixed("DIS" , 0x0071, CPU1802);
AddFixed("LDC" , 0x6806, CPU1804);
AddFixed("GEC" , 0x6808, CPU1804);
AddFixed("STPC" , 0x6800, CPU1804);
AddFixed("DTC" , 0x6801, CPU1804);
AddFixed("STM" , 0x6807, CPU1804);
AddFixed("SCM1" , 0x6805, CPU1804);
AddFixed("SCM2" , 0x6803, CPU1804);
AddFixed("SPM1" , 0x6804, CPU1804);
AddFixed("SPM2" , 0x6802, CPU1804);
AddFixed("ETQ" , 0x6809, CPU1804);
AddFixed("XIE" , 0x680a, CPU1804);
AddFixed("XID" , 0x680b, CPU1804);
AddFixed("CIE" , 0x680c, CPU1804);
AddFixed("CID" , 0x680d, CPU1804);
AddFixed("DSAV" , 0x6876, CPU1804A);
InstrZ = 0;
AddReg("LDA" , 0x0040, CPU1802);
AddReg("STR" , 0x0050, CPU1802);
AddReg("RLXA" , 0x6860, CPU1804);
AddReg("RSXD" , 0x68a0, CPU1804);
AddReg("INC" , 0x0010, CPU1802);
AddReg("DEC" , 0x0020, CPU1802);
AddReg("GLO" , 0x0080, CPU1802);
AddReg("PLO" , 0x00a0, CPU1802);
AddReg("GHI" , 0x0090, CPU1802);
AddReg("PHI" , 0x00b0, CPU1802);
AddReg("RNX" , 0x68b0, CPU1804);
AddReg("SEP" , 0x00d0, CPU1802);
AddReg("SEX" , 0x00e0, CPU1802);
AddReg("SRET" , 0x6890, CPU1804);
InstrZ = 0;
AddRegNoZero("LDN" , 0x0000, CPU1802);
InstrZ = 0;
AddRegImm16("RLDI" , 0x68c0, CPU1804);
InstrZ = 0;
AddImm("LDI" , 0x00f8, CPU1802);
AddImm("ORI" , 0x00f9, CPU1802);
AddImm("XRI" , 0x00fb, CPU1802);
AddImm("ANI" , 0x00fa, CPU1802);
AddImm("ADI" , 0x00fc, CPU1802);
AddImm("ADCI" , 0x007c, CPU1802);
AddImm("SDI" , 0x00fd, CPU1802);
AddImm("SDBI" , 0x007d, CPU1802);
AddImm("SMI" , 0x00ff, CPU1802);
AddImm("SMBI" , 0x007f, CPU1802);
AddImm("DADI" , 0x68fc, CPU1804A);
AddImm("DACI" , 0x687c, CPU1804A);
AddImm("DSMI" , 0x68ff, CPU1804A);
AddImm("DSBI" , 0x687f, CPU1804A);
InstrZ = 0;
AddRegLBranch("DBNZ" , 0x6820, CPU1804A);
AddRegLBranch("SCAL" , 0x6880, CPU1804);
InstrZ = 0;
AddLBranch("LBR" , 0x00c0, CPU1802);
AddLBranch("NLBR" , 0x00c8, CPU1802);
AddLBranch("LBZ" , 0x00c2, CPU1802);
AddLBranch("LBNZ" , 0x00ca, CPU1802);
AddLBranch("LBDF" , 0x00c3, CPU1802);
AddLBranch("LBPZ" , 0x00c3, CPU1802);
AddLBranch("LBGE" , 0x00c3, CPU1802);
AddLBranch("LBNF" , 0x00cb, CPU1802);
AddLBranch("LBM" , 0x00cb, CPU1802);
AddLBranch("LBL" , 0x00cb, CPU1802);
AddLBranch("LBQ" , 0x00c1, CPU1802);
AddLBranch("LBNQ" , 0x00c9, CPU1802);
InstrZ = 0;
AddSBranch("BR" , 0x0030, CPU1802);
AddSBranch("NBR" , 0x0038, CPU1802);
AddSBranch("BZ" , 0x0032, CPU1802);
AddSBranch("BNZ" , 0x003a, CPU1802);
AddSBranch("BDF" , 0x0033, CPU1802);
AddSBranch("BPZ" , 0x0033, CPU1802);
AddSBranch("BGE" , 0x0033, CPU1802);
AddSBranch("BNF" , 0x003b, CPU1802);
AddSBranch("BM" , 0x003b, CPU1802);
AddSBranch("BL" , 0x003b, CPU1802);
AddSBranch("BQ" , 0x0031, CPU1802);
AddSBranch("BNQ" , 0x0039, CPU1802);
AddSBranch("B1" , 0x0034, CPU1802);
AddSBranch("BN1" , 0x003c, CPU1802);
AddSBranch("B2" , 0x0035, CPU1802);
AddSBranch("BN2" , 0x003d, CPU1802);
AddSBranch("B3" , 0x0036, CPU1802);
AddSBranch("BN3" , 0x003e, CPU1802);
AddSBranch("B4" , 0x0037, CPU1802);
AddSBranch("BN4" , 0x003f, CPU1802);
AddSBranch("BCI" , 0x683e, CPU1804);
AddSBranch("BXI" , 0x683f, CPU1804);
InstrZ = 0;
AddIO("OUT" , 0x0060, CPU1802);
AddIO("INP" , 0x0068, CPU1802);
}
static void DeinitFields(void)
{
order_array_free(FixedOrders);
order_array_free(RegOrders);
order_array_free(RegNoZeroOrders);
order_array_free(RegImm16Orders);
order_array_free(RegLBranchOrders);
order_array_free(ImmOrders);
order_array_free(SBranchOrders);
order_array_free(LBranchOrders);
order_array_free(IOOrders);
DestroyInstTable(InstTable);
}
/*-------------------------------------------------------------------------*/
/* Interface to Upper Level */
static void MakeCode_1802(void)
{
CodeLen = 0; DontPrint = False;
/* to be ignored */
if (*OpPart.str.p_str == '\0') return;
/* Pseudo Instructions */
if (DecodeIntelPseudo(True)) return;
/* search */
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_1802(void)
{
return Memo("PORT");
}
static void SwitchFrom_1802(void)
{
DeinitFields();
}
static void SwitchTo_1802(void)
{
const TFamilyDescr *FoundDescr;
FoundDescr = FindFamilyByName("1802");
TurnWords = FALSE;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "$";
HeaderID = FoundDescr->Id;
NOPCode = 0xc4;
DivideChars = ",";
HasAttrs = False;
ValidSegs = (1 << SegCode) | (1 << SegIO);
Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
SegLimits[SegCode ] = 0xffff;
Grans[SegIO ] = 1; ListGrans[SegIO ] = 1; SegInits[SegIO ] = 1;
SegLimits[SegIO ] = 0x7;
MakeCode = MakeCode_1802;
IsDef = IsDef_1802;
InitFields();
SwitchFrom = SwitchFrom_1802;
}
/*-------------------------------------------------------------------------*/
/* Module Initialization */
void code1802_init(void)
{
CPU1802 = AddCPU("1802", SwitchTo_1802);
CPU1804 = AddCPU("1804", SwitchTo_1802);
CPU1805 = AddCPU("1805", SwitchTo_1802);
CPU1806 = AddCPU("1806", SwitchTo_1802);
CPU1804A = AddCPU("1804A", SwitchTo_1802);
CPU1805A = AddCPU("1805A", SwitchTo_1802);
CPU1806A = AddCPU("1806A", SwitchTo_1802);
}