/* code29k.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator AM29xxx-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "nls.h"
#include "strutil.h"
#include "bpemu.h"
#include "stringlists.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code29k.h"
typedef struct
{
Boolean MustSup
;
CPUVar MinCPU
;
LongWord Code
;
} StdOrder
;
typedef struct
{
Boolean HasReg
, HasInd
;
CPUVar MinCPU
;
LongWord Code
;
} JmpOrder
;
typedef struct
{
const char *Name
;
LongWord Code
;
} SPReg
;
#define REG_LRMARK 256
static StdOrder
*StdOrders
;
static StdOrder
*NoImmOrders
;
static StdOrder
*VecOrders
;
static JmpOrder
*JmpOrders
;
static StdOrder
*FixedOrders
;
static StdOrder
*MemOrders
;
static SPReg
*SPRegs
;
static CPUVar CPU29000
, CPU29240
, CPU29243
, CPU29245
;
static LongInt Reg_RBP
;
static StringList Emulations
;
/*-------------------------------------------------------------------------*/
static Boolean ChkSup
(void)
{
if (!SupAllowed
)
WrError
(ErrNum_PrivOrder
);
return SupAllowed
;
}
static Boolean IsSup
(LongWord RegNo
)
{
return ((RegNo
< 0x80) || (RegNo
>= 0xa0));
}
static Boolean ChkCPU
(CPUVar Min
)
{
return StringListPresent
(Emulations
, OpPart.
str.
p_str) ? True
: ChkMinCPU
(Min
);
}
/*-------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, LongWord *pResult)
* \brief check whether argument describes a CPU register
* \param pArg source argument
* \param pResult resulting register # if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore
(const char *pArg
, LongWord
*pResult
)
{
int l
= strlen(pArg
);
Boolean OK
;
if ((l
>= 2) && (as_toupper
(*pArg
) == 'R'))
{
*pResult
= ConstLongInt
(pArg
+ 1, &OK
, 10);
return OK
&& (*pResult
<= 255);
}
else if ((l
>= 3) && (as_toupper
(*pArg
) == 'G') && (as_toupper
(pArg
[1]) == 'R'))
{
*pResult
= ConstLongInt
(pArg
+ 2, &OK
, 10);
if (!OK
|| (*pResult
>= 128))
return False
;
*pResult
|= REG_LRMARK
;
return True
;
}
else if ((l
>= 3) && (as_toupper
(*pArg
) == 'L') && (as_toupper
(pArg
[1]) == 'R'))
{
*pResult
= ConstLongInt
(pArg
+ 2, &OK
, 10);
if (!OK
|| (*pResult
>= 128))
return False
;
*pResult
|= 128 | REG_LRMARK
;
return True
;
}
else
return False
;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_29K(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - 29K variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_29K
(char *pDest
, size_t DestSize
, tRegInt Value
, tSymbolSize InpSize
)
{
switch (InpSize
)
{
case eSymbolSize32Bit
:
if (Value
& REG_LRMARK
)
as_snprintf
(pDest
, DestSize
, "%cR%u", "GL"[(Value
>> 7) & 1], (unsigned)(Value
& 127));
else
as_snprintf
(pDest
, DestSize
, "R%u", (unsigned)Value
);
break;
default:
as_snprintf
(pDest
, DestSize
, "%d-%u", (int)InpSize
, (unsigned)Value
);
}
}
/*!------------------------------------------------------------------------
* \fn compare_reg_29k(tRegInt reg1_num, tSymbolSize reg1_size, tRegInt reg2_num, tRegInt reg2_size)
* \brief compare two register symbols
* \param reg1_num 1st register's number
* \param reg1_size 1st register's data size
* \param reg2_num 2nd register's number
* \param reg2_size 2nd register's data size
* \return 0, -1, 1, -2
* ------------------------------------------------------------------------ */
static int compare_reg_29k
(tRegInt reg1_num
, tSymbolSize size1
, tRegInt reg2_num
, tSymbolSize size2
)
{
if ((size1
!= eSymbolSize32Bit
) || (size2
!= eSymbolSize32Bit
))
return -2;
/* We have up to 512 registers, which conflicts with the generic ALIAS flag in bit 7.
So we have to compare on our own. R (0..255), GR (256...383), and LR (384...511)
spaces are disjoint: */
if ((reg1_num
^ reg2_num
) & REG_LRMARK
)
return -2;
if (reg1_num
& REG_LRMARK
)
{
if ((reg1_num
^ reg2_num
) & 128)
return -2;
reg1_num
&= 127;
reg2_num
&= 127;
}
else
{
reg1_num
&= 255;
reg2_num
&= 255;
}
if (reg1_num
< reg2_num
)
return -1;
else if (reg1_num
> reg2_num
)
return 1;
else
return 0;
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
* \brief check whether argument describes a CPU register
* \param pArg source argument
* \param pResult resulting register # if yes
* \param MustBeReg True if register is expected
* \return reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg
(const tStrComp
*pArg
, LongWord
*pResult
, Boolean MustBeReg
)
{
tRegEvalResult RegEvalResult
;
tEvalResult EvalResult
;
tRegDescr RegDescr
;
if (DecodeRegCore
(pArg
->str.
p_str, pResult
))
RegEvalResult
= eIsReg
;
else
{
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize32Bit
, MustBeReg
);
if (eIsReg
== RegEvalResult
)
*pResult
= RegDescr.
Reg;
}
if (eIsReg
== RegEvalResult
)
{
*pResult
&= ~REG_LRMARK
;
if ((*pResult
< 127) && (Odd
(Reg_RBP
>> (*pResult
>> 4))))
{
if (!ChkSup
())
RegEvalResult
= MustBeReg
? eIsNoReg
: eRegAbort
;
}
}
return RegEvalResult
;
}
static Boolean DecodeArgReg
(int ArgIndex
, LongWord
*pRes
)
{
return DecodeReg
(&ArgStr
[ArgIndex
], pRes
, True
);
}
static Boolean DecodeSpReg
(char *Asc_O
, LongWord
*Erg
)
{
int z
;
String Asc
;
strmaxcpy
(Asc
, Asc_O
, STRINGSIZE
);
NLS_UpString
(Asc
);
for (z
= 0; SPRegs
[z
].
Name; z
++)
if (!strcmp(Asc
, SPRegs
[z
].
Name))
{
*Erg
= SPRegs
[z
].
Code;
return True
;;
}
return False
;;
}
static Boolean DecodeArgSpReg
(int ArgIndex
, LongWord
*pRes
)
{
Boolean Result
= DecodeSpReg
(ArgStr
[ArgIndex
].
str.
p_str, pRes
);
if (!Result
)
WrStrErrorPos
(ErrNum_InvCtrlReg
, &ArgStr
[ArgIndex
]);
return Result
;
}
/*-------------------------------------------------------------------------*/
/* Variante 1: Register <-- Register op Register/uimm8 */
static void DecodeStd
(Word Index
)
{
const StdOrder
*pOrder
= StdOrders
+ Index
;
LongWord Dest
, Src1
, Src2
, Src3
;
Boolean OK
;
if (ChkArgCnt
(2, 3) && DecodeArgReg
(1, &Dest
))
{
OK
= True
;
if (ArgCnt
== 2) Src1
= Dest
;
else OK
= DecodeArgReg
(2, &Src1
);
if (OK
)
{
switch (DecodeReg
(&ArgStr
[ArgCnt
], &Src2
, False
))
{
case eIsReg
:
OK
= True
; Src3
= 0;
break;
case eIsNoReg
:
Src2
= EvalStrIntExpression
(&ArgStr
[ArgCnt
], UInt8
, &OK
);
Src3
= 0x1000000;
break;
case eRegAbort
:
return;
}
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = (pOrder
->Code
<< 24) + Src3
+ (Dest
<< 16) + (Src1
<< 8) + Src2
;
if (pOrder
->MustSup
)
ChkSup
();
}
}
}
}
/* Variante 2: Register <-- Register op Register */
static void DecodeNoImm
(Word Index
)
{
const StdOrder
*pOrder
= NoImmOrders
+ Index
;
Boolean OK
;
LongWord Dest
, Src1
, Src2
;
if (ChkArgCnt
(2, 3) && DecodeArgReg
(1, &Dest
))
{
OK
= True
;
if (ArgCnt
== 2) Src1
= Dest
;
else OK
= DecodeArgReg
(2, &Src1
);
if (OK
&& DecodeArgReg
(ArgCnt
, &Src2
))
{
CodeLen
= 4;
DAsmCode
[0] = (pOrder
->Code
<< 24) + (Dest
<< 16) + (Src1
<< 8) + Src2
;
if (pOrder
->MustSup
)
ChkSup
();
}
}
}
/* Variante 3: Vektor <-- Register op Register/uimm8 */
static void DecodeVec
(Word Index
)
{
const StdOrder
*pOrder
= VecOrders
+ Index
;
Boolean OK
;
tSymbolFlags Flags
;
LongWord Dest
, Src1
, Src2
, Src3
;
if (ChkArgCnt
(3, 3))
{
Dest
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], UInt8
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
)) Dest
= 64;
if (OK
)
{
if (DecodeArgReg
(2, &Src1
))
{
switch (DecodeReg
(&ArgStr
[ArgCnt
], &Src2
, False
))
{
case eIsReg
:
OK
= True
; Src3
= 0;
break;
case eIsNoReg
:
Src2
= EvalStrIntExpression
(&ArgStr
[ArgCnt
], UInt8
, &OK
);
Src3
= 0x1000000;
break;
default:
return;
}
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = (pOrder
->Code
<< 24) + Src3
+ (Dest
<< 16) + (Src1
<< 8) + Src2
;
if ((pOrder
->MustSup
) || (Dest
<= 63))
ChkSup
();
}
}
}
}
}
/* Variante 4: ohne Operanden */
static void DecodeFixed
(Word Code
)
{
const StdOrder
*pOrder
= FixedOrders
+ Code
;
if (ChkArgCnt
(0, 0))
{
CodeLen
= 4;
DAsmCode
[0] = pOrder
->Code
<< 24;
if (pOrder
->MustSup
)
ChkSup
();
}
}
/* Variante 5 : [0], Speichersteuerwort, Register, Register/uimm8 */
static void DecodeMem
(Word Index
)
{
const StdOrder
*pOrder
= MemOrders
+ Index
;
Boolean OK
;
LongWord AdrLong
, Dest
, Src1
, Src2
, Src3
;
if (ChkArgCnt
(3, 4))
{
if (ArgCnt
== 3)
{
OK
= True
; AdrLong
= 0;
}
else
{
AdrLong
= EvalStrIntExpression
(&ArgStr
[1], Int32
, &OK
);
if (OK
) OK
= ChkRange
(AdrLong
, 0, 0);
}
if (OK
)
{
Dest
= EvalStrIntExpression
(&ArgStr
[ArgCnt
- 2], UInt7
, &OK
);
if (OK
&& DecodeArgReg
(ArgCnt
- 1, &Src1
))
{
switch (DecodeReg
(&ArgStr
[ArgCnt
], &Src2
, False
))
{
case eIsReg
:
OK
= True
; Src3
= 0;
break;
case eIsNoReg
:
Src2
= EvalStrIntExpression
(&ArgStr
[ArgCnt
], UInt8
, &OK
);
Src3
= 0x1000000;
break;
default:
return;
}
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = (pOrder
->Code
<< 24) + Src3
+ (Dest
<< 16) + (Src1
<< 8) + Src2
;
if (pOrder
->MustSup
)
ChkSup
();
}
}
}
}
}
/* Sprungbefehle */
static void DecodeJmp
(Word Index
)
{
const JmpOrder
*pOrder
= JmpOrders
+ (Index
& 0xff);
Word Immediate
= Index
& 0x100;
LongWord Dest
, Src1
, AdrLong
;
LongInt AdrInt
;
Boolean OK
;
tSymbolFlags Flags
;
unsigned NumArgs
= 1 + Ord
(pOrder
->HasReg
);
if (!ChkArgCnt
(NumArgs
, NumArgs
))
return;
switch (DecodeReg
(&ArgStr
[ArgCnt
], &Src1
, False
))
{
case eIsReg
:
if (!pOrder
->HasReg
)
{
Dest
= 0;
OK
= True
;
}
else
OK
= DecodeReg
(&ArgStr
[1], &Dest
, True
);
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = ((pOrder
->Code
+ 0x20) << 24) + (Dest
<< 8) + Src1
;
}
break;
case eRegAbort
:
return;
case eIsNoReg
:
if (Immediate
) WrError
(ErrNum_InvAddrMode
);
else
{
if (!pOrder
->HasReg
)
{
Dest
= 0;
OK
= True
;
}
else
OK
= DecodeReg
(&ArgStr
[1], &Dest
, True
);
if (OK
)
{
AdrLong
= EvalStrIntExpressionWithFlags
(&ArgStr
[ArgCnt
], Int32
, &OK
, &Flags
);
AdrInt
= AdrLong
- EProgCounter
();
if (OK
)
{
if ((AdrLong
& 3) != 0) WrError
(ErrNum_NotAligned
);
else if ((AdrInt
<= 0x1ffff) && (AdrInt
>= -0x20000))
{
CodeLen
= 4;
AdrLong
-= EProgCounter
();
DAsmCode
[0] = (pOrder
->Code
<< 24)
+ ((AdrLong
& 0x3fc00) << 6)
+ (Dest
<< 8) + ((AdrLong
& 0x3fc) >> 2);
}
else if (!mSymbolQuestionable
(Flags
) && (AdrLong
> 0x3fffff)) WrError
(ErrNum_JmpDistTooBig
);
else
{
CodeLen
= 4;
DAsmCode
[0] = ((pOrder
->Code
+ 1) << 24)
+ ((AdrLong
& 0x3fc00) << 6)
+ (Dest
<< 8) + ((AdrLong
& 0x3fc) >> 2);
}
}
}
}
}
}
static void DecodeCLASS
(Word Code
)
{
LongWord Dest
, Src1
, Src2
;
Boolean OK
;
UNUSED
(Code
);
if (ChkArgCnt
(3, 3)
&& ChkCPU
(CPU29000
)
&& DecodeArgReg
(1, &Dest
)
&& DecodeArgReg
(2, &Src1
))
{
Src2
= EvalStrIntExpression
(&ArgStr
[3], UInt2
, &OK
);
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = 0xe6000000 + (Dest
<< 16) + (Src1
<< 8) + Src2
;
}
}
}
static void DecodeEMULATE
(Word Code
)
{
LongWord Dest
, Src1
, Src2
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Code
);
if (ChkArgCnt
(3, 3))
{
Dest
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], UInt8
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
)) Dest
= 64;
if (OK
)
{
if (DecodeArgReg
(2, &Src1
)
&& DecodeArgReg
(ArgCnt
, &Src2
))
{
CodeLen
= 4;
DAsmCode
[0] = 0xd7000000 + (Dest
<< 16) + (Src1
<< 8) + Src2
;
if (Dest
<= 63)
ChkSup
();
}
}
}
}
static void DecodeSQRT
(Word Code
)
{
Boolean OK
;
LongWord Src1
, Src2
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 3)
&& ChkCPU
(CPU29000
)
&& DecodeArgReg
(1, &Dest
))
{
if (ArgCnt
== 2)
{
OK
= True
;
Src1
= Dest
;
}
else
OK
= DecodeArgReg
(2, &Src1
);
if (OK
)
{
Src2
= EvalStrIntExpression
(&ArgStr
[ArgCnt
], UInt2
, &OK
);
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = 0xe5000000 + (Dest
<< 16) + (Src1
<< 8) + Src2
;
}
}
}
}
static void DecodeCLZ
(Word Code
)
{
Boolean OK
;
LongWord Src1
, Src3
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &Dest
))
{
switch (DecodeReg
(&ArgStr
[2], &Src1
, False
))
{
case eIsReg
:
OK
= True
; Src3
= 0;
break;
case eIsNoReg
:
Src1
= EvalStrIntExpression
(&ArgStr
[2], UInt8
, &OK
);
Src3
= 0x1000000;
break;
default:
return;
}
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = 0x08000000 + Src3
+ (Dest
<< 16) + Src1
;
}
}
}
static void DecodeCONST
(Word Code
)
{
Boolean OK
;
LongWord AdrLong
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &Dest
))
{
AdrLong
= EvalStrIntExpression
(&ArgStr
[2], Int32
, &OK
);
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = ((AdrLong
& 0xff00) << 8) + (Dest
<< 8) + (AdrLong
& 0xff);
AdrLong
= AdrLong
>> 16;
if (AdrLong
== 0xffff) DAsmCode
[0] += 0x01000000;
else
{
DAsmCode
[0] += 0x03000000;
if (AdrLong
!= 0)
{
CodeLen
= 8;
DAsmCode
[1] = 0x02000000 + ((AdrLong
& 0xff00) << 16) + (Dest
<< 8) + (AdrLong
& 0xff);
}
}
}
}
return;
}
static void DecodeCONSTH_CONSTN
(Word IsHi
)
{
Boolean OK
;
LongWord AdrLong
, Dest
;
tSymbolFlags Flags
;
if (ChkArgCnt
(2, 2) && DecodeArgReg
(1, &Dest
))
{
AdrLong
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], Int32
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
AdrLong
&= 0xffff;
if ((!IsHi
) && ((AdrLong
>> 16) == 0xffff))
AdrLong
&= 0xffff;
if (ChkRange
(AdrLong
, 0, 0xffff))
{
CodeLen
= 4;
DAsmCode
[0] = 0x1000000 + ((AdrLong
& 0xff00) << 8) + (Dest
<< 8) + (AdrLong
& 0xff);
if (IsHi
)
DAsmCode
[0] += 0x1000000;
}
}
}
static void DecodeCONVERT
(Word Code
)
{
Boolean OK
;
LongWord Src1
, Src2
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(6, 6)
&& ChkCPU
(CPU29000
)
&& DecodeArgReg
(1, &Dest
)
&& DecodeArgReg
(2, &Src1
))
{
Src2
= 0;
Src2
+= EvalStrIntExpression
(&ArgStr
[3], UInt1
, &OK
) << 7;
if (OK
)
{
Src2
+= EvalStrIntExpression
(&ArgStr
[4], UInt3
, &OK
) << 4;
if (OK
)
{
Src2
+= EvalStrIntExpression
(&ArgStr
[5], UInt2
, &OK
) << 2;
if (OK
)
{
Src2
+= EvalStrIntExpression
(&ArgStr
[6], UInt2
, &OK
);
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = 0xe4000000 + (Dest
<< 16) + (Src1
<< 8) + Src2
;
}
}
}
}
}
}
static void DecodeEXHWS
(Word Code
)
{
LongWord Src1
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& DecodeArgReg
(1, &Dest
)
&& DecodeArgReg
(2, &Src1
))
{
CodeLen
= 4;
DAsmCode
[0] = 0x7e000000 + (Dest
<< 16) + (Src1
<< 8);
}
}
static void DecodeINV_IRETINV
(Word Code
)
{
Boolean OK
;
LongWord Src1
;
if (ChkArgCnt
(0, 1))
{
if (ArgCnt
== 0)
{
Src1
= 0; OK
= True
;
}
else Src1
= EvalStrIntExpression
(&ArgStr
[1], UInt2
, &OK
);
if (OK
)
{
CodeLen
= 4;
DAsmCode
[0] = (((LongWord
)Code
) << 16) | Src1
<< 16;
ChkSup
();
}
}
}
static void DecodeMFSR
(Word Code
)
{
LongWord Src1
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& DecodeArgReg
(1, &Dest
)
&& DecodeArgSpReg
(2, &Src1
))
{
DAsmCode
[0] = 0xc6000000 + (Dest
<< 16) + (Src1
<< 8);
CodeLen
= 4;
if (IsSup
(Src1
))
ChkSup
();
}
}
static void DecodeMTSR
(Word Code
)
{
LongWord Src1
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& DecodeArgSpReg
(1, &Dest
)
&& DecodeArgReg
(2, &Src1
))
{
DAsmCode
[0] = 0xce000000 + (Dest
<< 8) + Src1
;
CodeLen
= 4;
if (IsSup
(Dest
))
ChkSup
();
}
}
static void DecodeMTSRIM
(Word Code
)
{
LongWord Src1
, Dest
;
Boolean OK
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2) && DecodeArgSpReg
(1, &Dest
))
{
Src1
= EvalStrIntExpression
(&ArgStr
[2], UInt16
, &OK
);
if (OK
)
{
DAsmCode
[0] = 0x04000000 + ((Src1
& 0xff00) << 8) + (Dest
<< 8) + Lo
(Src1
);
CodeLen
= 4;
if (IsSup
(Dest
))
ChkSup
();
}
}
}
static void DecodeMFTLB
(Word Code
)
{
LongWord Src1
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& DecodeArgReg
(1, &Dest
)
&& DecodeArgReg
(2, &Src1
))
{
DAsmCode
[0] = 0xb6000000 + (Dest
<< 16) + (Src1
<< 8);
CodeLen
= 4;
ChkSup
();
}
}
static void DecodeMTTLB
(Word Code
)
{
LongWord Src1
, Dest
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& DecodeArgReg
(1, &Dest
)
&& DecodeArgReg
(2, &Src1
))
{
DAsmCode
[0] = 0xbe000000 + (Dest
<< 8) + Src1
;
CodeLen
= 4;
ChkSup
();
}
}
static void DecodeEMULATED
(Word Code
)
{
int z
;
UNUSED
(Code
);
if (ChkArgCnt
(1, ArgCntMax
))
for (z
= 1; z
<= ArgCnt
; z
++)
{
NLS_UpString
(ArgStr
[z
].
str.
p_str);
if (!StringListPresent
(Emulations
, ArgStr
[z
].
str.
p_str))
AddStringListLast
(&Emulations
, ArgStr
[z
].
str.
p_str);
}
}
/*-------------------------------------------------------------------------*/
static void AddStd
(const char *NName
, CPUVar NMin
, Boolean NSup
, LongWord NCode
)
{
order_array_rsv_end
(StdOrders
, StdOrder
);
StdOrders
[InstrZ
].
Code = NCode
;
StdOrders
[InstrZ
].
MustSup = NSup
;
StdOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeStd
);
}
static void AddNoImm
(const char *NName
, CPUVar NMin
, Boolean NSup
, LongWord NCode
)
{
order_array_rsv_end
(NoImmOrders
, StdOrder
);
NoImmOrders
[InstrZ
].
Code = NCode
;
NoImmOrders
[InstrZ
].
MustSup = NSup
;
NoImmOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeNoImm
);
}
static void AddVec
(const char *NName
, CPUVar NMin
, Boolean NSup
, LongWord NCode
)
{
order_array_rsv_end
(VecOrders
, StdOrder
);
VecOrders
[InstrZ
].
Code = NCode
;
VecOrders
[InstrZ
].
MustSup = NSup
;
VecOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeVec
);
}
static void AddJmp
(const char *NName
, CPUVar NMin
, Boolean NHas
, Boolean NInd
, LongWord NCode
)
{
char IName
[30];
order_array_rsv_end
(JmpOrders
, JmpOrder
);
JmpOrders
[InstrZ
].
HasReg = NHas
;
JmpOrders
[InstrZ
].
HasInd = NInd
;
JmpOrders
[InstrZ
].
Code = NCode
;
JmpOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
, DecodeJmp
);
as_snprintf
(IName
, sizeof(IName
), "%sI", NName
);
AddInstTable
(InstTable
, IName
, 0x100 | InstrZ
, DecodeJmp
);
InstrZ
++;
}
static void AddFixed
(const char *NName
, CPUVar NMin
, Boolean NSup
, LongWord NCode
)
{
order_array_rsv_end
(FixedOrders
, StdOrder
);
FixedOrders
[InstrZ
].
Code = NCode
;
FixedOrders
[InstrZ
].
MustSup = NSup
;
FixedOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddMem
(const char *NName
, CPUVar NMin
, Boolean NSup
, LongWord NCode
)
{
order_array_rsv_end
(MemOrders
, StdOrder
);
MemOrders
[InstrZ
].
Code = NCode
;
MemOrders
[InstrZ
].
MustSup = NSup
;
MemOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeMem
);
}
static void AddSP
(const char *NName
, LongWord NCode
)
{
order_array_rsv_end
(SPRegs
, SPReg
);
SPRegs
[InstrZ
].
Name = NName
;
SPRegs
[InstrZ
++].
Code = NCode
;
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(307);
SetDynamicInstTable
(InstTable
);
AddInstTable
(InstTable
, "CLASS", 0, DecodeCLASS
);
AddInstTable
(InstTable
, "EMULATE", 0, DecodeEMULATE
);
AddInstTable
(InstTable
, "SQRT", 0, DecodeSQRT
);
AddInstTable
(InstTable
, "CLZ", 0, DecodeCLZ
);
AddInstTable
(InstTable
, "CONST", 0, DecodeCONST
);
AddInstTable
(InstTable
, "CONSTH", True
, DecodeCONSTH_CONSTN
);
AddInstTable
(InstTable
, "CONSTN", False
, DecodeCONSTH_CONSTN
);
AddInstTable
(InstTable
, "CONVERT", 0, DecodeCONVERT
);
AddInstTable
(InstTable
, "EXHWS", 0, DecodeEXHWS
);
AddInstTable
(InstTable
, "INV", 0x9f00, DecodeINV_IRETINV
);
AddInstTable
(InstTable
, "IRETINV", 0x8c00, DecodeINV_IRETINV
);
AddInstTable
(InstTable
, "MFSR", 0, DecodeMFSR
);
AddInstTable
(InstTable
, "MTSR", 0, DecodeMTSR
);
AddInstTable
(InstTable
, "MTSRIM", 0, DecodeMTSRIM
);
AddInstTable
(InstTable
, "MFTLB", 0, DecodeMFTLB
);
AddInstTable
(InstTable
, "MTTLB", 0, DecodeMTTLB
);
AddInstTable
(InstTable
, "EMULATED", 0, DecodeEMULATED
);
AddInstTable
(InstTable
, "REG", 0, CodeREG
);
InstrZ
= 0;
AddStd
("ADD" , CPU29245
, False
, 0x14); AddStd
("ADDC" , CPU29245
, False
, 0x1c);
AddStd
("ADDCS" , CPU29245
, False
, 0x18); AddStd
("ADDCU" , CPU29245
, False
, 0x1a);
AddStd
("ADDS" , CPU29245
, False
, 0x10); AddStd
("ADDU" , CPU29245
, False
, 0x12);
AddStd
("AND" , CPU29245
, False
, 0x90); AddStd
("ANDN" , CPU29245
, False
, 0x9c);
AddStd
("CPBYTE" , CPU29245
, False
, 0x2e); AddStd
("CPEQ" , CPU29245
, False
, 0x60);
AddStd
("CPGE" , CPU29245
, False
, 0x4c); AddStd
("CPGEU" , CPU29245
, False
, 0x4e);
AddStd
("CPGT" , CPU29245
, False
, 0x48); AddStd
("CPGTU" , CPU29245
, False
, 0x4a);
AddStd
("CPLE" , CPU29245
, False
, 0x44); AddStd
("CPLEU" , CPU29245
, False
, 0x46);
AddStd
("CPLT" , CPU29245
, False
, 0x40); AddStd
("CPLTU" , CPU29245
, False
, 0x42);
AddStd
("CPNEQ" , CPU29245
, False
, 0x62); AddStd
("DIV" , CPU29245
, False
, 0x6a);
AddStd
("DIV0" , CPU29245
, False
, 0x68); AddStd
("DIVL" , CPU29245
, False
, 0x6c);
AddStd
("DIVREM" , CPU29245
, False
, 0x6e); AddStd
("EXBYTE" , CPU29245
, False
, 0x0a);
AddStd
("EXHW" , CPU29245
, False
, 0x7c); AddStd
("EXTRACT", CPU29245
, False
, 0x7a);
AddStd
("INBYTE" , CPU29245
, False
, 0x0c); AddStd
("INHW" , CPU29245
, False
, 0x78);
AddStd
("MUL" , CPU29245
, False
, 0x64); AddStd
("MULL" , CPU29245
, False
, 0x66);
AddStd
("MULU" , CPU29245
, False
, 0x74); AddStd
("NAND" , CPU29245
, False
, 0x9a);
AddStd
("NOR" , CPU29245
, False
, 0x98); AddStd
("OR" , CPU29245
, False
, 0x92);
AddStd
("SLL" , CPU29245
, False
, 0x80); AddStd
("SRA" , CPU29245
, False
, 0x86);
AddStd
("SRL" , CPU29245
, False
, 0x82); AddStd
("SUB" , CPU29245
, False
, 0x24);
AddStd
("SUBC" , CPU29245
, False
, 0x2c); AddStd
("SUBCS" , CPU29245
, False
, 0x28);
AddStd
("SUBCU" , CPU29245
, False
, 0x2a); AddStd
("SUBR" , CPU29245
, False
, 0x34);
AddStd
("SUBRC" , CPU29245
, False
, 0x3c); AddStd
("SUBRCS" , CPU29245
, False
, 0x38);
AddStd
("SUBRCU" , CPU29245
, False
, 0x3a); AddStd
("SUBRS" , CPU29245
, False
, 0x30);
AddStd
("SUBRU" , CPU29245
, False
, 0x32); AddStd
("SUBS" , CPU29245
, False
, 0x20);
AddStd
("SUBU" , CPU29245
, False
, 0x22); AddStd
("XNOR" , CPU29245
, False
, 0x96);
AddStd
("XOR" , CPU29245
, False
, 0x94);
InstrZ
= 0;
AddNoImm
("DADD" , CPU29000
, False
, 0xf1); AddNoImm
("DDIV" , CPU29000
, False
, 0xf7);
AddNoImm
("DEQ" , CPU29000
, False
, 0xeb); AddNoImm
("DGE" , CPU29000
, False
, 0xef);
AddNoImm
("DGT" , CPU29000
, False
, 0xed); AddNoImm
("DIVIDE" , CPU29000
, False
, 0xe1);
AddNoImm
("DIVIDU" , CPU29000
, False
, 0xe3); AddNoImm
("DMUL" , CPU29000
, False
, 0xf5);
AddNoImm
("DSUB" , CPU29000
, False
, 0xf3); AddNoImm
("FADD" , CPU29000
, False
, 0xf0);
AddNoImm
("FDIV" , CPU29000
, False
, 0xf6); AddNoImm
("FDMUL" , CPU29000
, False
, 0xf9);
AddNoImm
("FEQ" , CPU29000
, False
, 0xea); AddNoImm
("FGE" , CPU29000
, False
, 0xee);
AddNoImm
("FGT" , CPU29000
, False
, 0xec); AddNoImm
("FMUL" , CPU29000
, False
, 0xf4);
AddNoImm
("FSUB" , CPU29000
, False
, 0xf2); AddNoImm
("MULTIPLU", CPU29243
, False
, 0xe2);
AddNoImm
("MULTIPLY", CPU29243
, False
, 0xe0); AddNoImm
("MULTM" , CPU29243
, False
, 0xde);
AddNoImm
("MULTMU" , CPU29243
, False
, 0xdf); AddNoImm
("SETIP" , CPU29245
, False
, 0x9e);
InstrZ
= 0;
AddVec
("ASEQ" , CPU29245
, False
, 0x70); AddVec
("ASGE" , CPU29245
, False
, 0x5c);
AddVec
("ASGEU" , CPU29245
, False
, 0x5e); AddVec
("ASGT" , CPU29245
, False
, 0x58);
AddVec
("ASGTU" , CPU29245
, False
, 0x5a); AddVec
("ASLE" , CPU29245
, False
, 0x54);
AddVec
("ASLEU" , CPU29245
, False
, 0x56); AddVec
("ASLT" , CPU29245
, False
, 0x50);
AddVec
("ASLTU" , CPU29245
, False
, 0x52); AddVec
("ASNEQ" , CPU29245
, False
, 0x72);
InstrZ
= 0;
AddJmp
("CALL" , CPU29245
, True
, True
, 0xa8); AddJmp
("JMP" , CPU29245
, False
, True
, 0xa0);
AddJmp
("JMPF" , CPU29245
, True
, True
, 0xa4); AddJmp
("JMPFDEC", CPU29245
, True
, False
, 0xb4);
AddJmp
("JMPT" , CPU29245
, True
, True
, 0xac);
InstrZ
= 0;
AddFixed
("HALT" , CPU29245
, True
, 0x89); AddFixed
("IRET" , CPU29245
, True
, 0x88);
InstrZ
= 0;
AddMem
("LOAD" , CPU29245
, False
, 0x16); AddMem
("LOADL" , CPU29245
, False
, 0x06);
AddMem
("LOADM" , CPU29245
, False
, 0x36); AddMem
("LOADSET", CPU29245
, False
, 0x26);
AddMem
("STORE" , CPU29245
, False
, 0x1e); AddMem
("STOREL" , CPU29245
, False
, 0x0e);
AddMem
("STOREM" , CPU29245
, False
, 0x3e);
InstrZ
= 0;
AddSP
("VAB", 0);
AddSP
("OPS", 1);
AddSP
("CPS", 2);
AddSP
("CFG", 3);
AddSP
("CHA", 4);
AddSP
("CHD", 5);
AddSP
("CHC", 6);
AddSP
("RBP", 7);
AddSP
("TMC", 8);
AddSP
("TMR", 9);
AddSP
("PC0", 10);
AddSP
("PC1", 11);
AddSP
("PC2", 12);
AddSP
("MMU", 13);
AddSP
("LRU", 14);
AddSP
("CIR", 29);
AddSP
("CDR", 30);
AddSP
("IPC", 128);
AddSP
("IPA", 129);
AddSP
("IPB", 130);
AddSP
("Q", 131);
AddSP
("ALU", 132);
AddSP
("BP", 133);
AddSP
("FC", 134);
AddSP
("CR", 135);
AddSP
("FPE", 160);
AddSP
("INTE",161);
AddSP
("FPS", 162);
AddSP
(NULL
, 0);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(StdOrders
);
order_array_free
(NoImmOrders
);
order_array_free
(VecOrders
);
order_array_free
(JmpOrders
);
order_array_free
(FixedOrders
);
order_array_free
(MemOrders
);
order_array_free
(SPRegs
);
}
/*-------------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn InternSymbol_29K(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on 29K
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_29K
(char *pArg
, TempResult
*pResult
)
{
LongWord Reg
;
if (DecodeRegCore
(pArg
, &Reg
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize32Bit
;
pResult
->Contents.
RegDescr.
Reg = Reg
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_29K
;
pResult
->Contents.
RegDescr.
compare = compare_reg_29k
;
}
}
static void MakeCode_29K
(void)
{
CodeLen
= 0;
DontPrint
= False
;
/* Nullanweisung */
if (Memo
("") && !*AttrPart.
str.
p_str && (ArgCnt
== 0))
return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo
(True
))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static void InitCode_29K
(void)
{
Reg_RBP
= 0;
ClearStringList
(&Emulations
);
}
static Boolean IsDef_29K
(void)
{
return Memo
("REG");
}
static void SwitchTo_29K
(void)
{
static ASSUMERec ASSUME29Ks
[] =
{
{"RBP", &Reg_RBP
, 0, 0xff, 0x00000000, NULL
}
};
static const int ASSUME29KCount
= sizeof(ASSUME29Ks
) / sizeof(*ASSUME29Ks
);
TurnWords
= True
;
SetIntConstMode
(eIntConstModeC
);
PCSymbol
= "$";
HeaderID
= 0x29;
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_29K
;
IsDef
= IsDef_29K
;
InternSymbol
= InternSymbol_29K
;
DissectReg
= DissectReg_29K
;
onoff_supmode_add
();
pASSUMERecs
= ASSUME29Ks
;
ASSUMERecCnt
= ASSUME29KCount
;
SwitchFrom
= DeinitFields
; InitFields
();
}
void code29k_init
(void)
{
CPU29245
= AddCPU
("AM29245", SwitchTo_29K
);
CPU29243
= AddCPU
("AM29243", SwitchTo_29K
);
CPU29240
= AddCPU
("AM29240", SwitchTo_29K
);
CPU29000
= AddCPU
("AM29000", SwitchTo_29K
);
Emulations
= NULL
;
AddInitPassProc
(InitCode_29K
);
}