/* codemcore.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator MCORE-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "nls.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 "codepseudo.h"
#include "motpseudo.h"
#include "asmitree.h"
#include "codevars.h"
#include "errmsg.h"
#include "codemcore.h"
/*--------------------------------------------------------------------------*/
/* Variablen */
#define REG_SP 0
#define REG_LR 15
typedef struct
{
Word Code
;
Boolean Priv
;
} FixedOrder
;
typedef struct
{
Word Code
;
Word Min
,Ofs
;
} ImmOrder
;
typedef struct
{
const char *Name
;
Word Code
;
} CReg
;
static CPUVar CPUMCORE
;
static tSymbolSize OpSize
;
static FixedOrder
*FixedOrders
;
static FixedOrder
*OneRegOrders
;
static FixedOrder
*TwoRegOrders
;
static ImmOrder
*UImm5Orders
;
static FixedOrder
*LJmpOrders
;
static CReg
*CRegs
;
/*--------------------------------------------------------------------------*/
/* Hilfsdekoder */
static const Word AllRegMask
= 0xffff;
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, Word *pResult)
* \brief check whether argument is a register
* \param pArg argument
* \param pResult register number if it is
* \return True if it is
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore
(const char *pArg
, Word
*pResult
)
{
if (!as_strcasecmp
(pArg
, "SP"))
*pResult
= REGSYM_FLAG_ALIAS
| REG_SP
;
else if (!as_strcasecmp
(pArg
, "LR"))
*pResult
= REGSYM_FLAG_ALIAS
| REG_LR
;
else if (as_toupper
(*pArg
) != 'R')
return False
;
else
{
char *endptr
;
*pResult
= strtol(pArg
+ 1, &endptr
, 10);
if (*endptr
|| (*pResult
> 15))
return False
;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_MCORE(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - M-CORE variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_MCORE
(char *pDest
, size_t DestSize
, tRegInt Value
, tSymbolSize InpSize
)
{
switch (InpSize
)
{
case eSymbolSize32Bit
:
switch (Value
)
{
case REGSYM_FLAG_ALIAS
| REG_SP
:
as_snprintf
(pDest
, DestSize
, "SP");
break;
case REGSYM_FLAG_ALIAS
| REG_LR
:
as_snprintf
(pDest
, DestSize
, "LR");
break;
default:
as_snprintf
(pDest
, DestSize
, "R%u", (unsigned)Value
);
}
break;
default:
as_snprintf
(pDest
, DestSize
, "%d-%u", (int)InpSize
, (unsigned)Value
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, Word *pResult, Word Mask, Boolean MustBeReg)
* \brief check whether argument is a CPU register or register alias
* \param pArg argument
* \param pResult register number if it is
* \param Mask bit mask of allowed registers
* \param MustBeReg operand is expected to be a register
* \return True if it is an allowed register
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg
(const tStrComp
*pArg
, Word
*pResult
, Word Mask
, Boolean MustBeReg
)
{
tRegEvalResult RegEvalResult
;
if (DecodeRegCore
(pArg
->str.
p_str, pResult
))
RegEvalResult
= eIsReg
;
else
{
tRegDescr RegDescr
;
tEvalResult EvalResult
;
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize32Bit
, MustBeReg
);
*pResult
= RegDescr.
Reg;
}
*pResult
&= ~REGSYM_FLAG_ALIAS
;
if ((RegEvalResult
== eIsReg
) && !(Mask
& (1 << *pResult
)))
{
RegEvalResult
= MustBeReg
? eRegAbort
: eIsNoReg
;
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
}
return RegEvalResult
;
}
static Boolean DecodeArgReg
(int Index
, Word
*pErg
, Word Mask
)
{
return (DecodeReg
(&ArgStr
[Index
], pErg
, Mask
, True
) == eIsReg
);
}
static Boolean DecodeArgIReg
(int Index
, Word
*pErg
, Word Mask
)
{
tStrComp RegComp
;
const char *pArg
= ArgStr
[Index
].
str.
p_str;
int l
= strlen(pArg
);
if ((l
<= 3) || (pArg
[0] != '(') || (pArg
[l
- 1] != ')'))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[Index
]);
return False
;
}
StrCompRefRight
(&RegComp
, &ArgStr
[Index
], 1);
StrCompShorten
(&RegComp
, 1);
return (DecodeReg
(&RegComp
, pErg
, Mask
, True
) == eIsReg
);
}
static Boolean DecodeArgRegPair
(int Index
, Word
*pFrom
, Word FromMask
, Word
*pTo
, Word ToMask
)
{
tStrComp FromComp
, ToComp
;
char *pSep
= strchr(ArgStr
[Index
].
str.
p_str, '-');
if (!pSep
)
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[Index
]);
return False
;
}
StrCompSplitRef
(&FromComp
, &ToComp
, &ArgStr
[Index
], pSep
);
return (DecodeReg
(&FromComp
, pFrom
, FromMask
, True
) == eIsReg
)
&& (DecodeReg
(&ToComp
, pTo
, ToMask
, True
) == eIsReg
);
}
static Boolean DecodeCReg
(char *Asc
, Word
*Erg
)
{
char *endptr
;
int z
;
for (z
= 0; CRegs
[z
].
Name; z
++)
if (!as_strcasecmp
(Asc
, CRegs
[z
].
Name))
{
*Erg
= CRegs
[z
].
Code;
return True
;
}
if ((as_toupper
(*Asc
) != 'C') || (as_toupper
(Asc
[1]) != 'R'))
return False
;
else
{
*Erg
= strtol(Asc
+ 2, &endptr
, 10);
return ((*endptr
== '\0') && (*Erg
<= 31));
}
}
static Boolean DecodeArgCReg
(int Index
, Word
*pErg
)
{
Boolean Result
= DecodeCReg
(ArgStr
[Index
].
str.
p_str, pErg
);
if (!Result
)
WrStrErrorPos
(ErrNum_InvCtrlReg
, &ArgStr
[Index
]);
return Result
;
}
static Boolean DecodeAdr
(const tStrComp
*pArg
, Word
*Erg
)
{
Word Base
= 0xff, Tmp
;
LongInt DispAcc
= 0, DMask
= (1 << OpSize
) - 1, DMax
= 15 << OpSize
;
Boolean OK
, FirstFlag
= False
;
tSymbolFlags Flags
;
char *Pos
;
tStrComp Arg
, Remainder
;
if (!IsIndirect
(pArg
->str.
p_str))
{
WrError
(ErrNum_InvAddrMode
);
return False
;
}
StrCompRefRight
(&Arg
,pArg
, 1);
StrCompShorten
(&Arg
, 1);
do
{
Pos
= QuotPos
(Arg.
str.
p_str,',');
if (Pos
)
StrCompSplitRef
(&Arg
, &Remainder
, &Arg
, Pos
);
switch (DecodeReg
(&Arg
, &Tmp
, AllRegMask
, False
))
{
case eIsReg
:
if (Base
== 0xff) Base
= Tmp
;
else
{
WrError
(ErrNum_InvAddrMode
);
return False
;
}
break;
case eIsNoReg
:
DispAcc
+= EvalStrIntExpressionWithFlags
(&Arg
, Int32
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
)) FirstFlag
= True
;
if (!OK
)
return False
;
break;
default:
return False
;
}
if (Pos
)
Arg
= Remainder
;
}
while (Pos
);
if (Base
== 0xff)
{
WrError
(ErrNum_InvAddrMode
);
return False
;
}
if (FirstFlag
)
{
DispAcc
-= DispAcc
& DMask
;
if (DispAcc
< 0) DispAcc
= 0;
if (DispAcc
> DMax
) DispAcc
= DMax
;
}
if ((DispAcc
& DMask
) != 0)
{
WrError
(ErrNum_NotAligned
);
return False
;
}
if (!ChkRange
(DispAcc
, 0, DMax
))
return False
;
*Erg
= Base
+ ((DispAcc
>> OpSize
) << 4);
return True
;
}
static void DecodeFixed
(Word Index
)
{
FixedOrder
*Instr
= FixedOrders
+ Index
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(0, 0))
{
if ((Instr
->Priv
) && (!SupAllowed
)) WrError
(ErrNum_PrivOrder
);
WAsmCode
[0] = Instr
->Code
;
CodeLen
= 2;
}
}
static void DecodeOneReg
(Word Index
)
{
FixedOrder
*Instr
= OneRegOrders
+ Index
;
Word RegX
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(1, 1) && DecodeArgReg
(1, &RegX
, AllRegMask
))
{
if ((Instr
->Priv
) && (!SupAllowed
)) WrError
(ErrNum_PrivOrder
);
WAsmCode
[0] = Instr
->Code
+ RegX
;
CodeLen
= 2;
}
}
static void DecodeTwoReg
(Word Index
)
{
FixedOrder
*Instr
= TwoRegOrders
+ Index
;
Word RegX
, RegY
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2)
&& DecodeArgReg
(1, &RegX
, AllRegMask
)
&& DecodeArgReg
(2, &RegY
, AllRegMask
))
{
if ((Instr
->Priv
) && (!SupAllowed
)) WrError
(ErrNum_PrivOrder
);
WAsmCode
[0] = Instr
->Code
+ (RegY
<< 4) + RegX
;
CodeLen
= 2;
}
}
static void DecodeUImm5
(Word Index
)
{
ImmOrder
*Instr
= UImm5Orders
+ Index
;
Word RegX
, ImmV
;
Boolean OK
;
tSymbolFlags Flags
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &RegX
, AllRegMask
))
{
ImmV
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], (Instr
->Ofs
> 0) ? UInt6
: UInt5
, &OK
, &Flags
);
if ((Instr
->Min
> 0) && (ImmV
< Instr
->Min
))
{
if (mFirstPassUnknown
(Flags
)) ImmV
= Instr
->Min
;
else
{
WrError
(ErrNum_UnderRange
); OK
= False
;
}
}
if ((Instr
->Ofs
> 0) && ((ImmV
< Instr
->Ofs
) || (ImmV
> 31 + Instr
->Ofs
)))
{
if (mFirstPassUnknown
(Flags
)) ImmV
= Instr
->Ofs
;
else
{
WrError
((ImmV
< Instr
->Ofs
) ? ErrNum_UnderRange
: ErrNum_OverRange
);
OK
= False
;
}
}
if (OK
)
{
WAsmCode
[0] = Instr
->Code
+ ((ImmV
- Instr
->Ofs
) << 4) + RegX
;
CodeLen
= 2;
}
}
}
static void DecodeLJmp
(Word Index
)
{
FixedOrder
*Instr
= LJmpOrders
+ Index
;
LongInt Dest
;
Boolean OK
;
tSymbolFlags Flags
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(1, 1))
{
Dest
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], UInt32
, &OK
, &Flags
) - (EProgCounter
() + 2);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && (Dest
& 1)) WrError
(ErrNum_DistIsOdd
);
else if (!mSymbolQuestionable
(Flags
) && ((Dest
> 2046) || (Dest
< -2048))) WrError
(ErrNum_JmpDistTooBig
);
else
{
if ((Instr
->Priv
) && (!SupAllowed
)) WrError
(ErrNum_PrivOrder
);
WAsmCode
[0] = Instr
->Code
+ ((Dest
>> 1) & 0x7ff);
CodeLen
= 2;
}
}
}
}
static void DecodeSJmp
(Word Index
)
{
LongInt Dest
;
Boolean OK
;
tSymbolFlags Flags
;
int l
= 0;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (!ChkArgCnt
(1, 1));
else if ((*ArgStr
[1].
str.
p_str != '[') || (ArgStr
[1].
str.
p_str[l
= strlen(ArgStr
[1].
str.
p_str) - 1] != ']')) WrError
(ErrNum_InvAddrMode
);
else
{
ArgStr
[1].
str.
p_str[l
] = '\0';
Dest
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[1], 1, UInt32
, &OK
, &Flags
);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && (Dest
& 3)) WrError
(ErrNum_NotAligned
);
else
{
Dest
= (Dest
- (EProgCounter
() + 2)) >> 2;
if ((EProgCounter
() & 3) < 2) Dest
++;
if (!mSymbolQuestionable
(Flags
) && ((Dest
< 0) || (Dest
> 255))) WrError
(ErrNum_JmpDistTooBig
);
else
{
WAsmCode
[0] = 0x7000 + (Index
<< 8) + (Dest
& 0xff);
CodeLen
= 2;
}
}
}
}
}
static void DecodeBGENI
(Word Index
)
{
Word RegX
, ImmV
;
Boolean OK
;
UNUSED
(Index
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &RegX
, AllRegMask
))
{
ImmV
= EvalStrIntExpression
(&ArgStr
[2], UInt5
, &OK
);
if (OK
)
{
if (ImmV
> 6)
WAsmCode
[0] = 0x3200 + (ImmV
<< 4) + RegX
;
else
WAsmCode
[0] = 0x6000 + (1 << (4 + ImmV
)) + RegX
;
CodeLen
= 2;
}
}
}
static void DecodeBMASKI
(Word Index
)
{
Word RegX
, ImmV
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Index
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &RegX
, AllRegMask
))
{
ImmV
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], UInt6
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
) && ((ImmV
< 1) || (ImmV
> 32))) ImmV
= 8;
if (OK
)
{
if (ChkRange
(ImmV
, 1, 32))
{
ImmV
&= 31;
if ((ImmV
< 1) || (ImmV
> 7))
WAsmCode
[0] = 0x2c00 + (ImmV
<< 4) + RegX
;
else
WAsmCode
[0] = 0x6000 + (((1 << ImmV
) - 1) << 4) + RegX
;
CodeLen
= 2;
}
}
}
}
static void DecodeLdSt
(Word Index
)
{
Word RegX
, RegZ
, NSize
;
if (*AttrPart.
str.
p_str && (Lo
(Index
) != 0xff)) WrError
(ErrNum_UseLessAttr
);
else if (!ChkArgCnt
(2, 2));
else if (OpSize
> eSymbolSize32Bit
) WrError
(ErrNum_InvOpSize
);
else
{
if (Lo
(Index
) != 0xff) OpSize
= (tSymbolSize
)Lo
(Index
);
if (DecodeArgReg
(1, &RegZ
, AllRegMask
) && DecodeAdr
(&ArgStr
[2], &RegX
))
{
NSize
= (OpSize
== eSymbolSize32Bit
) ? 0 : OpSize
+ 1;
WAsmCode
[0] = 0x8000 + (NSize
<< 13) + (Hi
(Index
) << 12) + (RegZ
<< 8) + RegX
;
CodeLen
= 2;
}
}
}
static void DecodeLdStm
(Word Index
)
{
Word RegF
, RegL
, RegI
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2)
&& DecodeArgIReg
(2, &RegI
, 0x0001)
&& DecodeArgRegPair
(1, &RegF
, 0x7ffe, &RegL
, 0x8000))
{
WAsmCode
[0] = 0x0060 + (Index
<< 4) + RegF
;
CodeLen
= 2;
}
}
static void DecodeLdStq
(Word Index
)
{
Word RegF
, RegL
, RegX
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2)
&& DecodeArgIReg
(2, &RegX
, 0xff0f)
&& DecodeArgRegPair
(1, &RegF
, 0x0010, &RegL
, 0x0080))
{
WAsmCode
[0] = 0x0040 + (Index
<< 4) + RegX
;
CodeLen
= 2;
}
}
static void DecodeLoopt
(Word Index
)
{
Word RegY
;
LongInt Dest
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Index
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &RegY
, AllRegMask
))
{
Dest
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], UInt32
, &OK
, &Flags
) - (EProgCounter
() + 2);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && (Dest
& 1)) WrError
(ErrNum_DistIsOdd
);
else if (!mSymbolQuestionable
(Flags
) && ((Dest
> -2) || (Dest
<- 32))) WrError
(ErrNum_JmpDistTooBig
);
else
{
WAsmCode
[0] = 0x0400 + (RegY
<< 4) + ((Dest
>> 1) & 15);
CodeLen
= 2;
}
}
}
}
static void DecodeLrm
(Word Index
)
{
LongInt Dest
;
Word RegZ
;
Boolean OK
;
tSymbolFlags Flags
;
int l
= 0;
UNUSED
(Index
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (!ChkArgCnt
(2, 2));
else if (!DecodeArgReg
(1, &RegZ
, 0x7ffe));
else if ((*ArgStr
[2].
str.
p_str != '[') || (ArgStr
[2].
str.
p_str[l
= strlen(ArgStr
[2].
str.
p_str) - 1] != ']')) WrError
(ErrNum_InvAddrMode
);
else
{
ArgStr
[2].
str.
p_str[l
] = '\0';
Dest
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[2], 1, UInt32
, &OK
, &Flags
);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && (Dest
& 3)) WrError
(ErrNum_NotAligned
);
else
{
Dest
= (Dest
- (EProgCounter
() + 2)) >> 2;
if ((EProgCounter
() & 3) < 2) Dest
++;
if (!mSymbolQuestionable
(Flags
) && ((Dest
< 0) || (Dest
> 255))) WrError
(ErrNum_JmpDistTooBig
);
else
{
WAsmCode
[0] = 0x7000 + (RegZ
<< 8) + (Dest
& 0xff);
CodeLen
= 2;
}
}
}
}
}
static void DecodeMcr
(Word Index
)
{
Word RegX
,CRegY
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2)
&& DecodeArgReg
(1, &RegX
, AllRegMask
)
&& DecodeArgCReg
(2, &CRegY
))
{
if (!SupAllowed
) WrError
(ErrNum_PrivOrder
);
WAsmCode
[0] = 0x1000 + (Index
<< 11) + (CRegY
<< 4) + RegX
;
CodeLen
= 2;
}
}
static void DecodeMovi
(Word Index
)
{
Word RegX
, ImmV
;
Boolean OK
;
UNUSED
(Index
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &RegX
, AllRegMask
))
{
ImmV
= EvalStrIntExpression
(&ArgStr
[2], UInt7
, &OK
);
if (OK
)
{
WAsmCode
[0] = 0x6000 + ((ImmV
& 127) << 4) + RegX
;
CodeLen
= 2;
}
}
}
static void DecodeTrap
(Word Index
)
{
Word ImmV
;
Boolean OK
;
UNUSED
(Index
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (!ChkArgCnt
(1, 1));
else if (*ArgStr
[1].
str.
p_str != '#') WrError
(ErrNum_OnlyImmAddr
);
else
{
ImmV
= EvalStrIntExpressionOffs
(&ArgStr
[1], 1, UInt2
, &OK
);
if (OK
)
{
WAsmCode
[0] = 0x0008 + ImmV
;
CodeLen
= 2;
}
}
}
/*--------------------------------------------------------------------------*/
/* Codetabellenverwaltung */
static void AddFixed
(const char *NName
, Word NCode
, Boolean NPriv
)
{
order_array_rsv_end
(FixedOrders
, FixedOrder
);
FixedOrders
[InstrZ
].
Code = NCode
;
FixedOrders
[InstrZ
].
Priv = NPriv
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddOneReg
(const char *NName
, Word NCode
, Boolean NPriv
)
{
order_array_rsv_end
(OneRegOrders
, FixedOrder
);
OneRegOrders
[InstrZ
].
Code = NCode
;
OneRegOrders
[InstrZ
].
Priv = NPriv
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeOneReg
);
}
static void AddTwoReg
(const char *NName
, Word NCode
, Boolean NPriv
)
{
order_array_rsv_end
(TwoRegOrders
, FixedOrder
);
TwoRegOrders
[InstrZ
].
Code = NCode
;
TwoRegOrders
[InstrZ
].
Priv = NPriv
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeTwoReg
);
}
static void AddUImm5
(const char *NName
, Word NCode
, Word NMin
, Word NOfs
)
{
order_array_rsv_end
(UImm5Orders
, ImmOrder
);
UImm5Orders
[InstrZ
].
Code = NCode
;
UImm5Orders
[InstrZ
].
Min = NMin
;
UImm5Orders
[InstrZ
].
Ofs = NOfs
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeUImm5
);
}
static void AddLJmp
(const char *NName
, Word NCode
, Boolean NPriv
)
{
order_array_rsv_end
(LJmpOrders
, FixedOrder
);
LJmpOrders
[InstrZ
].
Code = NCode
;
LJmpOrders
[InstrZ
].
Priv = NPriv
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeLJmp
);
}
static void AddCReg
(const char *NName
, Word NCode
)
{
order_array_rsv_end
(CRegs
, CReg
);
CRegs
[InstrZ
].
Name = NName
;
CRegs
[InstrZ
++].
Code = NCode
;
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(201);
AddInstTable
(InstTable
, "REG", 0, CodeREG
);
InstrZ
= 0;
AddFixed
("BKPT" , 0x0000, False
);
AddFixed
("DOZE" , 0x0006, True
);
AddFixed
("RFI" , 0x0003, True
);
AddFixed
("RTE" , 0x0002, True
);
AddFixed
("STOP" , 0x0004, True
);
AddFixed
("SYNC" , 0x0001, False
);
AddFixed
("WAIT" , 0x0005, True
);
InstrZ
= 0;
AddOneReg
("ABS" , 0x01e0, False
); AddOneReg
("ASRC" , 0x3a00, False
);
AddOneReg
("BREV" , 0x00f0, False
); AddOneReg
("CLRF" , 0x01d0, False
);
AddOneReg
("CLRT" , 0x01c0, False
); AddOneReg
("DECF" , 0x0090, False
);
AddOneReg
("DECGT" , 0x01a0, False
); AddOneReg
("DECLT", 0x0180, False
);
AddOneReg
("DECNE" , 0x01b0, False
); AddOneReg
("DECT" , 0x0080, False
);
AddOneReg
("DIVS" , 0x3210, False
); AddOneReg
("DIVU" , 0x2c10, False
);
AddOneReg
("FF1" , 0x00e0, False
); AddOneReg
("INCF" , 0x00b0, False
);
AddOneReg
("INCT" , 0x00a0, False
); AddOneReg
("JMP" , 0x00c0, False
);
AddOneReg
("JSR" , 0x00d0, False
); AddOneReg
("LSLC" , 0x3c00, False
);
AddOneReg
("LSRC" , 0x3e00, False
); AddOneReg
("MVC" , 0x0020, False
);
AddOneReg
("MVCV" , 0x0030, False
); AddOneReg
("NOT" , 0x01f0, False
);
AddOneReg
("SEXTB" , 0x0150, False
); AddOneReg
("SEXTH", 0x0170, False
);
AddOneReg
("TSTNBZ", 0x0190, False
); AddOneReg
("XSR" , 0x3800, False
);
AddOneReg
("XTRB0" , 0x0130, False
); AddOneReg
("XTRB1", 0x0120, False
);
AddOneReg
("XTRB2" , 0x0110, False
); AddOneReg
("XTRB3", 0x0100, False
);
AddOneReg
("ZEXTB" , 0x0140, False
); AddOneReg
("ZEXTH", 0x0160, False
);
InstrZ
= 0;
AddTwoReg
("ADDC" , 0x0600, False
); AddTwoReg
("ADDU" , 0x1c00, False
);
AddTwoReg
("AND" , 0x1600, False
); AddTwoReg
("ANDN" , 0x1f00, False
);
AddTwoReg
("ASR" , 0x1a00, False
); AddTwoReg
("BGENR", 0x1300, False
);
AddTwoReg
("CMPHS", 0x0c00, False
); AddTwoReg
("CMPLT", 0x0d00, False
);
AddTwoReg
("CMPNE", 0x0f00, False
); AddTwoReg
("IXH" , 0x1d00, False
);
AddTwoReg
("IXW" , 0x1500, False
); AddTwoReg
("LSL" , 0x1b00, False
);
AddTwoReg
("LSR" , 0x0b00, False
); AddTwoReg
("MOV" , 0x1200, False
);
AddTwoReg
("MOVF" , 0x0a00, False
); AddTwoReg
("MOVT" , 0x0200, False
);
AddTwoReg
("MULT" , 0x0300, False
); AddTwoReg
("OR" , 0x1e00, False
);
AddTwoReg
("RSUB" , 0x1400, False
); AddTwoReg
("SUBC" , 0x0700, False
);
AddTwoReg
("SUBU" , 0x0500, False
); AddTwoReg
("TST" , 0x0e00, False
);
AddTwoReg
("XOR" , 0x1700, False
);
InstrZ
= 0;
AddUImm5
("ADDI" , 0x2000, 0, 1); AddUImm5
("ANDI" , 0x2e00, 0, 0);
AddUImm5
("ASRI" , 0x3a00, 1, 0); AddUImm5
("BCLRI" , 0x3000, 0, 0);
AddUImm5
("BSETI" , 0x3400, 0, 0); AddUImm5
("BTSTI" , 0x3600, 0, 0);
AddUImm5
("CMPLTI", 0x2200, 0, 1); AddUImm5
("CMPNEI", 0x2a00, 0, 0);
AddUImm5
("LSLI" , 0x3c00, 1, 0); AddUImm5
("LSRI" , 0x3e00, 1, 0);
AddUImm5
("ROTLI" , 0x3800, 1, 0); AddUImm5
("RSUBI" , 0x2800, 0, 0);
AddUImm5
("SUBI" , 0x2400, 0, 1);
InstrZ
= 0;
AddLJmp
("BF" , 0xe800, False
); AddLJmp
("BR" , 0xf000, False
);
AddLJmp
("BSR" , 0xf800, False
); AddLJmp
("BT" , 0xe000, False
);
InstrZ
= 0;
AddCReg
("PSR" , 0); AddCReg
("VBR" , 1);
AddCReg
("EPSR", 2); AddCReg
("FPSR", 3);
AddCReg
("EPC" , 4); AddCReg
("FPC", 5);
AddCReg
("SS0", 6); AddCReg
("SS1", 7);
AddCReg
("SS2", 8); AddCReg
("SS3", 9);
AddCReg
("SS4", 10); AddCReg
("GCR", 11);
AddCReg
("GSR", 12); AddCReg
(NULL
, 0);
AddInstTable
(InstTable
, "BGENI" , 0, DecodeBGENI
);
AddInstTable
(InstTable
, "BMASKI", 0, DecodeBMASKI
);
AddInstTable
(InstTable
, "JMPI" , 0, DecodeSJmp
);
AddInstTable
(InstTable
, "JSRI" , 0, DecodeSJmp
);
AddInstTable
(InstTable
, "LD" , 0x0ff, DecodeLdSt
);
AddInstTable
(InstTable
, "LDB" , 0x000, DecodeLdSt
);
AddInstTable
(InstTable
, "LDH" , 0x001, DecodeLdSt
);
AddInstTable
(InstTable
, "LDW" , 0x002, DecodeLdSt
);
AddInstTable
(InstTable
, "ST" , 0x1ff, DecodeLdSt
);
AddInstTable
(InstTable
, "STB" , 0x100, DecodeLdSt
);
AddInstTable
(InstTable
, "STH" , 0x101, DecodeLdSt
);
AddInstTable
(InstTable
, "STW" , 0x102, DecodeLdSt
);
AddInstTable
(InstTable
, "LDM" , 0, DecodeLdStm
);
AddInstTable
(InstTable
, "STM" , 1, DecodeLdStm
);
AddInstTable
(InstTable
, "LDQ" , 0, DecodeLdStq
);
AddInstTable
(InstTable
, "STQ" , 1, DecodeLdStq
);
AddInstTable
(InstTable
, "LOOPT" , 0, DecodeLoopt
);
AddInstTable
(InstTable
, "LRM" , 0, DecodeLrm
);
AddInstTable
(InstTable
, "MFCR" , 0, DecodeMcr
);
AddInstTable
(InstTable
, "MTCR" , 1, DecodeMcr
);
AddInstTable
(InstTable
, "MOVI" , 0, DecodeMovi
);
AddInstTable
(InstTable
, "TRAP" , 0, DecodeTrap
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(FixedOrders
);
order_array_free
(OneRegOrders
);
order_array_free
(TwoRegOrders
);
order_array_free
(UImm5Orders
);
order_array_free
(LJmpOrders
);
order_array_free
(CRegs
);
}
/*--------------------------------------------------------------------------*/
/* Callbacks */
/*!------------------------------------------------------------------------
* \fn InternSymbol_MCORE(char *pArg, TempResult *pResult)
* \brief handle built-in (register) symbols for M-CORE
* \param pArg source argument
* \param pResult buffer for possible result
* ------------------------------------------------------------------------ */
static void InternSymbol_MCORE
(char *pArg
, TempResult
*pResult
)
{
Word RegNum
;
if (DecodeRegCore
(pArg
, &RegNum
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize32Bit
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_MCORE
;
pResult
->Contents.
RegDescr.
compare = NULL
;
pResult
->Contents.
RegDescr.
Reg = RegNum
;
}
}
static Boolean DecodeAttrPart_MCORE
(void)
{
if (strlen(AttrPart.
str.
p_str) > 1)
{
WrStrErrorPos
(ErrNum_UndefAttr
, &AttrPart
);
return False
;
}
/* operand size identifiers slightly differ from '68K Standard': */
switch (as_toupper
(*AttrPart.
str.
p_str))
{
case 'H': AttrPartOpSize
[0] = eSymbolSize16Bit
; break;
case 'W': AttrPartOpSize
[0] = eSymbolSize32Bit
; break;
case 'L': WrStrErrorPos
(ErrNum_UndefAttr
, &AttrPart
); return False
;
default:
return DecodeMoto16AttrSize
(*AttrPart.
str.
p_str, &AttrPartOpSize
[0], False
);
}
return True
;
}
static void MakeCode_MCORE
(void)
{
CodeLen
= 0;
OpSize
= (AttrPartOpSize
[0] != eSymbolSizeUnknown
) ? AttrPartOpSize
[0] : eSymbolSize32Bit
;
DontPrint
= False
;
/* Nullanweisung */
if ((*OpPart.
str.
p_str == '\0') && !*AttrPart.
str.
p_str && (ArgCnt
== 0)) return;
/* Pseudoanweisungen */
if (DecodeMoto16Pseudo
(OpSize
,True
)) return;
/* Befehlszaehler ungerade ? */
if (Odd
(EProgCounter
())) WrError
(ErrNum_AddrNotAligned
);
/* alles aus der Tabelle */
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_MCORE
(void)
{
return Memo
("REG");
}
static void SwitchTo_MCORE
(void)
{
TurnWords
= True
;
SetIntConstMode
(eIntConstModeMoto
);
PCSymbol
= "*"; HeaderID
= 0x03; NOPCode
= 0x1200; /* ==MOV r0,r0 */
DivideChars
= ","; HasAttrs
= True
; AttrChars
= ".";
ValidSegs
= (1 << SegCode
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 2; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = (LargeWord
)IntTypeDefs
[UInt32
].
Max;
DecodeAttrPart
= DecodeAttrPart_MCORE
;
MakeCode
= MakeCode_MCORE
;
IsDef
= IsDef_MCORE
;
InternSymbol
= InternSymbol_MCORE
;
DissectReg
= DissectReg_MCORE
;
SwitchFrom
= DeinitFields
; InitFields
();
onoff_supmode_add
();
AddMoto16PseudoONOFF
(True
);
}
/*--------------------------------------------------------------------------*/
/* Initialisierung */
void codemcore_init
(void)
{
CPUMCORE
= AddCPU
("MCORE", SwitchTo_MCORE
);
}