/* code96c141.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator TLCS-900(L) */
/* */
/* Historie: 27. 6.1996 Grundsteinlegung */
/* */
/*****************************************************************************/
#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 "asmallg.h"
#include "onoff_common.h"
#include "errmsg.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "asmitree.h"
#include "asmcode.h"
#include "codevars.h"
#include "errmsg.h"
#include "code96c141.h"
/*-------------------------------------------------------------------------*/
/* Daten */
typedef struct
{
Word Code;
Byte CPUFlag;
Boolean InSup;
} FixedOrder;
typedef struct
{
Word Code;
Boolean InSup;
Byte MinMax,MaxMax;
ShortInt Default;
} ImmOrder;
typedef struct
{
Word Code;
Byte OpMask;
} RegOrder;
typedef struct
{
const char *Name;
Byte Code;
} Condition;
#define ModNone (-1)
#define ModReg 0
#define MModReg (1 << ModReg)
#define ModXReg 1
#define MModXReg (1 << ModXReg)
#define ModMem 2
#define MModMem (1 << ModMem)
#define ModImm 3
#define MModImm (1 << ModImm)
#define ModCReg 4
#define MModCReg (1 << ModCReg)
#define COND_CODE_TRUE 8
static FixedOrder *FixedOrders;
static RegOrder *RegOrders;
static ImmOrder *ImmOrders;
static Condition *Conditions;
static ShortInt AdrType;
static ShortInt OpSize; /* -1/0/1/2 = nix/Byte/Word/Long */
static Byte AdrMode;
static Byte AdrVals[10];
static Boolean MinOneIs0, AutoIncSizeNeeded;
static CPUVar CPU96C141,CPU93C141;
/*---------------------------------------------------------------------------*/
/* Adressparser */
static Boolean IsRegBase(Byte No, Byte Size)
{
return ((Size == 2)
|| ((Size == 1) && (No < 0xf0) && (!MaxMode) && ((No & 3) == 0)));
}
static void ChkMaxMode(Boolean MustMax, Byte *Result)
{
if (MaxMode != MustMax)
{
*Result = 1;
WrError((MustMax) ? ErrNum_OnlyInMaxmode : ErrNum_NotInMaxmode);
}
}
static Boolean IsQuot(char Ch)
{
return ((Ch == '\'') || (Ch == '`'));
}
static Byte CodeEReg(char *Asc, Byte *ErgNo, Byte *ErgSize)
{
#define RegCnt 8
static const char Reg8Names[RegCnt + 1] = "AWCBEDLH";
static const char Reg16Names[RegCnt][3] =
{
"WA" ,"BC" ,"DE" ,"HL" ,"IX" ,"IY" ,"IZ" ,"SP"
};
static const char Reg32Names[RegCnt][4] =
{
"XWA","XBC","XDE","XHL","XIX","XIY","XIZ","XSP"
};
const char *pos;
String HAsc, Asc_N;
Byte Result;
strmaxcpy(Asc_N, Asc, STRINGSIZE);
NLS_UpString(Asc_N);
Asc = Asc_N;
Result = 2;
/* mom. Bank ? */
if (l == 1)
{
pos
= strchr(Reg8Names
, *Asc
);
if (pos)
{
z = pos - Reg8Names;
*ErgNo = 0xe0 + ((z & 6) << 1) + (z & 1);
*ErgSize = 0;
return Result;
}
}
for (z = 0; z < RegCnt; z++)
{
if (!strcmp(Asc
, Reg16Names
[z
]))
{
*ErgNo = 0xe0 + (z << 2);
*ErgSize = 1;
return Result;
}
if (!strcmp(Asc
, Reg32Names
[z
]))
{
*ErgNo = 0xe0 + (z << 2);
*ErgSize = 2;
if (z < 4)
ChkMaxMode(True, &Result);
return Result;
}
}
/* Bankregister, 8 Bit ? */
if ((l == 3) && ((*Asc == 'Q') || (*Asc == 'R')) && ((Asc[2] >= '0') && (Asc[2] <= '7')))
{
for (z = 0; z < RegCnt; z++)
if (Asc[1] == Reg8Names[z])
{
*ErgNo = ((Asc[2] - '0') << 4) + ((z & 6) << 1) + (z & 1);
if (*Asc == 'Q')
{
*ErgNo |= 2;
ChkMaxMode(True, &Result);
}
if (((*Asc == 'Q') || (MaxMode)) && (Asc[2] > '3'))
{
WrError(ErrNum_OverRange);
Result = 1;
}
*ErgSize = 0;
return Result;
}
}
/* Bankregister, 16 Bit ? */
if ((l == 4) && ((*Asc == 'Q') || (*Asc == 'R')) && ((Asc[3] >= '0') && (Asc[3] <= '7')))
{
HAsc[2] = '\0';
for (z = 0; z < RegCnt >> 1; z++)
if (!strcmp(HAsc
, Reg16Names
[z
]))
{
*ErgNo = ((Asc[3] - '0') << 4) + (z << 2);
if (*Asc == 'Q')
{
*ErgNo |= 2;
ChkMaxMode(True, &Result);
}
if (((*Asc == 'Q') || (MaxMode)) && (Asc[3] > '3'))
{
WrError(ErrNum_OverRange);
Result = 1;
}
*ErgSize = 1;
return Result;
}
}
/* Bankregister, 32 Bit ? */
if ((l == 4) && ((Asc[3] >= '0') && (Asc[3] <= '7')))
{
for (z = 0; z < RegCnt >> 1; z++)
if (strncmp(Asc
, Reg32Names
[z
], 3) == 0)
{
*ErgNo = ((Asc[3] - '0') << 4) + (z << 2);
ChkMaxMode(True, &Result);
if (Asc[3] > '3')
{
WrError(ErrNum_OverRange); Result = 1;
}
*ErgSize = 2;
return Result;
}
}
/* obere 8-Bit-Haelften momentaner Bank ? */
if ((l == 2) && (*Asc == 'Q'))
for (z = 0; z < RegCnt; z++)
if (Asc[1] == Reg8Names[z])
{
*ErgNo = 0xe2 + ((z & 6) << 1) + (z & 1);
ChkMaxMode(True, &Result);
*ErgSize = 0;
return Result;
}
/* obere 16-Bit-Haelften momentaner Bank und von XIX..XSP ? */
if ((l == 3) && (*Asc == 'Q'))
{
for (z = 0; z < RegCnt; z++)
if (!strcmp(Asc
+ 1, Reg16Names
[z
]))
{
*ErgNo = 0xe2 + (z << 2);
if (z < 4) ChkMaxMode(True, &Result);
*ErgSize = 1;
return Result;
}
}
/* 8-Bit-Teile von XIX..XSP ? */
if (((l == 3) || ((l == 4) && (*Asc == 'Q')))
&& ((Asc[l - 1] == 'L') || (Asc[l - 1] == 'H')))
{
strcpy(HAsc
, Asc
+ (l
- 3)); HAsc
[2] = '\0';
for (z = 0; z < RegCnt >> 1; z++)
if (!strcmp(HAsc
, Reg16Names
[z
+ 4]))
{
*ErgNo = 0xf0 + (z << 2) + ((l - 3) << 1) + (Ord(Asc[l - 1] == 'H'));
*ErgSize = 0;
return Result;
}
}
/* 8-Bit-Teile vorheriger Bank ? */
if (((l == 2) || ((l == 3) && (*Asc == 'Q'))) && (IsQuot(Asc[l - 1])))
for (z = 0; z < RegCnt; z++)
if (Asc[l - 2] == Reg8Names[z])
{
*ErgNo
= 0xd0 + ((z
& 6) << 1) + ((strlen(Asc
) - 2) << 1) + (z
& 1);
if (l == 3) ChkMaxMode(True, &Result);
*ErgSize = 0;
return Result;
}
/* 16-Bit-Teile vorheriger Bank ? */
if (((l == 3) || ((l == 4) && (*Asc == 'Q'))) && (IsQuot(Asc[l - 1])))
{
HAsc[l - 2] = '\0';
for (z = 0; z < RegCnt >> 1; z++)
if (!strcmp(HAsc
, Reg16Names
[z
]))
{
*ErgNo
= 0xd0 + (z
<< 2) + ((strlen(Asc
) - 3) << 1);
if (l == 4) ChkMaxMode(True, &Result);
*ErgSize = 1;
return Result;
}
}
/* 32-Bit-Register vorheriger Bank ? */
if ((l == 4) && (IsQuot(Asc[3])))
{
strcpy(HAsc
, Asc
); HAsc
[3] = '\0';
for (z = 0; z < RegCnt >> 1; z++)
if (!strcmp(HAsc
, Reg32Names
[z
]))
{
*ErgNo = 0xd0 + (z << 2);
ChkMaxMode(True, &Result);
*ErgSize = 2;
return Result;
}
}
return (Result = 0);
}
static void ChkL(CPUVar Must, Byte *Result)
{
if (MomCPU != Must)
{
WrError(ErrNum_InvCtrlReg);
*Result = 0;
}
}
static Byte CodeCReg(char *Asc, Byte *ErgNo, Byte *ErgSize)
{
Byte Result = 2;
if (!as_strcasecmp(Asc, "NSP"))
{
*ErgNo = 0x3c;
*ErgSize = 1;
ChkL(CPU96C141, &Result);
return Result;
}
if (!as_strcasecmp(Asc, "XNSP"))
{
*ErgNo = 0x3c;
*ErgSize = 2;
ChkL(CPU96C141, &Result);
return Result;
}
if (!as_strcasecmp(Asc,"INTNEST"))
{
*ErgNo = 0x3c;
*ErgSize = 1;
ChkL(CPU93C141, &Result);
return Result;
}
&& (!as_strncasecmp(Asc, "DMA", 3))
&& (Asc[4] >= '0') && (Asc[4] <= '3'))
{
switch (as_toupper(Asc[3]))
{
case 'S':
*ErgNo = (Asc[4] - '0') * 4;
*ErgSize = 2;
return Result;
case 'D':
*ErgNo = (Asc[4] - '0') * 4 + 0x10;
*ErgSize = 2;
return Result;
case 'M':
*ErgNo = (Asc[4] - '0') * 4 + 0x22;
*ErgSize = 0;
return Result;
case 'C':
*ErgNo = (Asc[4] - '0') * 4 + 0x20;
*ErgSize = 1;
return Result;
}
}
return (Result = 0);
}
typedef struct
{
char *Name;
Byte Num;
Boolean InMax, InMin;
} RegDesc;
static void SetOpSize(ShortInt NewSize)
{
if (OpSize == -1)
OpSize = NewSize;
else if (OpSize != NewSize)
{
WrError(ErrNum_ConfOpSizes);
AdrType = ModNone;
}
}
static Boolean IsRegCurrent(Byte No, Byte Size, Byte *Erg)
{
switch (Size)
{
case 0:
if ((No & 0xf2) == 0xe0)
{
*Erg = ((No & 0x0c) >> 1) + ((No & 1) ^ 1);
return True;
}
else
return False;
case 1:
case 2:
if ((No & 0xe3) == 0xe0)
{
*Erg = ((No & 0x1c) >> 2);
return True;
}
else
return False;
default:
return False;
}
}
static const char Sizes[] = "124";
static Boolean GetPostInc(const char *pArg, int ArgLen, ShortInt *pOpSize, int *pCutoffRight)
{
const char *pPos;
/* <reg>+ */
if ((ArgLen > 2) && (pArg[ArgLen - 1] == '+'))
{
*pOpSize = eSymbolSizeUnknown;
*pCutoffRight = 1;
return True;
}
/* <reg>++n, <reg>+:n */
if ((ArgLen
> 4) && (pArg
[ArgLen
- 3] == '+') && strchr(":+", pArg
[ArgLen
- 2]))
{
pPos
= strchr(Sizes
, pArg
[ArgLen
- 1]);
if (pPos)
{
*pOpSize = pPos - Sizes;
*pCutoffRight = 3;
return True;
}
}
return False;
}
static Boolean GetPreDec(const char *pArg, int ArgLen, ShortInt *pOpSize, int *pCutoffLeft, int *pCutoffRight)
{
const char *pPos;
/* n--<reg> */
if ((ArgLen > 4) && (pArg[1] == '-') && (pArg[2] == '-'))
{
pPos
= strchr(Sizes
, pArg
[0]);
if (pPos)
{
*pOpSize = pPos - Sizes;
*pCutoffLeft = 3;
*pCutoffRight = 0;
return True;
}
}
if ((ArgLen > 2) && (pArg[0] == '-'))
{
*pCutoffLeft = 1;
/* -<reg>:n */
if ((ArgLen > 4) && (pArg[ArgLen - 2] == ':'))
{
pPos
= strchr(Sizes
, pArg
[ArgLen
- 1]);
if (pPos)
{
*pOpSize = pPos - Sizes;
*pCutoffRight = 2;
return True;
}
}
/* -<reg> */
else
{
*pOpSize = eSymbolSizeUnknown;
*pCutoffRight = 0;
return True;
}
}
return False;
}
static void ChkAdr(Byte Erl)
{
if (AdrType != ModNone)
if (!(Erl & (1 << AdrType)))
{
WrError(ErrNum_InvAddrMode);
AdrType = ModNone;
}
}
static tSymbolSize SplitSize(tStrComp *pArg)
{
int l
= strlen(pArg
->str.
p_str);
if ((l
>= 3) && !strcmp(pArg
->str.
p_str + l
- 2, ":8"))
{
StrCompShorten(pArg, 2);
return eSymbolSize8Bit;
}
if ((l
>= 4) && !strcmp(pArg
->str.
p_str + l
- 3, ":16"))
{
StrCompShorten(pArg, 3);
return eSymbolSize16Bit;
}
if ((l
>= 4) && !strcmp(pArg
->str.
p_str + l
- 3, ":24"))
{
StrCompShorten(pArg, 3);
return eSymbolSize24Bit;
}
return eSymbolSizeUnknown;
}
static void DecodeAdrMem(const tStrComp *pArg)
{
LongInt DispPart, DispAcc;
char *EPos;
tStrComp Arg, Remainder;
Boolean NegFlag, NNegFlag, FirstFlag, OK;
Byte BaseReg, BaseSize;
Byte IndReg, IndSize;
Byte PartMask;
Byte HNum, HSize;
int CutoffLeft
, CutoffRight
, ArgLen
= strlen(pArg
->str.
p_str);
ShortInt IncOpSize;
tSymbolSize DispSize;
NegFlag = False;
NNegFlag = False;
FirstFlag = False;
PartMask = 0;
DispAcc = 0;
BaseReg = IndReg = BaseSize = IndSize = 0xff;
AdrType = ModNone;
AutoIncSizeNeeded = False;
/* post-increment */
if ((ArgLen > 2)
&& GetPostInc(pArg->str.p_str, ArgLen, &IncOpSize, &CutoffRight))
{
String Reg;
tStrComp RegComp;
StrCompMkTemp(&RegComp, Reg, sizeof(Reg));
StrCompCopy(&RegComp, pArg);
StrCompShorten(&RegComp, CutoffRight);
if (CodeEReg(RegComp.str.p_str, &HNum, &HSize) == 2)
{
if (!IsRegBase(HNum, HSize)) WrStrErrorPos(ErrNum_InvAddrMode, &RegComp);
else
{
if (IncOpSize == eSymbolSizeUnknown)
IncOpSize = OpSize;
AdrType = ModMem;
AdrMode = 0x45;
AdrCnt = 1;
AdrVals[0] = HNum;
if (IncOpSize == eSymbolSizeUnknown)
AutoIncSizeNeeded = True;
else
AdrVals[0] += IncOpSize;
}
return;
}
}
/* pre-decrement ? */
if ((ArgLen > 2)
&& GetPreDec(pArg->str.p_str, ArgLen, &IncOpSize, &CutoffLeft, &CutoffRight))
{
String Reg;
tStrComp RegComp;
StrCompMkTemp(&RegComp, Reg, sizeof(Reg));
StrCompCopySub(&RegComp, pArg, CutoffLeft, ArgLen - CutoffLeft - CutoffRight);
if (CodeEReg(RegComp.str.p_str, &HNum, &HSize) == 2)
{
if (!IsRegBase(HNum, HSize)) WrError(ErrNum_InvAddrMode);
else
{
if (IncOpSize == eSymbolSizeUnknown)
IncOpSize = OpSize;
AdrType = ModMem;
AdrMode = 0x44;
AdrCnt = 1;
AdrVals[0] = HNum;
if (IncOpSize == eSymbolSizeUnknown)
AutoIncSizeNeeded = True;
else
AdrVals[0] += IncOpSize;
}
return;
}
}
Arg = *pArg;
DispSize = eSymbolSizeUnknown;
do
{
/* Split off one component: */
EPos = indir_split_pos(Arg.str.p_str);
NNegFlag = EPos && (*EPos == '-');
if ((EPos
== Arg.
str.
p_str) || (EPos
== Arg.
str.
p_str + strlen(Arg.
str.
p_str) - 1))
{
WrError(ErrNum_InvAddrMode);
return;
}
if (EPos)
StrCompSplitRef(&Arg, &Remainder, &Arg, EPos);
KillPrefBlanksStrComp(&Arg);
KillPostBlanksStrComp(&Arg);
switch (CodeEReg(Arg.str.p_str, &HNum, &HSize))
{
case 0:
{
tSymbolSize ThisSize;
tSymbolFlags Flags;
if ((ThisSize = SplitSize(&Arg)) != eSymbolSizeUnknown)
if (ThisSize > DispSize)
DispSize = ThisSize;
DispPart = EvalStrIntExpressionWithFlags(&Arg, Int32, &OK, &Flags);
if (mFirstPassUnknown(Flags)) FirstFlag = True;
if (!OK) return;
if (NegFlag)
DispAcc -= DispPart;
else
DispAcc += DispPart;
PartMask |= 1;
break;
}
case 1:
break;
case 2:
if (NegFlag)
{
WrError(ErrNum_InvAddrMode); return;
}
else
{
Boolean MustInd;
if (HSize == 0)
MustInd = True;
else if (HSize == 2)
MustInd = False;
else if (!IsRegBase(HNum, HSize))
MustInd = True;
else if (PartMask & 4)
MustInd = True;
else
MustInd = False;
if (MustInd)
{
if (PartMask & 2)
{
WrError(ErrNum_InvAddrMode); return;
}
else
{
IndReg = HNum;
PartMask |= 2;
IndSize = HSize;
}
}
else
{
if (PartMask & 4)
{
WrError(ErrNum_InvAddrMode); return;
}
else
{
BaseReg = HNum;
PartMask |= 4;
BaseSize = HSize;
}
}
}
break;
}
NegFlag = NNegFlag;
NNegFlag = False;
if (EPos)
Arg = Remainder;
}
while (EPos);
/* auto-deduce address/displacement size? */
if (DispSize == eSymbolSizeUnknown)
{
switch (PartMask)
{
case 1:
if (DispAcc <= 0xff)
DispSize = eSymbolSize8Bit;
else if (DispAcc < 0xffff)
DispSize = eSymbolSize16Bit;
else
DispSize = eSymbolSize24Bit;
break;
case 5:
if (!DispAcc)
PartMask &= ~1;
else if (RangeCheck(DispAcc, SInt8) && IsRegCurrent(BaseReg, BaseSize, &AdrMode))
DispSize = eSymbolSize8Bit;
else
DispSize = eSymbolSize16Bit;
break;
}
}
switch (PartMask)
{
case 0:
case 2:
case 3:
case 7:
WrError(ErrNum_InvAddrMode);
break;
case 1:
switch (DispSize)
{
case eSymbolSize8Bit:
if (FirstFlag)
DispAcc &= 0xff;
if (DispAcc > 0xff) WrError(ErrNum_AdrOverflow);
else
{
AdrType = ModMem;
AdrMode = 0x40;
AdrCnt = 1;
AdrVals[0] = DispAcc;
}
break;
case eSymbolSize16Bit:
if (FirstFlag)
DispAcc &= 0xffff;
if (DispAcc > 0xffff) WrError(ErrNum_AdrOverflow);
else
{
AdrType = ModMem;
AdrMode = 0x41;
AdrCnt = 2;
AdrVals[0] = Lo(DispAcc);
AdrVals[1] = Hi(DispAcc);
}
break;
case eSymbolSize24Bit:
if (FirstFlag)
DispAcc &= 0xffffff;
if (DispAcc > 0xffffff) WrError(ErrNum_AdrOverflow);
else
{
AdrType = ModMem;
AdrMode = 0x42;
AdrCnt = 3;
AdrVals[0] = DispAcc & 0xff;
AdrVals[1] = (DispAcc >> 8) & 0xff;
AdrVals[2] = (DispAcc >> 16) & 0xff;
}
break;
default:
break; /* assert(0)? */
}
break;
case 4:
if (IsRegCurrent(BaseReg, BaseSize, &AdrMode))
{
AdrType = ModMem;
AdrCnt = 0;
}
else
{
AdrType = ModMem;
AdrMode = 0x43;
AdrCnt = 1;
AdrVals[0] = BaseReg;
}
break;
case 5:
switch (DispSize)
{
case eSymbolSize8Bit:
if (FirstFlag)
DispAcc &= 0x7f;
if (!IsRegCurrent(BaseReg, BaseSize, &AdrMode)) WrError(ErrNum_InvAddrMode);
else if (ChkRange(DispAcc, -128, 127))
{
AdrType = ModMem;
AdrMode += 8;
AdrCnt = 1;
AdrVals[0] = DispAcc & 0xff;
}
break;
case eSymbolSize16Bit:
if (FirstFlag)
DispAcc &= 0x7fff;
if (ChkRange(DispAcc, -32768, 32767))
{
AdrType = ModMem;
AdrMode = 0x43;
AdrCnt = 3;
AdrVals[0] = BaseReg + 1;
AdrVals[1] = DispAcc & 0xff;
AdrVals[2] = (DispAcc >> 8) & 0xff;
}
break;
case eSymbolSize24Bit:
WrError(ErrNum_InvAddrMode);
break;
default:
break; /* assert(0)? */
}
break;
case 6:
AdrType = ModMem;
AdrMode = 0x43;
AdrCnt = 3;
AdrVals[0] = 3 + (IndSize << 2);
AdrVals[1] = BaseReg;
AdrVals[2] = IndReg;
break;
}
}
static void DecodeAdr(const tStrComp *pArg, Byte Erl)
{
Byte HNum, HSize;
LongInt DispAcc;
Boolean OK;
AdrType = ModNone;
AutoIncSizeNeeded = False;
/* Register ? */
switch (CodeEReg(pArg->str.p_str, &HNum, &HSize))
{
case 1:
ChkAdr(Erl);
return;
case 2:
if (IsRegCurrent(HNum, HSize, &AdrMode))
AdrType = ModReg;
else
{
AdrType = ModXReg;
AdrMode = HNum;
}
SetOpSize(HSize);
ChkAdr(Erl);
return;
}
/* Steuerregister ? */
if (CodeCReg(pArg->str.p_str, &HNum, &HSize) == 2)
{
AdrType = ModCReg;
AdrMode = HNum;
SetOpSize(HSize);
ChkAdr(Erl);
return;
}
/* Speicheroperand ? */
if (IsIndirect(pArg->str.p_str))
{
tStrComp Arg;
StrCompRefRight(&Arg, pArg, 1);
StrCompShorten(&Arg, 1);
KillPrefBlanksStrCompRef(&Arg);
KillPostBlanksStrComp(&Arg);
DecodeAdrMem(&Arg);
ChkAdr(Erl); return;
}
/* bleibt nur noch immediate... */
if ((MinOneIs0) && (OpSize == -1))
OpSize = 0;
switch (OpSize)
{
case -1:
WrError(ErrNum_UndefOpSizes);
break;
case 0:
AdrVals[0] = EvalStrIntExpression(pArg, Int8, &OK);
if (OK)
{
AdrType = ModImm;
AdrCnt = 1;
}
break;
case 1:
DispAcc = EvalStrIntExpression(pArg, Int16, &OK);
if (OK)
{
AdrType = ModImm;
AdrCnt = 2;
AdrVals[0] = Lo(DispAcc);
AdrVals[1] = Hi(DispAcc);
}
break;
case 2:
DispAcc = EvalStrIntExpression(pArg, Int32, &OK);
if (OK)
{
AdrType = ModImm;
AdrCnt = 4;
AdrVals[0] = Lo(DispAcc);
AdrVals[1] = Hi(DispAcc);
AdrVals[2] = Lo(DispAcc >> 16);
AdrVals[3] = Hi(DispAcc >> 16);
}
break;
}
}
/*---------------------------------------------------------------------------*/
static void SetAutoIncSize(Byte AdrModePos, Byte FixupPos)
{
if ((BAsmCode[AdrModePos] & 0x4e) == 0x44)
BAsmCode[FixupPos] = (BAsmCode[FixupPos] & 0xfc) | OpSize;
}
static Boolean ArgPair(const char *Val1, const char *Val2)
{
return (((!as_strcasecmp(ArgStr[1].str.p_str, Val1)) && (!as_strcasecmp(ArgStr[2].str.p_str, Val2)))
|| ((!as_strcasecmp(ArgStr[1].str.p_str, Val2)) && (!as_strcasecmp(ArgStr[2].str.p_str, Val1))));
}
static LongInt ImmVal(void)
{
LongInt tmp;
tmp = AdrVals[0];
if (OpSize >= 1)
tmp += ((LongInt)AdrVals[1]) << 8;
if (OpSize == 2)
{
tmp += ((LongInt)AdrVals[2]) << 16;
tmp += ((LongInt)AdrVals[3]) << 24;
}
return tmp;
}
static Boolean IsPwr2(LongInt Inp, Byte *Erg)
{
LongInt Shift;
Shift = 1;
*Erg = 0;
do
{
if (Inp == Shift)
return True;
Shift += Shift;
(*Erg)++;
}
while (Shift != 0);
return False;
}
static Boolean IsShort(Byte Code)
{
return ((Code & 0x4e) == 0x40);
}
static void CheckSup(void)
{
if ((MomCPU == CPU96C141)
&& (!SupAllowed))
WrError(ErrNum_PrivOrder);
}
/*!------------------------------------------------------------------------
* \fn decode_condition(const char *p_asc, Byte *p_condition)
* \brief decode condition code identifier
* \param p_asc source argument
* \param p_condition resulting code if found
* \return True if found
* ------------------------------------------------------------------------ */
static Boolean decode_condition(const char *p_asc, Byte *p_condition)
{
int z;
for (z = 0; Conditions[z].Name; z++)
if (!as_strcasecmp(p_asc, Conditions[z].Name))
{
*p_condition = Conditions[z].Code;
return True;
}
return False;
}
static void SetInstrOpSize(Byte Size)
{
if (Size != 255)
OpSize = Size;
}
/*---------------------------------------------------------------------------*/
static void DecodeMULA(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg);
if ((AdrType != ModNone) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
else switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xd8 + AdrMode;
BAsmCode[1] = 0x19;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xd7;
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x19;
break;
}
}
}
static void DecodeJPCALL(Word Index)
{
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;
}
if (IsIndirect(ArgStr[ArgCnt].str.p_str))
DecodeAdr(&ArgStr[ArgCnt], MModMem);
else
DecodeAdrMem(&ArgStr[ArgCnt]);
if (AdrType == ModMem)
{
if ((cond_code == COND_CODE_TRUE) && ((AdrMode == 0x41) || (AdrMode == 0x42)))
{
CodeLen = 1 + AdrCnt;
BAsmCode[0] = 0x1a + 2 * Index + (AdrCnt - 2);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
}
else
{
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xb0 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0xd0 + (Index << 4) + cond_code;
}
}
}
}
static void DecodeJR(Word Index)
{
if (ChkArgCnt(1, 2))
{
Byte cond_code;
Boolean OK;
LongInt AdrLong;
tSymbolFlags Flags;
if (1 == ArgCnt)
cond_code = COND_CODE_TRUE;
else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
{
WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
return;
}
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int32, &OK, &Flags);
if (OK)
{
if (Index==1)
{
AdrLong -= EProgCounter() + 3;
if (((AdrLong > 0x7fffl) || (AdrLong < -0x8000l)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_DistTooBig);
else
{
CodeLen = 3;
BAsmCode[0] = 0x70 + cond_code;
BAsmCode[1] = Lo(AdrLong);
BAsmCode[2] = Hi(AdrLong);
if (!mFirstPassUnknown(Flags))
{
AdrLong++;
if ((AdrLong >= -128) && (AdrLong <= 127)) WrError(ErrNum_ShortJumpPossible);
}
}
}
else
{
AdrLong -= EProgCounter() + 2;
if (((AdrLong > 127) || (AdrLong < -128)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_DistTooBig);
else
{
CodeLen = 2;
BAsmCode[0] = 0x60 + cond_code;
BAsmCode[1] = Lo(AdrLong);
}
}
}
}
}
static void DecodeCALR(Word Index)
{
LongInt AdrLong;
Boolean OK;
tSymbolFlags Flags;
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags) - (EProgCounter() + 3);
if (OK)
{
if (((AdrLong < -32768) || (AdrLong > 32767)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_DistTooBig);
else
{
CodeLen = 3;
BAsmCode[0] = 0x1e;
BAsmCode[1] = Lo(AdrLong);
BAsmCode[2] = Hi(AdrLong);
}
}
}
}
static void DecodeRET(Word Index)
{
UNUSED(Index);
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] = 0x0e;
}
else
{
CodeLen = 2;
BAsmCode[0] = 0xb0;
BAsmCode[1] = 0xf0 + cond_code;
}
}
}
static void DecodeRETD(Word Index)
{
Word AdrWord;
Boolean OK;
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
if (OK)
{
CodeLen = 3;
BAsmCode[0] = 0x0f;
BAsmCode[1] = Lo(AdrWord);
BAsmCode[2] = Hi(AdrWord);
}
}
}
static void DecodeDJNZ(Word Index)
{
LongInt AdrLong;
Boolean OK;
tSymbolFlags Flags;
UNUSED(Index);
if (ChkArgCnt(1, 2))
{
if (ArgCnt == 1)
{
AdrType = ModReg;
AdrMode = 2;
OpSize = 0;
}
else
DecodeAdr(&ArgStr[1], MModReg | MModXReg);
if (AdrType != ModNone)
{
if (OpSize == 2) WrError(ErrNum_InvOpSize);
else
{
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int32, &OK, &Flags) - (EProgCounter() + 3 + Ord(AdrType == ModXReg));
if (OK)
{
if (((AdrLong < -128) || (AdrLong > 127)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
else
switch (AdrType)
{
case ModReg:
CodeLen = 3;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x1c;
BAsmCode[2] = AdrLong & 0xff;
break;
case ModXReg:
CodeLen = 4;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x1c;
BAsmCode[3] = AdrLong & 0xff;
break;
}
}
}
}
}
}
static void DecodeEX(Word Index)
{
Byte HReg;
UNUSED(Index);
/* work around the parser problem related to the ' character */
if (!as_strncasecmp(ArgStr[2].str.p_str, "F\'", 2))
ArgStr[2].str.p_str[2] = '\0';
if (!ChkArgCnt(2, 2));
else if ((ArgPair("F", "F\'")) || (ArgPair("F`", "F")))
{
CodeLen = 1;
BAsmCode[0] = 0x16;
}
else
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg | MModMem);
if (OpSize == 2) WrError(ErrNum_InvOpSize);
else
{
switch (AdrType)
{
case ModReg:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg | MModXReg | MModMem);
switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0xb8 + HReg;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0xb8 + HReg;
break;
case ModMem:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x30 + HReg;
break;
}
break;
case ModXReg:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg);
if (AdrType == ModReg)
{
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0xb8 + AdrMode;
}
break;
case ModMem:
{
Boolean FixupAutoIncSize = AutoIncSizeNeeded;
MinOneIs0 = True;
HReg = AdrCnt;
BAsmCode[0] = AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
DecodeAdr(&ArgStr[2], MModReg);
if (AdrType == ModReg)
{
CodeLen = 2 + HReg;
if (FixupAutoIncSize)
SetAutoIncSize(0, 1);
BAsmCode[0] += 0x80 + (OpSize << 4);
BAsmCode[1 + HReg] = 0x30 + AdrMode;
}
break;
}
}
}
}
}
static void DecodeBS1x(Word Index)
{
if (!ChkArgCnt(2, 2));
else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
else
{
DecodeAdr(&ArgStr[2], MModReg | MModXReg);
if (OpSize != 1) WrError(ErrNum_InvOpSize);
else switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xd8 + AdrMode;
BAsmCode[1] = 0x0e + Index; /* ANSI */
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xd7;
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x0e +Index; /* ANSI */
break;
}
}
}
static void DecodeLDA(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrType != ModNone)
{
if (OpSize < 1) WrError(ErrNum_InvOpSize);
else
{
HReg = AdrMode;
if (IsIndirect(ArgStr[2].str.p_str))
DecodeAdr(&ArgStr[2], MModMem);
else
DecodeAdrMem(&ArgStr[2]);
if (AdrType != ModNone)
{
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xb0 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x20 + ((OpSize - 1) << 4) + HReg;
}
}
}
}
}
static void DecodeLDAR(Word Index)
{
LongInt AdrLong;
Boolean OK;
tSymbolFlags Flags;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &OK, &Flags) - (EProgCounter() + 4);
if (OK)
{
if (((AdrLong < -32768) || (AdrLong > 32767)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_DistTooBig);
else
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrType != ModNone)
{
if (OpSize < 1) WrError(ErrNum_InvOpSize);
else
{
CodeLen = 5;
BAsmCode[0] = 0xf3;
BAsmCode[1] = 0x13;
BAsmCode[2] = Lo(AdrLong);
BAsmCode[3] = Hi(AdrLong);
BAsmCode[4] = 0x20 + ((OpSize - 1) << 4) + AdrMode;
}
}
}
}
}
}
static void DecodeLDC(Word Index)
{
Byte HReg;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg| MModCReg);
HReg = AdrMode;
switch (AdrType)
{
case ModReg:
DecodeAdr(&ArgStr[2], MModCReg);
if (AdrType != ModNone)
{
CodeLen = 3;
BAsmCode[0] = 0xc8 + (OpSize << 4) + HReg;
BAsmCode[1] = 0x2f;
BAsmCode[2] = AdrMode;
}
break;
case ModXReg:
DecodeAdr(&ArgStr[2], MModCReg);
if (AdrType != ModNone)
{
CodeLen = 4;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0x2f;
BAsmCode[3] = AdrMode;
};
break;
case ModCReg:
DecodeAdr(&ArgStr[2], MModReg | MModXReg);
switch (AdrType)
{
case ModReg:
CodeLen = 3;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x2e;
BAsmCode[2] = HReg;
break;
case ModXReg:
CodeLen = 4;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x2e;
BAsmCode[3] = HReg;
break;
}
break;
}
}
}
static void DecodeLDX(Word Index)
{
Boolean OK;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModMem);
if (AdrType != ModNone)
{
if (AdrMode != 0x40) WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[4] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
if (OK)
{
CodeLen = 6;
BAsmCode[0] = 0xf7;
BAsmCode[1] = 0;
BAsmCode[2] = AdrVals[0];
BAsmCode[3] = 0;
BAsmCode[5] = 0;
}
}
}
}
}
static void DecodeLINK(Word Index)
{
Word AdrWord;
Boolean OK;
UNUSED(Index);
if (ChkArgCnt(2, 2))
{
AdrWord = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
if (OK)
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg);
if ((AdrType != ModNone) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
else
switch (AdrType)
{
case ModReg:
CodeLen = 4;
BAsmCode[0] = 0xe8 + AdrMode;
BAsmCode[1] = 0x0c;
BAsmCode[2] = Lo(AdrWord);
BAsmCode[3] = Hi(AdrWord);
break;
case ModXReg:
CodeLen = 5;
BAsmCode[0] = 0xe7;
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x0c;
BAsmCode[3] = Lo(AdrWord);
BAsmCode[4] = Hi(AdrWord);
break;
}
}
}
}
static void DecodeLD(Word Code)
{
Byte HReg;
Boolean ShDest, ShSrc, OK;
SetInstrOpSize(Hi(Code));
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg | MModMem);
switch (AdrType)
{
case ModReg:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg | MModXReg| MModMem| MModImm);
switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x88 + HReg;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x88 + HReg;
break;
case ModMem:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x20 + HReg;
break;
case ModImm:
{
LongInt ImmValue = ImmVal();
if ((ImmValue <= 7) && (ImmValue >= 0))
{
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + HReg;
BAsmCode[1] = 0xa8 + AdrVals[0];
}
else
{
CodeLen = 1 + AdrCnt;
BAsmCode[0] = ((OpSize + 2) << 4) + HReg;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
}
break;
}
}
break;
case ModXReg:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModReg + MModImm);
switch (AdrType)
{
case ModReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0x98 + AdrMode;
break;
case ModImm:
{
LongInt ImmValue = ImmVal();
if ((ImmValue <= 7) && (ImmValue >= 0))
{
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0xa8 + AdrVals[0];
}
else
{
CodeLen = 3 + AdrCnt;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 3;
memcpy(BAsmCode
+ 3, AdrVals
, AdrCnt
);
}
break;
}
}
break;
case ModMem:
{
Boolean FixupAutoIncSize = AutoIncSizeNeeded;
BAsmCode[0] = AdrMode;
HReg = AdrCnt;
MinOneIs0 = True;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
DecodeAdr(&ArgStr[2], MModReg | MModMem | MModImm);
switch (AdrType)
{
case ModReg:
CodeLen = 2 + HReg;
BAsmCode[0] += 0xb0;
if (FixupAutoIncSize)
SetAutoIncSize(0, 1);
BAsmCode[1 + HReg] = 0x40 + (OpSize << 4) + AdrMode;
break;
case ModMem:
if (OpSize == -1) OpSize = 0;
ShDest = IsShort(BAsmCode[0]);
ShSrc = IsShort(AdrMode);
if (!(ShDest || ShSrc)) WrError(ErrNum_InvAddrMode);
else
{
if ((ShDest && (!ShSrc))) OK = True;
else if (ShSrc && (!ShDest)) OK = False;
else if (AdrMode == 0x40) OK = True;
else OK = False;
if (OK) /* dest=(dir8/16) */
{
CodeLen = 4 + AdrCnt;
HReg = BAsmCode[0];
BAsmCode[3 + AdrCnt] = (BAsmCode[0] == 0x40) ? 0 : BAsmCode[2];
BAsmCode[2 + AdrCnt] = BAsmCode[1];
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
AdrMode = HReg;
if (FixupAutoIncSize)
SetAutoIncSize(0, 1);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x19;
}
else
{
CodeLen = 4 + HReg;
BAsmCode[2 + HReg] = AdrVals[0];
BAsmCode[3 + HReg] = (AdrMode == 0x40) ? 0 : AdrVals[1];
BAsmCode[0] += 0xb0;
if (FixupAutoIncSize)
SetAutoIncSize(0, 1);
BAsmCode[1 + HReg] = 0x14 + (OpSize << 1);
}
}
break;
case ModImm:
if (BAsmCode[0] == 0x40)
{
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x08 + (OpSize << 1);
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
}
else
{
CodeLen = 2 + HReg + AdrCnt;
BAsmCode[0] += 0xb0;
BAsmCode[1 + HReg] = OpSize << 1;
memcpy(BAsmCode
+ 2 + HReg
, AdrVals
, AdrCnt
);
}
break;
}
break;
}
}
}
}
static void DecodeFixed(Word Index)
{
FixedOrder *FixedZ = FixedOrders + Index;
if (ChkArgCnt(0, 0)
&& (ChkExactCPUMask(FixedZ->CPUFlag, CPU96C141) >= 0))
{
if (Hi(FixedZ->Code) == 0)
{
CodeLen = 1;
BAsmCode[0] = Lo(FixedZ->Code);
}
else
{
CodeLen = 2;
BAsmCode[0] = Hi(FixedZ->Code);
BAsmCode[1] = Lo(FixedZ->Code);
}
if (FixedZ->InSup)
CheckSup();
}
}
static void DecodeImm(Word Index)
{
ImmOrder *ImmZ = ImmOrders + Index;
Word AdrWord;
Boolean OK;
if (ChkArgCnt((ImmZ->Default == -1) ? 1 : 0, 1))
{
if (ArgCnt == 0)
{
AdrWord = ImmZ->Default;
OK = True;
}
else
AdrWord = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
if (OK)
{
if (((MaxMode) && (AdrWord > ImmZ->MaxMax)) || ((!MaxMode) && (AdrWord > ImmZ->MinMax))) WrError(ErrNum_OverRange);
else if (Hi(ImmZ->Code) == 0)
{
CodeLen = 1;
BAsmCode[0] = Lo(ImmZ->Code) + AdrWord;
}
else
{
CodeLen = 2;
BAsmCode[0] = Hi(ImmZ->Code);
BAsmCode[1] = Lo(ImmZ->Code) + AdrWord;
}
}
if (ImmZ->InSup)
CheckSup();
}
}
static void DecodeALU2(Word Code);
static void DecodeReg(Word Index)
{
RegOrder *RegZ = RegOrders + Index;
/* dispatch to CPL as compare-long with two args: */
if ((Memo("CPL")) && (ArgCnt >= 2))
{
DecodeALU2(0x0207);
return;
}
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg);
if (AdrType != ModNone)
{
if (((1 << OpSize) & RegZ->OpMask) == 0) WrError(ErrNum_InvOpSize);
else if (AdrType == ModReg)
{
BAsmCode[0] = Hi(RegZ->Code) + 8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = Lo(RegZ->Code);
CodeLen = 2;
}
else
{
BAsmCode[0] = Hi(RegZ->Code) + 7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = Lo(RegZ->Code);
CodeLen = 3;
}
}
}
}
static void DecodeALU2(Word Code)
{
Byte HReg;
SetInstrOpSize(Hi(Code));
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg | MModMem);
switch (AdrType)
{
case ModReg:
HReg=AdrMode;
DecodeAdr(&ArgStr[2], MModReg | MModXReg | MModMem | MModImm);
switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x80 + (Lo(Code) << 4) + HReg;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x80 + (Lo(Code) << 4) + HReg;
break;
case ModMem:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + AdrMode + (OpSize << 4);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x80 + HReg + (Lo(Code) << 4);
break;
case ModImm:
if ((Lo(Code) == 7) && (OpSize != 2) && (ImmVal() <= 7) && (ImmVal() >= 0))
{
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + HReg;
BAsmCode[1] = 0xd8 + AdrVals[0];
}
else
{
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xc8 + (OpSize << 4) + HReg;
BAsmCode[1] = 0xc8 + Lo(Code);
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
}
break;
}
break;
case ModXReg:
HReg = AdrMode;
DecodeAdr(&ArgStr[2], MModImm);
switch (AdrType)
{
case ModImm:
if ((Lo(Code) == 7) && (OpSize != 2) && (ImmVal() <= 7) && (ImmVal() >= 0))
{
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0xd8 + AdrVals[0];
}
else
{
CodeLen = 3 + AdrCnt;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0xc8 + Lo(Code);
memcpy(BAsmCode
+ 3, AdrVals
, AdrCnt
);
}
break;
}
break;
case ModMem:
{
Boolean FixupAutoIncSize = AutoIncSizeNeeded;
MinOneIs0 = True;
HReg = AdrCnt;
BAsmCode[0] = AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
DecodeAdr(&ArgStr[2], MModReg | MModImm);
switch (AdrType)
{
case ModReg:
CodeLen = 2 + HReg;
if (FixupAutoIncSize)
SetAutoIncSize(0, 1);
BAsmCode[0] += 0x80 + (OpSize << 4);
BAsmCode[1 + HReg] = 0x88 + (Lo(Code) << 4) + AdrMode;
break;
case ModImm:
CodeLen = 2 + HReg + AdrCnt;
BAsmCode[0] += 0x80 + (OpSize << 4);
BAsmCode[1 + HReg] = 0x38 + Lo(Code);
memcpy(BAsmCode
+ 2 + HReg
, AdrVals
, AdrCnt
);
break;
};
break;
}
}
}
}
static void DecodePUSH_POP(Word Code)
{
SetInstrOpSize(Hi(Code));
if (!ChkArgCnt(1, 1));
else if (!as_strcasecmp(ArgStr[1].str.p_str, "F"))
{
CodeLen = 1;
BAsmCode[0] = 0x18 + Lo(Code);
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
{
CodeLen = 1;
BAsmCode[0] = 0x14 + Lo(Code);
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "SR"))
{
CodeLen = 1;
BAsmCode[0] = 0x02 + Lo(Code);
CheckSup();
}
else
{
MinOneIs0 = True;
DecodeAdr(&ArgStr[1], MModReg | MModXReg | MModMem | (Lo(Code) ? 0 : MModImm));
switch (AdrType)
{
case ModReg:
if (OpSize == 0)
{
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x04 + Lo(Code);
}
else
{
CodeLen = 1;
BAsmCode[0] = 0x28 + (Lo(Code) << 5) + ((OpSize - 1) << 4) + AdrMode;
}
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x04 + Lo(Code);
break;
case ModMem:
if (OpSize == -1)
OpSize=0;
CodeLen = 2 + AdrCnt;
if (Lo(Code))
BAsmCode[0] = 0xb0 + AdrMode;
else
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
if (Lo(Code))
BAsmCode[1 + AdrCnt] = 0x04 + (OpSize << 1);
else
BAsmCode[1 + AdrCnt] = 0x04;
break;
case ModImm:
if (OpSize == -1)
OpSize = 0;
BAsmCode[0] = 9 + (OpSize << 1);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
CodeLen = 1 + AdrCnt;
break;
}
}
}
static void DecodeShift(Word Code)
{
Boolean OK;
tSymbolFlags Flags;
Byte HReg;
SetInstrOpSize(Hi(Code));
if (ChkArgCnt(1, 2))
{
OK = True;
if (ArgCnt == 1)
HReg = 1;
else if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
HReg = 0xff;
else
{
HReg = EvalStrIntExpressionWithFlags(&ArgStr[1], Int8, &OK, &Flags);
if (OK)
{
if (mFirstPassUnknown(Flags))
HReg &= 0x0f;
else
{
if ((HReg == 0) || (HReg > 16))
{
WrError(ErrNum_OverRange);
OK = False;
}
else
HReg &= 0x0f;
}
}
}
if (OK)
{
DecodeAdr(&ArgStr[ArgCnt], MModReg | MModXReg | ((HReg == 0xff) ? 0 : MModMem));
switch (AdrType)
{
case ModReg:
CodeLen = 2 + Ord(HReg != 0xff);
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0xe8 + Lo(Code);
CodeLen = 2;
if (HReg == 0xff)
BAsmCode[1] += 0x10;
else
BAsmCode[CodeLen++] = HReg;
break;
case ModXReg:
BAsmCode[0] = 0xc7+(OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0xe8 + Lo(Code);
CodeLen = 3;
if (HReg == 0xff)
BAsmCode[2] += 0x10;
else
BAsmCode[CodeLen++] = HReg;
break;
case ModMem:
if (HReg != 1) WrError(ErrNum_InvAddrMode);
else
{
if (OpSize == -1)
OpSize = 0;
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
memcpy(BAsmCode
+ 1 , AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x78 + Lo(Code);
}
break;
}
}
}
}
static void DecodeMulDiv(Word Code)
{
Byte HReg;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg | MModXReg);
if (OpSize == 0) WrError(ErrNum_InvOpSize);
else
{
if ((AdrType == ModReg) && (OpSize == 1))
{
if (AdrMode > 3)
{
AdrType = ModXReg;
AdrMode = 0xe0 + (AdrMode << 2);
}
else
AdrMode += 1 + AdrMode;
}
OpSize--;
HReg = AdrMode;
switch (AdrType)
{
case ModReg:
DecodeAdr(&ArgStr[2], MModReg | MModXReg | MModMem | MModImm);
switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x40 + (Code << 3) + HReg;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x40 + (Code << 3) + HReg;
break;
case ModMem:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x40 + (Code << 3) + HReg;
break;
case ModImm:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xc8 + (OpSize << 4) + HReg;
BAsmCode[1] = 0x08 + Code;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
break;
}
break;
case ModXReg:
DecodeAdr(&ArgStr[2], MModImm);
if (AdrType == ModImm)
{
CodeLen = 3 + AdrCnt;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = HReg;
BAsmCode[2] = 0x08 + Code;
memcpy(BAsmCode
+ 3, AdrVals
, AdrCnt
);
}
break;
}
}
}
}
static void DecodeBitCF(Word Code)
{
Boolean OK;
Byte BitPos;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[2], MModReg | MModXReg | MModMem);
if (AdrType!=ModNone)
{
if (OpSize == 2) WrError(ErrNum_InvOpSize);
else
{
if (AdrType == ModMem)
OpSize = 0;
if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
{
BitPos = 0xff;
OK = True;
}
else
BitPos = EvalStrIntExpression(&ArgStr[1], (OpSize == 0) ? UInt3 : Int4, &OK);
if (OK)
switch (AdrType)
{
case ModReg:
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x20 + Code;
CodeLen = 2;
if (BitPos == 0xff)
BAsmCode[1] |= 0x08;
else
BAsmCode[CodeLen++] = BitPos;
break;
case ModXReg:
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x20 + Code;
CodeLen = 3;
if (BitPos == 0xff)
BAsmCode[2] |= 0x08;
else
BAsmCode[CodeLen++] = BitPos;
break;
case ModMem:
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0xb0 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = (BitPos == 0xff)
? 0x28 + Code
: 0x80 + (Code << 3) + BitPos;
break;
}
}
}
}
}
static void DecodeBit(Word Code)
{
Boolean OK;
Byte BitPos;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[2], MModReg | MModXReg | MModMem);
if (AdrType == ModMem)
OpSize = 0;
if (AdrType != ModNone)
{
if (OpSize == 2) WrError(ErrNum_InvOpSize);
else
{
BitPos = EvalStrIntExpression(&ArgStr[1], (OpSize == 0) ? UInt3 : Int4, &OK);
if (OK)
{
switch (AdrType)
{
case ModReg:
CodeLen = 3;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x30 + Code;
BAsmCode[2] = BitPos;
break;
case ModXReg:
CodeLen = 4;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x30 + Code;
BAsmCode[3] = BitPos;
break;
case ModMem:
CodeLen = 2 + AdrCnt;
Code = (Code == 4) ? 0 : Code + 1;
BAsmCode[0] = 0xb0 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0xa8 + (Code << 3) + BitPos;
break;
}
}
}
}
}
}
static void DecodeINC_DEC(Word Code)
{
Boolean OK;
Byte Incr;
tSymbolFlags Flags;
SetInstrOpSize(Hi(Code));
if (ChkArgCnt(1, 2))
{
if (ArgCnt == 1)
{
Incr = 1;
OK = True;
Flags = eSymbolFlag_None;
}
else
Incr = EvalStrIntExpressionWithFlags(&ArgStr[1], Int4, &OK, &Flags);
if (OK)
{
if (mFirstPassUnknown(Flags))
Incr &= 7;
else if ((Incr < 1) || (Incr > 8))
{
WrError(ErrNum_OverRange);
OK = False;
}
}
if (OK)
{
Incr &= 7; /* 8-->0 */
DecodeAdr(&ArgStr[ArgCnt], MModReg | MModXReg | MModMem);
switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x60 + (Lo(Code) << 3) + Incr;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x60 + (Lo(Code) << 3) + Incr;
break;
case ModMem:
if (OpSize == -1)
OpSize = 0;
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + AdrMode + (OpSize << 4);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = 0x60 + (Lo(Code) << 3) + Incr;
break;
}
}
}
}
static void DecodeCPxx(Word Code)
{
Boolean OK;
if (ChkArgCntExtEitherOr(ArgCnt, 0, 2))
{
OK = True;
if (ArgCnt == 0)
{
OpSize = 0;
AdrMode = 3;
}
else
{
Byte HReg;
int l
= strlen(ArgStr
[2].
str.
p_str);
const char *CmpStr;
if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
OpSize = 0;
else if (!as_strcasecmp(ArgStr[1].str.p_str, "WA"))
OpSize = 1;
CmpStr = (Code & 0x02) ? "-)" : "+)";
if (OpSize == -1) OK = False;
else if ((l < 2) || (*ArgStr[2].str.p_str != '(') || (as_strcasecmp(ArgStr[2].str.p_str + l - 2, CmpStr))) OK = False;
else
{
ArgStr[2].str.p_str[l - 2] = '\0';
if (CodeEReg(ArgStr[2].str.p_str + 1, &AdrMode, &HReg) != 2) OK = False;
else if (!IsRegBase(AdrMode, HReg)) OK = False;
else if (!IsRegCurrent(AdrMode, HReg, &AdrMode)) OK = False;
}
if (!OK)
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
if (OK)
{
CodeLen = 2;
BAsmCode[0] = 0x80 + (OpSize << 4) + AdrMode;
BAsmCode[1] = Code;
}
}
}
static void DecodeLDxx(Word Code)
{
SetInstrOpSize(Hi(Code));
if (OpSize == -1)
OpSize = 0;
if (OpSize == 2) WrError(ErrNum_InvOpSize);
else if (ChkArgCntExtEitherOr(ArgCnt, 0, 2))
{
Boolean OK;
Byte HReg = 0;
if (ArgCnt == 0)
{
OK = True;
}
else
{
const char *CmpStr;
int l1
= strlen(ArgStr
[1].
str.
p_str),
l2
= strlen(ArgStr
[2].
str.
p_str);
OK = True;
CmpStr = (Code & 0x02) ? "-)" : "+)";
if ((*ArgStr[1].str.p_str != '(') || (*ArgStr[2].str.p_str != '(')
|| (l1 < 3) || (l2 < 3)
|| (as_strcasecmp(ArgStr[1].str.p_str + l1 - 2, CmpStr))
|| (as_strcasecmp(ArgStr[2].str.p_str + l2 - 2, CmpStr)))
OK = False;
else
{
ArgStr[1].str.p_str[l1 - 2] = '\0';
ArgStr[2].str.p_str[l2 - 2] = '\0';
if ((!as_strcasecmp(ArgStr[1].str.p_str + 1,"XIX")) && (!as_strcasecmp(ArgStr[2].str.p_str + 1, "XIY")))
HReg = 2;
else if ((MaxMode) && (!as_strcasecmp(ArgStr[1].str.p_str + 1, "XDE")) && (!as_strcasecmp(ArgStr[2].str.p_str + 1 , "XHL")));
else if ((!MaxMode) && (!as_strcasecmp(ArgStr[1].str.p_str + 1, "DE")) && (!as_strcasecmp(ArgStr[2].str.p_str + 1 , "HL")));
else
OK = False;
}
}
if (!OK) WrError(ErrNum_InvAddrMode);
else
{
CodeLen = 2;
BAsmCode[0] = 0x83 + (OpSize << 4) + HReg;
BAsmCode[1] = Lo(Code);
}
}
}
static void DecodeMINC_MDEC(Word Code)
{
if (ChkArgCnt(2, 2))
{
Word AdrWord;
Boolean OK;
AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
if (OK)
{
Byte Pwr;
Byte ByteSizeLg2 = Code & 3, ByteSize = 1 << ByteSizeLg2;
if (!IsPwr2(AdrWord, &Pwr)) WrStrErrorPos(ErrNum_NotPwr2, &ArgStr[1]);
else if (Pwr <= ByteSizeLg2) WrStrErrorPos(ErrNum_UnderRange, &ArgStr[1]);
else
{
AdrWord -= ByteSize;
DecodeAdr(&ArgStr[2], MModReg | MModXReg);
if ((AdrType != ModNone) && (OpSize != 1)) WrError(ErrNum_InvOpSize);
else
switch (AdrType)
{
case ModReg:
CodeLen = 4;
BAsmCode[0] = 0xd8 + AdrMode;
BAsmCode[1] = Code;
BAsmCode[2] = Lo(AdrWord);
BAsmCode[3] = Hi(AdrWord);
break;
case ModXReg:
CodeLen = 5;
BAsmCode[0] = 0xd7;
BAsmCode[1] = AdrMode;
BAsmCode[2] = Code;
BAsmCode[3] = Lo(AdrWord);
BAsmCode[4] = Hi(AdrWord);
break;
}
}
}
}
}
static void DecodeRLD_RRD(Word Code)
{
if (!ChkArgCnt(1, 2));
else if ((ArgCnt == 2) && (as_strcasecmp(ArgStr[1].str.p_str, "A"))) WrError(ErrNum_InvAddrMode);
else
{
DecodeAdr(&ArgStr[ArgCnt], MModMem);
if (AdrType != ModNone)
{
CodeLen = 2 + AdrCnt;
BAsmCode[0] = 0x80 + AdrMode;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode[1 + AdrCnt] = Code;
}
}
}
static void DecodeSCC(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
Byte cond_code;
if (!decode_condition(ArgStr[1].str.p_str, &cond_code)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
else
{
DecodeAdr(&ArgStr[2], MModReg | MModXReg);
if (OpSize > 1) WrError(ErrNum_UndefOpSizes);
else
{
switch (AdrType)
{
case ModReg:
CodeLen = 2;
BAsmCode[0] = 0xc8 + (OpSize << 4) + AdrMode;
BAsmCode[1] = 0x70 + cond_code;
break;
case ModXReg:
CodeLen = 3;
BAsmCode[0] = 0xc7 + (OpSize << 4);
BAsmCode[1] = AdrMode;
BAsmCode[2] = 0x70 + cond_code;
break;
}
}
}
}
return;
}
/*---------------------------------------------------------------------------*/
static void AddSize(const char *NName, Byte NCode, InstProc Proc, Word SizeMask)
{
int l;
char SizeName[20];
AddInstTable(InstTable, NName, 0xff00 | NCode, Proc);
l = as_snprintf(SizeName, sizeof(SizeName), "%sB", NName);
if (SizeMask & 1)
AddInstTable(InstTable, SizeName, 0x0000 | NCode, Proc);
if (SizeMask & 2)
{
SizeName[l - 1] = 'W';
AddInstTable(InstTable, SizeName, 0x0100 | NCode, Proc);
}
/* CP(L) would generate conflict with CPL instruction - dispatch
it from CPL single-op instruction if ArgCnt >= 2! */
if ((SizeMask
& 4) && (strcmp(NName
, "CP")))
{
SizeName[l - 1] = 'L';
AddInstTable(InstTable, SizeName, 0x0200 | NCode, Proc);
}
}
static void AddMod(const char *NName, Byte NCode)
{
int l;
char SizeName[20];
l = as_snprintf(SizeName, sizeof(SizeName), "%s1", NName);
AddInstTable(InstTable, SizeName, NCode, DecodeMINC_MDEC);
SizeName[l - 1] = '2';
AddInstTable(InstTable, SizeName, NCode | 1, DecodeMINC_MDEC);
SizeName[l - 1] = '4';
AddInstTable(InstTable, SizeName, NCode | 2, DecodeMINC_MDEC);
}
static void AddFixed(const char *NName, Word NCode, Byte NFlag, Boolean NSup)
{
order_array_rsv_end(FixedOrders, FixedOrder);
FixedOrders[InstrZ].Code = NCode;
FixedOrders[InstrZ].CPUFlag = NFlag;
FixedOrders[InstrZ].InSup = NSup;
AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
}
static void AddReg(const char *NName, Word NCode, Byte NMask)
{
order_array_rsv_end(RegOrders, RegOrder);
RegOrders[InstrZ].Code = NCode;
RegOrders[InstrZ].OpMask = NMask;
AddInstTable(InstTable, NName, InstrZ++, DecodeReg);
}
static void AddImm(const char *NName, Word NCode, Boolean NInSup,
Byte NMinMax, Byte NMaxMax, ShortInt NDefault)
{
order_array_rsv_end(ImmOrders, ImmOrder);
ImmOrders[InstrZ].Code = NCode;
ImmOrders[InstrZ].InSup = NInSup;
ImmOrders[InstrZ].MinMax = NMinMax;
ImmOrders[InstrZ].MaxMax = NMaxMax;
ImmOrders[InstrZ].Default = NDefault;
AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
}
static void AddALU2(const char *NName, Byte NCode)
{
AddSize(NName, NCode, DecodeALU2, 7);
}
static void AddShift(const char *NName)
{
AddSize(NName, InstrZ++, DecodeShift, 7);
}
static void AddMulDiv(const char *NName)
{
AddInstTable(InstTable, NName, InstrZ++, DecodeMulDiv);
}
static void AddBitCF(const char *NName, Byte NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBitCF);
}
static void AddBit(const char *NName)
{
AddInstTable(InstTable, NName, InstrZ++, DecodeBit);
}
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(301);
SetDynamicInstTable(InstTable);
AddInstTable(InstTable, "MULA" , 0, DecodeMULA);
AddInstTable(InstTable, "JP" , 0, DecodeJPCALL);
AddInstTable(InstTable, "CALL" , 1, DecodeJPCALL);
AddInstTable(InstTable, "JR" , 0, DecodeJR);
AddInstTable(InstTable, "JRL" , 1, DecodeJR);
AddInstTable(InstTable, "CALR" , 0, DecodeCALR);
AddInstTable(InstTable, "RET" , 0, DecodeRET);
AddInstTable(InstTable, "RETD" , 0, DecodeRETD);
AddInstTable(InstTable, "DJNZ" , 0, DecodeDJNZ);
AddInstTable(InstTable, "EX" , 0, DecodeEX);
AddInstTable(InstTable, "BS1F" , 0, DecodeBS1x);
AddInstTable(InstTable, "BS1B" , 1, DecodeBS1x);
AddInstTable(InstTable, "LDA" , 0, DecodeLDA);
AddInstTable(InstTable, "LDAR" , 0, DecodeLDAR);
AddInstTable(InstTable, "LDC" , 0, DecodeLDC);
AddInstTable(InstTable, "LDX" , 0, DecodeLDX);
AddInstTable(InstTable, "LINK" , 0, DecodeLINK);
AddSize("LD", 0, DecodeLD, 7);
AddSize("PUSH", 0, DecodePUSH_POP, 7);
AddSize("POP" , 1, DecodePUSH_POP, 7);
AddSize("INC" , 0, DecodeINC_DEC, 7);
AddSize("DEC" , 1, DecodeINC_DEC, 7);
AddInstTable(InstTable, "CPI" , 0x14, DecodeCPxx);
AddInstTable(InstTable, "CPIR" , 0x15, DecodeCPxx);
AddInstTable(InstTable, "CPD" , 0x16, DecodeCPxx);
AddInstTable(InstTable, "CPDR" , 0x17, DecodeCPxx);
AddSize("LDI", 0x10 , DecodeLDxx, 3);
AddSize("LDIR", 0x11, DecodeLDxx, 3);
AddSize("LDD", 0x12 , DecodeLDxx, 3);
AddSize("LDDR", 0x13, DecodeLDxx, 3);
AddMod("MINC", 0x38);
AddMod("MDEC", 0x3c);
AddInstTable(InstTable, "RLD", 0x06, DecodeRLD_RRD);
AddInstTable(InstTable, "RRD", 0x07, DecodeRLD_RRD);
AddInstTable(InstTable, "SCC", 0, DecodeSCC);
InstrZ = 0;
AddFixed("CCF" , 0x0012, 3, False);
AddFixed("DECF" , 0x000d, 3, False);
AddFixed("DI" , 0x0607, 3, True );
AddFixed("HALT" , 0x0005, 3, True );
AddFixed("INCF" , 0x000c, 3, False);
AddFixed("MAX" , 0x0004, 1, True );
AddFixed("MIN" , 0x0004, 2, True );
AddFixed("NOP" , 0x0000, 3, False);
AddFixed("NORMAL", 0x0001, 1, True );
AddFixed("RCF" , 0x0010, 3, False);
AddFixed("RETI" , 0x0007, 3, True );
AddFixed("SCF" , 0x0011, 3, False);
AddFixed("ZCF" , 0x0013, 3, False);
InstrZ = 0;
AddReg("CPL" , 0xc006, 3);
AddReg("DAA" , 0xc010, 1);
AddReg("EXTS", 0xc013, 6);
AddReg("EXTZ", 0xc012, 6);
AddReg("MIRR", 0xc016, 2);
AddReg("NEG" , 0xc007, 3);
AddReg("PAA" , 0xc014, 6);
AddReg("UNLK", 0xc00d, 4);
InstrZ = 0;
AddImm("EI" , 0x0600, True, 7, 7, 0);
AddImm("LDF" , 0x1700, False, 7, 3, -1);
AddImm("SWI" , 0x00f8, False, 7, 7, 7);
AddALU2("ADC", 1);
AddALU2("ADD", 0);
AddALU2("AND", 4);
AddALU2("OR" , 6);
AddALU2("SBC", 3);
AddALU2("SUB", 2);
AddALU2("XOR", 5);
AddALU2("CP" , 7);
InstrZ = 0;
AddShift("RLC");
AddShift("RRC");
AddShift("RL");
AddShift("RR");
AddShift("SLA");
AddShift("SRA");
AddShift("SLL");
AddShift("SRL");
InstrZ = 0;
AddMulDiv("MUL");
AddMulDiv("MULS");
AddMulDiv("DIV");
AddMulDiv("DIVS");
AddBitCF("ANDCF" , 0);
AddBitCF("LDCF" , 3);
AddBitCF("ORCF" , 1);
AddBitCF("STCF" , 4);
AddBitCF("XORCF" , 2);
InstrZ = 0;
AddBit("RES");
AddBit("SET");
AddBit("CHG");
AddBit("BIT");
AddBit("TSET");
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(FixedOrders);
order_array_free(RegOrders);
order_array_free(ImmOrders);
order_array_free(Conditions);
}
static void MakeCode_96C141(void)
{
CodeLen = 0;
DontPrint = False;
OpSize = -1;
MinOneIs0 = False;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(False)) return;
/* vermischt */
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean ChkPC_96C141(LargeWord Addr)
{
Boolean ok;
switch (ActPC)
{
case SegCode:
if (MaxMode) ok = (Addr <= 0xffffff);
else ok = (Addr <= 0xffff);
break;
default:
ok = False;
}
return (ok);
}
static Boolean IsDef_96C141(void)
{
return False;
}
static Boolean ChkMoreOneArg(void)
{
return (ArgCnt > 1);
}
static void SwitchTo_96C141(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
SetIsOccupiedFnc = ChkMoreOneArg;
PCSymbol = "$";
HeaderID = 0x52;
NOPCode = 0x00;
DivideChars = ",";
HasAttrs = False;
ValidSegs = (1 << SegCode);
Grans[SegCode] = 1;
ListGrans[SegCode] = 1;
SegInits[SegCode] = 0;
SegLimits[SegCode] = 0xfffffful;
MakeCode = MakeCode_96C141;
ChkPC = ChkPC_96C141;
IsDef = IsDef_96C141;
SwitchFrom = DeinitFields;
onoff_maxmode_add();
onoff_supmode_add();
InitFields();
}
void code96c141_init(void)
{
CPU96C141 = AddCPU("96C141", SwitchTo_96C141);
CPU93C141 = AddCPU("93C141", SwitchTo_96C141);
}