/* code960.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* Makroassembler AS */
/* */
/* Codegenerator i960-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "be_le.h"
#include "strutil.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmitree.h"
#include "codevars.h"
#include "intpseudo.h"
#include "headids.h"
#include "errmsg.h"
#include "code960.h"
/*--------------------------------------------------------------------------*/
enum
{
ModNone = -1,
ModReg = 0,
ModFReg = 1,
ModImm = 2
};
#define MModReg (1 << ModReg)
#define MModFReg (1 << ModFReg)
#define MModImm (1 << ModImm)
typedef enum
{
NoneOp, IntOp, LongOp, QuadOp, SingleOp, DoubleOp, ExtOp, OpCnt
} OpType;
static LongWord OpMasks[OpCnt] =
{
0xffffffff, 0, 1, 3, 0, 1, 3
};
typedef struct
{
LongWord Code;
} FixedOrder;
typedef struct
{
LongWord Code;
Boolean HasSrc;
} CobrOrder;
typedef struct
{
LongWord Code;
OpType Src1Type, Src2Type, DestType;
Boolean Imm1, Imm2, Privileged;
} RegOrder;
typedef struct
{
LongWord Code;
OpType Type;
ShortInt RegPos;
} MemOrder;
typedef struct
{
char Name[4];
LongWord Code;
} SpecReg;
static FixedOrder *FixedOrders;
static RegOrder *RegOrders;
static CobrOrder *CobrOrders;
static FixedOrder *CtrlOrders;
static MemOrder *MemOrders;
static const SpecReg SpecRegs[] =
{
{ "FP" , 31 },
{ "PFP", 0 },
{ "SP" , 1 },
{ "RIP", 2 }
};
static CPUVar CPU80960;
/*--------------------------------------------------------------------------*/
static Boolean ChkAdr(int AMode, Byte Mask, LongWord *Erg, LongWord *Mode)
{
UNUSED(Erg);
if (!(Mask & (1 << AMode)))
{
WrError(ErrNum_InvAddrMode);
return False;
}
else
{
*Mode = (AMode != ModReg);
return True;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeIRegCore(const char *pArg, LongWord *pResult)
* \brief check whether argument is a CPU register
* \param pArg source argument
* \param pResult register # if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeIRegCore(const char *pArg, LongWord *pResult)
{
size_t z;
LongWord Offs;
for (z = 0; z < as_array_size(SpecRegs); z++)
if (!as_strcasecmp(pArg, SpecRegs[z].Name))
{
*pResult = REGSYM_FLAG_ALIAS | SpecRegs[z].Code;
return True;
}
switch (as_toupper(*pArg))
{
case 'G':
Offs = 16;
goto eval;
case 'R':
Offs = 0;
goto eval;
default:
return False;
eval:
{
char *pEnd;
*pResult
= strtoul(pArg
+ 1, &pEnd
, 10);
if (!*pEnd && (*pResult <= 15))
{
*pResult += Offs;
return True;
}
}
}
return False;
}
/*!------------------------------------------------------------------------
* \fn DecodeFPRegCore(const char *pArg, LongWord *pResult)
* \brief check whether argument is an FPU register
* \param pArg source argument
* \param pResult register # if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeFPRegCore(const char *pArg, LongWord *pResult)
{
if (!as_strncasecmp(pArg, "FP", 2))
{
char *pEnd;
*pResult
= strtoul(pArg
+ 2, &pEnd
, 10);
if (!*pEnd && (*pResult <= 3))
return True;
}
return False;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_960(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - i960 variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_960(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
{
switch (InpSize)
{
case eSymbolSize32Bit:
{
size_t z;
for (z = 0; z < as_array_size(SpecRegs); z++)
if (Value == (REGSYM_FLAG_ALIAS | SpecRegs[z].Code))
{
as_snprintf(pDest, DestSize, "%s", SpecRegs[z].Name);
return;
}
as_snprintf(pDest, DestSize, "%c%u", Value & 16 ? 'G' : 'R', (unsigned)(Value & 15));
break;
}
case eSymbolSizeFloat64Bit:
as_snprintf(pDest, DestSize, "FP%u", (unsigned)Value);
break;
default:
as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeIReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
* \brief check whether argument is a CPU register or register alias
* \param pArg source argument
* \param pResult register # if yes
* \param MustBeReg True if register is expected
* \return reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeIReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
{
if (DecodeIRegCore(pArg->str.p_str, pResult))
{
*pResult &= ~REGSYM_FLAG_ALIAS;
return eIsReg;
}
else
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
if (eIsReg == RegEvalResult)
*pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
return RegEvalResult;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeIOrFPReg(const tStrComp *pArg, LongWord *pResult, tSymbolSize *pSize, Boolean MustBeReg)
* \brief check whether argument is a CPU/FPU register or register alias
* \param pArg source argument
* \param pResult register # if yes
* \param pSize returns register size/type
* \param MustBeReg True if register is expected
* \return reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeIOrFPReg(const tStrComp *pArg, LongWord *pResult, tSymbolSize *pSize, Boolean MustBeReg)
{
if (DecodeIRegCore(pArg->str.p_str, pResult))
{
*pResult &= ~REGSYM_FLAG_ALIAS;
*pSize = eSymbolSize32Bit;
return eIsReg;
}
else if (DecodeFPRegCore(pArg->str.p_str, pResult))
{
*pSize = eSymbolSizeFloat64Bit;
return eIsReg;
}
else
{
tRegDescr RegDescr;
tEvalResult EvalResult;
tRegEvalResult RegEvalResult;
RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
if (eIsReg == RegEvalResult)
{
*pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
*pSize = EvalResult.DataSize;
}
return RegEvalResult;
}
}
static Boolean DecodeAdr(const tStrComp *pArg, Byte Mask, OpType Type, LongWord *Erg, LongWord *Mode)
{
Double FVal;
tEvalResult EvalResult;
tSymbolSize DataSize;
*Mode = ModNone;
*Erg = 0;
switch (DecodeIOrFPReg(pArg, Erg, &DataSize, False))
{
case eIsReg:
switch (DataSize)
{
case eSymbolSize32Bit:
if ((*Erg) & OpMasks[Type])
{
WrStrErrorPos(ErrNum_InvRegPair, pArg);
return False;
}
else
return ChkAdr(ModReg, Mask, Erg, Mode);
case eSymbolSizeFloat64Bit:
return ChkAdr(ModFReg, Mask, Erg, Mode);
default:
break;
}
break;
case eRegAbort:
return False;
case eIsNoReg:
break;
}
if (Type != IntOp)
{
FVal = EvalStrFloatExpressionWithResult(pArg, Float64, &EvalResult);
if (EvalResult.OK)
{
if (mFirstPassUnknown(EvalResult.Flags))
FVal = 0.0;
if (FVal == 0.0)
*Erg = 16;
else if (FVal == 1.0)
*Erg = 22;
else
{
WrError(ErrNum_OverRange);
EvalResult.OK = False;
}
if (EvalResult.OK)
return ChkAdr(ModImm, Mask, Erg, Mode);
}
}
else
{
*Erg = EvalStrIntExpressionWithResult(pArg, UInt5, &EvalResult);
if (EvalResult.OK)
return ChkAdr(ModImm, Mask, Erg, Mode);
}
return False;
}
#define NOREG 33
#define IPREG 32
static int AddrError(tErrorNum Num)
{
WrError(Num);
return -1;
}
static int DecodeMem(const tStrComp *pArg, LongWord *Erg, LongWord *Ext)
{
LongInt DispAcc;
LongWord Base, Index, Scale, Mode;
Boolean Done;
int ArgLen, Scale2;
char *p, *p2, *end;
Boolean OK;
tStrComp Arg = *pArg, RegArg, ScaleArg;
Base = Index = NOREG;
Scale = 0;
/* Register abhobeln */
Done = FALSE;
do
{
ArgLen
= strlen(Arg.
str.
p_str);
if (ArgLen == 0)
Done = True;
else switch (Arg.str.p_str[ArgLen - 1])
{
case ']':
if (Index != NOREG) return AddrError(ErrNum_InvAddrMode);
for (p = Arg.str.p_str + ArgLen - 1; p >= Arg.str.p_str; p--)
if (*p == '[')
break;
if (p < Arg.str.p_str) return AddrError(ErrNum_BrackErr);
StrCompShorten(&Arg, 1);
StrCompSplitRef(&Arg, &RegArg, &Arg, p);
p2
= strchr(RegArg.
str.
p_str, '*');
if (p2)
{
StrCompSplitRef(&RegArg, &ScaleArg, &RegArg, p2);
Scale2
= strtol(ScaleArg.
str.
p_str, &end
, 10);
if (*end != '\0') return AddrError(ErrNum_InvAddrMode);
for (Scale = 0; Scale < 5; Scale++, Scale2 = Scale2 >> 1)
if (Odd(Scale2))
break;
if (Scale2 != 1) return AddrError(ErrNum_InvAddrMode);
}
if (DecodeIReg(&RegArg, &Index, True) != eIsReg)
return -1;
break;
case ')':
if (Base != NOREG) return AddrError(ErrNum_InvAddrMode);
for (p = Arg.str.p_str + ArgLen - 1; p >= Arg.str.p_str; p--)
if (*p == '(')
break;
if (p < Arg.str.p_str) return AddrError(ErrNum_BrackErr);
StrCompShorten(&Arg, 1);
StrCompSplitRef(&Arg, &RegArg, &Arg, p);
if (!as_strcasecmp(RegArg.str.p_str, "IP"))
Base = IPREG;
else if (DecodeIReg(&RegArg, &Base, True) != eIsReg)
return -1;
break;
default:
Done = True;
}
}
while (!Done);
DispAcc = EvalStrIntExpression(&Arg, Int32, &OK);
if (Base == IPREG)
{
DispAcc -= EProgCounter() + 8;
if (Index != NOREG) return AddrError(ErrNum_InvAddrMode);
else
{
*Erg = (5 << 10);
*Ext = DispAcc;
return 1;
}
}
else if ((Index == NOREG) && (DispAcc >= 0) && (DispAcc <= 4095))
{
*Erg = DispAcc;
if (Base != NOREG)
*Erg += 0x2000 + (Base << 14);
return 0;
}
else
{
Mode = (Ord(DispAcc != 0) << 3) + 4 + (Ord(Index != NOREG) << 1) + Ord(Base != NOREG);
if ((Mode & 9) == 0)
Mode += 8;
if (Mode == 5)
Mode--;
*Erg = (Mode << 10);
if (Base != NOREG)
*Erg += Base << 14;
if (Index != NOREG)
*Erg += Index + (Scale << 7);
if (Mode < 8) return 0;
else
{
*Ext = DispAcc;
return 1;
}
}
}
/*--------------------------------------------------------------------------*/
static void DecodeFixed(Word Index)
{
FixedOrder *Op = FixedOrders + Index;
if (ChkArgCnt(0, 0))
{
DAsmCode[0] = Op->Code;
CodeLen = 4;
}
}
static void DecodeReg(Word Index)
{
RegOrder *Op = RegOrders + Index;
LongWord DReg = 0, DMode = 0;
LongWord S1Reg = 0, S1Mode = 0;
LongWord S2Reg = 0, S2Mode = 0;
unsigned NumArgs = 1 + Ord(Op->Src2Type != NoneOp) + Ord(Op->DestType != NoneOp), ActArgCnt;
tStrComp *pDestArg = NULL;
/* if destination required, but too few args, assume the last op is also destination */
ActArgCnt = ArgCnt;
if (Op->DestType != NoneOp)
{
if (ArgCnt == 1 + Ord(Op->Src2Type != NoneOp))
ActArgCnt++;
pDestArg = &ArgStr[ArgCnt];
}
if (!ChkArgCntExt(ActArgCnt, NumArgs, NumArgs));
else if (((Op->DestType >= SingleOp) || (Op->Src1Type >= SingleOp)) && (!FPUAvail)) WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
else if (((Op->DestType == NoneOp) || (DecodeAdr(pDestArg, MModReg | (Op->DestType >= SingleOp ? MModFReg : 0), Op->DestType, &DReg, &DMode)))
&& (DecodeAdr(&ArgStr[1], MModReg | (Op->Src1Type >= SingleOp ? MModFReg : 0) | (Op->Imm1 ? MModImm : 0 ), Op->Src1Type, &S1Reg, &S1Mode))
&& ((Op->Src2Type == NoneOp) || (DecodeAdr(&ArgStr[2], MModReg | (Op->Src2Type >= SingleOp ? MModFReg : 0) | (Op->Imm2 ? MModImm : 0), Op->Src2Type, &S2Reg, &S2Mode))))
{
DAsmCode[0] = ((Op->Code & 0xff0) << 20)
+ ((Op->Code & 0xf) << 7)
+ (S1Reg)
+ (S2Reg << 14)
+ (DReg << 19)
+ (S1Mode << 11)
+ (S2Mode << 12)
+ (DMode << 13);
CodeLen = 4;
if ((Op->Privileged) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
}
}
static void DecodeCobr(Word Index)
{
CobrOrder *Op = CobrOrders + Index;
LongWord S1Reg, S1Mode;
LongWord S2Reg = 0, S2Mode = 0;
LongInt AdrInt;
Boolean OK;
tSymbolFlags Flags;
unsigned NumArgs = 1 + 2 * Ord(Op->HasSrc);
if (!ChkArgCnt(NumArgs, NumArgs));
else if ((DecodeAdr(&ArgStr[1], MModReg | (Op->HasSrc ? MModImm : 0), IntOp, &S1Reg, &S1Mode))
&& ((!Op->HasSrc) || (DecodeAdr(&ArgStr[2], MModReg, IntOp, &S2Reg, &S2Mode))))
{
OK = True;
Flags = eSymbolFlag_None;
AdrInt = (Op->HasSrc) ? EvalStrIntExpressionWithFlags(&ArgStr[3], UInt32, &OK, &Flags) - EProgCounter() : 0;
if (mFirstPassUnknown(Flags))
AdrInt &= (~3);
if (OK)
{
if (AdrInt & 3) WrError(ErrNum_NotAligned);
else if (!mSymbolQuestionable(Flags) && ((AdrInt < -4096) || (AdrInt > 4090))) WrError(ErrNum_JmpDistTooBig);
else
{
DAsmCode[0] = (Op->Code << 24)
+ (S1Reg << 19)
+ (S2Reg << 14)
+ (S1Mode << 13)
+ (AdrInt & 0x1ffc);
CodeLen = 4;
}
}
}
}
static void DecodeCtrl(Word Index)
{
FixedOrder *Op = CtrlOrders + Index;
LongInt AdrInt;
tSymbolFlags Flags;
Boolean OK;
if (ChkArgCnt(1, 1))
{
AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags) - EProgCounter();
if (mFirstPassUnknown(Flags)) AdrInt &= (~3);
if (OK)
{
if (AdrInt & 3) WrError(ErrNum_NotAligned);
else if (!mSymbolQuestionable(Flags) && ((AdrInt < -8388608) || (AdrInt > 8388604))) WrError(ErrNum_JmpDistTooBig);
else
{
DAsmCode[0] = (Op->Code << 24) + (AdrInt & 0xfffffc);
CodeLen = 4;
}
}
}
}
static void DecodeMemO(Word Index)
{
MemOrder *Op = MemOrders + Index;
LongWord Reg = 0, Mem = 0;
int MemType;
ShortInt MemPos = (Op->RegPos > 0) ? 3 - Op->RegPos : 1;
unsigned NumArgs = 1 + Ord(Op->RegPos > 0);
if (!ChkArgCnt(NumArgs, NumArgs));
else if ((Op->RegPos > 0) && (DecodeIReg(&ArgStr[Op->RegPos], &Reg, True) != eIsReg));
else if (Reg & OpMasks[Op->Type]) WrStrErrorPos(ErrNum_InvReg, &ArgStr[Op->RegPos]);
else if ((MemType = DecodeMem(&ArgStr[MemPos], &Mem,DAsmCode + 1)) >= 0)
{
DAsmCode[0] = (Op->Code << 24) + (Reg << 19) + Mem;
CodeLen = (1 + MemType) << 2;
}
}
static void DecodeWORD(Word Code)
{
Boolean OK;
int z;
UNUSED(Code);
if (ChkArgCnt(1, ArgCntMax))
{
OK = True;
z = 1;
while ((z <= ArgCnt) && (OK))
{
DAsmCode[z - 1] = EvalStrIntExpression(&ArgStr[z], Int32, &OK);
z++;
}
if (OK)
CodeLen = 4 * ArgCnt;
}
}
static void DecodeSPACE(Word Code)
{
Boolean OK;
LongWord Size;
tSymbolFlags Flags;
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
Size = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &OK, &Flags);
if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
if (OK && !mFirstPassUnknown(Flags))
{
DontPrint = True;
if (!Size) WrError(ErrNum_NullResMem);
CodeLen = Size;
BookKeeping();
}
}
}
/*--------------------------------------------------------------------------*/
static void MakeCode_960(void)
{
CodeLen = 0;
DontPrint = False;
/* Nullanweisung */
if (Memo(""))
return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo(False))
return;
/* Befehlszaehler nicht ausgerichtet? */
if (EProgCounter() & 3)
WrError(ErrNum_AddrNotAligned);
/* CPU-Anweisungen */
if (!LookupInstTable(InstTable, OpPart.str.p_str))
WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}
/*--------------------------------------------------------------------------*/
static void AddFixed(const char *NName, LongWord NCode)
{
order_array_rsv_end(FixedOrders, FixedOrder);
FixedOrders[InstrZ].Code = NCode;
AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
}
static void AddReg(const char *NName, LongWord NCode,
OpType NSrc1, OpType NSrc2, OpType NDest,
Boolean NImm1, Boolean NImm2, Boolean NPriv)
{
order_array_rsv_end(RegOrders, RegOrder);
RegOrders[InstrZ].Code = NCode;
RegOrders[InstrZ].Src1Type = NSrc1;
RegOrders[InstrZ].Src2Type = NSrc2;
RegOrders[InstrZ].DestType = NDest;
RegOrders[InstrZ].Imm1 = NImm1;
RegOrders[InstrZ].Imm2 = NImm2;
RegOrders[InstrZ].Privileged = NPriv;
AddInstTable(InstTable, NName, InstrZ++, DecodeReg);
}
static void AddCobr(const char *NName, LongWord NCode, Boolean NHas)
{
order_array_rsv_end(CobrOrders, CobrOrder);
CobrOrders[InstrZ].Code = NCode;
CobrOrders[InstrZ].HasSrc = NHas;
AddInstTable(InstTable, NName, InstrZ++, DecodeCobr);
}
static void AddCtrl(const char *NName, LongWord NCode)
{
order_array_rsv_end(CtrlOrders, FixedOrder);
CtrlOrders[InstrZ].Code = NCode;
AddInstTable(InstTable, NName, InstrZ++, DecodeCtrl);
}
static void AddMem(const char *NName, LongWord NCode, OpType NType, int NPos)
{
order_array_rsv_end(MemOrders, MemOrder);
MemOrders[InstrZ].Code = NCode;
MemOrders[InstrZ].Type = NType;
MemOrders[InstrZ].RegPos = NPos;
AddInstTable(InstTable, NName, InstrZ++, DecodeMemO);
}
static void InitFields(void)
{
InstTable = CreateInstTable(301);
InstrZ = 0;
AddFixed("FLUSHREG", 0x66000680);
AddFixed("FMARK" , 0x66000600);
AddFixed("MARK" , 0x66000580);
AddFixed("RET" , 0x0a000000);
AddFixed("SYNCF" , 0x66000780);
AddFixed("FAULTNO" , 0x18000000);
AddFixed("FAULTG" , 0x19000000);
AddFixed("FAULTE" , 0x1a000000);
AddFixed("FAULTGE" , 0x1b000000);
AddFixed("FAULTL" , 0x1c000000);
AddFixed("FAULTNE" , 0x1d000000);
AddFixed("FAULTLE" , 0x1e000000);
AddFixed("FAULTO" , 0x1f000000);
InstrZ = 0;
/* Name OpCode Src1Type Src2Type DestType Imm1 Imm2 */
AddReg("ADDC" , 0x5b0, IntOp , IntOp , IntOp , True , True , False);
AddReg("ADDI" , 0x591, IntOp , IntOp , IntOp , True , True , False);
AddReg("ADDO" , 0x590, IntOp , IntOp , IntOp , True , True , False);
AddReg("ADDR" , 0x78f, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("ADDRL" , 0x79f, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("ALTERBIT", 0x58f, IntOp , IntOp , IntOp , True , True , False);
AddReg("AND" , 0x581, IntOp , IntOp , IntOp , True , True , False);
AddReg("ANDNOT" , 0x582, IntOp , IntOp , IntOp , True , True , False);
AddReg("ATADD" , 0x612, IntOp , IntOp , IntOp , True , True , False);
AddReg("ATANR" , 0x680, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("ATANRL" , 0x690, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("ATMOD" , 0x610, IntOp , IntOp , IntOp , True , True , False);
AddReg("CALLS" , 0x660, IntOp , NoneOp , NoneOp , True , False, False);
AddReg("CHKBIT" , 0x5ae, IntOp , IntOp , NoneOp , True , True , False);
AddReg("CLASSR" , 0x68f, SingleOp, NoneOp , NoneOp , True , False, False);
AddReg("CLASSRL" , 0x69f, DoubleOp, NoneOp , NoneOp , True , False, False);
AddReg("CLRBIT" , 0x58c, IntOp , IntOp , IntOp , True , True , False);
AddReg("CMPDECI" , 0x5a7, IntOp , IntOp , IntOp , True , False, False);
AddReg("CMPDECO" , 0x5a6, IntOp , IntOp , IntOp , True , False, False);
AddReg("CMPI" , 0x5a1, IntOp , IntOp , NoneOp , True , True , False);
AddReg("CMPO" , 0x5a0, IntOp , IntOp , NoneOp , True , True , False);
AddReg("CMPINCI" , 0x5a5, IntOp , IntOp , IntOp , True , False, False);
AddReg("CMPINCO" , 0x5a4, IntOp , IntOp , IntOp , True , False, False);
AddReg("CMPOR" , 0x684, SingleOp, SingleOp, NoneOp , True , True , False);
AddReg("CMPORL" , 0x694, DoubleOp, DoubleOp, NoneOp , True , True , False);
AddReg("CMPR" , 0x685, SingleOp, SingleOp, NoneOp , True , True , False);
AddReg("CMPRL" , 0x695, DoubleOp, DoubleOp, NoneOp , True , True , False);
AddReg("CONCMPI" , 0x5a3, IntOp , IntOp , NoneOp , True , True , False);
AddReg("CONCMPO" , 0x5a2, IntOp , IntOp , NoneOp , True , True , False);
AddReg("COSR" , 0x68d, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("COSRL" , 0x69d, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("CPYSRE" , 0x6e2, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("CPYRSRE" , 0x6e3, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("CVTIR" , 0x674, IntOp, NoneOp , SingleOp, True , False, False);
AddReg("CVTILR" , 0x675, LongOp, NoneOp , DoubleOp, True , False, False);
AddReg("CVTRI" , 0x6c0, SingleOp, NoneOp , IntOp , True , False, False);
AddReg("CVTRIL" , 0x6c1, SingleOp, NoneOp , LongOp , True , False, False);
AddReg("CVTZRI" , 0x6c2, IntOp , NoneOp , IntOp , True , False, False);
AddReg("CVTZRIL" , 0x6c2, LongOp , NoneOp , LongOp , True , False, False);
/* Name OpCode Src1Type Src2Type DestType Imm1 Imm2 */
AddReg("DADDC" , 0x642, IntOp , IntOp , IntOp , False, False, False);
AddReg("DIVI" , 0x74b, IntOp , IntOp , IntOp , True , True , False);
AddReg("DIVO" , 0x70b, IntOp , IntOp , IntOp , True , True , False);
AddReg("DIVR" , 0x78b, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("DIVRL" , 0x79b, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("DMOVT" , 0x644, IntOp , NoneOp , IntOp , False, False, False);
AddReg("DSUBC" , 0x643, IntOp , IntOp , IntOp , False, False, False);
AddReg("EDIV" , 0x671, IntOp , LongOp , LongOp , True , True , False);
AddReg("EMUL" , 0x670, IntOp , IntOp , LongOp , True , True , False);
AddReg("EXPR" , 0x689, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("EXPRL" , 0x699, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("EXTRACT" , 0x651, IntOp , IntOp , IntOp , True , True , False);
AddReg("LOGBNR" , 0x68a, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("LOGBNRL" , 0x69a, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("LOGEPR" , 0x681, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("LOGEPRL" , 0x691, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("LOGR" , 0x682, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("LOGRL" , 0x692, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("MODAC" , 0x645, IntOp , IntOp , IntOp , True , True , False);
AddReg("MODI" , 0x749, IntOp , IntOp , IntOp , True , True , False);
AddReg("MODIFY" , 0x650, IntOp , IntOp , IntOp , True , True , False);
AddReg("MODPC" , 0x655, IntOp , IntOp , IntOp , True , True , True );
AddReg("MODTC" , 0x654, IntOp , IntOp , IntOp , True , True , False);
AddReg("MOV" , 0x5cc, IntOp , NoneOp , IntOp , True , False, False);
AddReg("MOVL" , 0x5dc, LongOp , NoneOp , LongOp , True , False, False);
AddReg("MOVT" , 0x5ec, QuadOp , NoneOp , QuadOp , True , False, False);
AddReg("MOVQ" , 0x5fc, QuadOp , NoneOp , QuadOp , True , False, False);
AddReg("MOVR" , 0x6c9, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("MOVRL" , 0x6d9, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("MOVRE" , 0x6e1, ExtOp , NoneOp , ExtOp , True , False, False);
AddReg("MULI" , 0x741, IntOp , IntOp , IntOp , True , True , False);
AddReg("MULO" , 0x701, IntOp , IntOp , IntOp , True , True , False);
AddReg("MULR" , 0x78c, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("MULRL" , 0x79c, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("NAND" , 0x58e, IntOp , IntOp , IntOp , True , True , False);
AddReg("NOR" , 0x588, IntOp , IntOp , IntOp , True , True , False);
AddReg("NOT" , 0x58a, IntOp , NoneOp , IntOp , True , False, False);
AddReg("NOTAND" , 0x584, IntOp , IntOp , IntOp , True , True , False);
AddReg("NOTBIT" , 0x580, IntOp , IntOp , IntOp , True , True , False);
AddReg("NOTOR" , 0x58d, IntOp , IntOp , IntOp , True , True , False);
AddReg("OR" , 0x587, IntOp , IntOp , IntOp , True , True , False);
AddReg("ORNOT" , 0x58b, IntOp , IntOp , IntOp , True , True , False);
/* Name OpCode TwoSrc HDest Float Imm1 Imm2 */
AddReg("REMI" , 0x748, IntOp , IntOp , IntOp , True , True , False);
AddReg("REMO" , 0x708, IntOp , IntOp , IntOp , True , True , False);
AddReg("REMR" , 0x683, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("REMRL" , 0x693, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("ROTATE" , 0x59d, IntOp , IntOp , IntOp , True , True , False);
AddReg("ROUNDR" , 0x68b, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("ROUNDRL" , 0x69b, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("SCALER" , 0x677, IntOp , SingleOp, SingleOp, True , True , False);
AddReg("SCALERL" , 0x676, IntOp , DoubleOp, DoubleOp, True , True , False);
AddReg("SCANBIT" , 0x641, IntOp , NoneOp , IntOp , True , False, False);
AddReg("SCANBYTE", 0x5ac, IntOp , NoneOp , IntOp , True , False, False);
AddReg("SETBIT" , 0x583, IntOp , IntOp , IntOp , True , True , False);
AddReg("SHLO" , 0x59c, IntOp , IntOp , IntOp , True , True , False);
AddReg("SHRO" , 0x598, IntOp , IntOp , IntOp , True , True , False);
AddReg("SHLI" , 0x59e, IntOp , IntOp , IntOp , True , True , False);
AddReg("SHRI" , 0x59B, IntOp , IntOp , IntOp , True , True , False);
AddReg("SHRDI" , 0x59a, IntOp , IntOp , IntOp , True , True , False);
AddReg("SINR" , 0x68c, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("SINRL" , 0x69c, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("SPANBIT" , 0x640, IntOp , NoneOp , IntOp , True , False, False);
AddReg("SQRTR" , 0x688, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("SQRTRL" , 0x698, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("SUBC" , 0x5b2, IntOp , IntOp , IntOp , True , True , False);
AddReg("SUBI" , 0x593, IntOp , IntOp , IntOp , True , True , False);
AddReg("SUBO" , 0x592, IntOp , IntOp , IntOp , True , True , False);
AddReg("SUBR" , 0x78d, SingleOp, SingleOp, SingleOp, True , True , False);
AddReg("SUBRL" , 0x79d, DoubleOp, DoubleOp, DoubleOp, True , True , False);
AddReg("SYNLD" , 0x615, IntOp , NoneOp , IntOp , False, False, False);
AddReg("SYNMOV" , 0x600, IntOp , NoneOp , IntOp , False, False, False);
AddReg("SYNMOVL" , 0x601, IntOp , NoneOp , IntOp , False, False, False);
AddReg("SYNMOVQ" , 0x602, IntOp , NoneOp , IntOp , False, False, False);
AddReg("TANR" , 0x68e, SingleOp, NoneOp , SingleOp, True , False, False);
AddReg("TANRL" , 0x69e, DoubleOp, NoneOp , DoubleOp, True , False, False);
AddReg("XOR" , 0x589, IntOp , IntOp , IntOp , True , True , False);
AddReg("XNOR" , 0x589, IntOp , IntOp , IntOp , True , True , False);
InstrZ = 0;
AddCobr("BBC" , 0x30, True ); AddCobr("BBS" , 0x37, True );
AddCobr("CMPIBE" , 0x3a, True ); AddCobr("CMPOBE" , 0x32, True );
AddCobr("CMPIBNE", 0x3d, True ); AddCobr("CMPOBNE", 0x35, True );
AddCobr("CMPIBL" , 0x3c, True ); AddCobr("CMPOBL" , 0x34, True );
AddCobr("CMPIBLE", 0x3e, True ); AddCobr("CMPOBLE", 0x36, True );
AddCobr("CMPIBG" , 0x39, True ); AddCobr("CMPOBG" , 0x31, True );
AddCobr("CMPIBGE", 0x3b, True ); AddCobr("CMPOBGE", 0x33, True );
AddCobr("CMPIBO" , 0x3f, True ); AddCobr("CMPIBNO", 0x38, True );
AddCobr("TESTE" , 0x22, False); AddCobr("TESTNE" , 0x25, False);
AddCobr("TESTL" , 0x24, False); AddCobr("TESTLE" , 0x26, False);
AddCobr("TESTG" , 0x21, False); AddCobr("TESTGE" , 0x23, False);
AddCobr("TESTO" , 0x27, False); AddCobr("TESTNO" , 0x27, False);
InstrZ = 0;
AddCtrl("B" , 0x08); AddCtrl("CALL", 0x09);
AddCtrl("BAL" , 0x0b); AddCtrl("BNO" , 0x19);
AddCtrl("BG" , 0x11); AddCtrl("BE" , 0x12);
AddCtrl("BGE" , 0x13); AddCtrl("BL" , 0x14);
AddCtrl("BNE" , 0x15); AddCtrl("BLE" , 0x16);
AddCtrl("BO" , 0x17);
InstrZ = 0;
AddMem("LDOB" , 0x80, IntOp , 2);
AddMem("STOB" , 0x82, IntOp , 1);
AddMem("BX" , 0x84, IntOp , 0);
AddMem("BALX" , 0x85, IntOp , 2);
AddMem("CALLX", 0x86, IntOp , 0);
AddMem("LDOS" , 0x88, IntOp , 2);
AddMem("STOS" , 0x8a, IntOp , 1);
AddMem("LDA" , 0x8c, IntOp , 2);
AddMem("LD" , 0x90, IntOp , 2);
AddMem("ST" , 0x92, IntOp , 1);
AddMem("LDL" , 0x98, LongOp , 2);
AddMem("STL" , 0x9a, LongOp , 1);
AddMem("LDT" , 0xa0, QuadOp , 2);
AddMem("STT" , 0xa2, QuadOp , 1);
AddMem("LDQ" , 0xb0, QuadOp , 2);
AddMem("STQ" , 0xb2, QuadOp , 1);
AddMem("LDIB" , 0xc0, IntOp , 2);
AddMem("STIB" , 0xc2, IntOp , 1);
AddMem("LDIS" , 0xc8, IntOp , 2);
AddMem("STIS" , 0xca, IntOp , 1);
AddInstTable(InstTable, "WORD", 0, DecodeWORD);
AddInstTable(InstTable, "SPACE", 0, DecodeSPACE);
AddInstTable(InstTable, "REG", 0, CodeREG);
}
static void DeinitFields(void)
{
DestroyInstTable(InstTable);
order_array_free(FixedOrders);
order_array_free(RegOrders);
order_array_free(CobrOrders);
order_array_free(CtrlOrders);
}
/*--------------------------------------------------------------------------*/
static Boolean IsDef_960(void)
{
return Memo("REG");
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_960(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on i960
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_960(char *pArg, TempResult *pResult)
{
LongWord Reg;
if (DecodeIRegCore(pArg, &Reg))
{
pResult->Typ = TempReg;
pResult->DataSize = eSymbolSize32Bit;
pResult->Contents.RegDescr.Reg = Reg;
pResult->Contents.RegDescr.Dissect = DissectReg_960;
pResult->Contents.RegDescr.compare = NULL;
}
else if (DecodeFPRegCore(pArg, &Reg))
{
pResult->Typ = TempReg;
pResult->DataSize = eSymbolSizeFloat64Bit;
pResult->Contents.RegDescr.Reg = Reg;
pResult->Contents.RegDescr.Dissect = DissectReg_960;
pResult->Contents.RegDescr.compare = NULL;
}
}
static void SwitchTo_960(void)
{
const TFamilyDescr *FoundId;
TurnWords = False;
SetIntConstMode(eIntConstModeIntel);
FoundId = FindFamilyByName("i960");
if (!FoundId)
PCSymbol = "$";
HeaderID = FoundId->Id;
NOPCode = 0x000000000;
DivideChars = ",";
HasAttrs = False;
ValidSegs=(1 << SegCode);
Grans[SegCode] = 1;
ListGrans[SegCode] = 4;
SegInits[SegCode] = 0;
SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
MakeCode = MakeCode_960;
IsDef = IsDef_960;
InternSymbol = InternSymbol_960;
DissectReg = DissectReg_960;
SwitchFrom = DeinitFields;
onoff_fpu_add();
onoff_supmode_add();
InitFields();
}
void code960_init(void)
{
CPU80960 = AddCPU("80960", SwitchTo_960);
}