/* code90c141.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator Toshiba TLCS-90 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "nls.h"
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "asmcode.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code90c141.h"
typedef struct
{
const char *Name;
Byte Code;
} Condition;
#define AccReg 6
#define HLReg 2
#define COND_CODE_TRUE 8
enum
{
ModNone = -1,
ModReg8 = 0,
ModReg16 = 1,
ModIReg16 = 2,
ModIndReg = 3,
ModIdxReg = 4,
ModDir = 5,
ModMem = 6,
ModImm = 7
};
#define MModReg8 (1 << ModReg8)
#define MModReg16 (1 << ModReg16)
#define MModIReg16 (1 << ModIReg16)
#define MModIndReg (1 << ModIndReg)
#define MModIdxReg (1 << ModIdxReg)
#define MModDir (1 << ModDir)
#define MModMem (1 << ModMem)
#define MModImm (1 << ModImm)
#define MAssumeInd (1 << 12)
static ShortInt AdrType;
static Byte AdrMode;
static ShortInt OpSize;
static Byte AdrVals[10];
static Boolean MinOneIs0;
static Condition *Conditions;
static CPUVar CPU90C141;
/*---------------------------------------------------------------------------*/
static void SetOpSize(ShortInt New)
{
if (OpSize == -1)
OpSize = New;
else if (OpSize != New)
{
WrError(ErrNum_ConfOpSizes);
AdrType = ModNone;
AdrCnt = 0;
}
}
static void DecodeAdr(const tStrComp *pArg, Word Erl)
{
static const char Reg8Names[][2] = { "B", "C", "D", "E", "H", "L", "A" };
static const int Reg8Cnt = sizeof(Reg8Names) / sizeof(*Reg8Names);
static const char Reg16Names[][3] = { "BC", "DE", "HL", "\0", "IX", "IY", "SP" };
static const int Reg16Cnt = sizeof(Reg16Names) / sizeof(*Reg16Names);
static const char IReg16Names[][3] = {"IX", "IY", "SP" };
static const int IReg16Cnt = sizeof(IReg16Names) / sizeof(*IReg16Names);
int z;
char *p;
LongInt DispAcc, DispVal;
Byte OccFlag, BaseReg;
Boolean ok, fnd, NegFlag, NNegFlag, Unknown, is_indirect;
AdrType = ModNone; AdrCnt = 0;
/* 1. 8-Bit-Register */
for (z = 0; z < Reg8Cnt; z++)
if (!as_strcasecmp(pArg->str.p_str, Reg8Names[z]))
{
AdrType = ModReg8;
AdrMode = z;
SetOpSize(0);
goto chk;
}
/* 2. 16-Bit-Register, indiziert */
if (Erl & MModIReg16)
{
for (z = 0; z < IReg16Cnt; z++)
if (!as_strcasecmp(pArg->str.p_str, IReg16Names[z]))
{
AdrType = ModIReg16;
AdrMode = z;
SetOpSize(1);
goto chk;
}
}
/* 3. 16-Bit-Register, normal */
if (Erl & MModReg16)
{
for (z = 0; z < Reg16Cnt; z++)
if (!as_strcasecmp(pArg->str.p_str, Reg16Names[z]))
{
AdrType = ModReg16;
AdrMode = z;
SetOpSize(1);
goto chk;
}
}
/* Speicheradresse */
is_indirect = IsIndirect(pArg->str.p_str);
if (is_indirect || (Erl & MAssumeInd))
{
tStrComp Arg, Remainder;
OccFlag = 0;
BaseReg = 0;
DispAcc = 0;
ok = True;
NegFlag = False;
Unknown = False;
StrCompRefRight(&Arg, pArg, !!is_indirect);
if (is_indirect)
StrCompShorten(&Arg, 1);
KillPrefBlanksStrCompRef(&Arg);
KillPostBlanksStrComp(&Arg);
do
{
/* Split off one component: */
p = indir_split_pos(Arg.str.p_str);
NNegFlag = p && (*p == '-');
if (p)
StrCompSplitRef(&Arg, &Remainder, &Arg, p);
KillPrefBlanksStrComp(&Arg);
KillPostBlanksStrComp(&Arg);
fnd = False;
if (!as_strcasecmp(Arg.str.p_str, "A"))
{
fnd = True;
ok = ((!NegFlag) && (!(OccFlag & 1)));
if (ok)
OccFlag += 1;
else
WrError(ErrNum_InvAddrMode);
}
if (!fnd)
{
for (z = 0; z < Reg16Cnt; z++)
{
if (!as_strcasecmp(Arg.str.p_str, Reg16Names[z]))
{
fnd = True;
BaseReg = z;
ok = ((!NegFlag) && (!(OccFlag & 2)));
if (ok)
OccFlag += 2;
else
WrError(ErrNum_InvAddrMode);
}
}
}
if (!fnd)
{
tSymbolFlags Flags;
DispVal = EvalStrIntExpressionWithFlags(&Arg, Int32, &ok, &Flags);
if (ok)
{
DispAcc = NegFlag ? DispAcc - DispVal : DispAcc + DispVal;
if (mFirstPassUnknown(Flags))
Unknown = True;
}
}
NegFlag = NNegFlag;
if (p)
Arg = Remainder;
}
while (p && ok);
if (!ok)
return;
if (Unknown)
DispAcc &= 0x7f;
switch (OccFlag)
{
case 1:
WrError(ErrNum_InvAddrMode);
break;
case 3:
if ((BaseReg != 2) || (DispAcc!=0)) WrError(ErrNum_InvAddrMode);
else
{
AdrType = ModIdxReg;
AdrMode = 3;
}
break;
case 2:
if ((DispAcc > 127) || (DispAcc < -128)) WrError(ErrNum_OverRange);
else if (DispAcc == 0)
{
AdrType = ModIndReg;
AdrMode = BaseReg;
}
else if (BaseReg < 4) WrError(ErrNum_InvAddrMode);
else
{
AdrType = ModIdxReg;
AdrMode = BaseReg - 4;
AdrCnt = 1;
AdrVals[0] = DispAcc & 0xff;
}
break;
case 0:
if (DispAcc > 0xffff) WrError(ErrNum_AdrOverflow);
else if ((Hi(DispAcc) == 0xff) && (Erl & MModDir))
{
AdrType = ModDir;
AdrCnt = 1;
AdrVals[0] = Lo(DispAcc);
}
else
{
AdrType = ModMem;
AdrCnt = 2;
AdrVals[0] = Lo(DispAcc);
AdrVals[1] = Hi(DispAcc);
}
break;
}
}
/* immediate */
else
{
if ((OpSize == -1) && (MinOneIs0))
OpSize = 0;
switch (OpSize)
{
case -1:
WrError(ErrNum_InvOpSize);
break;
case 0:
AdrVals[0] = EvalStrIntExpression(pArg, Int8, &ok);
if (ok)
{
AdrType = ModImm;
AdrCnt = 1;
}
break;
case 1:
DispVal = EvalStrIntExpression(pArg, Int16, &ok);
if (ok)
{
AdrType = ModImm;
AdrCnt = 2;
AdrVals[0] = Lo(DispVal);
AdrVals[1] = Hi(DispVal);
}
break;
}
}
/* gefunden */
chk:
if ((AdrType != ModNone) && (!((1 << AdrType) & Erl)))
{
WrError(ErrNum_InvAddrMode);
AdrType = ModNone;
AdrCnt = 0;
}
}
static Boolean ArgPair(const char *Arg1, const char *Arg2)
{
return (((!as_strcasecmp(ArgStr[1].str.p_str, Arg1)) && (!as_strcasecmp(ArgStr[2].str.p_str, Arg2)))
|| ((!as_strcasecmp(ArgStr[1].str.p_str, Arg2)) && (!as_strcasecmp(ArgStr[2].str.p_str, Arg1))));
}
/*!------------------------------------------------------------------------
* \fn decode_condition(const char *p_cond_str, Byte *p_cond_code)
* \brief parse condition code
* \param p_cond_str source argument
* \param p_cond_code returns machine code of condition if found
* \return True if found
* ------------------------------------------------------------------------ */
static Boolean decode_condition(const char *p_cond_str, Byte *p_cond_code)
{
int z;
for (z = 0; Conditions[z].Name; z++)
if (!as_strcasecmp(p_cond_str, Conditions[z].Name))
{
*p_cond_code = Conditions[z].Code;
return True;
}
return False;
}
/*-------------------------------------------------------------------------*/
/* ohne Argument */
static void DecodeFixed(Word Code)
{
if (ChkArgCnt(0, 0))
{
CodeLen = 1;
BAsmCode[0] = Code;
}
}
static void DecodeMove(Word Code)
{
if (ChkArgCnt(0, 0))
{
CodeLen = 2;
BAsmCode[0] = 0xfe;
BAsmCode[1] = Code;
}
}
static void DecodeShift(Word Code)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], (Hi(Code) ? MModReg8 : 0) | MModIndReg | MModIdxReg | MModMem | MModDir);
switch (AdrType)
{
case ModReg8:
CodeLen = 2;
BAsmCode[0] = 0xf8 + AdrMode;
BAsmCode[1] = Lo(Code);
if (AdrMode == AccReg)
WrError(ErrNum_ShortAddrPossible);
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 + AdrMode;
BAsmCode[1] = Lo(Code);
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = Lo(Code);
break;
case ModDir:
CodeLen = 3;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = Lo(Code);
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[3] = Lo(Code);
break;
}
}
}
/* Logik */
static void DecodeBit(Word Code)
{
Byte BitPos;
Boolean OK;
if (ChkArgCnt(2, 2))
{
BitPos = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
if (OK)
{
DecodeAdr(&ArgStr[2], MModReg8 | MModIndReg | MModIdxReg | MModMem | MModDir);
switch (AdrType)
{
case ModReg8:
CodeLen = 2;
BAsmCode[0] = 0xf8 + AdrMode;
BAsmCode[1] = Code + BitPos;
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 + AdrMode;
BAsmCode[1] = Code + BitPos;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[0] = 0xf0 + AdrMode;
BAsmCode[1 + AdrCnt] = Code + BitPos;
break;
case ModMem:
CodeLen = 4;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[0] = 0xe3;
BAsmCode[1 + AdrCnt] = Code + BitPos;
break;
case ModDir:
BAsmCode[1] = AdrVals[0];
if (Code == 0x18)
{
BAsmCode[0] = 0xe7;
BAsmCode[2] = Code + BitPos;
CodeLen = 3;
}
else
{
BAsmCode[0] = Code + BitPos;
CodeLen = 2;
}
break;
}
}
}
}
static void DecodeAcc(Word Code)
{
if (!ChkArgCnt(1, 1));
else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrError(ErrNum_InvAddrMode);
else
{
CodeLen = 1;
BAsmCode[0] = Code;
}
}
static void DecodeALU2(Word Code)
{
Byte HReg;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModIdxReg | MModIndReg | MModDir | MModMem);
switch (AdrType)
{
case ModReg8:
DecodeAdr(&ArgStr[2], MModImm | (((HReg = AdrMode) == AccReg) ? MModReg8 | MModIndReg | MModIdxReg | MModDir | MModMem:0));
switch(AdrType)
{
case ModReg8:
CodeLen = 2;
BAsmCode[0] = 0xf8 | AdrMode;
BAsmCode[1] = 0x60 | Code;
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 | AdrMode; BAsmCode[1] = 0x60 | Code;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 | AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x60 | Code;
break;
case ModDir:
CodeLen = 2;
BAsmCode[0] = 0x60 | Code;
BAsmCode[1] = AdrVals[0];
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
BAsmCode[3] = 0x60 | Code;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
case ModImm:
if (HReg == AccReg)
{
CodeLen = 2;
BAsmCode[0] = 0x68 | Code;
BAsmCode[1] = AdrVals[0];
}
else
{
CodeLen = 3;
BAsmCode[0] = 0xf8 | HReg;
BAsmCode[1] = 0x68 | Code;
BAsmCode[2] = AdrVals[0];
}
break;
}
break;
case ModReg16:
if ((AdrMode == 2) || ((Code == 0) && (AdrMode >= 4)))
{
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg16 | MModIndReg | MModIdxReg | MModDir | MModMem | MModImm);
switch (AdrType)
{
case ModReg16:
CodeLen = 2;
BAsmCode[0] = 0xf8 | AdrMode;
BAsmCode[1] = (HReg >= 4) ? 0x14 + HReg - 4 : 0x70 + Code;
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 | AdrMode;
BAsmCode[1] = (HReg >= 4) ? 0x14 + HReg - 4 : 0x70 + Code;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 | AdrMode;
memcpy(BAsmCode
+ 1,AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = (HReg >= 4) ? 0x14 + HReg - 4 : 0x70 + Code;
break;
case ModDir:
if (HReg >= 4)
{
CodeLen = 3;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = 0x10 | HReg;
}
else
{
CodeLen = 2;
BAsmCode[0] = 0x70 | Code;
BAsmCode[1] = AdrVals[0];
}
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
memcpy(BAsmCode
+ 1, AdrVals
, 2);
BAsmCode[3] = (HReg >= 4) ? 0x14 + HReg - 4 : 0x70 + Code;
break;
case ModImm:
CodeLen = 3;
BAsmCode[0] = (HReg >= 4) ? 0x14 + HReg - 4 : 0x78 + Code;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
}
}
else WrError(ErrNum_InvAddrMode);
break;
case ModIndReg:
case ModIdxReg:
case ModDir:
case ModMem:
OpSize = 0;
switch (AdrType)
{
case ModIndReg:
HReg = 3;
BAsmCode[0] = 0xe8 | AdrMode;
BAsmCode[1] = 0x68 | Code;
break;
case ModIdxReg:
HReg = 3 + AdrCnt;
BAsmCode[0] = 0xf4 | AdrMode;
BAsmCode[1 + AdrCnt] = 0x68 | Code;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
case ModDir:
HReg = 4;
BAsmCode[0] = 0xef;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = 0x68 | Code;
break;
case ModMem:
HReg = 5;
BAsmCode[0] = 0xeb;
memcpy(BAsmCode
+ 1, AdrVals
, 2);
BAsmCode[3] = 0x68 | Code;
break;
default:
HReg = 0;
}
DecodeAdr(&ArgStr[2], MModImm);
if (AdrType == ModImm)
{
BAsmCode[HReg-1] = AdrVals[0];
CodeLen = HReg;
}
break;
}
}
}
static void DecodeLD(Word Code)
{
Byte HReg;
if (Hi(Code))
SetOpSize(1);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModIndReg | MModIdxReg | MModDir | MModMem);
switch (AdrType)
{
case ModReg8:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg8 | MModIndReg | MModIdxReg | MModDir | MModMem | MModImm);
switch (AdrType)
{
case ModReg8:
if (HReg == AccReg)
{
CodeLen = 1;
BAsmCode[0] = 0x20 | AdrMode;
}
else if (AdrMode == AccReg)
{
CodeLen = 1;
BAsmCode[0] = 0x28 | HReg;
}
else
{
CodeLen = 2;
BAsmCode[0] = 0xf8 | AdrMode;
BAsmCode[1] = 0x30 | HReg;
}
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 | AdrMode;
BAsmCode[1] = 0x28 | HReg;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 | AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x28 | HReg;
break;
case ModDir:
if (HReg == AccReg)
{
CodeLen = 2;
BAsmCode[0] = 0x27;
BAsmCode[1] = AdrVals[0];
}
else
{
CodeLen = 3;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = 0x28 | HReg;
}
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[3] = 0x28 | HReg;
break;
case ModImm:
CodeLen = 2;
BAsmCode[0] = 0x30 | HReg;
BAsmCode[1] = AdrVals[0];
break;
}
break;
case ModReg16:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg16 | MModIndReg | MModIdxReg | MModDir | MModMem | MModImm);
switch (AdrType)
{
case ModReg16:
if (HReg == HLReg)
{
CodeLen = 1;
BAsmCode[0] = 0x40 | AdrMode;
}
else if (AdrMode == HLReg)
{
CodeLen = 1;
BAsmCode[0] = 0x48 | HReg;
}
else
{
CodeLen = 2;
BAsmCode[0] = 0xf8 | AdrMode;
BAsmCode[1] = 0x38 | HReg;
}
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 | AdrMode;
BAsmCode[1] = 0x48 | HReg;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 | AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x48 | HReg;
break;
case ModDir:
if (HReg == HLReg)
{
CodeLen = 2;
BAsmCode[0] = 0x47;
BAsmCode[1] = AdrVals[0];
}
else
{
CodeLen = 3;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = 0x48 | HReg;
}
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
BAsmCode[3] = 0x48 | HReg;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
case ModImm:
CodeLen = 3;
BAsmCode[0] = 0x38 | HReg;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
}
break;
case ModIndReg:
case ModIdxReg:
case ModDir:
case ModMem:
MinOneIs0 = True;
HReg = AdrCnt;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
switch (AdrType)
{
case ModIndReg:
BAsmCode[0] = 0xe8 | AdrMode;
break;
case ModIdxReg:
BAsmCode[0] = 0xf4 | AdrMode;
break;
case ModMem:
BAsmCode[0] = 0xeb;
break;
case ModDir:
BAsmCode[0] = 0x0f;
break;
}
DecodeAdr(&ArgStr[2], MModReg16 | MModReg8 | MModImm);
if (BAsmCode[0] == 0x0f)
switch (AdrType)
{
case ModReg8:
if (AdrMode == AccReg)
{
CodeLen = 2;
BAsmCode[0] = 0x2f;
}
else
{
CodeLen = 3;
BAsmCode[0] = 0xef;
BAsmCode[2] = 0x20 | AdrMode;
}
break;
case ModReg16:
if (AdrMode == HLReg)
{
CodeLen = 2;
BAsmCode[0] = 0x4f;
}
else
{
CodeLen = 3;
BAsmCode[0] = 0xef;
BAsmCode[2] = 0x40 | AdrMode;
}
break;
case ModImm:
CodeLen = 3 + OpSize;
BAsmCode[0] = 0x37 | (OpSize << 3);
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
break;
}
else
{
switch (AdrType)
{
case ModReg8:
BAsmCode[1 + HReg] = 0x20 | AdrMode;
break;
case ModReg16:
BAsmCode[1 + HReg] = 0x40 | AdrMode;
break;
case ModImm:
BAsmCode[1 + HReg] = 0x37 | (OpSize << 3);
break;
}
memcpy(BAsmCode
+ 2 + HReg
, AdrVals
, AdrCnt
);
CodeLen = 1 + HReg + 1 + AdrCnt;
}
break;
}
}
}
static void DecodePUSH_POP(Word Code)
{
if (ChkArgCnt(1, 1))
{
if (!as_strcasecmp(ArgStr[1].str.p_str, "AF"))
{
CodeLen = 1;
BAsmCode[0] = 0x56 | Code;
}
else
{
DecodeAdr(&ArgStr[1], MModReg16);
if (AdrType == ModReg16)
{
if (AdrMode == 6) WrError(ErrNum_InvAddrMode);
else
{
CodeLen = 1;
BAsmCode[0] = 0x50 | Code | AdrMode;
}
}
}
}
}
static void DecodeLDA(Word Code)
{
Byte HReg;
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg16);
if (AdrType == ModReg16)
{
HReg = 0x38 + AdrMode;
DecodeAdr(&ArgStr[2], MModIndReg | MModIdxReg | MAssumeInd);
switch (AdrType)
{
case ModIndReg:
if (AdrMode < 4) WrError(ErrNum_InvAddrMode);
else
{
CodeLen = 3;
BAsmCode[0] = 0xf0 | AdrMode;
BAsmCode[1] = 0;
BAsmCode[2] = HReg;
}
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf4 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = HReg;
break;
}
}
}
}
static void DecodeLDAR(Word Code)
{
UNUSED(Code);
if (!ChkArgCnt(2, 2));
else if (as_strcasecmp(ArgStr[1].str.p_str, "HL")) WrError(ErrNum_InvAddrMode);
else
{
Boolean OK;
Integer AdrInt = EvalStrIntExpression(&ArgStr[2], Int16, &OK) - (EProgCounter() + 2);
if (OK)
{
CodeLen = 3;
BAsmCode[0] = 0x17;
BAsmCode[1] = Lo(AdrInt);
BAsmCode[2] = Hi(AdrInt);
}
}
}
static void DecodeEX(Word Code)
{
Byte HReg;
UNUSED(Code);
/* work around the parser problem related to the ' character */
if (!as_strncasecmp(ArgStr[2].str.p_str, "AF\'", 3))
ArgStr[2].str.p_str[3] = '\0';
if (!ChkArgCnt(2, 2));
else if (ArgPair("DE", "HL"))
{
CodeLen = 1;
BAsmCode[0] = 0x08;
}
else if ((ArgPair("AF", "AF\'")) || (ArgPair("AF", "AF`")))
{
CodeLen = 1;
BAsmCode[0] = 0x09;
}
else
{
DecodeAdr(&ArgStr[1], MModReg16 | MModIndReg | MModIdxReg | MModMem | MModDir);
switch (AdrType)
{
case ModReg16:
HReg = 0x50 | AdrMode;
DecodeAdr(&ArgStr[2], MModIndReg | MModIdxReg | MModMem | MModDir);
switch (AdrType)
{
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 | AdrMode;
BAsmCode[1] = HReg;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 | AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = HReg;
break;
case ModDir:
CodeLen = 3;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = HReg;
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[3] = HReg;
break;
}
break;
case ModIndReg:
case ModIdxReg:
case ModDir:
case ModMem:
switch (AdrType)
{
case ModIndReg:
BAsmCode[0] = 0xe0 | AdrMode;
break;
case ModIdxReg:
BAsmCode[0] = 0xf0 | AdrMode;
break;
case ModDir:
BAsmCode[0] = 0xe7;
break;
case ModMem:
BAsmCode[0] = 0xe3;
break;
}
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
HReg = 2 + AdrCnt;
DecodeAdr(&ArgStr[2], MModReg16);
if (AdrType == ModReg16)
{
BAsmCode[HReg - 1] = 0x50 | AdrMode;
CodeLen = HReg;
}
break;
}
}
}
static void DecodeINC_DEC(Word Code)
{
if (Hi(Code))
SetOpSize(1);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModIndReg | MModIdxReg | MModDir | MModMem);
if (OpSize==-1)
OpSize = 0;
switch (AdrType)
{
case ModReg8:
CodeLen = 1;
BAsmCode[0] = 0x80 | Lo(Code) | AdrMode;
break;
case ModReg16:
CodeLen = 1;
BAsmCode[0] = 0x90 | Lo(Code) | AdrMode;
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 | AdrMode;
BAsmCode[1] = 0x87 | (OpSize << 4) | Lo(Code);
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 | AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x87 | (OpSize << 4) | Lo(Code);
break;
case ModDir:
CodeLen = 2;
BAsmCode[0] = 0x87 | (OpSize << 4) | Lo(Code);
BAsmCode[1] = AdrVals[0];
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[3] = 0x87 | (OpSize << 4) | Lo(Code);
BAsmCode[1] = AdrVals[0];
break;
}
}
}
static void DecodeINCX_DECX(Word Code)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModDir);
if (AdrType == ModDir)
{
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] = AdrVals[0];
}
}
}
static void DecodeMUL_DIV(Word Code)
{
if (!ChkArgCnt(2, 2));
else if (as_strcasecmp(ArgStr[1].str.p_str, "HL")) WrError(ErrNum_InvAddrMode);
else
{
OpSize = 0;
DecodeAdr(&ArgStr[2], MModReg8 | MModIndReg | MModIdxReg | MModDir | MModMem | MModImm);
switch (AdrType)
{
case ModReg8:
CodeLen = 2;
BAsmCode[0] = 0xf8 + AdrMode;
BAsmCode[1] = Code;
break;
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe0 + AdrMode;
BAsmCode[1] = Code;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf0 + AdrMode;
BAsmCode[1 + AdrCnt] = Code;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
case ModDir:
CodeLen = 3;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = Code;
break;
case ModMem:
CodeLen = 4;
BAsmCode[0] = 0xe3;
BAsmCode[3] = Code;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
break;
case ModImm:
CodeLen = 2;
BAsmCode[0] = Code;
BAsmCode[1] = AdrVals[0];
break;
}
}
}
static void DecodeJR(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 2))
{
Byte cond_code;
Boolean OK;
tSymbolFlags Flags;
Integer AdrInt;
if (ArgCnt == 1)
cond_code = COND_CODE_TRUE;
else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int16, &OK, &Flags) - (EProgCounter() + 2);
if (OK)
{
if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 2;
BAsmCode[0] = 0xc0 | cond_code;
BAsmCode[1] = AdrInt & 0xff;
}
}
}
}
static void DecodeCALL_JP(Word Code)
{
if (ChkArgCnt(1, 2))
{
Byte cond_code;
if (ArgCnt == 1)
cond_code = COND_CODE_TRUE;
else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
OpSize = 1;
DecodeAdr(&ArgStr[ArgCnt], MModIndReg | MModIdxReg | MModMem | MAssumeInd);
switch (AdrType)
{
case ModIndReg:
CodeLen = 2;
BAsmCode[0] = 0xe8 | AdrMode;
BAsmCode[1] = 0xc0 | (Code << 4) | cond_code;
break;
case ModIdxReg:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xf4 | AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0xc0 | (Code << 4) | cond_code;
break;
case ModMem:
if (cond_code == COND_CODE_TRUE)
{
CodeLen = 3;
BAsmCode[0] = 0x1a + (Code << 1);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
}
else
{
CodeLen = 4;
BAsmCode[0] = 0xeb;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[3] = 0xc0 | (Code << 4) | cond_code;
}
break;
}
}
}
static void DecodeRET(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(0, 1))
{
Byte cond_code;
if (ArgCnt == 0)
cond_code = COND_CODE_TRUE;
else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
if (cond_code == COND_CODE_TRUE)
{
CodeLen = 1;
BAsmCode[0] = 0x1e;
}
else
{
CodeLen = 2;
BAsmCode[0] = 0xfe;
BAsmCode[1] = 0xd0 | cond_code;
}
}
}
static void DecodeDJNZ(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 2))
{
if (ArgCnt == 1)
{
AdrType = ModReg8;
AdrMode = 0;
OpSize = 0;
}
else
DecodeAdr(&ArgStr[1], MModReg8 | MModReg16);
if (AdrType != ModNone)
{
if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
else
{
Boolean OK;
tSymbolFlags Flags;
Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int16, &OK, &Flags) - (EProgCounter() + 2);
if (OK)
{
if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128))) WrError(ErrNum_JmpDistTooBig);
else
{
CodeLen = 2;
BAsmCode[0] = 0x18 | OpSize;
BAsmCode[1] = AdrInt & 0xff;
}
}
}
}
}
}
static void DecodeJRL_CALR(Word Code)
{
if (ChkArgCnt(1, 1))
{
Boolean OK;
Integer AdrInt = EvalStrIntExpression(&ArgStr[1], Int16, &OK) - (EProgCounter() + 2);
if (OK)
{
CodeLen = 3;
BAsmCode[0] = Code;
if ((Code == 0x1b)
&& (AdrInt >= -128)
&& (AdrInt <= 127))
WrError(ErrNum_ShortJumpPossible);
BAsmCode[1] = Lo(AdrInt);
BAsmCode[2] = Hi(AdrInt);
}
}
}
/*-------------------------------------------------------------------------*/
static void AddW(const char *Name, Word Code, InstProc Proc)
{
char Str[20];
AddInstTable(InstTable, Name, Code, Proc);
as_snprintf(Str, sizeof(Str), "%sW", Name);
AddInstTable(InstTable, Str, Code | 0x100, Proc);
}
static void AddFixed(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFixed);
}
static void AddMove(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMove);
}
static void AddShift(const char *NName, Word NCode, Boolean NMay)
{
AddInstTable(InstTable, NName, NCode | (NMay ? 0x100 : 0), DecodeShift);
}
static void AddBit(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBit);
}
static void AddAcc(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeAcc);
}
static void AddCondition(const char *NName, Byte NCode)
{
order_array_rsv_end(Conditions, Condition);
Conditions[InstrZ].Name = NName;
Conditions[InstrZ++].Code = NCode;
}
static void InitFields(void)
{
InstTable = CreateInstTable(207);
SetDynamicInstTable(InstTable);
AddW("LD", 0, DecodeLD);
AddInstTable(InstTable, "PUSH", 0, DecodePUSH_POP);
AddInstTable(InstTable, "POP" , 8, DecodePUSH_POP);
AddInstTable(InstTable, "LDA", 0, DecodeLDA);
AddInstTable(InstTable, "LDAR", 0, DecodeLDAR);
AddInstTable(InstTable, "EX", 0, DecodeEX);
AddW("INC", 0, DecodeINC_DEC);
AddW("DEC", 8, DecodeINC_DEC);
AddInstTable(InstTable, "INCX", 0x07, DecodeINCX_DECX);
AddInstTable(InstTable, "DECX", 0x0f, DecodeINCX_DECX);
AddInstTable(InstTable, "MUL", 0x12, DecodeMUL_DIV);
AddInstTable(InstTable, "DIV", 0x13, DecodeMUL_DIV);
AddInstTable(InstTable, "JR", 0, DecodeJR);
AddInstTable(InstTable, "CALL", 1, DecodeCALL_JP);
AddInstTable(InstTable, "JP", 0, DecodeCALL_JP);
AddInstTable(InstTable, "RET", 0, DecodeRET);
AddInstTable(InstTable, "DJNZ", 0, DecodeDJNZ);
AddInstTable(InstTable, "JRL", 0x1b, DecodeJRL_CALR);
AddInstTable(InstTable, "CALR", 0x1d, DecodeJRL_CALR);
AddFixed("EXX" , 0x0a); AddFixed("CCF" , 0x0e);
AddFixed("SCF" , 0x0d); AddFixed("RCF" , 0x0c);
AddFixed("NOP" , 0x00); AddFixed("HALT", 0x01);
AddFixed("DI" , 0x02); AddFixed("EI" , 0x03);
AddFixed("SWI" , 0xff); AddFixed("RLCA", 0xa0);
AddFixed("RRCA", 0xa1); AddFixed("RLA" , 0xa2);
AddFixed("RRA" , 0xa3); AddFixed("SLAA", 0xa4);
AddFixed("SRAA", 0xa5); AddFixed("SLLA", 0xa6);
AddFixed("SRLA", 0xa7); AddFixed("RETI", 0x1f);
AddMove("LDI" , 0x58);
AddMove("LDIR", 0x59);
AddMove("LDD" , 0x5a);
AddMove("LDDR", 0x5b);
AddMove("CPI" , 0x5c);
AddMove("CPIR", 0x5d);
AddMove("CPD" , 0x5e);
AddMove("CPDR", 0x5f);
AddShift("RLC", 0xa0, True );
AddShift("RRC", 0xa1, True );
AddShift("RL" , 0xa2, True );
AddShift("RR" , 0xa3, True );
AddShift("SLA", 0xa4, True );
AddShift("SRA", 0xa5, True );
AddShift("SLL", 0xa6, True );
AddShift("SRL", 0xa7, True );
AddShift("RLD", 0x10, False);
AddShift("RRD", 0x11, False);
AddBit("BIT" , 0xa8);
AddBit("SET" , 0xb8);
AddBit("RES" , 0xb0);
AddBit("TSET", 0x18);
AddAcc("DAA", 0x0b);
AddAcc("CPL", 0x10);
AddAcc("NEG", 0x11);
InstrZ = 0;
AddInstTable(InstTable, "ADD", InstrZ++, DecodeALU2);
AddInstTable(InstTable, "ADC", InstrZ++, DecodeALU2);
AddInstTable(InstTable, "SUB", InstrZ++, DecodeALU2);
AddInstTable(InstTable, "SBC", InstrZ++, DecodeALU2);
AddInstTable(InstTable, "AND", InstrZ++, DecodeALU2);
AddInstTable(InstTable, "XOR", InstrZ++, DecodeALU2);
AddInstTable(InstTable, "OR" , InstrZ++, DecodeALU2);
AddInstTable(InstTable, "CP" , InstrZ++, DecodeALU2);
InstrZ = 0;
AddCondition("F" , 0); AddCondition("T" , COND_CODE_TRUE);
AddCondition("Z" , 6); AddCondition("NZ" , 14);
AddCondition("C" , 7); AddCondition("NC" , 15);
AddCondition("PL" , 13); AddCondition("MI" , 5);
AddCondition("P" , 13); AddCondition("M" , 5);
AddCondition("NE" , 14); AddCondition("EQ" , 6);
AddCondition("OV" , 4); AddCondition("NOV", 12);
AddCondition("PE" , 4); AddCondition("PO" , 12);
AddCondition("GE" , 9); AddCondition("LT" , 1);
AddCondition("GT" , 10); AddCondition("LE" , 2);
AddCondition("UGE", 15); AddCondition("ULT", 7);
AddCondition("UGT", 11); AddCondition("ULE", 3);
AddCondition(NULL , 0);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
order_array_free(Conditions);
}
static void MakeCode_90C141(void)
{
CodeLen = 0; DontPrint = False; OpSize = -1;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(False)) return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*-------------------------------------------------------------------------*/
static Boolean IsDef_90C141(void)
{
return False;
}
static void SwitchFrom_90C141(void)
{
DeinitFields();
}
static Boolean ChkMoreOneArg(void)
{
return (ArgCnt > 1);
}
static void SwitchTo_90C141(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
SetIsOccupiedFnc = ChkMoreOneArg;
PCSymbol = "$";
HeaderID = 0x53;
NOPCode = 0x00;
DivideChars = ",";
HasAttrs = False;
ValidSegs = 1 << SegCode;
Grans[SegCode] = 1;
ListGrans[SegCode] = 1;
SegInits[SegCode] = 0;
SegLimits[SegCode] = 0xffff;
MakeCode = MakeCode_90C141;
IsDef = IsDef_90C141;
SwitchFrom = SwitchFrom_90C141;
InitFields();
}
void code90c141_init(void)
{
CPU90C141 = AddCPU("90C141", SwitchTo_90C141);
}