/* coderx.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator Renesas RX */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "nls.h"
#include "strutil.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codevars.h"
#include "codepseudo.h"
#include "headids.h"
#include "errmsg.h"
#include "ieeefloat.h"
#include "onoff_common.h"
#include "intpseudo.h"
#include "be_le.h"
#include "coderx.h"
/*---------------------------------------------------------------------------*/
/* Define this to use Renesas Assembler like pseudo instructions */
#define COMPAT
/*---------------------------------------------------------------------------*/
typedef enum
{
eRn,
eDRn,
eDRHn,
eDRLn,
eDCRn
} tRegType;
typedef enum
{
eRXv1,
eRXv2,
eRXv3
} tInstSet;
typedef struct
{
char Name[7];
tInstSet InstSet;
Boolean hasFloat;
Boolean hasDouble;
Word RegBank;
Boolean hasMVTIPL;
} tCPUProps;
/*---------------------------------------------------------------------------*/
static const tCPUProps *pCurrCPUProps;
static tStrComp Temp1;
static tStrComp Temp2;
/*---------------------------------------------------------------------------*/
static Boolean ChkNoAttr(void)
{
if (AttrPart.str.p_str[0])
{
WrError(ErrNum_UseLessAttr);
return False;
}
return True;
}
static Boolean CheckSup(void)
{
if (SupAllowed) return True;
WrStrErrorPos(ErrNum_PrivOrder, &OpPart);
return False;
}
static Boolean CheckV2(void)
{
if (pCurrCPUProps->InstSet >= eRXv2) return True;
WrError(ErrNum_InstructionNotSupported);
return False;
}
static Boolean CheckV3(void)
{
if (pCurrCPUProps->InstSet >= eRXv3) return True;
WrError(ErrNum_InstructionNotSupported);
return False;
}
static Boolean CheckFloat(void)
{
if (pCurrCPUProps->hasFloat) return True;
WrError(ErrNum_FPUNotEnabled);
return False;
}
static Boolean CheckDouble(void)
{
if (pCurrCPUProps->hasDouble) return True;
WrError(ErrNum_FPUNotEnabled);
return False;
}
static const char *DCReg[] = {
"DPSW",
"DCMR",
"DECNT",
"DEPC"
};
static Boolean DecodeReg(const tStrComp *pArg, Byte *pResult, tRegType type)
{
const char *str = pArg->str.p_str;
int i;
int num = 16;
switch (type)
{
case eRn:
if (as_strncasecmp(str, "R", 1)) return False;
i = 1;
break;
case eDRn:
if (as_strncasecmp(str, "DR", 2)) return False;
i = 2;
break;
case eDRHn:
if (as_strncasecmp(str, "DRH", 3)) return False;
i = 3;
break;
case eDRLn:
if (as_strncasecmp(str, "DRL", 3)) return False;
i = 3;
break;
case eDCRn:
for (i = 0; i < 4; i++)
{
if (!as_strcasecmp(str, DCReg[i]))
{
*pResult = i;
return True;
}
}
if (as_strncasecmp(str, "DCR", 3)) return False;
i = 3;
num = 4;
break;
}
*pResult = 0;
for (; i < len; i++)
{
if (!isdigit(str
[i
])) return False
;
*pResult = *pResult * 10 + (str[i] - '0');
}
return *pResult < num;
}
static Boolean DecodeImm(const tStrComp *pArg, LongInt *pResult, tSymbolFlags *pFlags)
{
const char *str = pArg->str.p_str;
tStrComp ImmArg;
Boolean ValOK;
tSymbolFlags flags;
if (str[0] != '#') return False;
StrCompRefRight(&ImmArg, pArg, 1);
*pResult = EvalStrIntExpressionWithFlags(&ImmArg, Int32, &ValOK, &flags);
if (pFlags) *pFlags = flags;
return ValOK;
}
static Byte ImmSize32(LongInt value, tSymbolFlags flags)
{
if (mFirstPassUnknown(flags)) return 0x00; /* Temporarily return maximum size */
if ((value & 0xFFFFFF80) == 0xFFFFFF80 ||
(value & 0xFFFFFF80) == 0x00000000) return 0x01; /* SIMM:8 */
if ((value & 0xFFFF8000) == 0xFFFF8000 ||
(value & 0xFFFF8000) == 0x00000000) return 0x02; /* SIMM:16 */
if ((value & 0xFF800000) == 0xFF800000 ||
(value & 0xFF800000) == 0x00000000) return 0x03; /* SIMM:24 */
return 0x00; /* IMM:32 */
}
static Byte ImmSize16(LongInt value, tSymbolFlags flags)
{
if (mFirstPassUnknown(flags)) return 0x02; /* Temporarily return maximum size */
if ((value & 0xFFFFFF80) == 0xFFFFFF80 ||
(value & 0xFFFFFF80) == 0x00000000) return 0x01; /* SIMM:8 */
return 0x02; /* IMM:16 */
}
static int ImmOut(int pos, Byte size, LongInt imm)
{
int i;
if (size == 0x00) size = 4;
for (i = 0; i < size; i++)
{
BAsmCode[pos+i] = imm & 0xFF;
imm >>= 8;
}
return pos + size;
}
static Boolean DecodeIndirectADC(const tStrComp *pArg, Byte *reg, LongInt *disp, tSymbolFlags *flags)
{
const char *str = pArg->str.p_str;
int pos;
Boolean ValOK;
if (str[len-1] != ']') return False;
for (pos = len - 2; pos >= 0; pos--)
{
if (str[pos] == '[') break;
}
if (pos < 0) return False;
StrCompCopySub(&Temp1, pArg, pos + 1, len - pos - 2);
if (!DecodeReg(&Temp1, reg, eRn)) return False;
if (pos == 0)
{
*flags = eSymbolFlag_None;
*disp = 0;
return True;
}
StrCompCopySub(&Temp1, pArg, 0, pos);
*disp = EvalStrIntExpressionWithFlags(&Temp1, UInt20, &ValOK, flags);
return ValOK;
}
static Byte DispSize(LongInt disp, tSymbolFlags flags, Byte scale)
{
Byte size = 0;
Byte mask = scale - 1;
UNUSED(flags);
if (disp & mask)
{
WrStrErrorPos(ErrNum_NotAligned, &ArgStr[1]);
return 0;
}
disp /= scale;
if (disp == 0) size = 0x00;
else if (disp < 0) size = 0xFF;
else if (disp < 256) size = 0x01;
else if (disp < 65536) size = 0x02;
else size = 0xFF;
return size;
}
static int DispOut(int pos, Byte size, LongInt disp, Byte scale)
{
int i;
disp /= scale;
if (size > 0x02) size = 0x00;
for (i = 0; i < size; i++ )
{
BAsmCode[pos+i] = disp & 0xFF;
disp >>= 8;
}
return pos + size;
}
static Boolean DecodeIndirectADD(const tStrComp *pArg, Byte *reg, LongInt *disp, tSymbolFlags *flags, Byte *memex, Byte *scale)
{
const char *str = pArg->str.p_str;
if (len > 2 && str[len-2] == '.')
{
switch (as_toupper(str[len-1]))
{
case 'B':
*memex = 0x00;
*scale = 1;
break;
case 'W':
*memex = 0x01;
*scale = 2;
break;
case 'L':
*memex = 0x02;
*scale = 4;
break;
default:
return False;
}
StrCompCopySub(&Temp2, pArg, 0, len - 2);
pArg = &Temp2;
}
else if (len > 3 && str[len-3] == '.' && as_toupper(str[len-2]) == 'U')
{
switch (as_toupper(str[len-1]))
{
case 'B':
*memex = 0x80;
*scale = 1;
break;
case 'W':
*memex = 0x03;
*scale = 2;
break;
default:
return False;
}
StrCompCopySub(&Temp2, pArg, 0, len - 3);
pArg = &Temp2;
}
return DecodeIndirectADC(pArg, reg, disp, flags);
}
static Boolean DecodeFloat(const tStrComp *pArg, LongInt *pResult)
{
const char *str = pArg->str.p_str;
tStrComp ImmArg;
TempResult temp;
Boolean Result = True;
if (str[0] != '#') return False;
StrCompRefRight(&ImmArg, pArg, 1);
as_tempres_ini(&temp);
EvalStrExpression(&ImmArg, &temp);
switch (temp.Typ)
{
case TempInt:
*pResult = temp.Contents.Int;
break;
case TempFloat:
Double_2_ieee4(temp.Contents.Float, (unsigned char *)pResult, False);
/* TODO: rework this - we should better pass in a byte array as pResult */
if (HostBigEndian)
DSwap(pResult, 4);
break;
default:
Result = False;
}
as_tempres_free(&temp);
return Result;
}
static Boolean DecodeIndirectL(const tStrComp *pArg, Byte *reg, LongInt *disp, tSymbolFlags *flags)
{
Boolean result;
Byte memex = 0x02; /* L */
Byte scale;
result = DecodeIndirectADD(pArg, reg, disp, flags, &memex, &scale);
if (result && memex != 0x02) result = False;
return result;
}
static tSymbolSize DecodeAttrSize(void)
{
switch (strlen(AttrPart.
str.
p_str))
{
case 0:
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return eSymbolSizeUnknown;
case 1:
switch (AttrPart.str.p_str[0])
{
case 'B':
return eSymbolSize8Bit;
case 'W':
return eSymbolSize16Bit;
case 'L':
return eSymbolSize32Bit;
default:
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return eSymbolSizeUnknown;
}
default:
WrStrErrorPos(ErrNum_TooLongAttr, &AttrPart);
return eSymbolSizeUnknown;
}
}
static Boolean DecodeRelative(const tStrComp *pArg, Byte *reg, LongInt *disp, tSymbolFlags *flags)
{ /* dsp:5[Rn] (R0-R7) */
const char *str = pArg->str.p_str;
int pos;
Boolean ValOK;
if (str[len-1] != ']') return False;
for (pos = len - 2; pos > 0; pos--)
{
if (str[pos] == '[') break;
}
if (pos < 1) return False;
StrCompCopySub(&Temp1, pArg, pos + 1, len - pos - 2);
if (!DecodeReg(&Temp1, reg, eRn)) return False;
if (*reg > 7) return False;
StrCompCopySub(&Temp1, pArg, 0, pos);
*disp = EvalStrIntExpressionWithFlags(&Temp1, UInt20, &ValOK, flags);
return ValOK;
}
static int Size2Scale(Byte size)
{
Byte scale;
switch (size)
{
case 0x00: /* B */
scale = 1;
break;
case 0x01: /* W */
scale = 2;
break;
case 0x02: /* L */
scale = 4;
break;
default:
return -1;
}
return scale;
}
static Boolean ChkDisp5(Byte size, LongInt disp, tSymbolFlags flags)
{
const int scale = Size2Scale(size);
if (scale < 0) return False;
if (!mFirstPassUnknown(flags))
{
if (disp & (scale - 1))
{
WrError(ErrNum_AddrMustBeAligned);
return False;
}
if (disp / scale > 31 || disp < 0) return False;
}
return True;
}
static Byte DispSize5(Byte size, LongInt disp)
{
const Byte scale = Size2Scale(size);
return disp / scale;
}
static Boolean DecodeIndexed(tStrComp *pArg, Byte *regi, Byte *regb)
{ /* [Ri,Rb] */
const char *str = pArg->str.p_str;
int pos;
if (str[0] != '[' || str[len-1] != ']') return False;
for (pos = 2; pos < len - 2; pos++)
{
if (str[pos] == ',') break;
}
StrCompCopySub(&Temp1, pArg, 1, pos - 1);
if (!DecodeReg(&Temp1, regi, eRn)) return False;
StrCompCopySub(&Temp1, pArg, pos + 1, len - pos - 2);
if (!DecodeReg(&Temp1, regb, eRn)) return False;
return True;
}
static Boolean DecodeIncDec(tStrComp *pArg, Byte *reg, Byte *id)
{ /* [Rn+] / [-Rn]] */
const char *str = pArg->str.p_str;
if (len < 5) return False;
if (str[0] != '[' || str[len-1] != ']') return False;
if (str[len-2] == '+')
{
*id = 0x00;
StrCompCopySub(&Temp1, pArg, 1, len - 3);
}
else if (str[1] == '-')
{
*id = 0x01;
StrCompCopySub(&Temp1, pArg, 2, len - 3);
}
else return False;
return DecodeReg(&Temp1, reg, eRn);
}
static Boolean DecodeRegRange(tStrComp *pArg, Byte *range)
{
const char *str = pArg->str.p_str;
Byte reg1;
Byte reg2;
int pos;
if (len < 5) return False;
for (pos = 2; pos < len - 2; pos++)
{
if (str[pos] == '-') break;
}
if (pos >= len - 2) return False;
StrCompCopySub(&Temp1, pArg, 0, pos);
if (!DecodeReg(&Temp1, ®1, eRn)) return False;
StrCompCopySub(&Temp1, pArg, pos + 1, len - pos - 1);
if (!DecodeReg(&Temp1, ®2, eRn)) return False;
if (reg1 == 0 || reg1 >= reg2) return False;
*range = (reg1 << 4) | reg2;
return True;
}
static Boolean DecodeIndirect(tStrComp *pArg, Byte *reg)
{
const char *str = pArg->str.p_str;
if (str[0] != '[') return False;
if (str[len-1] != ']') return False;
StrCompCopySub(&Temp1, pArg, 1, len - 2);
if (!DecodeReg(&Temp1, reg, eRn)) return False;
return True;
}
static Boolean DecodeAcc(tStrComp *pArg, Byte *acc)
{
const char *str = pArg->str.p_str;
if (len != 2) return False;
if (as_toupper(str[0]) != 'A') return False;
if (str[1] != '0' && str[1] != '1') return False;
*acc = str[1] - '0';
return True;
}
static Boolean DecodeAttrDouble(Byte *size)
{
if (strlen(AttrPart.
str.
p_str) != 1)
{
WrStrErrorPos(ErrNum_TooLongAttr, &AttrPart);
return False;
}
switch (as_toupper(AttrPart.str.p_str[0]))
{
case 'L':
*size = 0;
break;
case 'D':
*size = 1;
break;
default:
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return False;
}
return True;
}
/*---------------------------------------------------------------------------*/
static void DecodeABS(Word Index)
{
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,2)) return;
if (ArgCnt == 1)
{
Byte reg;
if (!DecodeReg(&ArgStr[1], ®, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[1]);
return;
}
BAsmCode[0] = 0x7E;
BAsmCode[1] = (Index >> 8) | reg;
CodeLen = 2;
}
else
{
Byte regs;
Byte regd;
if (!DecodeReg(&ArgStr[1], ®s, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
BAsmCode[0] = 0xFC;
BAsmCode[1] = Index & 0xFF;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
}
}
static void DecodeADC(Word Index)
{
Byte regs;
Byte regd;
Byte size;
LongInt imm;
tSymbolFlags flags;
LongInt disp;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if ((Index & 0x0800) && DecodeImm(&ArgStr[1], &imm, &flags)) /* ADC only */
{
size = ImmSize32(imm, flags);
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x70 | (size << 2);
BAsmCode[2] = 0x20 | regd;
CodeLen = ImmOut(3, size, imm);
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0x03 | (Index >> 8);
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
if (DecodeIndirectL(&ArgStr[1], ®s, &disp, &flags))
{
if (mFirstPassUnknown(flags)) size = 0x02;
else size = DispSize(disp, flags, 4);
BAsmCode[0] = 0x06;
BAsmCode[1] = 0xA0 | size;
BAsmCode[2] = Index & 0xFF;
BAsmCode[3] = (regs << 4) | regd;
CodeLen = DispOut(4, size, disp, 4);
}
}
static const struct {
Byte OpcImm4; /* #IMM:4,Rd */
Byte OpcImm1; /* #IMM:*(,Rs),Rd 1st byte */
Byte OpcImm2; /* 2nd byte */
Byte Opc2; /* Rs,Rd / [Rs].UB,Rd */
Byte Opc3; /* Rs,Rs2,Rd */
Byte Opc4; /* [Rs],Rd */
Byte flags; /* 1<<0:, 1<<1:, 1<<2:#UIMM8 1<<3:Rs,Rs,Rd */
} OpTabADD[] = {
{ 0x62, 0x70, 0x00, 0x48, 0x20, 0x08, 0x0B }, /* ADD */
{ 0x64, 0x74, 0x20, 0x50, 0x40, 0x10, 0x09 }, /* AND */
{ 0x61, 0x74, 0x00, 0x44, 0, 0x04, 0x05 }, /* CMP */
{ 0x63, 0x74, 0x10, 0x4C, 0x30, 0x0C, 0x09 }, /* MUL */
{ 0x65, 0x74, 0x30, 0x54, 0x50, 0x14, 0x09 }, /* OR */
{ 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x08 }, /* SUB */
};
static void DecodeADD(Word Index)
{
Byte regs1;
Byte regs2;
Byte regd;
Byte size;
LongInt imm;
tSymbolFlags flags;
LongInt disp;
Byte memex;
Byte scale;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,3)) return;
if (!DecodeReg(&ArgStr[2], ®s2, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if (ArgCnt == 2)
regd = regs2;
else
{
if (!DecodeReg(&ArgStr[3], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[3]);
return;
}
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (ArgCnt == 2 && !mFirstPassUnknown(flags) && imm >= 0 && imm < 16 )
{ /* #UIMM:4 */
BAsmCode[0] = OpTabADD[Index].OpcImm4;
BAsmCode[1] = (imm << 4) | regd;
CodeLen = 2;
return;
}
if ((OpTabADD[Index].flags & 0x04) && ArgCnt == 2 &&
!mFirstPassUnknown(flags) && imm >= 0 && imm < 256)
{ /* #UIMM:8 */
BAsmCode[0] = 0x75;
BAsmCode[1] = 0x50 | regd;
BAsmCode[2] = imm;
CodeLen = 3;
return;
}
if (((OpTabADD[Index].flags & 0x01) && ArgCnt == 2) || (OpTabADD[Index].flags & 0x02))
{ /* #SIMM:* */
size = ImmSize32(imm, flags);
BAsmCode[0] = OpTabADD[Index].OpcImm1 | size;
if (OpTabADD[Index].flags & 0x02)
if (ArgCnt == 2)
BAsmCode[1] = (regd << 4) | regd; /* #Imm,Rd */
else
BAsmCode[1] = (regs2 << 4) | regd; /* #imm,Rs,Rd */
else
BAsmCode[1] = OpTabADD[Index].OpcImm2 | regd;
CodeLen = ImmOut(2, size, imm);
return;
}
}
if (DecodeReg(&ArgStr[1], ®s1, eRn))
{ /* Rs */
if (ArgCnt == 2)
{
BAsmCode[0] = OpTabADD[Index].Opc2 | 0x03;
BAsmCode[1] = (regs1 << 4) | regd;
CodeLen = 2;
}
else if (OpTabADD[Index].flags & 0x08)
{
BAsmCode[0] = 0xFF;
BAsmCode[1] = OpTabADD[Index].Opc3 | regd;
BAsmCode[2] = (regs1 << 4) | regs2;
CodeLen = 3;
}
else WrStrErrorPos(ErrNum_TooManyArgs, &ArgStr[3]);
return;
}
if (ArgCnt == 2 && DecodeIndirectADD(&ArgStr[1], ®s1, &disp, &flags, &memex, &scale))
{
if (memex == 0x80)
{
size = DispSize(disp, flags, 1);
BAsmCode[0] = OpTabADD[Index].Opc2 | size;
BAsmCode[1] = (regs1 << 4) | regd;
CodeLen = DispOut(2, size, disp, 1);
return;
}
size = DispSize(disp, flags, scale);
BAsmCode[0] = 0x06;
BAsmCode[1] = OpTabADD[Index].Opc4 | (memex << 6) | size;
BAsmCode[2] = (regs1 << 4) | regd;
CodeLen = DispOut(3, size, disp, scale);
return;
}
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
}
static const struct {
Byte OpcIM1; /* Imm3,[Rd] */
Byte OpcIM2;
Byte OpcRM; /* Rs,[Rd] / Rs,Rd */
Byte OpcIR; /* #Imm5,Rd */
Byte flags;
} OpTabBCLR[] = {
{ 0xF0, 0x08, 0x64, 0x7A, 0x00 }, /* BCLR */
{ 0xF0, 0x00, 0x6C, 0, 0x01 }, /* BNOT */
{ 0xF0, 0x00, 0x60, 0x78, 0x00 }, /* BSET */
{ 0xF4, 0x00, 0x68, 0x7C, 0x00 }, /* BTST */
};
static void DecodeBCLR(Word Index)
{
Byte regs;
Byte regd;
Byte size;
Byte memex;
Byte scale;
LongInt imm;
LongInt disp;
tSymbolFlags flags;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
memex = 0;
if (DecodeIndirectADD(&ArgStr[2], ®d, &disp, &flags, &memex, &scale))
{
if (memex)
{
WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[2]);
return;
}
size = DispSize(disp, flags, 1);
if (size > 0x02){
WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!mSymbolQuestionable(flags) && (imm < 0 || imm > 7))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
if (OpTabBCLR[Index].flags & 0x01)
{ /* BNOT */
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0xE0 | (imm << 2) | size;
BAsmCode[2] = 0x0F | (regd << 4);
CodeLen = DispOut(3, size, disp, 1);
}
else
{ /* BCLR, BSET, BTST */
BAsmCode[0] = OpTabBCLR[Index].OpcIM1 | size;
BAsmCode[1] = OpTabBCLR[Index].OpcIM2 | (regd << 4) | imm;
CodeLen = DispOut(2, size, disp, 1);
}
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabBCLR[Index].OpcRM | size;
BAsmCode[2] = regs | (regd << 4);
CodeLen = DispOut(3, size, disp, 1);
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
}
else if (DecodeReg(&ArgStr[2], ®d, eRn))
{
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!mSymbolQuestionable(flags) && (imm < 0 || imm > 31))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
if (OpTabBCLR[Index].flags & 0x01)
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0xE0 | imm;
BAsmCode[2] = 0xF0 | regd;
CodeLen = 3;
}
else
{
BAsmCode[0] = OpTabBCLR[Index].OpcIR | (imm >> 4);
BAsmCode[1] = ((imm & 0x0F) << 4) | regd;
CodeLen = 2;
}
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabBCLR[Index].OpcRM | 0x03;
BAsmCode[2] = regs | (regd << 4);
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
static void DecodeBCnd(Word Index)
{
const char *str = AttrPart.str.p_str;
Byte attr = 0;
Byte reg;
LongInt addr;
tSymbolFlags flags;
Boolean ValOK;
LongInt disp;
if (len > 1)
{
WrStrErrorPos(ErrNum_TooLongAttr, &AttrPart);
return;
}
if (len == 1)
{
attr = as_toupper(str[0]);
switch (attr)
{
case 'S':
break;
case 'B':
break;
case 'W':
break;
case 'A':
case 'L':
if (Index != 14)
{
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return;
}
break;
default:
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return;
}
}
if (!ChkArgCnt(1,1)) return;
if ((attr == 0 || attr == 'L') && DecodeReg(&ArgStr[1], ®, eRn))
{
BAsmCode[0] = 0x7F;
BAsmCode[1] = 0x40 | reg;
CodeLen = 2;
return;
}
addr = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &flags);
if (ValOK)
{
if (attr == 'L')
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
disp = addr - EProgCounter();
/* Try 3 bit */
if ((attr == 0 || attr == 'S') && disp >= 3 && disp <= 10)
{
if (disp > 7) disp -= 8;
if (Index == 0 || Index == 1)
{
BAsmCode[0] = 0x10 | (Index << 3) | disp;
CodeLen = 1;
return;
}
if (Index == 14)
{
BAsmCode[0] = 0x08 | disp;
CodeLen = 1;
return;
}
WrError(ErrNum_InternalError);
}
if (attr == 'S' && !mFirstPassUnknownOrQuestionable(flags))
{
WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
return;
}
/* Try 8 bit */
if ((attr == 0 || attr == 'B') &&
((disp & 0xFFFFFF80) == 0xFFFFFF80 ||
(disp & 0xFFFFFF80) == 0x00000000))
{
BAsmCode[0] = 0x20 | Index;
BAsmCode[1] = disp & 0xFF;
CodeLen = 2;
return;
}
if (attr == 'B' && !mFirstPassUnknownOrQuestionable(flags))
{
WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
return;
}
/* Try 16 bit */
if ((attr == 0 || attr == 'W') &&
((disp & 0xFFFF8000) == 0xFFFF8000 ||
(disp & 0xFFFF8000) == 0x00000000))
{
if (Index == 0 || Index == 1)
{
BAsmCode[0] = 0x3A | Index;
BAsmCode[1] = disp & 0xFF;
BAsmCode[2] = (disp >> 8) & 0xFF;
CodeLen = 3;
return;
}
if (Index == 14)
{
BAsmCode[0] = 0x38;
BAsmCode[1] = disp & 0xFF;
BAsmCode[2] = (disp >> 8) & 0xFF;
CodeLen = 3;
return;
}
WrError(ErrNum_JmpDistTooBig);
return;
}
if (attr == 'W' && !mFirstPassUnknownOrQuestionable(flags))
{
WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
return;
}
/* Try 24 bit */
if ((disp & 0xFF800000) == 0xFF800000 ||
(disp & 0xFF800000) == 0x00000000)
{
if (Index == 14)
{
BAsmCode[0] = 0x04;
BAsmCode[1] = disp & 0xFF;
BAsmCode[2] = (disp >> 8) & 0xFF;
BAsmCode[3] = (disp >> 16) & 0xFF;
CodeLen = 4;
return;
}
}
WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
}
}
static void DecodeBMCnd(Word Index)
{
Byte regd;
Byte size;
Byte memex;
Byte scale;
LongInt imm;
LongInt disp;
tSymbolFlags flags;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
memex = 0;
if (DecodeIndirectADD(&ArgStr[2], ®d, &disp, &flags, &memex, &scale))
{
if (memex)
{
WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[2]);
return;
}
size = DispSize(disp, flags, 1);
if (size > 0x02){
WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
return;
}
}
else if (DecodeReg(&ArgStr[2], ®d, eRn))
{
size = 0x03;
}
else
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (size < 0x03)
{
/* #imm,disp[Rd] */
if (!mSymbolQuestionable(flags) && (imm < 0 || imm > 7))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0xE0 | (imm << 2) | size;
BAsmCode[2] = (regd << 4) | Index;
CodeLen = DispOut(3, size, disp, 1);
return;
}
else
{
/* #imm,Rd */
if (!mSymbolQuestionable(flags) && (imm < 0 || imm > 31))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0xE0 | imm;
BAsmCode[2] = (Index << 4) | regd;
CodeLen = 3;
return;
}
}
WrError(ErrNum_OverRange);
}
static void DecodeBRK(Word Index)
{
if (!ChkNoAttr()) return;
if (!ChkArgCnt(0,0)) return;
BAsmCode[0] = Index;
CodeLen = 1;
}
static void DecodeBSR(Word Index)
{
const char *str = AttrPart.str.p_str;
Byte attr = 0;
Byte reg;
LongInt addr;
tSymbolFlags flags;
Boolean ValOK;
LongInt disp;
UNUSED(Index);
if (len > 1)
{
WrStrErrorPos(ErrNum_TooLongAttr, &AttrPart);
return;
}
if (len == 1)
{
attr = as_toupper(str[0]);
switch (attr)
{
case 'W':
case 'A':
case 'L':
break;
default:
WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
return;
}
}
if (!ChkArgCnt(1,1)) return;
if ((attr == 0 || attr == 'L') && DecodeReg(&ArgStr[1], ®, eRn))
{
BAsmCode[0] = 0x7F;
BAsmCode[1] = 0x50 | reg;
CodeLen = 2;
return;
}
addr = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &flags);
if (ValOK)
{
if (attr == 'L')
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
disp = addr - EProgCounter();
/* Try 16 bit */
if ((attr == 0 || attr == 'W') &&
((disp & 0xFFFF8000) == 0xFFFF8000 ||
(disp & 0xFFFF8000) == 0x00000000))
{
BAsmCode[0] = 0x39;
BAsmCode[1] = disp & 0xFF;
BAsmCode[2] = (disp >> 8) & 0xFF;
CodeLen = 3;
return;
}
if (attr == 'W' && !mFirstPassUnknownOrQuestionable(flags))
{
WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
return;
}
/* Try 24 bit */
if ((disp & 0xFF800000) == 0xFF800000 ||
(disp & 0xFF800000) == 0x00000000)
{
BAsmCode[0] = 0x05;
BAsmCode[1] = disp & 0xFF;
BAsmCode[2] = (disp >> 8) & 0xFF;
BAsmCode[3] = (disp >> 16) & 0xFF;
CodeLen = 4;
return;
}
WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
}
}
static const char *BitPSW[] = {
"C", "Z", "S", "O", NULL, NULL, NULL, NULL,
"I", "U", NULL, NULL, NULL, NULL, NULL, NULL };
static void DecodeCLRPSW(Word Index)
{
int i;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
for (i = 0; i < 16; i++)
{
if (BitPSW[i] && !as_strcasecmp(ArgStr[1].str.p_str, BitPSW[i])) break;
}
if (i < 16)
{
BAsmCode[0] = 0x7F;
BAsmCode[1] = Index | i;
CodeLen = 2;
}
else WrStrErrorPos(ErrNum_UnknownFlag, &ArgStr[1]);
}
static const struct {
Byte OpcI;
Byte Opc2;
Byte OpcM;
} OpTabDIV[] = {
{ 0x80, 0x20, 0x08 }, /* DIV */
{ 0x90, 0x24, 0x09 }, /* DIVU */
{ 0x60, 0x18, 0x06 }, /* EMUL */
{ 0x70, 0x1C, 0x07 }, /* EMULU */
{ 0x40, 0x10, 0x04 }, /* MAX */
{ 0x50, 0x14, 0x05 }, /* MIN */
};
static void DecodeDIV(Word Index)
{
Byte regs;
Byte regd;
Byte size;
LongInt imm;
tSymbolFlags flags;
LongInt disp;
Byte memex;
Byte scale;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
size = ImmSize32(imm, flags);
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x70 | (size << 2);
BAsmCode[2] = OpTabDIV[Index].OpcI | regd;
CodeLen = ImmOut(3, size, imm);
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabDIV[Index].Opc2 | 0x03;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
if (DecodeIndirectADD(&ArgStr[1], ®s, &disp, &flags, &memex, &scale))
{
if (memex == 0x80)
{
size = DispSize(disp, flags, 1);
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabDIV[Index].Opc2 | size;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = DispOut(3, size, disp, 1);
return;
}
size = DispSize(disp, flags, scale);
BAsmCode[0] = 0x06;
BAsmCode[1] = 0x20 | (memex << 6) | size;
BAsmCode[2] = OpTabDIV[Index].OpcM;
BAsmCode[3] = (regs << 4) | regd;
CodeLen = DispOut(4, size, disp, scale);
return;
}
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
}
static const struct {
Byte OpcI;
Byte OpcM;
Byte Opc3;
Byte flags;
} OpTabFADD[] = {
{ 0x20, 0x88, 0xA0, 0x03 }, /* FADD */
{ 0x10, 0x84, 0, 0x01 }, /* FCMP */
{ 0x40, 0x90, 0, 0x01 }, /* FDIV */
{ 0x30, 0x8C, 0xB0, 0x03 }, /* FMUL */
{ 0x00, 0x80, 0x80, 0x03 }, /* FSUB */
{ 0, 0x94, 0, 0x00 }, /* FTOI */
{ 0, 0x98, 0, 0x00 }, /* ROUND */
{ 0, 0xA0, 0, 0x10 }, /* FSQRT */
{ 0, 0xA4, 0, 0x10 }, /* FTOU */
};
static void DecodeFADD(Word Index)
{
Byte regs;
Byte regd;
Byte size;
LongInt imm;
LongInt disp;
tSymbolFlags flags;
if (!ChkNoAttr()) return;
if (!CheckFloat()) return;
if ((OpTabFADD[Index].flags & 0x02) && ArgCnt == 3)
{
Byte regs2;
if (!DecodeReg(&ArgStr[1], ®s, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®s2, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[2]);
return;
}
if (!DecodeReg(&ArgStr[3], ®d, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[3]);
return;
}
BAsmCode[0] = 0xFF;
BAsmCode[1] = OpTabFADD[Index].Opc3 | regd;
BAsmCode[2] = (regs << 4) | regs2;
CodeLen = 3;
return;
}
if (!ChkArgCnt(2,2)) return;
if (OpTabFADD[Index].flags & 0x10)
{
if (!CheckV2()) return;
}
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if ((OpTabFADD[Index].flags & 0x01) &&
DecodeFloat(&ArgStr[1], &imm))
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x72;
BAsmCode[2] = OpTabFADD[Index].OpcI | regd;
CodeLen = ImmOut(3, 0, imm); /* size==0 means 4 byte */
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
size = 0x03;
disp = 0;
}
else if (DecodeIndirectL(&ArgStr[1], ®s, &disp, &flags))
{
if (mFirstPassUnknown(flags)) size = 0x02;
else size = DispSize(disp, flags, 4);
}
else
{
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
return;
}
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabFADD[Index].OpcM | size;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = DispOut(3, size, disp, 4);
}
static void DecodeINT(Word Index)
{
LongInt imm;
tSymbolFlags flags;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!mFirstPassUnknown(flags) && (imm < -128 || imm > 255))
{
WrStrErrorPos(ErrNum_ArgOutOfRange, &ArgStr[1]);
return;
}
BAsmCode[0] = 0x75;
BAsmCode[1] = 0x60;
BAsmCode[2] = imm & 0xFF;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
}
static const struct {
Byte Opc1;
Byte Opc2;
Byte flags;
} OpTabITOF[] = {
{ 0x44, 0x11, 0x00 }, /* ITOF */
{ 0x54, 0x15, 0x10 }, /* UTOF */
};
static void DecodeITOF(Word Index)
{
Byte regs;
Byte regd;
Byte size;
Byte memex;
Byte scale;
LongInt disp;
tSymbolFlags flags;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!CheckFloat()) return;
if ((OpTabITOF[Index].flags & 0x10) && !CheckV2()) return;
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
size = 0x03;
disp = 0;
memex = 0;
}
else if (DecodeIndirectADD(&ArgStr[1], ®s, &disp, &flags, &memex, &scale))
{
if (mFirstPassUnknown(flags)) size = 0x02;
else size = DispSize(disp, flags, scale);
}
else
{
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
return;
}
if (memex == 0x80 || size == 0x03)
{
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabITOF[Index].Opc1 | size;
BAsmCode[2] = (regs << 4) | regd;
if (size < 0x03) CodeLen = DispOut(3, size, disp, scale);
else CodeLen = 3;
return;
}
BAsmCode[0] = 0x06;
BAsmCode[1] = 0x20 | (memex << 6) | size;
BAsmCode[2] = OpTabITOF[Index].Opc2;
BAsmCode[3] = (regs << 4) | regd;
CodeLen = DispOut(4, size, disp, scale);
}
static const struct {
Byte Opc1;
Byte Opc2;
} OpTabJMP[] = {
{ 0x7F, 0x00 }, /* JMP */
{ 0x7F, 0x10 }, /* JSR */
{ 0x7E, 0xB0 }, /* POP */
{ 0x7E, 0x50 }, /* ROLC */
{ 0x7E, 0x40 }, /* RORC */
{ 0x7E, 0x30 }, /* SAT */
};
static void DecodeJMP(Word Index)
{
Byte reg;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
if (DecodeReg(&ArgStr[1], ®, eRn))
{
BAsmCode[0] = OpTabJMP[Index].Opc1;
BAsmCode[1] = OpTabJMP[Index].Opc2 | reg;
CodeLen = 2;
return;
}
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
}
static const struct {
Byte Opc;
Byte flags;
} OpTabMACHI[] = {
{ 0x04, 0x01 }, /* MACHI */
{ 0x05, 0x01 }, /* MACLO */
{ 0x00, 0x01 }, /* MULHI */
{ 0x01, 0x01 }, /* MULLO */
{ 0x67, 0x00 }, /* REVL */
{ 0x65, 0x00 }, /* REVW */
{ 0x07, 0x11 }, /* EMACA */
{ 0x47, 0x11 }, /* EMSBA */
{ 0x03, 0x11 }, /* EMULA */
{ 0x06, 0x11 }, /* MACLH */
{ 0x44, 0x11 }, /* MSBHI */
{ 0x46, 0x11 }, /* MSBLH */
{ 0x45, 0x11 }, /* MSBLO */
{ 0x02, 0x11 }, /* MULLH */
};
static void DecodeMACHI(Word Index)
{
Byte reg1;
Byte reg2;
Byte acc = 0;
if ((OpTabMACHI[Index].flags & 0x10) && !CheckV2()) return;
if (!ChkNoAttr()) return;
if (pCurrCPUProps->InstSet == eRXv1)
{
if (!ChkArgCnt(2,2)) return;
}
else
{
if (OpTabMACHI[Index].flags & 0x01)
{
if (!ChkArgCnt(3,3)) return;
if (!DecodeAcc(&ArgStr[3], &acc))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[3]);
return;
}
}
else
{
if (!ChkArgCnt(2,2)) return;
}
}
if (!DecodeReg(&ArgStr[1], ®1, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®2, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabMACHI[Index].Opc | (acc << 3);
BAsmCode[2] = (reg1 << 4) | reg2;
CodeLen = 3;
}
static void DecodeMOV(Word Index)
{
tSymbolSize size;
Byte regs;
Byte regd;
LongInt imm;
LongInt disp;
tSymbolFlags flags;
tSymbolFlags flags2;
Byte disp2;
Byte isize;
Byte dsize;
Byte scale;
Byte regi;
UNUSED(Index);
size = DecodeAttrSize();
if (size == eSymbolSizeUnknown) return;
scale = Size2Scale(size);
if (DecodeReg(&ArgStr[1], ®s, eRn) && regs < 8 &&
DecodeRelative(&ArgStr[2], ®d, &disp, &flags))
{ /* (1) */
if (ChkDisp5(size, disp, flags))
{
disp2 = DispSize5(size, disp);
BAsmCode[0] = 0x80 | (size << 4) | ((disp2 >> 2) & 0x07);
BAsmCode[1] = ((disp2 << 6) & 0x80) | (regd << 4) | ((disp2 << 3) & 0x08) | regs;
CodeLen = 2;
return;
}
}
if (DecodeRelative(&ArgStr[1], ®s, &disp, &flags) &&
DecodeReg(&ArgStr[2], ®d, eRn) && regd < 8)
{ /* (2) */
if (ChkDisp5(size, disp, flags))
{
disp2 = DispSize5(size, disp);
BAsmCode[0] = 0x88 | (size << 4) | ((disp2 >> 2) & 0x07);
BAsmCode[1] = ((disp2 << 6) & 0x80) | (regs << 4) | ((disp2 << 3) & 0x08) | regd;
CodeLen = 2;
return;
}
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (size == 0x02 && DecodeReg(&ArgStr[2], ®d, eRn) &&
!mFirstPassUnknown(flags) && imm >= 0 && imm < 16)
{ /* (3) */
BAsmCode[0] = 0x66;
BAsmCode[1] = (imm << 4) | regd;
CodeLen = 2;
return;
}
if (DecodeRelative(&ArgStr[2], ®d, &disp, &flags))
{ /* (4) */
if ((size == 0x00 && imm >= -128 && imm < 256) ||
(size != 0x00 && imm >= 0 && imm < 256))
{
disp2 = DispSize5(size, disp);
BAsmCode[0] = 0x3C | size;
BAsmCode[1] = ((disp2 << 3) & 0x80) | (regd << 4) | (disp2 & 0x0F);
BAsmCode[2] = imm;
CodeLen = 3;
return;
}
}
if (DecodeReg(&ArgStr[2], ®d, eRn))
{
if (size == 0x02 && !mFirstPassUnknown(flags) &&
imm >= 0 && imm < 256)
{ /* (5) */
BAsmCode[0] = 0x75;
BAsmCode[1] = 0x40 | regd;
BAsmCode[2] = imm;
CodeLen = 3;
return;
}
/* (6) */
isize = ImmSize32(imm, flags);
BAsmCode[0] = 0xFB;
BAsmCode[1] = (regd << 4) | (isize << 2) | 0x02;
CodeLen = ImmOut(2, isize, imm);
return;
}
if (DecodeIndirectADC(&ArgStr[2], ®d, &disp, &flags2))
{ /* (8) */
switch (size)
{
case 0x00: /* B */
if (imm < -128 || imm > 255)
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
isize = 0x01;
break;
case 0x01: /* W */
if (imm < -32768 || imm > 65535)
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
isize = ImmSize16(imm, flags);
break;
case 0x02: /* L */
isize = ImmSize32(imm, flags);
break;
default:
WrError(ErrNum_InternalError);
return;
}
dsize = DispSize(disp, flags2, scale);
BAsmCode[0] = 0xF8 | dsize;
BAsmCode[1] = (regd << 4) | (isize << 2) | size;
CodeLen = DispOut(2, dsize, disp, scale);
CodeLen = ImmOut(CodeLen, isize, imm);
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
if (DecodeReg(&ArgStr[2], ®d, eRn))
{ /* (7) */
BAsmCode[0] = 0xCF | (size << 4);
BAsmCode[1] = (regs << 4) | regd;
CodeLen = 2;
return;
}
if (DecodeIndirectADC(&ArgStr[2], ®d, &disp, &flags))
{ /* (11) */
dsize = DispSize(disp, flags, scale);
BAsmCode[0] = 0xC3 | (size << 4) | (dsize << 2);
BAsmCode[1] = (regd << 4) | regs;
CodeLen = DispOut(2, dsize, disp, scale);
return;
}
if (DecodeIndexed(&ArgStr[2], ®i, ®d))
{ /* (12) */
BAsmCode[0] = 0xFE;
BAsmCode[1] = (size << 4) | regi;
BAsmCode[2] = (regd << 4) | regs;
CodeLen = 3;
return;
}
if (DecodeIncDec(&ArgStr[2], ®d, ®i))
{ /* (14) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x20 | (regi << 2) | size;
BAsmCode[2] = (regd << 4) | regs;
CodeLen = 3;
return;
}
}
if (DecodeIndirectADC(&ArgStr[1], ®s, &disp, &flags))
{
if (DecodeReg(&ArgStr[2], ®d, eRn))
{ /* (9) */
dsize = DispSize(disp, flags, scale);
BAsmCode[0] = 0xCC | (size << 4) | dsize;
BAsmCode[1] = (regs << 4) | regd;
CodeLen = DispOut(2, dsize, disp, scale);
return;
}
if (DecodeIndirectADC(&ArgStr[2], ®d, &imm, &flags2))
{ /* (13) */
dsize = DispSize(disp, flags, scale); /* src */
isize = DispSize(imm, flags2, scale); /* dst */
BAsmCode[0] = 0xC0 | (size << 4) | (isize << 2) | dsize;
BAsmCode[1] = (regs << 4) | regd;
CodeLen = DispOut(2, dsize, disp, scale);
CodeLen = DispOut(CodeLen, isize, imm, scale);
return;
}
}
if (DecodeIndexed(&ArgStr[1], ®i, ®s) &&
DecodeReg(&ArgStr[2], ®d, eRn))
{ /* (10) */
BAsmCode[0] = 0xFE;
BAsmCode[1] = 0x40 | (size << 4) | regi;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
if (DecodeIncDec(&ArgStr[1], ®s, ®i) &&
DecodeReg(&ArgStr[2], ®d, eRn))
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x28 | (regi << 2) | size;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
}
static void DecodeMOVU(Word Index)
{
tSymbolSize size;
Byte regs;
Byte regd;
Byte scale;
LongInt disp;
tSymbolFlags flags;
Byte disp2;
Byte dsize;
Byte regi;
UNUSED(Index);
size = DecodeAttrSize();
if (size == eSymbolSizeUnknown || size == eSymbolSize32Bit) return;
scale = Size2Scale(size);
if (DecodeReg(&ArgStr[2], ®d, eRn))
{
if (DecodeRelative(&ArgStr[1], ®s, &disp, &flags) &&
ChkDisp5(size, disp, flags) && regd < 8)
{ /* (1) */
disp2 = DispSize5(size, disp);
BAsmCode[0] = 0xB0 | (size << 3) | ((disp2 >> 2) & 0x07);
BAsmCode[1] = ((disp2 << 6) & 0x80) | (regs << 4) | ((disp2 << 3) & 0x08) | regd;
CodeLen = 2;
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{ /* (2)-1 */
BAsmCode[0] = 0x5B | (size << 2);
BAsmCode[1] = (regs << 4) | regd;
CodeLen = 2;
return;
}
if (DecodeIndirectADC(&ArgStr[1], ®s, &disp, &flags))
{ /* (2)-2 */
dsize = DispSize(disp, flags, scale);
BAsmCode[0] = 0x58 | (size << 2) | dsize;
BAsmCode[1] = (regs << 4) | regd;
CodeLen = DispOut(2, dsize, disp, scale);
return;
}
if (DecodeIndexed(&ArgStr[1], ®i, ®s))
{ /* (3) */
BAsmCode[0] = 0xFE;
BAsmCode[1] = 0xC0 | (size << 4) | regi;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
if (DecodeIncDec(&ArgStr[1], ®s, ®i))
{ /* (4) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x38 | (regi << 2) | size;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
}
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
}
static const struct {
Byte Opc2;
Byte Opc3;
Byte flags;
} OpTabMVFACHI[] = {
{ 0x1E, 0x00, 0x00 }, /* MVFACHI */
{ 0x1E, 0x20, 0x00 }, /* MVFACMI */
{ 0x1E, 0x30, 0x10 }, /* MVFACGU */
{ 0x1E, 0x10, 0x10 }, /* MVFACLO */
};
static void DecodeMVFACHI(Word Index)
{
LongInt imm;
tSymbolFlags flags;
Byte acc;
Byte reg;
if ((OpTabMVFACHI[Index].flags & 0x10) && !CheckV2()) return;
if (!ChkNoAttr()) return;
if (pCurrCPUProps->InstSet == eRXv1)
{
if (!ChkArgCnt(1,1)) return;
imm = 0x02;
acc = 0x00;
}
else
{
if (!ChkArgCnt(3,3)) return;
if (!DecodeImm(&ArgStr[1], &imm, &flags))
{
WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
return;
}
switch (imm)
{
case 0:
imm = 0x02;
break;
case 1:
imm = 0x03;
break;
case 2:
imm = 0x00;
break;
default:
if (mSymbolQuestionable(flags)) break;
WrStrErrorPos(ErrNum_ArgOutOfRange, &ArgStr[1]);
return;
}
if (!DecodeAcc(&ArgStr[2], &acc))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
}
if (!DecodeReg(&ArgStr[ArgCnt], ®, eRn))
{
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[ArgCnt]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabMVFACHI[Index].Opc2 | ((imm >> 1) & 0x01);
BAsmCode[2] = OpTabMVFACHI[Index].Opc3 | (acc << 7) | ((imm << 6) & 0x40) | reg;
CodeLen = 3;
}
static const char *SPReg[] = {
"PSW", "PC", "USP", "FPSW", NULL, NULL, NULL, NULL,
"BPSW", "BPC", "ISP", "FINTV", "INTB", "EXTB", NULL, NULL,
};
static void DecodeMVFC(Word Index)
{
Byte reg;
size_t i;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (DecodeReg(&ArgStr[2], ®, eRn))
{
for (i = 0; i < as_array_size(SPReg); i++)
{
if (i == 13 && pCurrCPUProps->InstSet == eRXv1)
{
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[2]);
}
if (SPReg[i] && !as_strcasecmp(SPReg[i], ArgStr[1].str.p_str))
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x6A;
BAsmCode[2] = (i << 4) | reg;
CodeLen = 3;
return;
}
}
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
static const struct {
Byte Opc2;
Byte Opc3;
Byte flags;
} OpTabMVTACHI[] = {
{ 0x17, 0x00, 0x00 }, /* MVTACHI */
{ 0x17, 0x10, 0x00 }, /* MVTACLO */
{ 0x17, 0x30, 0x10 }, /* MVTACGU */
};
static void DecodeMVTACHI(Word Index)
{
Byte acc;
Byte reg;
if ((OpTabMVTACHI[Index].flags & 0x10) && !CheckV2()) return;
if (!ChkNoAttr()) return;
if (pCurrCPUProps->InstSet == eRXv1)
{
if (!ChkArgCnt(1,1)) return;
acc = 0x00;
}
else
{
if (!ChkArgCnt(2,2)) return;
if (!DecodeAcc(&ArgStr[2], &acc))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
}
if (!DecodeReg(&ArgStr[1], ®, eRn))
{
WrStrErrorPos(ErrNum_AddrModeNotSupported, &ArgStr[1]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabMVTACHI[Index].Opc2;
BAsmCode[2] = OpTabMVTACHI[Index].Opc3 | (acc << 7) | reg;
CodeLen = 3;
}
static void DecodeMVTC(Word Index)
{
Byte reg;
LongInt imm;
Byte size;
tSymbolFlags flags;
size_t i;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
for (i = 0; i < as_array_size(SPReg); i++)
{
if (SPReg[i] && !as_strcasecmp(SPReg[i], ArgStr[2].str.p_str))
{
if (i == 1)
{
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[2]);
return;
}
if (i == 13 && pCurrCPUProps->InstSet == eRXv1)
{
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[2]);
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
size = ImmSize32(imm, flags);
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x73 | (size << 2);
BAsmCode[2] = i;
CodeLen = ImmOut(3, size, imm);
return;
}
if (DecodeReg(&ArgStr[1], ®, eRn))
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x68;
BAsmCode[2] = (reg << 4) | i;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
}
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
static void DecodeMVTIPL(Word Index)
{
LongInt imm;
tSymbolFlags flags;
UNUSED(Index);
if (!CheckSup()) return;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
if (!pCurrCPUProps->hasMVTIPL)
{
WrError(ErrNum_InstructionNotSupported);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!mFirstPassUnknown(flags) && (imm < 0 || imm > 15))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
return;
}
BAsmCode[0] = 0x75;
BAsmCode[1] = 0x70;
BAsmCode[2] = imm;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
static const Byte OpTabPOPC[] = {
0xE0, /* POPC */
0xC0, /* PUSHC */
};
static void DecodePOPC(Word Index)
{
size_t i;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
for (i = 0; i < as_array_size(SPReg); i++)
{
if (SPReg[i] && !as_strcasecmp(SPReg[i], ArgStr[1].str.p_str))
{
if (Index == 0 && i == 1)
{
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
return;
}
if (i == 13 && pCurrCPUProps->InstSet == eRXv1)
{
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[2]);
}
BAsmCode[0] = 0x7E;
BAsmCode[1] = OpTabPOPC[Index] | i;
CodeLen = 2;
return;
}
}
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
}
static const Byte OpTabPOPM[] = {
0x6F, /* POPM */
0x6E, /* PUSHM */
};
static void DecodePOPM(Word Index)
{
Byte range;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
if (DecodeRegRange(&ArgStr[1], &range))
{
BAsmCode[0] = OpTabPOPM[Index];
BAsmCode[1] = range;
CodeLen = 2;
return;
}
WrStrErrorPos(ErrNum_InvRegList, &ArgStr[1]);
}
static void DecodePUSH(Word Index)
{
tSymbolSize size;
Byte reg;
LongInt disp;
tSymbolFlags flags;
Byte dsize;
Byte scale;
UNUSED(Index);
size = DecodeAttrSize();
if (size == eSymbolSizeUnknown) return;
if (!ChkArgCnt(1,1)) return;
scale = Size2Scale(size);
if (DecodeReg(&ArgStr[1], ®, eRn))
{
BAsmCode[0] = 0x7E;
BAsmCode[1] = 0x80 | (size << 4) | reg;
CodeLen = 2;
return;
}
if (DecodeIndirectADC(&ArgStr[1], ®, &disp, &flags))
{
dsize = DispSize(disp, flags, scale);
BAsmCode[0] = 0xF4 | dsize;
BAsmCode[1] = 0x08 | (reg << 4) | size;
CodeLen = DispOut(2, dsize, disp, scale);
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
}
static const struct {
Byte Opc2;
Byte Opc3;
Byte flags;
} OpTabRACW[] = {
{ 0x18, 0x00, 0x00 }, /* RACW */
{ 0x19, 0x00, 0x10 }, /* RACL */
{ 0x19, 0x40, 0x10 }, /* RDACL */
{ 0x18, 0x40, 0x10 }, /* RDACW */
};
static void DecodeRACW(Word Index)
{
LongInt imm;
tSymbolFlags flags;
Byte acc = 0;
if ((OpTabRACW[Index].flags & 0x10) && !CheckV2()) return;
if (!ChkNoAttr()) return;
if (pCurrCPUProps->InstSet == eRXv1)
{
if (!ChkArgCnt(1,1)) return;
}
else
{
if (!ChkArgCnt(2,2)) return;
if (!DecodeAcc(&ArgStr[2], &acc))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
return;
}
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (mFirstPassUnknown(flags) || imm == 1 || imm == 2)
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabRACW[Index].Opc2;
BAsmCode[2] = OpTabRACW[Index].Opc3 | (acc << 7) | ((imm - 1) << 4);
CodeLen = 3;
return;
}
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
}
static void DecodeRMPA(Word Index)
{
tSymbolSize size;
size = DecodeAttrSize();
if (size == eSymbolSizeUnknown) return;
if (!ChkArgCnt(0,0)) return;
BAsmCode[0] = 0x7F;
BAsmCode[1] = Index | size;
CodeLen = 2;
}
static const struct {
Byte Opc1;
Byte Opc2;
} OpTabROTL[] = {
{ 0x6E, 0x66 }, /* ROTL */
{ 0x6C, 0x64 }, /* ROTR */
};
static void DecodeROTL(Word Index)
{
Byte regs;
Byte regd;
LongInt imm;
tSymbolFlags flags;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!mFirstPassUnknown(flags) && (imm < 0 || imm > 31))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabROTL[Index].Opc1 | ((imm >> 4) & 0x01);
BAsmCode[2] = ((imm << 4) & 0xF0) | regd;
CodeLen = 3;
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabROTL[Index].Opc2;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
}
static void DecodeRTE(Word Index)
{
if (!ChkNoAttr()) return;
if (!ChkArgCnt(0,0)) return;
switch (Index)
{
case 0x7F95: /* RTE */
case 0x7F94: /* RTFI */
case 0x7F96: /* WAIT */
if (!CheckSup()) return;
}
BAsmCode[0] = Index >> 8;
BAsmCode[1] = Index;
CodeLen = 2;
}
static void DecodeRTSD(Word Index)
{
LongInt imm;
tSymbolFlags flags;
Byte range;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,2)) return;
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (mSymbolQuestionable(flags) && (imm < 0 || imm > 255))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
if (ArgCnt == 2 && DecodeRegRange(&ArgStr[2], &range))
{
BAsmCode[0] = 0x3F;
BAsmCode[1] = range;
BAsmCode[2] = imm;
CodeLen = 3;
return;
}
if (ArgCnt > 1)
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
BAsmCode[0] = 0x67;
BAsmCode[1] = imm;
CodeLen = 2;
return;
}
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
static void DecodeSCCnd(Word Index)
{
tSymbolSize size;
Byte reg;
LongInt disp;
tSymbolFlags flags;
Byte dsize;
Byte scale;
size = DecodeAttrSize();
if (size == eSymbolSizeUnknown) return;
if (!ChkArgCnt(1,1)) return;
scale = Size2Scale(size);
if (DecodeReg(&ArgStr[1], ®, eRn))
{
if (size != 0x02)
{
WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
return;
}
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0xD3 | (size << 2);
BAsmCode[2] = (reg << 4) | Index;
CodeLen = 3;
return;
}
if (DecodeIndirectADC(&ArgStr[1], ®, &disp, &flags))
{
dsize = DispSize(disp, flags, scale);
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0xD0 | (size << 2) | dsize;
BAsmCode[2] = (reg << 4) | Index;
CodeLen = DispOut(3, dsize, disp, scale);
return;
}
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
static const struct {
Byte Opc1;
Byte Opc2;
Byte Opc3;
} OpTabSHAR[] = {
{ 0x6A, 0x61, 0xA0 }, /* SHAR */
{ 0x6C, 0x62, 0xC0 }, /* SHLL */
{ 0x68, 0x60, 0x80 }, /* SHLR */
};
static void DecodeSHAR(Word Index)
{
Byte regs;
Byte regd;
LongInt imm;
tSymbolFlags flags;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,3)) return;
if (!DecodeReg(&ArgStr[ArgCnt], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvRegName, &ArgStr[2]);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!mFirstPassUnknown(flags) && (imm < 0 || imm > 31))
{
WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
return;
}
if (ArgCnt == 3)
{
if (DecodeReg(&ArgStr[2], ®s, eRn))
{ /* (3) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabSHAR[Index].Opc3 | imm;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
return;
}
/* (1) */
BAsmCode[0] = OpTabSHAR[Index].Opc1 | (imm >> 4);
BAsmCode[1] = ((imm << 4) & 0xF0) | regd;
CodeLen = 2;
return;
}
if (ArgCnt > 2)
{
WrStrErrorPos(ErrNum_TooManyArgs, &ArgStr[2]);
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{ /* (2) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = OpTabSHAR[Index].Opc2;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
static const struct {
Byte OpcIR;
Byte OpcRR;
} OpTabSTNZ[] = {
{ 0xF0, 0x4F }, /* STNZ */
{ 0xE0, 0x4B }, /* STZ */
};
static void DecodeSTNZ(Word Index)
{
LongInt imm;
tSymbolFlags flags;
Byte regd;
Byte regs;
Byte size;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
size = ImmSize32(imm, flags);
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x70 | (size << 2);
BAsmCode[2] = OpTabSTNZ[Index].OpcIR | regd;
CodeLen = ImmOut(3, size, imm);
return;
}
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
if (!CheckV2()) return;
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabSTNZ[Index].OpcRR;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
static const struct {
Byte Opc1;
Byte Opc2;
Byte Opc3;
Byte flags;
} OpTabTST[] = {
{ 0xC0, 0x30, 0x0C, 0x01 }, /* TST */
{ 0, 0x40, 0x10, 0x00 }, /* XCHG */
{ 0xD0, 0x34, 0x0D, 0x03 }, /* XOR */
};
static void DecodeTST(Word Index)
{
Byte reg1;
Byte reg2;
LongInt imm;
LongInt disp;
tSymbolFlags flags;
Byte size;
Byte memex;
Byte scale;
if (!ChkNoAttr()) return;
if ((OpTabTST[Index].flags & 0x02) && ArgCnt == 3)
{
Byte reg3;
if (!CheckV3()) return;
if (!DecodeReg(&ArgStr[1], ®1, eRn))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®2, eRn))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
if (!DecodeReg(&ArgStr[3], ®3, eRn))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[3]);
return;
}
BAsmCode[0] = 0xFF;
BAsmCode[1] = 0x60 | reg3;
BAsmCode[2] = (reg1 << 4) | reg2;
CodeLen = 3;
return;
}
if (!ChkArgCnt(2,2)) return;
if (!DecodeReg(&ArgStr[2], ®2, eRn))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
if ((OpTabTST[Index].flags & 0x01) &&
DecodeImm(&ArgStr[1], &imm, &flags))
{
size = ImmSize32(imm, flags);
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x70 | (size << 2);
BAsmCode[2] = OpTabTST[Index].Opc1 | reg2;
CodeLen = ImmOut(3, size, imm);
return;
}
if (DecodeReg(&ArgStr[1], ®1, eRn))
{
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabTST[Index].Opc2 | 0x03;
BAsmCode[2] = (reg1 << 4) | reg2;
CodeLen = 3;
return;
}
if (DecodeIndirectADD(&ArgStr[1], ®1, &disp, &flags, &memex, &scale))
{
if (memex == 0x80)
{
size = DispSize(disp, flags, 1);
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabTST[Index].Opc2 | size;
BAsmCode[2] = (reg1 << 4) | reg2;
CodeLen = DispOut(3, size, disp, 1);
return;
}
size = DispSize(disp, flags, scale);
BAsmCode[0] = 0x06;
BAsmCode[1] = 0x20 | (memex << 6) | size;
BAsmCode[2] = OpTabTST[Index].Opc3;
BAsmCode[3] = (reg1 << 4) | reg2;
CodeLen = DispOut(4, size, disp, scale);
return;
}
}
static void DecodeMOVCO(Word Index)
{
Byte regs;
Byte regd;
UNUSED(Index);
if (!CheckV2()) return;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!DecodeReg(&ArgStr[1], ®s, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
if (!DecodeIndirect(&ArgStr[2], ®d))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[2]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x27;
BAsmCode[2] = (regd << 4) | regs;
CodeLen = 3;
}
static void DecodeMOVLI(Word Index)
{
Byte regs;
Byte regd;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!DecodeIndirect(&ArgStr[1], ®s))
{
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®d, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[2]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x2F;
BAsmCode[2] = (regs << 4) | regd;
CodeLen = 3;
}
static const Byte OpTabBFMOV[] = {
0x5E, /* BFMOV */
0x5A, /* BFMOVZ */
};
static void DecodeBFMOV(Word Index)
{
LongInt slsb;
LongInt dlsb;
LongInt width;
tSymbolFlags flags;
Byte regs;
Byte regd;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(5,5)) return;
if (!CheckV3()) return;
if (!DecodeImm(&ArgStr[1], &slsb, &flags))
{
WrStrErrorPos(ErrNum_ExpectInt, &ArgStr[1]);
return;
}
if (!mFirstPassUnknownOrQuestionable(flags) && !ChkRange(slsb, 0, 31)) return;
if (!DecodeImm(&ArgStr[2], &dlsb, &flags))
{
WrStrErrorPos(ErrNum_ExpectInt, &ArgStr[2]);
return;
}
if (!mFirstPassUnknownOrQuestionable(flags) && !ChkRange(dlsb, 0, 31)) return;
if (!DecodeImm(&ArgStr[3], &width, &flags))
{
WrStrErrorPos(ErrNum_ExpectInt, &ArgStr[3]);
return;
}
if (!mFirstPassUnknownOrQuestionable(flags) && !ChkRange(width, 1, 31)) return;
if (!DecodeReg(&ArgStr[4], ®s, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[4]);
return;
}
if (!DecodeReg(&ArgStr[5], ®d, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[5]);
return;
}
if (slsb + width > 32 || dlsb + width > 32)
{
WrError(ErrNum_OverRange);
return;
}
BAsmCode[0] = 0xFC;
BAsmCode[1] = OpTabBFMOV[Index];
BAsmCode[2] = (regs << 4) | regd;
BAsmCode[3] = ((dlsb - slsb) & 0x1f) | ((dlsb << 5) & 0xE0);
BAsmCode[4] = ((dlsb >> 3) & 0x03) | (((dlsb + width) << 2) & 0x7C);
CodeLen = 5;
}
static const struct {
Byte OpcI;
Byte OpcR;
} OpTabRSTR[] = {
{ 0xF0, 0xD0 }, /* RSTR */
{ 0xE0, 0xC0 }, /* SAVE */
};
static void DecodeRSTR(Word Index)
{
LongInt imm;
tSymbolFlags flags;
Byte reg;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
if (!CheckV3()) return;
if (!pCurrCPUProps->RegBank)
{
WrError(ErrNum_InstructionNotSupported);
return;
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (!ChkRange(imm, 0, pCurrCPUProps->RegBank - 1)) return;
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x76;
BAsmCode[2] = OpTabRSTR[Index].OpcI;
BAsmCode[3] = imm;
CodeLen = 4;
return;
}
if (DecodeReg(&ArgStr[1], ®, eRn))
{
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x76;
BAsmCode[2] = OpTabRSTR[Index].OpcR | reg;
BAsmCode[3] = 0x00;
CodeLen = 4;
return;
}
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
static const struct {
Byte Opc1;
Byte Opc2;
} OpTabDABS[] = {
{ 0x0C, 0x01 }, /* DABS */
{ 0x0C, 0x02 }, /* DNEG */
{ 0x0D, 0x0D }, /* DROUND */
{ 0x0D, 0x00 }, /* DSQRT */
{ 0x0D, 0x0C }, /* DTOF */
{ 0x0D, 0x08 }, /* DTOI */
{ 0x0D, 0x09 }, /* DTOU */
};
static void DecodeDABS(Word Index)
{
Byte regs;
Byte regd;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
if (!DecodeReg(&ArgStr[1], ®s, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®d, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[2]);
return;
}
BAsmCode[0] = 0x76;
BAsmCode[1] = 0x90;
BAsmCode[2] = OpTabDABS[Index].Opc1 | (regs << 4);
BAsmCode[3] = OpTabDABS[Index].Opc2 | (regd << 4);
CodeLen = 4;
}
static const struct {
Byte Opc;
} OpTabDADD[] = {
{ 0x00 }, /* DADD */
{ 0x05 }, /* DDIV */
{ 0x02 }, /* DMUL */
{ 0x01 }, /* DSUB */
};
static void DecodeDADD(Word Index)
{
Byte regs1;
Byte regs2;
Byte regd;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(3,3)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
if (!DecodeReg(&ArgStr[1], ®s1, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®s2, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[2]);
return;
}
if (!DecodeReg(&ArgStr[3], ®d, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[3]);
return;
}
BAsmCode[0] = 0x76;
BAsmCode[1] = 0x90;
BAsmCode[2] = OpTabDADD[Index].Opc | (regs2 << 4);
BAsmCode[3] = (regd << 4) | regs1;
CodeLen = 4;
}
static void DecodeDCMPcm(Word Index)
{
Byte regs1;
Byte regs2;
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
if (!DecodeReg(&ArgStr[1], ®s1, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®s2, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[2]);
return;
}
BAsmCode[0] = 0x76;
BAsmCode[1] = 0x90;
BAsmCode[2] = 0x08 | (regs2 << 4);
BAsmCode[3] = ((Index << 4) & 0xF0) | regs1;
CodeLen = 4;
}
static void DecodeDMOV(Word Index)
{
Byte size;
Byte regs;
Byte regd;
LongInt disp;
LongInt imm;
tSymbolFlags flags;
Byte dsize;
UNUSED(Index);
if (!ChkArgCnt(2,2)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
if (!DecodeAttrDouble(&size)) return;
if (DecodeReg(&ArgStr[1], ®s, eRn))
{
if (DecodeReg(&ArgStr[2], ®d, eDRHn))
{ /* (1) / (2) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x77;
BAsmCode[2] = 0x80 | regs;
BAsmCode[3] = 0x02 | (regd << 4) | size;
CodeLen = 4;
return;
}
if (DecodeReg(&ArgStr[2], ®d, eDRLn) && !size)
{ /* (3) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x77;
BAsmCode[2] = 0x80 | regs;
BAsmCode[3] = 0x00 | (regd << 4);
CodeLen = 4;
return;
}
}
if (DecodeReg(&ArgStr[2], ®d, eRn))
{
if (DecodeReg(&ArgStr[1], ®s, eDRHn) && !size)
{ /* (4) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x75;
BAsmCode[2] = 0x80 | regd;
BAsmCode[3] = 0x02 | (regs << 4);
CodeLen = 4;
return;
}
if (DecodeReg(&ArgStr[1], ®s, eDRLn) && !size)
{ /* (5) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x75;
BAsmCode[2] = 0x80 | regd;
BAsmCode[3] = 0x00 | (regs << 4);
CodeLen = 4;
return;
}
}
if (DecodeReg(&ArgStr[1], ®s, eDRn) && size)
{
if (DecodeReg(&ArgStr[2], ®d, eDRn))
{ /* (6) */
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x90;
BAsmCode[2] = 0x0C | (regs << 4);
BAsmCode[3] = 0x00 | (regd << 4);
CodeLen = 4;
return;
}
if (DecodeIndirectADC(&ArgStr[2], ®d, &disp, &flags) && size)
{ /* (7) */
dsize = DispSize(disp, flags, 8);
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0x78 | dsize;
BAsmCode[2] = 0x08 | (regd << 4);
CodeLen = DispOut(3, dsize, disp, 8);
BAsmCode[CodeLen++] = 0x00 | (regs << 4);
return;
}
}
if (DecodeIndirectADC(&ArgStr[1], ®s, &disp, &flags) && size)
{
if (DecodeReg(&ArgStr[2], ®d, eDRn))
{ /* (8) */
dsize = DispSize(disp, flags, 8);
BAsmCode[0] = 0xFC;
BAsmCode[1] = 0xC8 | dsize;
BAsmCode[2] = 0x08 | (regs << 4);
CodeLen = DispOut(3, dsize, disp, 8);
BAsmCode[CodeLen++] = 0x00 | (regd << 4);
return;
}
}
if (DecodeImm(&ArgStr[1], &imm, &flags))
{
if (DecodeReg(&ArgStr[2], ®d, eDRHn))
{ /* (9) / (10) */
BAsmCode[0] = 0xF9;
BAsmCode[1] = 0x03;
BAsmCode[2] = 0x02 | (regd << 4) | size;
CodeLen = ImmOut(3, 0, imm);
return;
}
if (DecodeReg(&ArgStr[2], ®d, eDRLn) && !size)
{ /* (11) */
BAsmCode[0] = 0xF9;
BAsmCode[1] = 0x03;
BAsmCode[2] = 0x00 | (regd << 4);
CodeLen = ImmOut(3, 0, imm);
return;
}
}
WrError(ErrNum_InvArg);
}
static const Byte OpTabDPOPM[] = {
0xA8, /* DPOPM */
0xA0 /* DPUSHM */
};
static void DecodeDPOPM(Word Index)
{
const int len
= strlen(ArgStr
[1].
str.
p_str);
Byte size;
Byte reg1;
Byte reg2;
int i;
if (!DecodeAttrDouble(&size)) return;
if (!ChkArgCnt(1,1)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
for (i = 0; i < len; i++)
{
if (ArgStr[1].str.p_str[i] == '-') break;
}
if (i >= len)
{
WrStrErrorPos(ErrNum_InvRegList, &ArgStr[1]);
return;
}
StrCompCopySub(&Temp1, &ArgStr[1], 0, i);
if (!DecodeReg(&Temp1, ®1, size ? eDRn : eDCRn))
{
WrStrErrorPos(ErrNum_InvRegList, &ArgStr[1]);
return;
}
StrCompCopySub(&Temp1, &ArgStr[1], i + 1, len - i - 1);
if (!DecodeReg(&Temp1, ®2, size ? eDRn : eDCRn))
{
WrStrErrorPos(ErrNum_InvRegList, &ArgStr[1]);
return;
}
if (reg2 >= reg1)
{
BAsmCode[0] = 0x75;
BAsmCode[1] = OpTabDPOPM[Index] | (size << 4);
BAsmCode[2] = (reg1 << 4) | (reg2 - reg1);
CodeLen = 3;
return;
}
WrStrErrorPos(ErrNum_InvRegList, &ArgStr[1]);
}
static const struct {
Byte Opc1;
Byte Opc2;
} OpTabFTOD[] = {
{ 0x80, 0x0A }, /* FTOD */
{ 0x80, 0x09 }, /* ITOD */
{ 0x80, 0x0D }, /* UTOD */
};
static void DecodeFTOD(Word Index)
{
Byte regs;
Byte regd;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
if (!DecodeReg(&ArgStr[1], ®s, eRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[1]);
return;
}
if (!DecodeReg(&ArgStr[2], ®d, eDRn))
{
WrStrErrorPos(ErrNum_ExpectReg, &ArgStr[2]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x77;
BAsmCode[2] = OpTabFTOD[Index].Opc1 | regs;
BAsmCode[3] = OpTabFTOD[Index].Opc2 | (regd << 4);
CodeLen = 4;
}
static void DecodeMVFDC(Word Index)
{
Byte regc;
Byte reg;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(2,2)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
if (!DecodeReg(&ArgStr[Index + 1], ®c, eDCRn))
{
WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[Index + 1]);
return;
}
if (!DecodeReg(&ArgStr[2 - Index], ®, eRn))
{
WrStrErrorPos(ErrNum_InvReg, &ArgStr[2 - Index]);
return;
}
BAsmCode[0] = 0xFD;
BAsmCode[1] = 0x75 | (Index << 1);
BAsmCode[2] = 0x80 | reg;
BAsmCode[3] = 0x04 | (regc << 4);
CodeLen = 4;
}
static void DecodeMVFDR(Word Index)
{
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(0,0)) return;
if (!CheckV3()) return;
if (!CheckDouble()) return;
BAsmCode[0] = 0x75;
BAsmCode[1] = 0x90;
BAsmCode[2] = 0x1B;
CodeLen = 3;
}
#ifdef COMPAT
#define BigEndianSymName "BIGENDIAN" /* T.B.D. */
static void DecodeENDIAN(Word Index)
{
const char *str;
UNUSED(Index);
if (!ChkNoAttr()) return;
if (!ChkArgCnt(1,1)) return;
str = ArgStr[1].str.p_str;
if (!as_strcasecmp(str, "BIG"))
SetFlag(&TargetBigEndian, BigEndianSymName, True);
else if (!as_strcasecmp(str, "LITTLE"))
SetFlag(&TargetBigEndian, BigEndianSymName, False);
else
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
static void DecodeWORD(Word flags)
{
DecodeIntelDW(flags | (TargetBigEndian ? eIntPseudoFlag_BigEndian : 0));
}
static void DecodeLWORD(Word flags)
{
DecodeIntelDD(flags | (TargetBigEndian ? eIntPseudoFlag_BigEndian : 0));
}
static void DecodeFLOAT(Word flags)
{
DecodeIntelDD(flags | (TargetBigEndian ? eIntPseudoFlag_BigEndian : 0));
}
static void DecodeDOUBLE(Word flags)
{
DecodeIntelDQ(flags | (TargetBigEndian ? eIntPseudoFlag_BigEndian : 0));
}
#endif /* COMPAT */
/*---------------------------------------------------------------------------*/
static void AddABS(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeABS);
}
static void AddADC(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeADC);
}
static void AddADD(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeADD);
}
static void AddBCLR(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBCLR);
}
static void AddBCnd(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBCnd);
}
static void AddBMCnd(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBMCnd);
}
static void AddBRK(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBRK);
}
static void AddBSR(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBSR);
}
static void AddCLRPSW(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeCLRPSW);
}
static void AddDIV(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeDIV);
}
static void AddFADD(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFADD);
}
static void AddINT(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeINT);
}
static void AddITOF(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeITOF);
}
static void AddJMP(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeJMP);
}
static void AddMACHI(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMACHI);
}
static void AddMOV(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMOV);
}
static void AddMOVU(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMOVU);
}
static void AddMVFACHI(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVFACHI);
}
static void AddMVFC(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVFC);
}
static void AddMVTACHI(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVTACHI);
}
static void AddMVTC(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVTC);
}
static void AddMVTIPL(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVTIPL);
}
static void AddPOPC(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodePOPC);
}
static void AddPOPM(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodePOPM);
}
static void AddPUSH(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodePUSH);
}
static void AddRACW(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRACW);
}
static void AddRMPA(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRMPA);
}
static void AddROTL(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeROTL);
}
static void AddRTE(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRTE);
}
static void AddRTSD(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRTSD);
}
static void AddSCCnd(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeSCCnd);
}
static void AddSHAR(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeSHAR);
}
static void AddSTNZ(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeSTNZ);
}
static void AddTST(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeTST);
}
static void AddMOVCO(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMOVCO);
}
static void AddMOVLI(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMOVLI);
}
static void AddBFMOV(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeBFMOV);
}
static void AddRSTR(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeRSTR);
}
static void AddDABS(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeDABS);
}
static void AddDADD(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeDADD);
}
static void AddDCMPcm(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeDCMPcm);
}
static void AddDMOV(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeDMOV);
}
static void AddDPOPM(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeDPOPM);
}
static void AddFTOD(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeFTOD);
}
static void AddMVFDC(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVFDC);
}
static void AddMVFDR(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeMVFDR);
}
#ifdef COMPAT
static void AddBLK(const char *NName, Word NCode)
{
AddInstTable(InstTable, NName, NCode, DecodeIntelDS);
}
#endif /* COMPAT */
static Boolean TrueFnc(void)
{
return True;
}
static void InitFields(void)
{
InstTable = CreateInstTable(201);
/* RXv1 */
AddABS("ABS", 0x200F);
AddADC("ADC", 0x0802);
AddADD("ADD", 0);
AddADD("AND", 1);
AddBCLR("BCLR", 0);
AddBCnd("BEQ", 0);
AddBCnd("BZ", 0);
AddBCnd("BNE", 1);
AddBCnd("BNZ", 1);
AddBCnd("BGEU", 2);
AddBCnd("BC", 2);
AddBCnd("BLTU", 3);
AddBCnd("BNC", 3);
AddBCnd("BGTU", 4);
AddBCnd("BLEU", 5);
AddBCnd("BPZ", 6);
AddBCnd("BN", 7);
AddBCnd("BGE", 8);
AddBCnd("BLT", 9);
AddBCnd("BGT", 10);
AddBCnd("BLE", 11);
AddBCnd("BO", 12);
AddBCnd("BNO", 13);
AddBMCnd("BMEQ", 0);
AddBMCnd("BMZ", 0);
AddBMCnd("BMNE", 1);
AddBMCnd("BMNZ", 1);
AddBMCnd("BMGEU", 2);
AddBMCnd("BMC", 2);
AddBMCnd("BMLTU", 3);
AddBMCnd("BMNC", 3);
AddBMCnd("BMGTU", 4);
AddBMCnd("BMLEU", 5);
AddBMCnd("BMPZ", 6);
AddBMCnd("BMN", 7);
AddBMCnd("BMGE", 8);
AddBMCnd("BMLT", 9);
AddBMCnd("BMGT", 10);
AddBMCnd("BMLE", 11);
AddBMCnd("BMO", 12);
AddBMCnd("BMNO", 13);
AddBCLR("BNOT", 1);
AddBCnd("BRA", 14);
AddBRK("BRK", 0x0000);
AddBCLR("BSET", 2);
AddBSR("BSR", 0);
AddBCLR("BTST", 3);
AddCLRPSW("CLRPSW", 0xB0);
AddADD("CMP", 2);
AddDIV("DIV", 0);
AddDIV("DIVU", 1);
AddDIV("EMUL", 2);
AddDIV("EMULU", 3);
AddFADD("FADD", 0);
AddFADD("FCMP", 1);
AddFADD("FDIV", 2);
AddFADD("FMUL", 3);
AddFADD("FSUB", 4);
AddFADD("FTOI", 5);
AddINT("INT", 0);
AddITOF("ITOF", 0);
AddJMP("JMP", 0);
AddJMP("JSR", 1);
AddMACHI("MACHI", 0);
AddMACHI("MACLO", 1);
AddDIV("MAX", 4);
AddDIV("MIN", 5);
AddMOV("MOV", 0);
AddMOVU("MOVU", 0);
AddADD("MUL", 3);
AddMACHI("MULHI", 2);
AddMACHI("MULLO", 3);
AddMVFACHI("MVFACHI", 0);
AddMVFACHI("MVFACMI", 1);
AddMVFC("MVFC", 0);
AddMVTACHI("MVTACHI", 0);
AddMVTACHI("MVTACLO", 1);
AddMVTC("MVTC", 0);
AddMVTIPL("MVTIPL", 0);
AddABS("NEG", 0x1007);
AddBRK("NOP", 0x0003);
AddABS("NOT", 0x003B);
AddADD("OR", 4);
AddJMP("POP", 2);
AddPOPC("POPC", 0);
AddPOPM("POPM", 0);
AddPUSH("PUSH", 0);
AddPOPC("PUSHC", 1);
AddPOPM("PUSHM", 1);
AddRACW("RACW", 0);
AddMACHI("REVL", 4);
AddMACHI("REVW", 5);
AddRMPA("RMPA", 0x8C);
AddJMP("ROLC", 3);
AddJMP("RORC", 4);
AddROTL("ROTL", 0);
AddROTL("ROTR", 1);
AddFADD("ROUND", 6);
AddRTE("RTE", 0x7F95);
AddRTE("RTFI", 0x7F94);
AddBRK("RTS", 0x0002);
AddRTSD("RTSD", 0);
AddJMP("SAT", 5);
AddRTE("SATR", 0x7F93);
AddADC("SBB", 0x0000);
AddSCCnd("SCEQ", 0);
AddSCCnd("SCZ", 0);
AddSCCnd("SCNE", 1);
AddSCCnd("SCNZ", 1);
AddSCCnd("SCGEU", 2);
AddSCCnd("SCC", 2);
AddSCCnd("SCLTU", 3);
AddSCCnd("SCNC", 3);
AddSCCnd("SCGTU", 4);
AddSCCnd("SCLEU", 5);
AddSCCnd("SCPZ", 6);
AddSCCnd("SCN", 7);
AddSCCnd("SCGE", 8);
AddSCCnd("SCLT", 9);
AddSCCnd("SCGT", 10);
AddSCCnd("SCLE", 11);
AddSCCnd("SCO", 12);
AddSCCnd("SCNO", 13);
AddRTE("SCMPU", 0x7F83);
AddCLRPSW("SETPSW", 0xA0);
AddSHAR("SHAR", 0);
AddSHAR("SHLL", 1);
AddSHAR("SHLR", 2);
AddRTE("SMOVB", 0x7F8B);
AddRTE("SMOVF", 0x7F8F);
AddRTE("SMOVU", 0x7F87);
AddRMPA("SSTR", 0x88);
AddSTNZ("STNZ", 0);
AddSTNZ("STZ", 1);
AddADD("SUB", 5);
AddRMPA("SUNTIL", 0x80);
AddRMPA("SWHILE", 0x84);
AddTST("TST", 0);
AddRTE("WAIT", 0x7F96);
AddTST("XCHG", 1);
AddTST("XOR", 2);
/* RXv2 */
AddFADD("FSQRT", 7);
AddFADD("FTOU", 8);
AddITOF("UTOF", 1);
AddMOVCO("MOVCO", 0);
AddMOVLI("MOVLI", 0);
AddMACHI("EMACA", 6);
AddMACHI("EMSBA", 7);
AddMACHI("EMULA", 8);
AddMACHI("MACLH", 9);
AddMACHI("MSBHI", 10);
AddMACHI("MSBLH", 11);
AddMACHI("MSBLO", 12);
AddMACHI("MULLH", 13);
AddMVFACHI("MVFACGU", 2);
AddMVFACHI("MVFACLO", 3);
AddMVTACHI("MVTACGU", 2);
AddRACW("RACL", 1);
AddRACW("RDACL", 2);
AddRACW("RDACW", 3);
/* RXv3 */
AddBFMOV("BFMOV", 0);
AddBFMOV("BFMOVZ", 1);
AddRSTR("RSTR", 0);
AddRSTR("SAVE", 1); SaveIsOccupiedFnc = TrueFnc;
AddDABS("DABS", 0);
AddDADD("DADD", 0);
AddDCMPcm("DCMPUN", 0x01);
AddDCMPcm("DCMPEQ", 0x02);
AddDCMPcm("DCMPLT", 0x04);
AddDCMPcm("DCMPLE", 0x06);
AddDADD("DDIV", 1);
AddDMOV("DMOV", 0);
AddDADD("DMUL", 2);
AddDABS("DNEG", 1);
AddDPOPM("DPOPM", 0);
AddDPOPM("DPUSHM", 1);
AddDABS("DROUND", 2);
AddDABS("DSQRT", 3);
AddDADD("DSUB", 3);
AddDABS("DTOF", 4);
AddDABS("DTOI", 5);
AddDABS("DTOU", 6);
AddFTOD("FTOD", 0);
AddFTOD("ITOD", 1);
AddMVFDC("MVFDC", 0);
AddMVFDR("MVFDR", 0);
AddMVFDC("MVTDC", 1);
AddFTOD("UTOD", 2);
/* Pseudo Instructions */
#ifdef COMPAT
AddInstTable(InstTable, "ENDIAN", 0, DecodeENDIAN);
AddBLK("BLKB", 1);
AddBLK("BLKW", 2);
AddBLK("BLKL", 4);
AddBLK("BLKD", 8);
AddInstTable(InstTable, "BYTE", eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString, DecodeIntelDB);
AddInstTable(InstTable, "WORD", eIntPseudoFlag_AllowInt, DecodeWORD);
AddInstTable(InstTable, "LWORD", eIntPseudoFlag_AllowInt, DecodeLWORD);
AddInstTable(InstTable, "FLOAT", eIntPseudoFlag_AllowFloat, DecodeFLOAT);
AddInstTable(InstTable, "DOUBLE", eIntPseudoFlag_AllowFloat, DecodeDOUBLE);
#endif
StrCompAlloc(&Temp1, STRINGSIZE);
StrCompAlloc(&Temp2, STRINGSIZE);
}
static void DeinitFields(void)
{
StrCompFree(&Temp2);
StrCompFree(&Temp1);
DestroyInstTable(InstTable);
}
/*---------------------------------------------------------------------------*/
static void MakeCode_RX(void)
{
CodeLen = 0;
DontPrint = False;
if (Memo("")) return;
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
static Boolean IsDef_RX(void)
{
return False;
}
static void SwitchFrom_RX(void)
{
DeinitFields();
}
static void SwitchTo_RX(void *pUser)
{
const TFamilyDescr *pDescr;
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
pDescr = FindFamilyByName("RX");
PCSymbol = "$";
HeaderID = pDescr->Id;
NOPCode = 0x03;
DivideChars = ",";
HasAttrs = True;
AttrChars = ".";
ValidSegs = (1 << SegCode);
Grans[SegCode] = 1;
ListGrans[SegCode] = 1;
SegInits[SegCode] = 0x0000;
SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
MakeCode = MakeCode_RX;
IsDef = IsDef_RX;
SwitchFrom = SwitchFrom_RX;
InitFields();
onoff_supmode_add();
onoff_bigendian_add();
pCurrCPUProps = (const tCPUProps *)pUser;
}
static const tCPUProps CPUProps[] =
{
/* Group InsSet FLT DBL RegB MVTIPL */
{ "RXV1", eRXv1, True, False, 0, True }, /* Generic RXv1 (Full option) */
{ "RX110", eRXv1, False, False, 0, True },
{ "RX111", eRXv1, False, False, 0, True },
{ "RX113", eRXv1, False, False, 0, True },
{ "RX130", eRXv1, False, False, 0, True },
{ "RX210", eRXv1, False, False, 0, True },
{ "RX21A", eRXv1, False, False, 0, True },
{ "RX220", eRXv1, False, False, 0, True },
{ "RX610", eRXv1, True, False, 0, False },
{ "RX621", eRXv1, True, False, 0, True },
{ "RX62N", eRXv1, True, False, 0, True },
{ "RX630", eRXv1, True, False, 0, True },
{ "RX631", eRXv1, True, False, 0, True },
{ "RXV2", eRXv2, True, False, 0, True }, /* Generic RXv2 */
{ "RX140", eRXv2, True, False, 0, True },
{ "RX230", eRXv2, True, False, 0, True },
{ "RX231", eRXv2, True, False, 0, True },
{ "RX64M", eRXv2, True, False, 0, True },
{ "RX651", eRXv2, True, False, 0, True },
{ "RXV3", eRXv3, True, True, 256, True }, /* Generic RXv3 (Full option) */
{ "RX660", eRXv3, True, False, 16, True },
{ "RX671", eRXv3, True, True, 16, True },
{ "RX72M", eRXv3, True, True, 16, True },
{ "RX72N", eRXv3, True, True, 16, True },
{ "" , eRXv1, False, False, 0, False }
};
void coderx_init(void)
{
const tCPUProps *pProp;
for (pProp = CPUProps; pProp->Name[0]; pProp++)
(void)AddCPUUser(pProp->Name, SwitchTo_RX, (void *)pProp, NULL);
AddCopyright("Renesas RX Generator (C) 2023 Haruo Asano");
}