/* codest9.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator SGS-Thomson ST9 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "codest9.h"
typedef struct
{
char *Name;
Word Code;
} FixedOrder;
#define WorkOfs 0xd0
#define ModNone (-1)
#define ModReg 0
#define MModReg (1l << ModReg) /* Rn */
#define ModWReg 1
#define MModWReg (1l << ModWReg) /* rn */
#define ModRReg 2
#define MModRReg (1l << ModRReg) /* RRn */
#define ModWRReg 3
#define MModWRReg (1l << ModWRReg) /* rrn */
#define ModIReg 4
#define MModIReg (1l << ModIReg) /* (Rn) */
#define ModIWReg 5
#define MModIWReg (1l << ModIWReg) /* (rn) */
#define ModIRReg 6
#define MModIRReg (1l << ModIRReg) /* (RRn) */
#define ModIWRReg 7
#define MModIWRReg (1l << ModIWRReg) /* (rrn) */
#define ModIncWReg 8
#define MModIncWReg (1l << ModIncWReg) /* (rn)+ */
#define ModIncWRReg 9
#define MModIncWRReg (1l << ModIncWRReg) /* (rrn)+ */
#define ModDecWRReg 10
#define MModDecWRReg (1l << ModDecWRReg) /* -(rrn) */
#define ModDisp8WReg 11
#define MModDisp8WReg (1l << ModDisp8WReg) /* d8(rn) */
#define ModDisp8WRReg 12
#define MModDisp8WRReg (1l << ModDisp8WRReg) /* d8(rrn) */
#define ModDisp16WRReg 13
#define MModDisp16WRReg (1l << ModDisp16WRReg) /* d16(rrn) */
#define ModDispRWRReg 14
#define MModDispRWRReg (1l << ModDispRWRReg) /* rrm(rrn */
#define ModAbs 15
#define MModAbs (1l << ModAbs) /* NN */
#define ModImm 16
#define MModImm (1l << ModImm) /* #N/#NN */
#define ModDisp8RReg 17
#define MModDisp8RReg (1l << ModDisp8RReg) /* d8(RRn) */
#define ModDisp16RReg 18
#define MModDisp16RReg (1l << ModDisp16RReg) /* d16(RRn) */
static CPUVar CPUST9020,CPUST9030,CPUST9040,CPUST9050;
static ShortInt AdrMode,AbsSeg;
static Byte AdrPart,OpSize;
static Byte AdrVals[3];
static LongInt DPAssume;
#define ASSUMEST9Count 1
static ASSUMERec ASSUMEST9s[ASSUMEST9Count] =
{
{"DP", &DPAssume, 0, 1, 0x0, NULL}
};
/*--------------------------------------------------------------------------*/
/* helper functions */
static Boolean DecodeReg(char *Asc_O, Byte *Erg, Byte *Size)
{
Boolean Res;
char *Asc;
*Size = 0;
Asc=Asc_O;
if (strlen(Asc
) < 2) return False
;
if (*Asc != 'r')
return False;
Asc++;
if (*Asc == 'r')
{
if (strlen(Asc
) < 2) return False
;
*Size = 1; Asc++;
}
else
*Size = 0;
*Erg = ConstLongInt(Asc, &Res, 10);
if ((!Res) || (*Erg > 15)) return False;
if ((*Size == 1) && (Odd(*Erg))) return False;
return True;
}
static void DecodeAdr(tStrComp *pArg, LongWord Mask)
{
Word AdrWord;
int level;
Byte flg,Size;
Boolean OK, IsIndirect;
tEvalResult EvalResult;
char *p;
int l;
AdrMode = ModNone; AdrCnt = 0;
/* 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);
AdrVals[0] = Hi(AdrWord);
AdrVals[1] = Lo(AdrWord);
break;
}
if (OK)
{
AdrMode = ModImm;
AdrCnt = OpSize + 1;
}
goto func_exit;
}
/* Arbeitsregister */
if (DecodeReg(pArg->str.p_str, &AdrPart, &Size))
{
if (Size == 0)
{
if (Mask & MModWReg) AdrMode = ModWReg;
else
{
AdrVals[0] = WorkOfs + AdrPart;
AdrCnt = 1;
AdrMode = ModReg;
}
}
else
{
if (Mask & MModWRReg) AdrMode = ModWRReg;
else
{
AdrVals[0] = WorkOfs + AdrPart;
AdrCnt = 1;
AdrMode = ModRReg;
}
}
goto func_exit;
}
/* Postinkrement */
if ((l > 0) && (pArg->str.p_str[l - 1] == '+'))
{
if ((l < 3) || (*pArg->str.p_str != '(') || (pArg->str.p_str[l - 2] != ')')) WrError(ErrNum_InvAddrMode);
else
{
tStrComp RegComp;
pArg->str.p_str[l - 2] = '\0'; pArg->Pos.Len -= 2;
StrCompRefRight(&RegComp, pArg, 1);
if (!DecodeReg(RegComp.str.p_str, &AdrPart, &Size)) WrStrErrorPos(ErrNum_InvReg, &RegComp);
AdrMode = (Size == 0) ? ModIncWReg : ModIncWRReg;
}
goto func_exit;
}
/* Predekrement */
if ((*pArg->str.p_str == '-') && (pArg->str.p_str[1] == '(') && (pArg->str.p_str[l - 1] == ')'))
{
tStrComp RegComp;
pArg->str.p_str[l - 1] = '\0'; pArg->Pos.Len--;
StrCompRefRight(&RegComp, pArg, 2);
if (DecodeReg(RegComp.str.p_str, &AdrPart, &Size))
{
if (Size == 0) WrError(ErrNum_InvAddrMode); else AdrMode = ModDecWRReg;
goto func_exit;
}
}
/* indirekt<->direkt */
if ((l < 3) || (pArg->str.p_str[l - 1] != ')'))
{
IsIndirect = False; p = pArg->str.p_str;
}
else
{
level = 0; p = pArg->str.p_str + l - 2; flg = 0;
while ((p >= pArg->str.p_str) && (level >= 0))
{
switch (*p)
{
case '(': if (flg == 0) level--; break;
case ')': if (flg == 0) level++; break;
case '\'': if ((!(flg & 2))) flg ^= 1; break;
case '"': if ((!(flg & 1))) flg ^= 2; break;
}
p--;
}
IsIndirect
= (level
== -1) && ((p
< pArg
->str.
p_str) || ((*p
== '.') || (*p
== '_') || (isdigit(((unsigned int)*p
) & 0xff)) || (isalpha(((unsigned int)*p
) & 0xff))));
}
/* indirekt */
if (IsIndirect)
{
tStrComp RegComp;
/* discard closing ) at end */
pArg->str.p_str[--l] = '\0'; pArg->Pos.Len--;
/* split off part in () */
StrCompRefRight(&RegComp, pArg, p + 2 - pArg->str.p_str);
/* truncate arg to everything before ( */
p[1] = '\0';
pArg->Pos.Len = p + 1 - pArg->str.p_str;
if (DecodeReg(RegComp.str.p_str, &AdrPart, &Size))
{
if (Size == 0) /* d(r) */
{
AdrVals[0] = EvalStrIntExpression(pArg, Int8, &OK);
if (OK)
{
if ((Mask & MModIWReg) && (AdrVals[0] == 0)) AdrMode = ModIWReg;
else if (((Mask & MModIReg) != 0) && (AdrVals[0] == 0))
{
AdrVals[0] = WorkOfs + AdrPart; AdrMode = ModIReg; AdrCnt = 1;
}
else
{
AdrMode = ModDisp8WReg; AdrCnt = 1;
}
}
}
else /* ...(rr) */
{
if (DecodeReg(pArg->str.p_str, AdrVals, &Size))
{ /* rr(rr) */
if (Size != 1) WrError(ErrNum_InvAddrMode);
else
{
AdrMode = ModDispRWRReg; AdrCnt = 1;
}
}
else
{ /* d(rr) */
AdrWord = EvalStrIntExpression(pArg, Int16, &OK);
if ((AdrWord == 0) && (Mask & (MModIRReg | MModIWRReg)))
{
if (Mask & MModIWRReg) AdrMode = ModIWRReg;
else
{
AdrMode = ModIRReg; AdrVals[0] = AdrPart + WorkOfs; AdrCnt = 1;
}
}
else if ((AdrWord < 0x100) && (Mask & (MModDisp8WRReg | MModDisp8RReg)))
{
if (Mask & MModDisp8WRReg)
{
AdrVals[0] = Lo(AdrWord); AdrCnt = 1; AdrMode = ModDisp8WRReg;
}
else
{
AdrVals[0] = AdrPart + WorkOfs;
AdrVals[1] = Lo(AdrWord);
AdrCnt = 2;
AdrMode = ModDisp8RReg;
}
}
else if (Mask & MModDisp16WRReg)
{
AdrVals[0] = Hi(AdrWord);
AdrVals[1] = Lo(AdrWord);
AdrCnt = 2;
AdrMode = ModDisp16WRReg;
}
else
{
AdrVals[0] = AdrPart + WorkOfs;
AdrVals[2] = Hi(AdrWord);
AdrVals[1] = Lo(AdrWord);
AdrCnt = 3;
AdrMode = ModDisp16RReg;
}
}
}
}
else /* ...(RR) */
{
AdrWord = EvalStrIntExpressionWithResult(&RegComp, UInt9, &EvalResult);
if (!(EvalResult.AddrSpaceMask & (1 << SegReg))) WrError(ErrNum_InvAddrMode);
else if (AdrWord < 0xff)
{
AdrVals[0] = Lo(AdrWord);
AdrWord = EvalStrIntExpression(pArg, Int8, &OK);
if (AdrWord != 0) WrError(ErrNum_OverRange);
else
{
AdrCnt = 1; AdrMode = ModIReg;
}
}
else if ((AdrWord > 0x1ff) || (Odd(AdrWord))) WrError(ErrNum_InvAddrMode);
else
{
AdrVals[0] = Lo(AdrWord);
AdrWord = EvalStrIntExpression(pArg, Int16, &OK);
if ((AdrWord == 0) && (Mask & MModIRReg))
{
AdrCnt = 1; AdrMode = ModIRReg;
}
else if ((AdrWord < 0x100) && (Mask & MModDisp8RReg))
{
AdrVals[1] = Lo(AdrWord); AdrCnt = 2; AdrMode = ModDisp8RReg;
}
else
{
AdrVals[2] = Hi(AdrWord);
AdrVals[1] = Lo(AdrWord);
AdrCnt = 3;
AdrMode = ModDisp16RReg;
}
}
}
goto func_exit;
}
/* direkt */
AdrWord = EvalStrIntExpressionWithResult(pArg, UInt16, &EvalResult);
if (EvalResult.OK)
{
if (!(EvalResult.AddrSpaceMask & (1 << SegReg)))
{
AdrMode = ModAbs;
AdrVals[0] = Hi(AdrWord);
AdrVals[1] = Lo(AdrWord);
AdrCnt = 2;
ChkSpace(AbsSeg, EvalResult.AddrSpaceMask);
}
else if (AdrWord < 0xff)
{
AdrMode = ModReg;
AdrVals[0] = Lo(AdrWord);
AdrCnt = 1;
}
else if ((AdrWord > 0x1ff) || (Odd(AdrWord))) WrError(ErrNum_InvAddrMode);
else
{
AdrMode = ModRReg;
AdrVals[0] = Lo(AdrWord);
AdrCnt = 1;
}
}
func_exit:
if ((AdrMode != ModNone) && (((1l << AdrMode) & Mask) == 0))
{
WrError(ErrNum_InvAddrMode); AdrMode = ModNone; AdrCnt = 0;
}
}
static Boolean SplitBit(tStrComp *pDest, const tStrComp *pSrc, Byte *pErg)
{
char *p;
Boolean OK;
Byte Inv = 0;
StrCompRefRight(pDest, pSrc, 0);
p = RQuotPos(pDest->str.p_str, '.');
if ((!p
) || (p
== pDest
->str.
p_str + strlen(pDest
->str.
p_str) + 1))
{
Integer val;
if (*pDest->str.p_str == '!')
{
Inv = 1;
pDest->str.p_str++;
pDest->Pos.StartCol++;
pDest->Pos.Len--;
}
val = EvalStrIntExpression(pDest, UInt8, &OK);
if (OK)
{
*pErg = (val & 15) ^ Inv;
as_snprintf(pDest->str.p_str, STRINGSIZE, "r%d", (int)(val >> 4));
return True;
}
return False;
}
Inv = !!(p[1] == '!');
*pErg = Inv + (EvalStrIntExpressionOffs(pSrc, p + 1 + Inv - pSrc->str.p_str, UInt3, &OK) << 1);
*p = '\0';
return OK;
}
/*--------------------------------------------------------------------------*/
/* Instruction Decoders */
static void DecodeFixed(Word Code)
{
if (ChkArgCnt(0, 0))
{
if (Hi(Code))
BAsmCode[CodeLen++] = Hi(Code);
BAsmCode[CodeLen++] = Lo(Code);
}
}
static void DecodeLD(Word IsLDW)
{
Byte HReg, HPart;
Word Mask1, Mask2;
if (ChkArgCnt(2, 2))
{
if (IsLDW)
{
OpSize = 1; Mask1 = MModWRReg; Mask2 = MModRReg;
}
else
{
Mask1 = MModWReg; Mask2 = MModReg;
}
DecodeAdr(&ArgStr[1], Mask1 | Mask2 | MModIWReg | MModDisp8WReg | MModIncWReg |
MModIWRReg | MModIncWRReg | MModDecWRReg | MModDisp8WRReg |
MModDisp16WRReg | MModDispRWRReg | MModAbs | MModIRReg);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask1 | Mask2 | MModIWReg | MModDisp8WReg | MModIWRReg |
MModIncWRReg | MModDecWRReg | MModDispRWRReg | MModDisp8WRReg |
MModDisp16WRReg | MModAbs | MModImm);
switch (AdrMode)
{
case ModWReg:
BAsmCode[0] = (HReg << 4) + 8;
BAsmCode[1] = WorkOfs + AdrPart;
CodeLen = 2;
break;
case ModWRReg:
BAsmCode[0] = 0xe3;
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
break;
case ModReg:
BAsmCode[0] = (HReg << 4) + 8;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModRReg:
BAsmCode[0] = 0xef;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = HReg + WorkOfs;
CodeLen = 3;
break;
case ModIWReg:
if (OpSize == 0)
{
BAsmCode[0] = 0xe4;
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
}
else
{
BAsmCode[0] = 0xa6;
BAsmCode[1] = 0xf0 + AdrPart;
BAsmCode[2] = WorkOfs + HReg;
CodeLen = 3;
}
break;
case ModDisp8WReg:
BAsmCode[0] = 0xb3 + (OpSize * 0x2b);
BAsmCode[1] = (HReg << 4) + AdrPart;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
case ModIWRReg:
BAsmCode[0] = 0xb5 + (OpSize * 0x2e);
BAsmCode[1] = (HReg << 4) + AdrPart + OpSize;
CodeLen = 2;
break;
case ModIncWRReg:
BAsmCode[0] = 0xb4 + (OpSize * 0x21);
BAsmCode[1] = 0xf1 + AdrPart;
BAsmCode[2] = WorkOfs + HReg;
CodeLen = 3;
break;
case ModDecWRReg:
BAsmCode[0] = 0xc2 + OpSize;
BAsmCode[1] = 0xf1 + AdrPart;
BAsmCode[2] = WorkOfs + HReg;
CodeLen = 3;
break;
case ModDispRWRReg:
BAsmCode[0] = 0x60;
BAsmCode[1] = (0x10 * (1 - OpSize)) + (AdrVals[0] << 4) + AdrPart;
BAsmCode[2] = 0xf0 + HReg;
CodeLen = 3;
break;
case ModDisp8WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = 0xf1 + AdrPart;
BAsmCode[2] = AdrVals[0];
BAsmCode[3] = HReg + WorkOfs;
CodeLen = 4;
break;
case ModDisp16WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = 0xf0 + AdrPart;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
BAsmCode[2 + AdrCnt] = HReg + WorkOfs;
CodeLen = 3 + AdrCnt;
break;
case ModAbs:
BAsmCode[0] = 0xc4 + (OpSize * 0x1e);
BAsmCode[1] = 0xf0 + AdrPart;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
break;
case ModImm:
if (OpSize == 0)
{
BAsmCode[0] = (HReg << 4) + 0x0c;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
CodeLen = 1 + AdrCnt;
}
else
{
BAsmCode[0] = 0xbf;
BAsmCode[1] = WorkOfs + HReg;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
}
break;
}
break;
case ModReg:
case ModRReg:
HReg = AdrVals[0];
DecodeAdr(&ArgStr[2], Mask1 | Mask2 | MModIWReg | MModIWRReg | MModIncWRReg |
MModDecWRReg | MModDispRWRReg | MModDisp8WRReg | MModDisp16WRReg |
MModImm);
switch (AdrMode)
{
case ModWReg:
BAsmCode[0] = (AdrPart << 4) + 0x09;
BAsmCode[1] = HReg;
CodeLen = 2;
break;
case ModWRReg:
BAsmCode[0] = 0xef;
BAsmCode[1] = WorkOfs + AdrPart;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModReg:
case ModRReg:
BAsmCode[0] = 0xf4 - (OpSize * 5);
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModIWReg:
BAsmCode[0] = 0xe7 - (0x41 * OpSize);
BAsmCode[1] = 0xf0 + AdrPart;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModIWRReg:
BAsmCode[0] = 0x72 + (OpSize * 12);
BAsmCode[1] = 0xf1 + AdrPart - OpSize;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModIncWRReg:
BAsmCode[0] = 0xb4 + (0x21 * OpSize);
BAsmCode[1] = 0xf1 + AdrPart;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModDecWRReg:
BAsmCode[0] = 0xc2 + OpSize;
BAsmCode[1] = 0xf1 + AdrPart;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModDisp8WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = 0xf1 + AdrPart;
BAsmCode[2] = AdrVals[0];
BAsmCode[3] = HReg;
CodeLen = 4;
break;
case ModDisp16WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = 0xf0 + AdrPart;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
BAsmCode[2 + AdrCnt] = HReg;
CodeLen = 3 + AdrCnt;
break;
case ModImm:
BAsmCode[0] = 0xf5 - (OpSize * 0x36);
BAsmCode[1] = HReg;
memcpy(BAsmCode
+ 2, AdrVals
, 2);
CodeLen = 2 + AdrCnt;
break;
}
break;
case ModIWReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2 | Mask1);
switch (AdrMode)
{
case ModWReg:
BAsmCode[0] = 0xe5;
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
break;
case ModWRReg:
BAsmCode[0] = 0x96;
BAsmCode[1] = WorkOfs + AdrPart;
BAsmCode[2] = 0xf0 + HReg;
CodeLen = 3;
break;
case ModReg:
case ModRReg:
BAsmCode[0] = 0xe6 - (0x50 * OpSize);
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = 0xf0 + HReg;
CodeLen = 3;
break;
}
break;
case ModDisp8WReg:
BAsmCode[2] = AdrVals[0]; HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask1);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
BAsmCode[0] = 0xb2 + (OpSize * 0x2c);
BAsmCode[1] = (AdrPart << 4) + (OpSize << 4) + HReg;
CodeLen = 3;
break;
}
break;
case ModIncWReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModIncWRReg * (1 - OpSize));
switch (AdrMode)
{
case ModIncWRReg:
BAsmCode[0] = 0xd7;
BAsmCode[1] = (HReg << 4) + AdrPart + 1;
CodeLen = 2;
break;
}
break;
case ModIWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], (MModIWReg * (1 - OpSize)) | Mask1 | Mask2 | MModIWRReg | MModImm);
switch (AdrMode)
{
case ModIWReg:
BAsmCode[0] = 0xb5;
BAsmCode[1] = (AdrPart << 4) + HReg + 1;
CodeLen = 2;
break;
case ModWReg:
BAsmCode[0] = 0x72;
BAsmCode[1] = 0xf0 + HReg;
BAsmCode[2] = AdrPart + WorkOfs;
CodeLen = 3;
break;
case ModWRReg:
BAsmCode[0] = 0xe3;
BAsmCode[1] = (HReg << 4) + 0x10 + AdrPart;
CodeLen = 2;
break;
case ModReg:
case ModRReg:
BAsmCode[0] = 0x72 + (OpSize * 0x4c);
BAsmCode[1] = 0xf0 + HReg + OpSize;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
case ModIWRReg:
if (OpSize == 0)
{
BAsmCode[0] = 0x73;
BAsmCode[1] = 0xf0 + AdrPart;
BAsmCode[2] = WorkOfs + HReg;
CodeLen = 3;
}
else
{
BAsmCode[0] = 0xe3;
BAsmCode[1] = 0x11 + (HReg << 4) + AdrPart;
CodeLen = 2;
}
break;
case ModImm:
BAsmCode[0] = 0xf3 - (OpSize * 0x35);
BAsmCode[1] = 0xf0 + HReg;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
break;
}
break;
case ModIncWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2 | (MModIncWReg * (1 - OpSize)));
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0xb4 + (OpSize * 0x21);
BAsmCode[1] = 0xf0 + HReg;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
case ModIncWReg:
BAsmCode[0] = 0xd7;
BAsmCode[1] = (AdrPart << 4) + HReg;
CodeLen = 2;
break;
}
break;
case ModDecWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2);
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0xc2 + OpSize;
BAsmCode[1] = 0xf0 + HReg;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
}
break;
case ModDispRWRReg:
HReg = AdrPart; HPart = AdrVals[0];
DecodeAdr(&ArgStr[2], Mask1);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
BAsmCode[0] = 0x60;
BAsmCode[1] = (0x10 * (1 - OpSize)) + 0x01 + (HPart << 4) + HReg;
BAsmCode[2] = 0xf0 + AdrPart;
CodeLen = 3;
break;
}
break;
case ModDisp8WRReg:
BAsmCode[2] = AdrVals[0]; HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2 | (OpSize * MModImm));
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0x26 + (OpSize * 0x60);
BAsmCode[1] = 0xf1 + HReg;
BAsmCode[3] = AdrVals[0];
CodeLen = 4;
break;
case ModImm:
BAsmCode[0] = 0x06;
BAsmCode[1] = 0xf1 + HReg;
memcpy(BAsmCode
+ 3, AdrVals
, AdrCnt
);
CodeLen = 3 + AdrCnt;
break;
}
break;
case ModDisp16WRReg:
memcpy(BAsmCode
+ 2, AdrVals
, 2); HReg
= AdrPart
;
DecodeAdr(&ArgStr[2], Mask2 | (OpSize * MModImm));
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0x26 + (OpSize * 0x60);
BAsmCode[1] = 0xf0 + HReg;
BAsmCode[4] = AdrVals[0];
CodeLen = 5;
break;
case ModImm:
BAsmCode[0] = 0x06;
BAsmCode[1] = 0xf0 + HReg;
memcpy(BAsmCode
+ 4, AdrVals
, AdrCnt
);
CodeLen =4 + AdrCnt;
break;
}
break;
case ModAbs:
memcpy(BAsmCode
+ 2, AdrVals
, 2);
DecodeAdr(&ArgStr[2], Mask1 | MModImm);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
BAsmCode[0] = 0xc5 + (OpSize * 0x1d);
BAsmCode[1] = 0xf0 + AdrPart + OpSize;
CodeLen = 4;
break;
case ModImm:
memmove(BAsmCode
+ 2 + AdrCnt
, BAsmCode
+ 2, 2);
BAsmCode[0] = 0x2f + (OpSize * 7);
BAsmCode[1] = 0xf1;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 4 + AdrCnt;
break;
}
break;
case ModIRReg:
HReg = AdrVals[0];
DecodeAdr(&ArgStr[2], MModIWRReg * (1 - OpSize));
switch (AdrMode)
{
case ModIWRReg:
BAsmCode[0] = 0x73;
BAsmCode[1] = 0xf0 + AdrPart;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
}
break;
}
}
}
static void DecodeLoad(Word Code)
{
Byte HReg;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModIncWRReg);
if (AdrMode == ModIncWRReg)
{
HReg = AdrPart << 4;
DecodeAdr(&ArgStr[2], MModIncWRReg);
if (AdrMode == ModIncWRReg)
{
BAsmCode[0] = 0xd6;
BAsmCode[1] = Code + HReg + AdrPart;
CodeLen = 2;
}
}
}
}
static void DecodePEA_PEAU(Word Code)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModDisp8RReg | MModDisp16RReg);
if (AdrMode != ModNone)
{
BAsmCode[0] = 0x8f;
BAsmCode[1] = Code;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
BAsmCode[2] += AdrCnt - 2;
CodeLen =2 + AdrCnt;
}
}
}
static void DecodePUSH_PUSHU(Word IsU)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModImm);
switch (AdrMode)
{
case ModReg:
BAsmCode[0] = 0x66 - (IsU * 0x36);
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModIReg:
BAsmCode[0] = 0xf7 - (IsU * 0xc6);
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModImm:
BAsmCode[0] = 0x8f;
BAsmCode[1] = 0xf1 + (IsU * 2);
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
}
}
}
static void DecodePUSHW_PUSHUW(Word IsU)
{
OpSize = 1;
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModRReg | MModImm);
switch (AdrMode)
{
case ModRReg:
BAsmCode[0] = 0x74 + (IsU * 0x42);
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModImm:
BAsmCode[0] = 0x8f;
BAsmCode[1] = 0xc1 + (IsU * 2);
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
break;
}
}
}
static void DecodeXCH(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModReg);
if (AdrMode == ModReg)
{
BAsmCode[2] = AdrVals[0];
DecodeAdr(&ArgStr[2], MModReg);
if (AdrMode == ModReg)
{
BAsmCode[1] = AdrVals[0];
BAsmCode[0] = 0x16;
CodeLen = 3;
}
}
}
}
static void DecodeALU(Word Code)
{
Word Mask1, Mask2;
Byte HReg, HPart;
Byte CodeMask = Lo(Code) << 4;
if (ChkArgCnt(2, 2))
{
if (Hi(Code))
{
OpSize = 1; Mask1 = MModWRReg; Mask2 = MModRReg;
}
else
{
Mask1 = MModWReg; Mask2 = MModReg;
}
DecodeAdr(&ArgStr[1], Mask1 | Mask2 | MModIWReg | MModIWRReg | MModIncWRReg |
MModDecWRReg | MModDispRWRReg | MModDisp8WRReg | MModDisp16WRReg |
MModAbs | MModIRReg);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask1 | MModIWReg | Mask2 | MModIWRReg | MModIncWRReg |
MModDecWRReg | MModDispRWRReg | MModDisp8WRReg | MModDisp16WRReg |
MModAbs | MModImm);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
BAsmCode[0] = CodeMask + 2 + (OpSize * 12);
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
break;
case ModIWReg:
if (OpSize == 0)
{
BAsmCode[0] = CodeMask + 3;
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
}
else
{
BAsmCode[0] = 0xa6;
BAsmCode[1] = CodeMask + AdrPart;
BAsmCode[2] = WorkOfs + HReg;
CodeLen = 3;
}
break;
case ModReg:
case ModRReg:
BAsmCode[0] = CodeMask + 4 + (OpSize * 3);
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = HReg + WorkOfs;
CodeLen = 3;
break;
case ModIWRReg:
if (OpSize == 0)
{
BAsmCode[0] = 0x72;
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = HReg + WorkOfs;
CodeLen = 3;
}
else
{
BAsmCode[0] = CodeMask + 0x0e;
BAsmCode[1] = (HReg << 4) + AdrPart + 1;
CodeLen = 2;
}
break;
case ModIncWRReg:
BAsmCode[0] = 0xb4 + (OpSize * 0x21);
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = HReg + WorkOfs;
CodeLen = 3;
break;
case ModDecWRReg:
BAsmCode[0] = 0xc2 + OpSize;
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = HReg + WorkOfs;
CodeLen = 3;
break;
case ModDispRWRReg:
BAsmCode[0] = 0x60;
BAsmCode[1] = 0x10 * (1 - OpSize) + (AdrVals[0] << 4) + AdrPart;
BAsmCode[2] = CodeMask + HReg;
CodeLen = 3;
break;
case ModDisp8WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = AdrVals[0];
BAsmCode[3] = WorkOfs + HReg;
CodeLen = 4;
break;
case ModDisp16WRReg:
BAsmCode[0]= 0x7f + (OpSize * 7);
BAsmCode[1] = CodeMask + AdrPart;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
BAsmCode[2 + AdrCnt] = WorkOfs + HReg;
CodeLen = 3 + AdrCnt;
break;
case ModAbs:
BAsmCode[0] = 0xc4 + (OpSize * 30);
BAsmCode[1] = CodeMask + HReg;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
break;
case ModImm:
BAsmCode[0] = CodeMask + 5 + (OpSize * 2);
BAsmCode[1] = WorkOfs + HReg + OpSize;
memcpy(BAsmCode
+ 2,AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
break;
}
break;
case ModReg:
case ModRReg:
HReg = AdrVals[0];
DecodeAdr(&ArgStr[2], Mask2 | MModIWReg | MModIWRReg | MModIncWRReg | MModDecWRReg |
MModDisp8WRReg | MModDisp16WRReg | MModImm);
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = CodeMask + 4 + (OpSize * 3);
CodeLen = 3;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = HReg;
break;
case ModIWReg:
BAsmCode[0] = 0xa6 + 65 * (1 - OpSize);
BAsmCode[1] = CodeMask + AdrPart;
BAsmCode[2] = HReg;
CodeLen=3;
break;
case ModIWRReg:
BAsmCode[0] = 0x72 + (OpSize * 12);
BAsmCode[1] = CodeMask + AdrPart + (1 - OpSize);
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModIncWRReg:
BAsmCode[0] = 0xb4 + (OpSize * 0x21);
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModDecWRReg:
BAsmCode[0] = 0xc2 + OpSize;
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
case ModDisp8WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = CodeMask + AdrPart + 1;
BAsmCode[2] = AdrVals[0];
BAsmCode[3] = HReg;
CodeLen = 4;
break;
case ModDisp16WRReg:
BAsmCode[0] = 0x7f + (OpSize * 7);
BAsmCode[1] = CodeMask + AdrPart;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
BAsmCode[2 + AdrCnt] = HReg;
CodeLen = 3 + AdrCnt;
break;
case ModImm:
BAsmCode[0] = CodeMask + 5 + (OpSize * 2);
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
); BAsmCode
[1] = HReg
+ OpSize
;
CodeLen = 2 + AdrCnt;
break;
}
break;
case ModIWReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2);
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0xe6 - (OpSize * 0x50);
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = CodeMask + HReg;
CodeLen = 3;
break;
}
break;
case ModIWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], (OpSize * MModWRReg) | Mask2 | MModIWRReg | MModImm);
switch (AdrMode)
{
case ModWRReg:
BAsmCode[0] = CodeMask + 0x0e;
BAsmCode[1] = (HReg << 4) + 0x10 + AdrPart;
CodeLen = 2;
break;
case ModReg:
case ModRReg:
BAsmCode[0] = 0x72 + (OpSize * 76);
BAsmCode[1] = CodeMask + HReg + OpSize;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
case ModIWRReg:
if (OpSize == 0)
{
BAsmCode[0] = 0x73;
BAsmCode[1] = CodeMask + AdrPart;
BAsmCode[2] = HReg + WorkOfs;
CodeLen = 3;
}
else
{
BAsmCode[0] = CodeMask + 0x0e;
BAsmCode[1] = 0x11 + (HReg << 4) + AdrPart;
CodeLen = 2;
}
break;
case ModImm:
BAsmCode[0] = 0xf3 - (OpSize * 0x35);
BAsmCode[1] = CodeMask + HReg;
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
CodeLen = 2 + AdrCnt;
break;
}
break;
case ModIncWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2);
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0xb4 + (OpSize * 0x21);
BAsmCode[1] = CodeMask + HReg;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
}
break;
case ModDecWRReg:
HReg = AdrPart;
DecodeAdr(&ArgStr[2], Mask2);
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0xc2 + OpSize;
BAsmCode[1] = CodeMask + HReg;
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
}
break;
case ModDispRWRReg:
HReg = AdrPart; HPart = AdrVals[0];
DecodeAdr(&ArgStr[2], Mask1);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
BAsmCode[0] = 0x60;
BAsmCode[1] = 0x11 - (OpSize * 0x10) + (HPart << 4) + HReg;
BAsmCode[2] = CodeMask + AdrPart;
CodeLen = 3;
break;
}
break;
case ModDisp8WRReg:
HReg = AdrPart;
BAsmCode[2] = AdrVals[0];
DecodeAdr(&ArgStr[2], Mask2 + (OpSize * MModImm));
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0x26 + (OpSize * 0x60);
BAsmCode[1] = CodeMask + HReg + 1;
BAsmCode[3] = AdrVals[0] + OpSize;
CodeLen = 4;
break;
case ModImm:
BAsmCode[0] = 0x06;
BAsmCode[1] = CodeMask + HReg + 1;
memcpy(BAsmCode
+ 3, AdrVals
, AdrCnt
);
CodeLen = 3 + AdrCnt;
break;
}
break;
case ModDisp16WRReg:
HReg
= AdrPart
; memcpy(BAsmCode
+ 2, AdrVals
, 2);
DecodeAdr(&ArgStr[2], Mask2 | (OpSize * MModImm));
switch (AdrMode)
{
case ModReg:
case ModRReg:
BAsmCode[0] = 0x26 + (OpSize * 0x60);
BAsmCode[1] = CodeMask + HReg;
BAsmCode[4] = AdrVals[0] + OpSize;
CodeLen = 5;
break;
case ModImm:
BAsmCode[0] = 0x06;
BAsmCode[1] = CodeMask + HReg;
memcpy(BAsmCode
+ 4, AdrVals
, AdrCnt
);
CodeLen = 4 + AdrCnt;
break;
}
break;
case ModAbs:
memcpy(BAsmCode
+ 2, AdrVals
, 2);
DecodeAdr(&ArgStr[2], Mask1 | MModImm);
switch (AdrMode)
{
case ModWReg:
case ModWRReg:
BAsmCode[0] = 0xc5 + (OpSize * 29);
BAsmCode[1] = CodeMask + AdrPart + OpSize;
CodeLen = 4;
break;
case ModImm:
memmove(BAsmCode
+ 2 + AdrCnt
, BAsmCode
+ 2, 2);
memcpy(BAsmCode
+ 2, AdrVals
, AdrCnt
);
BAsmCode[0] = 0x2f + (OpSize * 7);
BAsmCode[1] = CodeMask + 1;
CodeLen = 4 + AdrCnt;
break;
}
break;
case ModIRReg:
HReg = AdrVals[0];
DecodeAdr(&ArgStr[2], MModIWRReg *(1 - OpSize));
switch (AdrMode)
{
case ModIWRReg:
BAsmCode[0] = 0x73;
BAsmCode[1] = CodeMask + AdrPart;
BAsmCode[2] = HReg;
CodeLen = 3;
break;
}
break;
}
}
}
static void DecodeReg8(Word Code)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModReg | MModIReg);
switch (AdrMode)
{
case ModReg:
BAsmCode[0] = Code;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
case ModIReg:
BAsmCode[0] = Code + 1;
BAsmCode[1] = AdrVals[0];
CodeLen = 2;
break;
}
}
}
static void DecodeReg16(Word Code)
{
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModRReg);
switch (AdrMode)
{
case ModRReg:
BAsmCode[0] = Lo(Code);
BAsmCode[1] = AdrVals[0] + Hi(Code);
CodeLen = 2;
break;
}
}
}
static void DecodeDIV_MUL(Word Code)
{
Byte HReg;
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModWRReg);
if (AdrMode == ModWRReg)
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModWReg);
if (AdrMode == ModWReg)
{
BAsmCode[0] = Code;
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
}
}
}
}
static void DecodeDIVWS(Word Code)
{
Byte HReg;
UNUSED(Code);
if (ChkArgCnt(3, 3))
{
DecodeAdr(&ArgStr[1], MModWRReg);
if (AdrMode == ModWRReg)
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModWRReg);
if (AdrMode == ModWRReg)
{
BAsmCode[2] = (HReg << 4) + AdrPart;
DecodeAdr(&ArgStr[3], MModRReg);
if (AdrMode == ModRReg)
{
BAsmCode[0] = 0x56;
BAsmCode[1] = AdrVals[0];
CodeLen = 3;
}
}
}
}
}
static void DecodeBit2(Word Code)
{
Byte HReg, HPart;
tStrComp Comp;
if (ChkArgCnt(2, 2) && SplitBit(&Comp, &ArgStr[1], &HReg))
{
if (Odd(HReg)) WrError(ErrNum_InvAddrMode);
else
{
DecodeAdr(&Comp, MModWReg);
if (AdrMode == ModWReg)
{
HReg = (HReg << 4) + AdrPart;
if (SplitBit(&Comp, &ArgStr[2], &HPart))
{
DecodeAdr(&Comp, MModWReg);
if (AdrMode == ModWReg)
{
HPart = (HPart << 4) + AdrPart;
BAsmCode[0] = Code;
switch (Code)
{
case 0xf2: /* BLD */
BAsmCode[1] = HPart | 0x10;
BAsmCode[2] = HReg | (HPart & 0x10);
break;
case 0x6f: /* BXOR */
BAsmCode[1] = 0x10 + HReg;
BAsmCode[2] = HPart;
break;
default:
BAsmCode[1] = 0x10 + HReg;
BAsmCode[2] = HPart ^ 0x10;
}
CodeLen = 3;
}
}
}
}
}
}
static void DecodeBit1(Word Code)
{
Byte HReg;
tStrComp Comp;
if (ChkArgCnt(1, 1) && SplitBit(&Comp, &ArgStr[1], &HReg))
{
if (Odd(HReg)) WrError(ErrNum_InvAddrMode);
else
{
DecodeAdr(&Comp, MModWReg + (Hi(Code) * MModIWRReg));
switch (AdrMode)
{
case ModWReg:
BAsmCode[0] = Lo(Code);
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
break;
case ModIWRReg:
BAsmCode[0] = 0xf6;
BAsmCode[1] = (HReg << 4) + AdrPart;
CodeLen = 2;
break;
}
}
}
}
static void DecodeBTJF_BTJT(Word Code)
{
Byte HReg;
Integer AdrInt;
tStrComp Comp;
if (ChkArgCnt(2, 2) && SplitBit(&Comp, &ArgStr[1], &HReg))
{
if (Odd(HReg)) WrError(ErrNum_InvAddrMode);
else
{
DecodeAdr(&Comp, MModWReg);
if (AdrMode == ModWReg)
{
tEvalResult EvalResult;
BAsmCode[1] = (HReg << 4) + AdrPart + Code;
AdrInt = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &EvalResult) - (EProgCounter() + 3);
if (EvalResult.OK)
{
if (!mSymbolQuestionable(EvalResult.Flags) && ((AdrInt < -128) || (AdrInt > 127))) WrError(ErrNum_JmpDistTooBig);
else
{
BAsmCode[0] = 0xaf;
BAsmCode[2] = AdrInt & 0xff;
CodeLen = 3;
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
}
}
}
}
}
}
static void DecodeJP_CALL(Word Code)
{
if (ChkArgCnt(1, 1))
{
AbsSeg = SegCode;
DecodeAdr(&ArgStr[1], MModIRReg | MModAbs);
switch (AdrMode)
{
case ModIRReg:
BAsmCode[0] = Hi(Code);
BAsmCode[1] = AdrVals[0] + Ord(Memo("CALL"));
CodeLen = 2;
break;
case ModAbs:
BAsmCode[0] = Lo(Code);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
CodeLen =1 + AdrCnt;
break;
}
}
}
static void DecodeCPJFI_CPJTI(Word Code)
{
Byte HReg;
Integer AdrInt;
if (ChkArgCnt(3, 3))
{
DecodeAdr(&ArgStr[1], MModWReg);
if (AdrMode == ModWReg)
{
HReg = AdrPart;
DecodeAdr(&ArgStr[2], MModIWRReg);
if (AdrMode == ModIWRReg)
{
tEvalResult EvalResult;
BAsmCode[1] = (AdrPart << 4) + Code + HReg;
AdrInt = EvalStrIntExpressionWithResult(&ArgStr[3], UInt16, &EvalResult) - (EProgCounter() + 3);
if (EvalResult.OK)
{
if (!mSymbolQuestionable(EvalResult.Flags) && ((AdrInt<-128) || (AdrInt>127))) WrError(ErrNum_JmpDistTooBig);
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[0] = 0x9f;
BAsmCode[2] = AdrInt & 0xff;
CodeLen = 3;
}
}
}
}
}
}
static void DecodeDJNZ(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModWReg);
if (AdrMode == ModWReg)
{
Integer AdrInt;
tEvalResult EvalResult;
BAsmCode[0] = (AdrPart << 4) + 0x0a;
AdrInt = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &EvalResult) - (EProgCounter() + 2);
if (EvalResult.OK)
{
if (!mSymbolQuestionable(EvalResult.Flags) && ((AdrInt < -128) || (AdrInt > 127))) WrError(ErrNum_JmpDistTooBig);
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[1] = AdrInt & 0xff;
CodeLen = 2;
}
}
}
}
}
static void DecodeDWJNZ(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(2, 2))
{
DecodeAdr(&ArgStr[1], MModRReg);
if (AdrMode == ModRReg)
{
Integer AdrInt;
tEvalResult EvalResult;
BAsmCode[1] = AdrVals[0];
AdrInt = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &EvalResult) - (EProgCounter() + 3);
if (EvalResult.OK)
{
if (!mSymbolQuestionable(EvalResult.Flags) && ((AdrInt < -128) || (AdrInt > 127))) WrError(ErrNum_JmpDistTooBig);
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[0] = 0xc6;
BAsmCode[2] = AdrInt & 0xff;
CodeLen = 3;
}
}
}
}
}
static void DecodeCondAbs(Word Code)
{
if (ChkArgCnt(1, 1))
{
tEvalResult EvalResult;
Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
if (EvalResult.OK)
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[0] = 0x0d + Code;
BAsmCode[1] = Hi(AdrWord);
BAsmCode[2] = Lo(AdrWord);
CodeLen = 3;
}
}
}
static void DecodeCondRel(Word Code)
{
if (ChkArgCnt(1, 1))
{
tEvalResult EvalResult;
Integer AdrInt = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult) - (EProgCounter() + 2);
if (EvalResult.OK)
{
if (!mSymbolQuestionable(EvalResult.Flags) && ((AdrInt < -128) || (AdrInt > 127))) WrError(ErrNum_JmpDistTooBig);
else
{
ChkSpace(SegCode, EvalResult.AddrSpaceMask);
BAsmCode[0] = 0x0b + Code;
BAsmCode[1] = AdrInt & 0xff;
CodeLen = 2;
}
}
}
}
static void DecodeSPP(Word Code)
{
Boolean OK;
UNUSED(Code);
if (!ChkArgCnt(1, 1));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[1] = (EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt6, &OK) << 2) + 0x02;
if (OK)
{
BAsmCode[0] = 0xc7;
CodeLen = 2;
}
}
}
static void DecodeSRP(Word Code)
{
Boolean OK;
if (!ChkArgCnt(1, 1));
else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_InvAddrMode);
else
{
BAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt5, &OK) << 3;
if (OK)
{
BAsmCode[0] = 0xc7;
BAsmCode[1] += Code;
CodeLen=2;
}
}
}
static void DecodeSLA(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModWReg | MModReg | MModIWRReg);
switch (AdrMode)
{
case ModWReg:
BAsmCode[0] = 0x42;
BAsmCode[1] = (AdrPart << 4) + AdrPart;
CodeLen = 2;
break;
case ModReg:
BAsmCode[0] = 0x44;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
case ModIWRReg:
BAsmCode[0] = 0x73;
BAsmCode[1] = 0x40 + AdrPart;
BAsmCode[2] = WorkOfs + AdrPart;
CodeLen = 3;
break;
}
}
}
static void DecodeSLAW(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
DecodeAdr(&ArgStr[1], MModWRReg | MModRReg | MModIWRReg);
switch (AdrMode)
{
case ModWRReg:
BAsmCode[0] = 0x4e;
BAsmCode[1] = (AdrPart << 4) + AdrPart;
CodeLen = 2;
break;
case ModRReg:
BAsmCode[0] = 0x47;
BAsmCode[1] = AdrVals[0];
BAsmCode[2] = AdrVals[0];
CodeLen = 3;
break;
case ModIWRReg:
BAsmCode[0] = 0x4e;
BAsmCode[1] = 0x11 + (AdrPart << 4) + AdrPart;
CodeLen = 2;
break;
}
}
}
static void DecodeREG(Word Code)
{
UNUSED(Code);
CodeEquate(SegReg,0,0x1ff);
}
static void DecodeBIT(Word Code)
{
Byte Bit;
tStrComp Comp;
UNUSED(Code);
if (ChkArgCnt(1, 1) && SplitBit(&Comp, &ArgStr[1], &Bit))
{
DecodeAdr(&Comp, MModWReg);
if (AdrMode == ModWReg)
{
PushLocHandle(-1);
EnterIntSymbol(&LabPart, (AdrPart << 4) + Bit, SegNone, False);
PopLocHandle();
as_snprintf(ListLine, STRINGSIZE, "=r%d.%s%c",
(int)AdrPart,
(Odd(Bit)) ? "!" : "", (Bit >> 1) + AscOfs);
}
}
}
/*--------------------------------------------------------------------------*/
/* Code Table Handling */
static void AddFixed(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFixed);
}
static void AddALU(const char *NName8, const char *NName16, Word NCode)
{
AddInstTable(InstTable, NName8, NCode, DecodeALU);
AddInstTable(InstTable, NName16, NCode | 0x100, DecodeALU);
}
static void AddReg(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeReg8);
}
static void AddReg16(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeReg16);
}
static void AddBit2(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBit2);
}
static void AddBit1(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBit1);
}
static void AddCondition(const char *NameAbs, const char *NameRel, Word NCode)
{
AddInstTable(InstTable, NameAbs, NCode << 4, DecodeCondAbs);
AddInstTable(InstTable, NameRel, NCode << 4, DecodeCondRel);
}
static void AddLoad(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeLoad);
}
static void InitFields(void)
{
InstTable = CreateInstTable(201);
AddInstTable(InstTable, "LD", 0, DecodeLD);
AddInstTable(InstTable, "LDW", 1, DecodeLD);
AddInstTable(InstTable, "PEA", 0x01, DecodePEA_PEAU);
AddInstTable(InstTable, "PEAU", 0x03, DecodePEA_PEAU);
AddInstTable(InstTable, "PUSH", 0, DecodePUSH_PUSHU);
AddInstTable(InstTable, "PUSHU", 1, DecodePUSH_PUSHU);
AddInstTable(InstTable, "PUSHW", 0, DecodePUSHW_PUSHUW);
AddInstTable(InstTable, "PUSHUW", 1, DecodePUSHW_PUSHUW);
AddInstTable(InstTable, "XCH", 0, DecodeXCH);
AddInstTable(InstTable, "DIV", 0x5f, DecodeDIV_MUL);
AddInstTable(InstTable, "MUL", 0x4f, DecodeDIV_MUL);
AddInstTable(InstTable, "DIVWS", 0, DecodeDIVWS);
AddInstTable(InstTable, "BTJF", 0x10, DecodeBTJF_BTJT);
AddInstTable(InstTable, "BTJT", 0, DecodeBTJF_BTJT);
AddInstTable(InstTable, "JP", 0xd48d, DecodeJP_CALL);
AddInstTable(InstTable, "CALL", 0x74d2, DecodeJP_CALL);
AddInstTable(InstTable, "CPJFI", 0, DecodeCPJFI_CPJTI);
AddInstTable(InstTable, "CPJTI", 0x10, DecodeCPJFI_CPJTI);
AddInstTable(InstTable, "DJNZ", 0, DecodeDJNZ);
AddInstTable(InstTable, "DWJNZ", 0, DecodeDWJNZ);
AddInstTable(InstTable, "SPP", 0, DecodeSPP);
AddInstTable(InstTable, "SRP", 0x00, DecodeSRP);
AddInstTable(InstTable, "SRP0", 0x04, DecodeSRP);
AddInstTable(InstTable, "SRP1", 0x05, DecodeSRP);
AddInstTable(InstTable, "SLA", 0, DecodeSLA);
AddInstTable(InstTable, "SLAW", 0, DecodeSLAW);
AddInstTable(InstTable, "REG", 0, DecodeREG);
AddInstTable(InstTable, "BIT", 0, DecodeBIT);
AddFixed("CCF" , 0x0061); AddFixed("DI" , 0x0010);
AddFixed("EI" , 0x0000); AddFixed("HALT", 0xbf01);
AddFixed("IRET", 0x00d3); AddFixed("NOP" , 0x00ff);
AddFixed("RCF" , 0x0011); AddFixed("RET" , 0x0046);
AddFixed("SCF" , 0x0001); AddFixed("SDM" , 0x00fe);
AddFixed("SPM" , 0x00ee); AddFixed("WFI" , 0xef01);
AddALU("ADC", "ADCW", 3); AddALU("ADD", "ADDW", 4); AddALU("AND", "ANDW", 1);
AddALU("CP" , "CPW" , 9); AddALU("OR" , "ORW" , 0); AddALU("SBC", "SBCW", 2);
AddALU("SUB", "SUBW", 5); AddALU("TCM", "TCMW", 8); AddALU("TM" , "TMW" , 10);
AddALU("XOR", "XORW", 6);
AddReg("CLR" , 0x90); AddReg("CPL" , 0x80); AddReg("DA" , 0x70);
AddReg("DEC" , 0x40); AddReg("INC" , 0x50); AddReg("POP" , 0x76);
AddReg("POPU", 0x20); AddReg("RLC" , 0xb0); AddReg("ROL" , 0xa0);
AddReg("ROR" , 0xc0); AddReg("RRC" , 0xd0); AddReg("SRA" , 0xe0);
AddReg("SWAP", 0xf0);
AddReg16("DECW" , 0x00cf); AddReg16("EXT" , 0x01c6);
AddReg16("INCW" , 0x00df); AddReg16("POPUW", 0x00b7);
AddReg16("POPW" , 0x0075); AddReg16("RLCW" , 0x008f);
AddReg16("RRCW" , 0x0036); AddReg16("SRAW" , 0x002f);
AddBit2("BAND", 0x1f); AddBit2("BLD" , 0xf2);
AddBit2("BOR" , 0x0f); AddBit2("BXOR", 0x6f);
AddBit1("BCPL", 0x006f); AddBit1("BRES" , 0x001f);
AddBit1("BSET", 0x000f); AddBit1("BTSET", 0x01f2);
AddCondition("JPF" , "JRF" , 0x0); AddCondition("JPT" , "JRT" , 0x8);
AddCondition("JPC" , "JRC" , 0x7); AddCondition("JPNC" , "JRNC" , 0xf);
AddCondition("JPZ" , "JRZ" , 0x6); AddCondition("JPNZ" , "JRNZ" , 0xe);
AddCondition("JPPL" , "JRPL" , 0xd); AddCondition("JPMI" , "JRMI" , 0x5);
AddCondition("JPOV" , "JROV" , 0x4); AddCondition("JPNOV" , "JRNOV" , 0xc);
AddCondition("JPEQ" , "JREQ" , 0x6); AddCondition("JPNE" , "JRNE" , 0xe);
AddCondition("JPGE" , "JRGE" , 0x9); AddCondition("JPLT" , "JRLT" , 0x1);
AddCondition("JPGT" , "JRGT" , 0xa); AddCondition("JPLE" , "JRLE" , 0x2);
AddCondition("JPUGE" , "JRUGE" , 0xf); AddCondition("JPUL" , "JRUL" , 0x7);
AddCondition("JPUGT" , "JRUGT" , 0xb); AddCondition("JPULE" , "JRULE" , 0x3);
AddLoad("LDPP", 0x00); AddLoad("LDDP", 0x10);
AddLoad("LDPD", 0x01); AddLoad("LDDD", 0x11);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
}
/*--------------------------------------------------------------------------*/
static void MakeCode_ST9(void)
{
CodeLen = 0; DontPrint = False; OpSize = 0;
AbsSeg = (DPAssume == 1) ? SegData : SegCode;
/* zu ignorierendes */
if (Memo("")) return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(True)) return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static void InitCode_ST9(void)
{
DPAssume = 0;
}
static Boolean IsDef_ST9(void)
{
return (Memo("REG") || Memo("BIT"));
}
static void SwitchFrom_ST9(void)
{
DeinitFields();
}
static void InternSymbol_ST9(char *Asc, TempResult *Erg)
{
Boolean OK;
Boolean Pair;
LargeInt Num;
as_tempres_set_none(Erg);
if ((strlen(Asc
) < 2) || (*Asc
!= 'R'))
return;
Asc++;
if (*Asc == 'R')
{
Pair = True; Asc++;
}
else
Pair = False;
Num = ConstLongInt(Asc, &OK, 10);
if (!OK || (Num < 0) || (Num > 255)) return;
if ((Num & 0xf0) == 0xd0) return;
if (Pair && Odd(Num)) return;
if (Pair) Num += 0x100;
as_tempres_set_int(Erg, Num); Erg->AddrSpaceMask |= (1 << SegReg);
}
static void SwitchTo_ST9(void)
{
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
PCSymbol = "PC"; HeaderID = 0x32; NOPCode = 0xff;
DivideChars = ","; HasAttrs = False;
ValidSegs = (1 << SegCode) | (1 << SegData) | ( 1 << SegReg);
Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
SegLimits[SegCode] = 0xffff;
Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0;
SegLimits[SegData] = 0xffff;
Grans[SegReg ] = 1; ListGrans[SegReg ] = 1; SegInits[SegReg ] = 0;
SegLimits[SegReg ] = 0xff;
MakeCode=MakeCode_ST9; IsDef=IsDef_ST9;
SwitchFrom=SwitchFrom_ST9; InternSymbol=InternSymbol_ST9;
pASSUMERecs = ASSUMEST9s;
ASSUMERecCnt = ASSUMEST9Count;
InitFields();
}
void codest9_init(void)
{
CPUST9020 = AddCPU("ST9020", SwitchTo_ST9);
CPUST9030 = AddCPU("ST9030", SwitchTo_ST9);
CPUST9040 = AddCPU("ST9040", SwitchTo_ST9);
CPUST9050 = AddCPU("ST9050", SwitchTo_ST9);
AddInitPassProc(InitCode_ST9);
}