/* code78k0.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator 78K0-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code78k0.h"
enum
{
ModNone = -1,
ModReg8 = 0,
ModReg16 = 1,
ModImm = 2,
ModShort = 3,
ModSFR = 4,
ModAbs = 5,
ModIReg = 6,
ModIndex = 7,
ModDisp = 8
};
#define MModReg8 (1 << ModReg8)
#define MModReg16 (1 << ModReg16)
#define MModImm (1 << ModImm)
#define MModShort (1 << ModShort)
#define MModSFR (1 << ModSFR)
#define MModAbs (1 << ModAbs)
#define MModIReg (1 << ModIReg)
#define MModIndex (1 << ModIndex)
#define MModDisp (1 << ModDisp)
#define AccReg 1
#define AccReg16 0
static Byte OpSize,AdrPart;
static Byte AdrVals[2];
static ShortInt AdrMode;
static CPUVar CPU78070;
/*-------------------------------------------------------------------------*/
/* Adressausdruck parsen */
static void DecodeAdr(const tStrComp *pArg, Word Mask)
{
static const char RegNames[8][2] =
{
"X","A","C","B","E","D","L","H"
};
Word AdrWord;
int z;
Boolean OK, LongFlag;
int ArgLen
= strlen(pArg
->str.
p_str);
tSymbolFlags Flags;
AdrMode = ModNone;
AdrCnt = 0;
/* Register */
for (z = 0; z < 8; z++)
if (!as_strcasecmp(pArg->str.p_str, RegNames[z]))
{
AdrMode = ModReg8;
AdrPart = z;
goto chk;
}
if (as_toupper(*pArg->str.p_str) == 'R')
{
if ((strlen(pArg
->str.
p_str) == 2) && (pArg
->str.
p_str[1] >= '0') && (pArg
->str.
p_str[1] <= '7'))
{
AdrMode = ModReg8;
AdrPart = pArg->str.p_str[1] - '0';
goto chk;
}
else if ((ArgLen == 3) && (as_toupper(pArg->str.p_str[1]) == 'P') && (pArg->str.p_str[2] >= '0') && (pArg->str.p_str[2] <= '3'))
{
AdrMode = ModReg16;
AdrPart = pArg->str.p_str[2] - '0';
goto chk;
}
}
if (ArgLen == 2)
{
for (z = 0; z < 4; z++)
if ((as_toupper(*pArg->str.p_str) == *RegNames[(z << 1) + 1])
&& (as_toupper(pArg->str.p_str[1]) == *RegNames[z << 1]))
{
AdrMode = ModReg16;
AdrPart = z;
goto chk;
}
}
/* immediate */
if (*pArg->str.p_str == '#')
{
switch (OpSize)
{
case 0:
AdrVals[0] = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK);
break;
case 1:
AdrWord = EvalStrIntExpressionOffs(pArg, 1, Int16, &OK);
if (OK)
{
AdrVals[0] = Lo(AdrWord);
AdrVals[1] = Hi(AdrWord);
}
break;
}
if (OK)
{
AdrMode = ModImm;
AdrCnt = OpSize + 1;
}
goto chk;
}
/* indirekt */
if ((*pArg->str.p_str == '[') && (pArg->str.p_str[ArgLen - 1] == ']'))
{
tStrComp Arg;
StrCompRefRight(&Arg, pArg, 1);
StrCompShorten(&Arg, 1);
if ((!as_strcasecmp(Arg.str.p_str, "DE")) || (!as_strcasecmp(Arg.str.p_str, "RP2")))
{
AdrMode = ModIReg;
AdrPart = 0;
}
else if ((!as_strncasecmp(Arg.str.p_str, "HL", 2)) && (!as_strncasecmp(Arg.str.p_str, "RP3", 3))) WrStrErrorPos(ErrNum_InvReg, &Arg);
else
{
StrCompIncRefLeft(&Arg, 2);
if (*Arg.str.p_str == '3')
StrCompIncRefLeft(&Arg, 1);
if ((!as_strcasecmp(Arg.str.p_str, "+B")) || (!as_strcasecmp(Arg.str.p_str, "+R3")))
{
AdrMode = ModIndex;
AdrPart = 1;
}
else if ((!as_strcasecmp(Arg.str.p_str, "+C")) || (!as_strcasecmp(Arg.str.p_str, "+R2")))
{
AdrMode = ModIndex;
AdrPart = 0;
}
else
{
AdrVals[0] = EvalStrIntExpression(&Arg, UInt8, &OK);
if (OK)
{
if (AdrVals[0] == 0)
{
AdrMode = ModIReg;
AdrPart = 1;
}
else
{
AdrMode = ModDisp;
AdrCnt = 1;
}
}
}
}
goto chk;
}
/* erzwungen lang ? */
LongFlag = !!(*pArg->str.p_str == '!');
/* -->absolut */
AdrWord = EvalStrIntExpressionOffsWithFlags(pArg, LongFlag, UInt16, &OK, &Flags);
if (mFirstPassUnknown(Flags))
{
AdrWord &= 0xffffe;
if (!(Mask & MModAbs))
AdrWord = (AdrWord | 0xff00) & 0xff1f;
}
if (OK)
{
if ((!LongFlag) && (Mask & MModShort) && (AdrWord >= 0xfe20) && (AdrWord <= 0xff1f))
{
AdrMode = ModShort;
AdrCnt = 1;
AdrVals[0] = Lo(AdrWord);
}
else if ((!LongFlag) && (Mask & MModSFR) && (((AdrWord >= 0xff00) && (AdrWord <= 0xffcf)) || (AdrWord >= 0xffe0)))
{
AdrMode = ModSFR;
AdrCnt = 1;
AdrVals[0] = Lo(AdrWord);
}
else
{
AdrMode = ModAbs;
AdrCnt = 2;
AdrVals[0] = Lo(AdrWord);
AdrVals[1] = Hi(AdrWord);
}
}
chk:
if ((AdrMode != ModNone) && (!(Mask & (1 << AdrMode))))
{
WrError(ErrNum_InvAddrMode);
AdrMode = ModNone;
AdrCnt = 0;
}
}
static void ChkEven(void)
{
if ((AdrMode==ModAbs) || (AdrMode==ModShort) || (AdrMode==ModSFR))
if ((AdrVals[0]&1)==1) WrError(ErrNum_AddrNotAligned);
}
static Boolean DecodeBitAdr(const tStrComp *pArg, Byte *Erg)
{
char *p;
Boolean OK;
tStrComp Reg, Bit;
p = RQuotPos(pArg->str.p_str, '.');
if (!p)
{
WrError(ErrNum_InvBitPos);
return False;
}
StrCompSplitRef(&Reg, &Bit, pArg, p);
*Erg = EvalStrIntExpression(&Bit, UInt3, &OK) << 4;
if (!OK)
return False;
DecodeAdr(&Reg, MModShort | MModSFR | MModIReg | MModReg8);
switch (AdrMode)
{
case ModReg8:
if (AdrPart != AccReg)
{
WrError(ErrNum_InvAddrMode);
return False;
}
else
{
*Erg += 0x88;
return True;
}
case ModShort:
return True;
case ModSFR:
*Erg += 0x08;
return True;
case ModIReg:
if (AdrPart == 0)
{
WrError(ErrNum_InvAddrMode);
return False;
}
else
{
*Erg += 0x80;
return True;
}
default:
return False;
}
}
/*-------------------------------------------------------------------------*/
/* Instruction Decoders */
/* ohne Argument */
static void DecodeFixed(Word Code)
{
if (ChkArgCnt(0, 0))
{
if (Hi(Code))
BAsmCode[CodeLen++] = Hi(Code);
BAsmCode[CodeLen++] = Lo(Code);
}
}
/* Datentransfer */
static void DecodeMOV(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg8 | MModShort | MModSFR | MModAbs
| MModIReg | MModIndex | MModDisp);
switch (AdrMode)
{
case ModReg8:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModImm | MModReg8
| ((HReg == AccReg) ? MModShort | MModSFR | MModAbs | MModIReg | MModIndex | MModDisp : 0));
switch (AdrMode)
{
case ModReg8:
if ((HReg == AccReg) == (AdrPart == AccReg)) WrError(ErrNum_InvAddrMode);
else if (HReg == AccReg)
{
CodeLen = 1;
BAsmCode[0] = 0x60 + AdrPart;
}
else
{
CodeLen = 1;
BAsmCode[0] = 0x70 + HReg;
}
break;
case ModImm:
CodeLen = 2;
BAsmCode[0] = 0xa0 + HReg;
BAsmCode[1] = AdrVals[0];
break;
case ModShort:
CodeLen = 2;
BAsmCode[0] = 0xf0;
BAsmCode[1] = AdrVals[0];
break;
case ModSFR:
CodeLen = 2;
BAsmCode[0] = 0xf4;
BAsmCode[1] = AdrVals[0];
break;
case ModAbs:
CodeLen = 3;
BAsmCode[0] = 0x8e;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
case ModIReg:
CodeLen = 1;
BAsmCode[0] = 0x85 + (AdrPart << 1);
break;
case ModIndex:
CodeLen = 1;
BAsmCode[0] = 0xaa + AdrPart;
break;
case ModDisp:
CodeLen = 2;
BAsmCode[0] = 0xae;
BAsmCode[1] = AdrVals[0];
break;
}
break;
case ModShort:
BAsmCode[1] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg8 | MModImm);
switch (AdrMode)
{
case ModReg8:
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0xf2;
CodeLen = 2;
}
break;
case ModImm:
BAsmCode[0] = 0x11;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
}
break;
case ModSFR:
BAsmCode[1] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg8 | MModImm);
switch (AdrMode)
{
case ModReg8:
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0xf6;
CodeLen = 2;
}
break;
case ModImm:
BAsmCode[0] = 0x13;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
}
break;
case ModAbs:
memcpy(BAsmCode
+ 1, AdrVals
, 2);
DecodeAdr(&ArgStr[2], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x9e;
CodeLen = 3;
}
}
break;
case ModIReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x95 | (HReg << 1);
CodeLen = 1;
}
}
break;
case ModIndex:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0xba + HReg;
CodeLen = 1;
}
}
break;
case ModDisp:
BAsmCode[1] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0xbe;
CodeLen = 2;
}
}
break;
}
}
}
static void DecodeXCH(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
Boolean Swap = (!as_strcasecmp(ArgStr[2].str.p_str, "A")) || (!as_strcasecmp(ArgStr[2].str.p_str, "RP1"));
tStrComp *pArg1 = Swap ? &ArgStr[2] : &ArgStr[1],
*pArg2 = Swap ? &ArgStr[1] : &ArgStr[2];
DecodeAdr(pArg1, MModReg8);
if (AdrMode != ModNone)
{
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
DecodeAdr(pArg2, MModReg8 | MModShort | MModSFR | MModAbs
| MModIReg | MModIndex | MModDisp);
switch (AdrMode)
{
case ModReg8:
if (AdrPart == AccReg) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x30 + AdrPart;
CodeLen = 1;
}
break;
case ModShort:
BAsmCode[0] = 0x83;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModSFR:
BAsmCode[0] = 0x93;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModAbs:
BAsmCode[0] = 0xce;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
CodeLen = 3;
break;
case ModIReg:
BAsmCode[0] = 0x05 + (AdrPart << 1);
CodeLen = 1;
break;
case ModIndex:
BAsmCode[0] = 0x31;
BAsmCode[1] = 0x8a + AdrPart;
CodeLen = 2;
break;
case ModDisp:
BAsmCode[0] = 0xde;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
}
}
}
}
}
static void DecodeMOVW(Word Index)
{
Byte HReg;
UNUSED(Index);
OpSize = 1;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg16 | MModShort | MModSFR | MModAbs);
switch (AdrMode)
{
case ModReg16:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg16 | MModImm
| ((HReg == AccReg16) ? MModShort | MModSFR | MModAbs : 0));
switch (AdrMode)
{
case ModReg16:
if ((HReg == AccReg16) == (AdrPart == AccReg16)) WrError(ErrNum_InvAddrMode);
else if (HReg == AccReg16)
{
BAsmCode[0] = 0xc0 + (AdrPart << 1);
CodeLen = 1;
}
else
{
BAsmCode[0] = 0xd0 + (HReg << 1);
CodeLen = 1;
}
break;
case ModImm:
BAsmCode[0] = 0x10 + (HReg << 1);
memcpy(BAsmCode
+ 1, AdrVals
, 2);
CodeLen = 3;
break;
case ModShort:
BAsmCode[0] = 0x89;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
ChkEven();
break;
case ModSFR:
BAsmCode[0] = 0xa9;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
ChkEven();
break;
case ModAbs:
BAsmCode[0] = 0x02;
memcpy(BAsmCode
+ 1, AdrVals
, 2);
CodeLen = 3;
ChkEven();
break;
}
break;
case ModShort:
ChkEven();
BAsmCode[1] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg16 | MModImm);
switch (AdrMode)
{
case ModReg16:
if (AdrPart != AccReg16) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x99;
CodeLen = 2;
}
break;
case ModImm:
BAsmCode[0] = 0xee;
memcpy(BAsmCode
+ 2, AdrVals
, 2);
CodeLen = 4;
break;
}
break;
case ModSFR:
ChkEven();
BAsmCode[1] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg16 | MModImm);
switch (AdrMode)
{
case ModReg16:
if (AdrPart != AccReg16) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0xb9;
CodeLen = 2;
}
break;
case ModImm:
BAsmCode[0] = 0xfe;
memcpy(BAsmCode
+ 2,AdrVals
, 2);
CodeLen = 4;
break;
}
break;
case ModAbs:
ChkEven();
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
DecodeAdr(&ArgStr[2], MModReg16);
if (AdrMode == ModReg16)
{
if (AdrPart != AccReg16) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x03;
CodeLen = 3;
}
}
break;
}
}
}
static void DecodeXCHW(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg16);
if (AdrMode == ModReg16)
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg16);
if (AdrMode == ModReg16)
{
if ((HReg == AccReg16) == (AdrPart == AccReg16)) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = (HReg == AccReg16) ? 0xe0 + (AdrPart << 1) : 0xe0 + (HReg << 1);
CodeLen = 1;
}
}
}
}
}
static void DecodeStack(Word Index)
{
if (!ChkArgCnt(1, 1));
else if (!as_strcasecmp(ArgStr[1].str.p_str, "PSW"))
{
BAsmCode[0] = 0x22 + Index;
CodeLen = 1;
}
else
{
DecodeAdr(&ArgStr[1], MModReg16);
if (AdrMode == ModReg16)
{
BAsmCode[0] = 0xb1 - Index + (AdrPart << 1);
CodeLen = 1;
}
}
}
/* Arithmetik */
static void DecodeAri(Word Index)
{
Byte HReg;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg8 | MModShort);
switch (AdrMode)
{
case ModReg8:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModReg8 | ((HReg == AccReg) ? (MModImm | MModShort | MModAbs | MModIReg | MModIndex | MModDisp) : 0));
switch (AdrMode)
{
case ModReg8:
if (AdrPart == AccReg)
{
BAsmCode[0] = 0x61;
BAsmCode[1] = (Index << 4) + HReg;
CodeLen = 2;
}
else if (HReg == AccReg)
{
BAsmCode[0] = 0x61;
BAsmCode[1] = 0x08 + (Index << 4) + AdrPart;
CodeLen = 2;
}
else WrError(ErrNum_InvAddrMode);
break;
case ModImm:
BAsmCode[0] = (Index << 4) + 0x0d;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModShort:
BAsmCode[0] = (Index << 4) + 0x0e;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModAbs:
BAsmCode[0] = (Index << 4) + 0x08;
memcpy(BAsmCode
+ 1, AdrVals
, 2);
CodeLen = 3;
break;
case ModIReg:
if (AdrPart == 0) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = (Index << 4) + 0x0f;
CodeLen = 1;
}
break;
case ModIndex:
BAsmCode[0] = 0x31;
BAsmCode[1] = (Index << 4) + 0x0a + AdrPart;
CodeLen = 2;
break;
case ModDisp:
BAsmCode[0] = (Index << 4) + 0x09;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
}
break;
case ModShort:
BAsmCode[1] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModImm);
if (AdrMode == ModImm)
{
BAsmCode[0] = (Index << 4) + 0x88;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
}
break;
}
}
}
static void DecodeAri16(Word Index)
{
if (ChkArgCnt(2, 2))
{
OpSize = 1;
DecodeAdr(&ArgStr[1], MModReg16);
if (AdrMode == ModReg16)
{
DecodeAdr(&ArgStr[2], MModImm);
if (AdrMode == ModImm)
{
BAsmCode[0] = 0xca + (Index << 4);
memcpy(BAsmCode
+ 1, AdrVals
, 2);
CodeLen = 3;
}
}
}
}
static void DecodeMULU(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != 0) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x31;
BAsmCode[1] = 0x88;
CodeLen = 2;
}
}
}
}
static void DecodeDIVUW(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != 2) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x31;
BAsmCode[1] = 0x82;
CodeLen = 2;
}
}
}
}
static void DecodeINCDEC(Word Index)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg8 | MModShort);
switch (AdrMode)
{
case ModReg8:
BAsmCode[0] = 0x40 + AdrPart + Index;
CodeLen = 1;
break;
case ModShort:
BAsmCode[0] = 0x81 + Index;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
}
}
}
static void DecodeINCDECW(Word Index)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg16);
if (AdrMode == ModReg16)
{
BAsmCode[0] = 0x80 + Index + (AdrPart << 1);
CodeLen = 1;
}
}
}
static void DecodeShift(Word Index)
{
Byte HReg;
Boolean OK;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg8);
if (AdrMode == ModReg8)
{
if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
else
{
HReg = EvalStrIntExpression(&ArgStr[2], UInt1, &OK);
if (OK)
{
if (HReg != 1) WrError(ErrNum_UnderRange);
else
{
BAsmCode[0] = 0x24 + Index;
CodeLen = 1;
}
}
}
}
}
}
static void DecodeRot4(Word Index)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModIReg);
if (AdrMode == ModIReg)
{
if (AdrPart == 0) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x31;
BAsmCode[1] = 0x80 + Index;
CodeLen = 2;
}
}
}
}
/* Bitoperationen */
static void DecodeMOV1(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
Boolean Swap = !as_strcasecmp(ArgStr[2].str.p_str, "CY");
tStrComp *pArg1 = Swap ? &ArgStr[2] : &ArgStr[1],
*pArg2 = Swap ? &ArgStr[1] : &ArgStr[2];
int z = Swap ? 1 : 4;
if (as_strcasecmp(pArg1->str.p_str, "CY")) WrError(ErrNum_InvAddrMode);
else if (DecodeBitAdr(pArg2, &HReg))
{
BAsmCode[0] = 0x61 + (Ord((HReg & 0x88) != 0x88) << 4);
BAsmCode[1] = z + HReg;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
}
}
}
static void DecodeBit2(Word Index)
{
Byte HReg;
if (!ChkArgCnt(2, 2));
else if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrError(ErrNum_InvAddrMode);
else if (DecodeBitAdr(&ArgStr[2], &HReg))
{
BAsmCode[0] = 0x61 + (Ord((HReg & 0x88) != 0x88) << 4);
BAsmCode[1] = Index + 5 + HReg;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
}
}
static void DecodeSETCLR1(Word Index)
{
Byte HReg;
if (!ChkArgCnt(1, 1));
else if (!as_strcasecmp(ArgStr[1].str.p_str, "CY"))
{
BAsmCode[0] = 0x20 + Index;
CodeLen = 1;
}
else if (DecodeBitAdr(&ArgStr[1], &HReg))
{
if ((HReg & 0x88) == 0)
{
BAsmCode[0] = 0x0a + Index + (HReg & 0x70);
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
}
else
{
BAsmCode[0] =0x61 + (Ord((HReg & 0x88) != 0x88) << 4);
BAsmCode[1] =HReg + 2 + Index;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen=2 + AdrCnt;
}
}
}
static void DecodeNOT1(Word Index)
{
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[0] = 0x01;
CodeLen = 1;
}
}
/* Spruenge */
static void DecodeCALL(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModAbs);
if (AdrMode == ModAbs)
{
BAsmCode[0] = 0x9a;
memcpy(BAsmCode
+ 1, AdrVals
, 2);
CodeLen = 3;
}
}
}
static void DecodeCALLF(Word Index)
{
Word AdrWord;
Boolean OK;
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
AdrWord = EvalStrIntExpressionOffs(&ArgStr[1], !!(*ArgStr[1].str.p_str == '!'), UInt11, &OK);
if (OK)
{
BAsmCode[0] = 0x0c | (Hi(AdrWord) << 4);
BAsmCode[1] = Lo(AdrWord);
CodeLen = 2;
}
}
}
static void DecodeCALLT(Word Index)
{
Word AdrWord;
Boolean OK;
int l
= strlen(ArgStr
[1].
str.
p_str);
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if ((*ArgStr[1].str.p_str != '[') || (ArgStr[1].str.p_str[l - 1] != ']')) WrError(ErrNum_InvAddrMode);
else
{
tSymbolFlags Flags;
ArgStr[1].str.p_str[l - 1] = '\0';
AdrWord = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, UInt6, &OK, &Flags);
if (mFirstPassUnknown(Flags)) AdrWord &= 0xfffe;
if (OK)
{
if (Odd(AdrWord)) WrError(ErrNum_NotAligned);
else
{
BAsmCode[0] = 0xc1 + (AdrWord & 0x3e);
CodeLen = 1;
}
}
}
}
static void DecodeBR(Word Index)
{
Word AdrWord;
Integer AdrInt;
Boolean OK;
Byte HReg;
UNUSED(Index);
if (!ChkArgCnt(1, 1));
else if ((!as_strcasecmp(ArgStr[1].str.p_str, "AX")) || (!as_strcasecmp(ArgStr[1].str.p_str, "RP0")))
{
BAsmCode[0] = 0x31;
BAsmCode[1] = 0x98;
CodeLen = 2;
}
else
{
unsigned Offset = 0;
tSymbolFlags Flags;
if (*ArgStr[1].str.p_str == '!')
{
Offset++;
HReg = 1;
}
else if (*ArgStr[1].str.p_str == '$')
{
Offset++;
HReg = 2;
}
else HReg = 0;
AdrWord = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], Offset, UInt16, &OK, &Flags);
if (OK)
{
if (HReg == 0)
{
AdrInt = AdrWord - (EProgCounter() - 2);
HReg = ((AdrInt >= -128) && (AdrInt < 127)) ? 2 : 1;
}
switch (HReg)
{
case 1:
BAsmCode[0] = 0x9b;
BAsmCode[1] = Lo(AdrWord);
BAsmCode[2] = Hi(AdrWord);
CodeLen = 3;
break;
case 2:
AdrInt = AdrWord - (EProgCounter() + 2);
if (((AdrInt < -128) || (AdrInt > 127)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[0] = 0xfa;
BAsmCode[1] = AdrInt & 0xff;
CodeLen = 2;
}
break;
}
}
}
}
static void DecodeRel(Word Index)
{
Integer AdrInt;
Boolean OK;
tSymbolFlags Flags;
if (ChkArgCnt(1, 1))
{
AdrInt = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], ('$' == *ArgStr[1].str.p_str), UInt16, &OK, &Flags) - (EProgCounter() + 2);
if (OK)
{
if (((AdrInt < -128) || (AdrInt > 127)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[0] = 0x8d + (Index << 4);
BAsmCode[1] = AdrInt & 0xff;
CodeLen = 2;
}
}
}
}
static void DecodeBRel(Word Index)
{
Integer AdrInt;
tSymbolFlags Flags;
Byte HReg;
Boolean OK;
if (!ChkArgCnt(2, 2));
else if (DecodeBitAdr(&ArgStr[1], &HReg))
{
if ((Index == 1) && ((HReg & 0x88) == 0))
{
BAsmCode[0] = 0x8c + HReg;
BAsmCode[1] = AdrVals[0];
HReg = 2;
}
else
{
BAsmCode[0] = 0x31;
switch (HReg & 0x88)
{
case 0x00:
BAsmCode[1] = 0x00;
break;
case 0x08:
BAsmCode[1] = 0x04;
break;
case 0x80:
BAsmCode[1] = 0x84;
break;
case 0x88:
BAsmCode[1] = 0x0c;
break;
}
BAsmCode[1] += (HReg & 0x70) + Index + 1;
BAsmCode[2] = AdrVals[0];
HReg = 2 + AdrCnt;
}
AdrInt = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], !!(*ArgStr[2].str.p_str == '$'), UInt16, &OK, &Flags) - (EProgCounter() + HReg + 1);
if (OK)
{
if (((AdrInt < -128) || (AdrInt > 127)) & !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[HReg] = AdrInt & 0xff;
CodeLen = HReg + 1;
}
}
}
}
static void DecodeDBNZ(Word Index)
{
Integer AdrInt;
tSymbolFlags Flags;
Boolean OK;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg8 + MModShort);
if ((AdrMode == ModReg8) && ((AdrPart & 6) != 2)) WrError(ErrNum_InvAddrMode);
else if (AdrMode != ModNone)
{
BAsmCode[0] = (AdrMode == ModReg8) ? 0x88 + AdrPart : 0x04;
BAsmCode[1] = AdrVals[0];
AdrInt = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], !!(*ArgStr[2].str.p_str == '$'), UInt16, &OK, &Flags) - (EProgCounter() + AdrCnt + 2);
if (OK)
{
if (((AdrInt < -128) || (AdrInt > 127)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[AdrCnt + 1] = AdrInt & 0xff;
CodeLen = AdrCnt + 2;
}
}
}
}
}
/* Steueranweisungen */
static void DecodeSEL(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ArgCnt != 1) WrError(ErrNum_InvAddrMode);
else if ((strlen(ArgStr
[1].
str.
p_str) != 3) || (as_strncasecmp
(ArgStr
[1].
str.
p_str, "RB", 2) != 0)) WrError
(ErrNum_InvAddrMode
);
else
{
HReg = ArgStr[1].str.p_str[2] - '0';
if (ChkRange(HReg, 0, 3))
{
BAsmCode[0] = 0x61;
BAsmCode[1] = 0xd0 + ((HReg & 1) << 3) + ((HReg & 2) << 4);
CodeLen = 2;
}
}
}
/*-------------------------------------------------------------------------*/
/* dynamische Codetabellenverwaltung */
static void AddFixed(const char *NewName, Word NewCode)
{
AddInstTable(InstTable, NewName, NewCode, DecodeFixed);
}
static void AddAri(const char *NewName)
{
AddInstTable(InstTable, NewName, InstrZ++, DecodeAri);
}
static void AddAri16(const char *NewName)
{
AddInstTable(InstTable, NewName, InstrZ++, DecodeAri16);
}
static void AddShift(const char *NewName)
{
AddInstTable(InstTable, NewName, InstrZ++, DecodeShift);
}
static void AddBit2(const char *NewName)
{
AddInstTable(InstTable, NewName, InstrZ++, DecodeBit2);
}
static void AddRel(const char *NewName)
{
AddInstTable(InstTable, NewName, InstrZ++, DecodeRel);
}
static void AddBRel(const char *NewName)
{
AddInstTable(InstTable, NewName, InstrZ++, DecodeBRel);
}
static void InitFields(void)
{
InstTable = CreateInstTable(201);
AddInstTable(InstTable, "MOV" , 0, DecodeMOV);
AddInstTable(InstTable, "XCH" , 0, DecodeXCH);
AddInstTable(InstTable, "MOVW" , 0, DecodeMOVW);
AddInstTable(InstTable, "XCHW" , 0, DecodeXCHW);
AddInstTable(InstTable, "PUSH" , 0, DecodeStack);
AddInstTable(InstTable, "POP" , 1, DecodeStack);
AddInstTable(InstTable, "MULU" , 0, DecodeMULU);
AddInstTable(InstTable, "DIVUW", 0, DecodeDIVUW);
AddInstTable(InstTable, "INC" , 0, DecodeINCDEC);
AddInstTable(InstTable, "DEC" ,16, DecodeINCDEC);
AddInstTable(InstTable, "INCW" , 0, DecodeINCDECW);
AddInstTable(InstTable, "DECW" ,16, DecodeINCDECW);
AddInstTable(InstTable, "ROL4" , 0, DecodeRot4);
AddInstTable(InstTable, "ROR4" ,16, DecodeRot4);
AddInstTable(InstTable, "MOV1" , 0, DecodeMOV1);
AddInstTable(InstTable, "SET1" , 0, DecodeSETCLR1);
AddInstTable(InstTable, "CLR1" , 1, DecodeSETCLR1);
AddInstTable(InstTable, "NOT1" , 1, DecodeNOT1);
AddInstTable(InstTable, "CALL" , 0, DecodeCALL);
AddInstTable(InstTable, "CALLF", 0, DecodeCALLF);
AddInstTable(InstTable, "CALLT", 0, DecodeCALLT);
AddInstTable(InstTable, "BR" , 0, DecodeBR);
AddInstTable(InstTable, "DBNZ" , 0, DecodeDBNZ);
AddInstTable(InstTable, "SEL" , 0, DecodeSEL);
AddFixed("BRK" , 0x00bf); AddFixed("RET" , 0x00af);
AddFixed("RETB" , 0x009f); AddFixed("RETI" , 0x008f);
AddFixed("HALT" , 0x7110); AddFixed("STOP" , 0x7100);
AddFixed("NOP" , 0x0000); AddFixed("EI" , 0x7a1e);
AddFixed("DI" , 0x7b1e); AddFixed("ADJBA", 0x6180);
AddFixed("ADJBS", 0x6190);
InstrZ = 0;
AddAri("ADD" ); AddAri("SUB" ); AddAri("ADDC"); AddAri("SUBC");
AddAri("CMP" ); AddAri("AND" ); AddAri("OR" ); AddAri("XOR" );
InstrZ = 0;
AddAri16("ADDW"); AddAri16("SUBW"); AddAri16("CMPW");
InstrZ = 0;
AddShift("ROR"); AddShift("RORC"); AddShift("ROL"); AddShift("ROLC");
InstrZ = 0;
AddBit2("AND1"); AddBit2("OR1"); AddBit2("XOR1");
InstrZ = 0;
AddRel("BC"); AddRel("BNC"); AddRel("BZ"); AddRel("BNZ");
InstrZ = 0;
AddBRel("BTCLR"); AddBRel("BT"); AddBRel("BF");
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
}
/*-------------------------------------------------------------------------*/
static void MakeCode_78K0(void)
{
CodeLen = 0;
DontPrint = False;
OpSize = 0;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(False)) return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_78K0(void)
{
return False;
}
static void SwitchFrom_78K0(void)
{
DeinitFields();
}
static void SwitchTo_78K0(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "PC";
HeaderID = 0x7c;
NOPCode = 0x00;
DivideChars = ",";
HasAttrs = False;
ValidSegs = 1 << SegCode;
Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
SegLimits[SegCode] = 0xffff;
MakeCode = MakeCode_78K0;
IsDef = IsDef_78K0;
SwitchFrom = SwitchFrom_78K0;
InitFields();
}
void code78k0_init(void)
{
CPU78070 = AddCPU("78070", SwitchTo_78K0);
}