/* code7000.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator SH7x00 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "literals.h"
#include "onoff_common.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "code7000.h"
enum
{
ModNone
= -1,
ModReg
= 0,
ModIReg
= 1,
ModPreDec
= 2,
ModPostInc
= 3,
ModIndReg
= 4,
ModR0Base
= 5,
ModGBRBase
= 6,
ModGBRR0
= 7,
ModPCRel
= 8,
ModImm
= 9
};
#define MModReg (1 << ModReg)
#define MModIReg (1 << ModIReg)
#define MModPreDec (1 << ModPreDec)
#define MModPostInc (1 << ModPostInc)
#define MModIndReg (1 << ModIndReg)
#define MModR0Base (1 << ModR0Base)
#define MModGBRBase (1 << ModGBRBase)
#define MModGBRR0 (1 << ModGBRR0)
#define MModPCRel (1 << ModPCRel)
#define MModImm (1 << ModImm)
#define REG_SP 15
#define RegNone (-1)
#define RegPC (-2)
#define RegGBR (-3)
#define CompLiteralsName "COMPRESSEDLITERALS"
typedef struct
{
CPUVar MinCPU
;
Boolean Priv
;
Word Code
;
} FixedOrder
;
typedef struct
{
CPUVar MinCPU
;
Boolean Priv
;
Word Code
;
Boolean Delayed
;
} OneRegOrder
;
typedef struct
{
CPUVar MinCPU
;
Boolean Priv
;
Word Code
;
ShortInt DefSize
;
} TwoRegOrder
;
typedef struct
{
CPUVar MinCPU
;
Word Code
;
} FixedMinOrder
;
typedef struct
{
const char *Name
;
Word Code
;
CPUVar MinCPU
;
Boolean NeedsDSP
;
} TRegDef
;
static tSymbolSize OpSize
; /* Groesse=8*(2^OpSize) */
static ShortInt AdrMode
; /* Ergebnisadressmodus */
static Word AdrPart
; /* Adressierungsmodusbits im Opcode */
static CPUVar CPU7000
, CPU7600
, CPU7700
;
static FixedOrder
*FixedOrders
;
static OneRegOrder
*OneRegOrders
;
static TwoRegOrder
*TwoRegOrders
;
static FixedMinOrder
*MulRegOrders
;
static FixedOrder
*BWOrders
;
static TRegDef
*RegDefs
;
static Boolean CurrDelayed
, PrevDelayed
, CompLiterals
, DSPAvail
;
static LongInt DelayedAdr
;
/*-------------------------------------------------------------------------*/
/* die PC-relative Adresse: direkt nach verzoegerten Spruengen = Sprungziel+2 */
static LongInt PCRelAdr
(void)
{
if (PrevDelayed
) return DelayedAdr
+ 2;
else return EProgCounter
() + 4;
}
static void ChkDelayed
(void)
{
if (PrevDelayed
) WrError
(ErrNum_Pipeline
);
}
/*-------------------------------------------------------------------------*/
/* Adressparsing */
static void SetOpSize
(tSymbolSize Size
)
{
if (OpSize
== eSymbolSizeUnknown
) OpSize
= Size
;
else if (Size
!= OpSize
)
{
WrError
(ErrNum_ConfOpSizes
); AdrMode
= ModNone
;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pArg, Word *pResult)
* \brief check whether argument is a CPU register
* \param pArg source argument
* \param pResult register # if yes
* \return True if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore
(const char *pArg
, Word
*pResult
)
{
size_t l
;
Boolean OK
;
if (!as_strcasecmp
(pArg
, "SP"))
{
*pResult
= REG_SP
| REGSYM_FLAG_ALIAS
;
return True
;
}
l
= strlen(pArg
);
if ((l
< 2) || (l
> 3) || (as_toupper
(*pArg
) != 'R'))
return False
;
*pResult
= ConstLongInt
(pArg
+ 1, &OK
, 10);
return OK
&& (*pResult
<= 15);
}
/*!------------------------------------------------------------------------
* \fn DissectReg_7000(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - SH7x00 variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_7000
(char *pDest
, size_t DestSize
, tRegInt Value
, tSymbolSize InpSize
)
{
switch (InpSize
)
{
case eSymbolSize32Bit
:
if (Value
== (REG_SP
| REGSYM_FLAG_ALIAS
))
as_snprintf
(pDest
, DestSize
, "SP");
else
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, Boolean MustBeReg)
* \brief check whether argument is a CPU register or register alias
* \param pArg source argument
* \param pResult register # if yes
* \return eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg
(const tStrComp
*pArg
, Word
*pResult
, Boolean MustBeReg
)
{
tRegEvalResult RegEvalResult
;
tEvalResult EvalResult
;
tRegDescr RegDescr
;
if (DecodeRegCore
(pArg
->str.
p_str, pResult
))
{
*pResult
&= ~REGSYM_FLAG_ALIAS
;
return eIsReg
;
}
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize32Bit
, MustBeReg
);
*pResult
= RegDescr.
Reg & ~REGSYM_FLAG_ALIAS
;
return RegEvalResult
;
}
static Boolean DecodeCtrlReg
(char *Asc
, Word
*Erg
)
{
CPUVar MinCPU
= CPU7000
;
*Erg
= 0xff;
if (!as_strcasecmp
(Asc
, "SR")) *Erg
= 0;
else if (!as_strcasecmp
(Asc
, "GBR")) *Erg
= 1;
else if (!as_strcasecmp
(Asc
, "VBR")) *Erg
= 2;
else if (!as_strcasecmp
(Asc
, "SSR"))
{
*Erg
= 3; MinCPU
= CPU7700
;
}
else if (!as_strcasecmp
(Asc
, "SPC"))
{
*Erg
= 4; MinCPU
= CPU7700
;
}
else if ((strlen(Asc
) == 7) && (as_toupper
(*Asc
) == 'R')
&& (!as_strcasecmp
(Asc
+ 2, "_BANK"))
&& (Asc
[1] >= '0') && (Asc
[1] <= '7'))
{
*Erg
= Asc
[1] - '0' + 8; MinCPU
= CPU7700
;
}
if ((*Erg
== 0xff) || (MomCPU
< MinCPU
))
{
WrXError
(ErrNum_InvCtrlReg
, Asc
); return False
;
}
else return True
;
}
static Boolean DecodeSReg
(char *Asc
, Word
*Erg
)
{
int z
;
Boolean Result
= FALSE
;
for (z
= 0; RegDefs
[z
].
Name; z
++)
if (!as_strcasecmp
(Asc
, RegDefs
[z
].
Name))
break;
if (RegDefs
[z
].
Name)
{
if (MomCPU
< RegDefs
[z
].
MinCPU);
else if ((!DSPAvail
) && RegDefs
[z
].
NeedsDSP);
else
{
Result
= TRUE
;
*Erg
= RegDefs
[z
].
Code;
}
}
return Result
;
}
static LongInt ExtOp
(LongInt Inp
, Byte Src
, Boolean Signed
)
{
switch (Src
)
{
case 0:
Inp
&= 0xff;
break;
case 1:
Inp
&= 0xffff;
break;
}
if (Signed
)
{
if (Src
< 1)
if ((Inp
& 0x80) == 0x80)
Inp
+= 0xff00;
if (Src
< 2)
if ((Inp
& 0x8000) == 0x8000)
Inp
+= 0xffff0000;
}
return Inp
;
}
static LongInt OpMask
(ShortInt OpSize
)
{
switch (OpSize
)
{
case eSymbolSize8Bit
:
return 0xff;
case eSymbolSize16Bit
:
return 0xffff;
case eSymbolSize32Bit
:
return 0xffffffff;
default:
return 0;
}
}
static void DecodeAdr
(const tStrComp
*pArg
, Word Mask
, Boolean Signed
)
{
Word HReg
;
char *pos
;
ShortInt BaseReg
, IndReg
;
tSymbolSize DOpSize
;
LongInt DispAcc
;
Boolean OK
, FirstFlag
;
tSymbolFlags Flags
;
AdrMode
= ModNone
;
switch (DecodeReg
(pArg
, &HReg
, False
))
{
case eIsReg
:
AdrPart
= HReg
;
AdrMode
= ModReg
;
goto chk
;
case eIsNoReg
:
break;
case eRegAbort
:
return;
}
if (*pArg
->str.
p_str == '@')
{
tStrComp Arg
;
StrCompRefRight
(&Arg
, pArg
, 1);
if (IsIndirect
(Arg.
str.
p_str))
{
tStrComp Remainder
;
StrCompIncRefLeft
(&Arg
, 1);
StrCompShorten
(&Arg
, 1);
BaseReg
= RegNone
;
IndReg
= RegNone
;
DispAcc
= 0;
FirstFlag
= False
;
OK
= True
;
do
{
pos
= QuotPos
(Arg.
str.
p_str, ',');
if (pos
)
StrCompSplitRef
(&Arg
, &Remainder
, &Arg
, pos
);
if (!as_strcasecmp
(Arg.
str.
p_str, "PC"))
{
if (BaseReg
== RegNone
)
BaseReg
= RegPC
;
else
{
WrError
(ErrNum_InvAddrMode
);
OK
= False
;
}
}
else if (!as_strcasecmp
(Arg.
str.
p_str, "GBR"))
{
if (BaseReg
== RegNone
)
BaseReg
= RegGBR
;
else
{
WrError
(ErrNum_InvAddrMode
);
OK
= False
;
}
}
else switch (DecodeReg
(&Arg
, &HReg
, False
))
{
case eIsReg
:
if (IndReg
== RegNone
)
IndReg
= HReg
;
else if ((BaseReg
== RegNone
) && (HReg
== 0))
BaseReg
= 0;
else if ((IndReg
== 0) && (BaseReg
== RegNone
))
{
BaseReg
= 0;
IndReg
= HReg
;
}
else
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &Arg
); OK
= False
;
}
break;
case eIsNoReg
:
DispAcc
+= EvalStrIntExpressionWithFlags
(&Arg
, Int32
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
FirstFlag
= True
;
break;
case eRegAbort
:
OK
= False
;
}
if (pos
)
Arg
= Remainder
;
}
while (pos
&& OK
);
if (FirstFlag
) DispAcc
= 0;
if ((OK
) && ((DispAcc
& ((1 << OpSize
) - 1)) != 0))
{
WrError
(ErrNum_NotAligned
);
OK
= False
;
}
else if ((OK
) && (DispAcc
< 0))
{
WrXError
(ErrNum_UnderRange
, "Disp<0");
OK
= False
;
}
else DispAcc
= DispAcc
>> OpSize
;
if (OK
)
{
switch (BaseReg
)
{
case 0:
if ((IndReg
< 0) || (DispAcc
!= 0)) WrError
(ErrNum_InvAddrMode
);
else
{
AdrMode
= ModR0Base
;
AdrPart
= IndReg
;
}
break;
case RegGBR
:
if ((IndReg
== 0) && (DispAcc
== 0)) AdrMode
= ModGBRR0
;
else if (IndReg
!= RegNone
) WrError
(ErrNum_InvAddrMode
);
else if (DispAcc
> 255) WrError
(ErrNum_OverRange
);
else
{
AdrMode
= ModGBRBase
;
AdrPart
= DispAcc
;
}
break;
case RegNone
:
if (IndReg
== RegNone
) WrError
(ErrNum_InvAddrMode
);
else if (DispAcc
> 15) WrError
(ErrNum_OverRange
);
else
{
AdrMode
= ModIndReg
;
AdrPart
= (IndReg
<< 4) + DispAcc
;
}
break;
case RegPC
:
if (IndReg
!= RegNone
) WrError
(ErrNum_InvAddrMode
);
else if (DispAcc
> 255) WrError
(ErrNum_OverRange
);
else
{
AdrMode
= ModPCRel
;
AdrPart
= DispAcc
;
}
break;
}
}
goto chk
;
}
else /* !IsIndirect */
{
int ArgLen
= strlen(Arg.
str.
p_str);
if ((ArgLen
> 1) && (*Arg.
str.
p_str == '-'))
{
StrCompIncRefLeft
(&Arg
, 1);
if (DecodeReg
(&Arg
, &HReg
, True
) == eIsReg
)
{
AdrPart
= HReg
;
AdrMode
= ModPreDec
;
}
}
else if ((ArgLen
> 1) && (Arg.
str.
p_str[ArgLen
- 1] == '+'))
{
StrCompShorten
(&Arg
, 1);
if (DecodeReg
(&Arg
, &HReg
, True
) == eIsReg
)
{
AdrPart
= HReg
;
AdrMode
= ModPostInc
;
}
}
else if (DecodeReg
(&Arg
, &HReg
, True
))
{
AdrPart
= HReg
;
AdrMode
= ModIReg
;
}
goto chk
;
}
}
if (*pArg
->str.
p_str == '#')
{
switch (OpSize
)
{
case eSymbolSize8Bit
:
DispAcc
= EvalStrIntExpressionOffsWithFlags
(pArg
, 1, Int8
, &OK
, &Flags
);
break;
case eSymbolSize16Bit
:
DispAcc
= EvalStrIntExpressionOffsWithFlags
(pArg
, 1, Int16
, &OK
, &Flags
);
break;
case eSymbolSize32Bit
:
DispAcc
= EvalStrIntExpressionOffsWithFlags
(pArg
, 1, Int32
, &OK
, &Flags
);
break;
default:
DispAcc
= 0;
OK
= True
;
Flags
= eSymbolFlag_None
;
}
if (OK
)
{
Boolean Critical
= mFirstPassUnknown
(Flags
) || mUsesForwards
(Flags
);
/* minimale Groesse optimieren */
DOpSize
= (OpSize
== eSymbolSize8Bit
) ? eSymbolSize8Bit
: (Critical
? eSymbolSize16Bit
: eSymbolSize8Bit
);
while (((ExtOp
(DispAcc
, DOpSize
, Signed
) ^ DispAcc
) & OpMask
(OpSize
)) != 0)
DOpSize
++;
if (DOpSize
== 0)
{
AdrPart
= DispAcc
& 0xff;
AdrMode
= ModImm
;
}
else if (Mask
& MModPCRel
)
{
tStrComp LStrComp
;
String LStr
;
tSymbolSize lit_size
;
Byte data_offset
= 0;
StrCompMkTemp
(&LStrComp
, LStr
, sizeof(LStr
));
lit_size
= (DOpSize
== 2) ? eSymbolSize32Bit
: eSymbolSize16Bit
;
literal_make
(&LStrComp
, &data_offset
, DispAcc
, lit_size
, Critical
);
/* Distanz abfragen - im naechsten Pass... */
DispAcc
= EvalStrIntExpressionWithFlags
(&LStrComp
, Int32
, &OK
, &Flags
) + data_offset
;
if (OK
)
{
if (mFirstPassUnknown
(Flags
))
DispAcc
= 0;
else if (lit_size
== eSymbolSize32Bit
)
DispAcc
= (DispAcc
- (PCRelAdr
() & 0xfffffffc)) >> 2;
else
DispAcc
= (DispAcc
- PCRelAdr
()) >> 1;
if (DispAcc
< 0)
{
WrXError
(ErrNum_UnderRange
, "Disp<0");
OK
= False
;
}
else if ((DispAcc
> 255) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_DistTooBig
);
else
{
AdrMode
= ModPCRel
;
AdrPart
= DispAcc
;
OpSize
= lit_size
;
}
}
}
else
WrError
(ErrNum_InvAddrMode
);
}
goto chk
;
}
/* absolut ueber PC-relativ abwickeln */
if ((OpSize
!= eSymbolSize16Bit
) && (OpSize
!= eSymbolSize32Bit
)) WrError
(ErrNum_InvOpSize
);
else
{
DispAcc
= EvalStrIntExpressionWithFlags
(pArg
, Int32
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
DispAcc
= 0;
else if (OpSize
== eSymbolSize32Bit
)
DispAcc
-= (PCRelAdr
() & 0xfffffffc);
else
DispAcc
-= PCRelAdr
();
if (DispAcc
< 0)
WrXError
(ErrNum_UnderRange
, "Disp<0");
else if ((DispAcc
& ((1 << OpSize
) - 1)) != 0)
WrError
(ErrNum_NotAligned
);
else
{
DispAcc
= DispAcc
>> OpSize
;
if (DispAcc
> 255) WrError
(ErrNum_OverRange
);
else
{
AdrMode
= ModPCRel
;
AdrPart
= DispAcc
;
}
}
}
chk
:
if ((AdrMode
!= ModNone
) && ((Mask
& (1 << AdrMode
)) == 0))
{
WrError
(ErrNum_InvAddrMode
);
AdrMode
= ModNone
;
}
}
static void SetCode
(Word Code
)
{
CodeLen
= 2;
WAsmCode
[0] = Code
;
}
/*-------------------------------------------------------------------------*/
/* Instruction Decoders */
static void DecodeFixed
(Word Index
)
{
const FixedOrder
*pOrder
= FixedOrders
+ Index
;
if (!ChkArgCnt
(0, 0));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkMinCPU
(pOrder
->MinCPU
))
{
SetCode
(pOrder
->Code
);
if ((!SupAllowed
) && (pOrder
->Priv
)) WrError
(ErrNum_PrivOrder
);
}
}
static void DecodeMOV
(Word Code
)
{
Word HReg
;
UNUSED
(Code
);
if (OpSize
== eSymbolSizeUnknown
)
SetOpSize
(eSymbolSize32Bit
);
if (!ChkArgCnt
(2, 2));
else if (OpSize
> eSymbolSize32Bit
) WrError
(ErrNum_InvOpSize
);
else if (DecodeReg
(&ArgStr
[1], &HReg
, False
) == eIsReg
)
{
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg
| MModPreDec
| MModIndReg
| MModR0Base
| MModGBRBase
, True
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
!= eSymbolSize32Bit
) WrError
(ErrNum_InvOpSize
);
else
SetCode
(0x6003 + (HReg
<< 4) + (AdrPart
<< 8));
break;
case ModIReg
:
SetCode
(0x2000 + (HReg
<< 4) + (AdrPart
<< 8) + OpSize
);
break;
case ModPreDec
:
SetCode
(0x2004 + (HReg
<< 4) + (AdrPart
<< 8) + OpSize
);
break;
case ModIndReg
:
if (OpSize
== eSymbolSize32Bit
)
SetCode
(0x1000 + (HReg
<< 4) + (AdrPart
& 15) + ((AdrPart
& 0xf0) << 4));
else if (HReg
!= 0)
WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0x8000 + AdrPart
+ (((Word
)OpSize
) << 8));
break;
case ModR0Base
:
SetCode
(0x0004 + (AdrPart
<< 8) + (HReg
<< 4) + OpSize
);
break;
case ModGBRBase
:
if (HReg
!= 0)
WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0xc000 + AdrPart
+ (((Word
)OpSize
) << 8));
break;
}
}
else if (DecodeReg
(&ArgStr
[2], &HReg
, False
) == eIsReg
)
{
DecodeAdr
(&ArgStr
[1], MModImm
| MModPCRel
| MModIReg
| MModPostInc
| MModIndReg
| MModR0Base
| MModGBRBase
, True
);
switch (AdrMode
)
{
case ModIReg
:
SetCode
(0x6000 + (AdrPart
<< 4) + (((Word
)HReg
) << 8) + OpSize
);
break;
case ModPostInc
:
SetCode
(0x6004 + (AdrPart
<< 4) + (((Word
)HReg
) << 8) + OpSize
);
break;
case ModIndReg
:
if (OpSize
== eSymbolSize32Bit
)
SetCode
(0x5000 + (((Word
)HReg
) << 8) + AdrPart
);
else if (HReg
!= 0)
WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0x8400 + AdrPart
+ (((Word
)OpSize
) << 8));
break;
case ModR0Base
:
SetCode
(0x000c + (AdrPart
<< 4) + (((Word
)HReg
) << 8) + OpSize
);
break;
case ModGBRBase
:
if (HReg
!= 0)
WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0xc400 + AdrPart
+ (((Word
)OpSize
) << 8));
break;
case ModPCRel
:
if (OpSize
== eSymbolSize8Bit
)
WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0x9000 + (((Word
)OpSize
- 1) << 14) + (((Word
)HReg
) << 8) + AdrPart
);
break;
case ModImm
:
SetCode
(0xe000 + (((Word
)HReg
) << 8) + AdrPart
);
break;
}
}
else
WrError
(ErrNum_InvAddrMode
);
}
static void DecodeMOVA
(Word Code
)
{
Word HReg
;
UNUSED
(Code
);
if (!ChkArgCnt
(2, 2));
else if (!DecodeReg
(&ArgStr
[2], &HReg
, True
));
else if (HReg
!= 0) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[2]);
else
{
SetOpSize
(eSymbolSize32Bit
);
DecodeAdr
(&ArgStr
[1], MModPCRel
, False
);
if (AdrMode
!= ModNone
)
SetCode
(0xc700 + AdrPart
);
}
}
static void DecodePREF
(Word Code
)
{
UNUSED
(Code
);
if (!ChkArgCnt
(1, 1));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
DecodeAdr
(&ArgStr
[1], MModIReg
, False
);
if (AdrMode
!= ModNone
)
SetCode
(WAsmCode
[0] = 0x0083 + (AdrPart
<< 8));
}
}
static void DecodeLDC_STC
(Word IsLDC
)
{
if (OpSize
== eSymbolSizeUnknown
)
SetOpSize
(eSymbolSize32Bit
);
if (ChkArgCnt
(2, 2))
{
tStrComp
*pArg1
= IsLDC
? &ArgStr
[2] : &ArgStr
[1],
*pArg2
= IsLDC
? &ArgStr
[1] : &ArgStr
[2];
Word HReg
;
if (DecodeCtrlReg
(pArg1
->str.
p_str, &HReg
))
{
DecodeAdr
(pArg2
, MModReg
| (IsLDC
? MModPostInc
: MModPreDec
), False
);
switch (AdrMode
)
{
case ModReg
:
SetCode
((IsLDC
? 0x400e : 0x0002) + (AdrPart
<< 8) + (HReg
<< 4));
break;
case ModPostInc
:
SetCode
(0x4007 + (AdrPart
<< 8) + (HReg
<< 4));
break;
case ModPreDec
:
SetCode
(0x4003 + (AdrPart
<< 8) + (HReg
<< 4));
break;
}
if ((AdrMode
!= ModNone
) && (!SupAllowed
))
WrError
(ErrNum_PrivOrder
);
}
}
}
static void DecodeLDS_STS
(Word IsLDS
)
{
if (OpSize
== eSymbolSizeUnknown
)
SetOpSize
(eSymbolSize32Bit
);
if (ChkArgCnt
(2, 2))
{
tStrComp
*pArg1
= IsLDS
? &ArgStr
[2] : &ArgStr
[1],
*pArg2
= IsLDS
? &ArgStr
[1] : &ArgStr
[2];
Word HReg
;
if (!DecodeSReg
(pArg1
->str.
p_str, &HReg
)) WrError
(ErrNum_InvCtrlReg
);
else
{
DecodeAdr
(pArg2
, MModReg
| (IsLDS
? MModPostInc
: MModPreDec
), False
);
switch (AdrMode
)
{
case ModReg
:
SetCode
((IsLDS
<< 14) + 0x000a + (AdrPart
<< 8) + (HReg
<< 4));
break;
case ModPostInc
:
SetCode
(0x4006 + (AdrPart
<< 8) + (HReg
<< 4));
break;
case ModPreDec
:
SetCode
(0x4002 + (AdrPart
<< 8) + (HReg
<< 4));
break;
}
}
}
}
static void DecodeOneReg
(Word Index
)
{
const OneRegOrder
*pOrder
= OneRegOrders
+ Index
;
if (!ChkArgCnt
(1, 1));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkMinCPU
(pOrder
->MinCPU
))
{
DecodeAdr
(&ArgStr
[1], MModReg
, False
);
if (AdrMode
!= ModNone
)
SetCode
(pOrder
->Code
+ (AdrPart
<< 8));
if ((!SupAllowed
) && (pOrder
->Priv
)) WrError
(ErrNum_PrivOrder
);
if (pOrder
->Delayed
)
{
CurrDelayed
= True
;
DelayedAdr
= 0x7fffffff;
ChkDelayed
();
}
}
}
static void DecodeTAS
(Word Code
)
{
UNUSED
(Code
);
if (OpSize
== eSymbolSizeUnknown
)
SetOpSize
(eSymbolSize8Bit
);
if (!ChkArgCnt
(1, 1));
else if (OpSize
!= eSymbolSize8Bit
) WrError
(ErrNum_InvOpSize
);
else
{
DecodeAdr
(&ArgStr
[1], MModIReg
, False
);
if (AdrMode
!= ModNone
)
SetCode
(0x401b + (AdrPart
<< 8));
}
}
static void DecodeTwoReg
(Word Index
)
{
const TwoRegOrder
*pOrder
= TwoRegOrders
+ Index
;
if (!ChkArgCnt
(2, 2));
else if (*AttrPart.
str.
p_str && (OpSize
!= pOrder
->DefSize
)) WrError
(ErrNum_UseLessAttr
);
else if (ChkMinCPU
(pOrder
->MinCPU
))
{
DecodeAdr
(&ArgStr
[1], MModReg
, False
);
if (AdrMode
!= ModNone
)
{
WAsmCode
[0] = pOrder
->Code
+ (AdrPart
<< 4);
DecodeAdr
(&ArgStr
[2], MModReg
, False
);
if (AdrMode
!= ModNone
)
SetCode
(WAsmCode
[0] + (((Word
)AdrPart
) << 8));
if ((!SupAllowed
) && (pOrder
->Priv
))
WrError
(ErrNum_PrivOrder
);
}
}
}
static void DecodeMulReg
(Word Index
)
{
const FixedMinOrder
*pOrder
= MulRegOrders
+ Index
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(pOrder
->MinCPU
))
{
if (!*AttrPart.
str.
p_str)
OpSize
= eSymbolSize32Bit
;
if (OpSize
!= eSymbolSize32Bit
) WrError
(ErrNum_InvOpSize
);
else
{
DecodeAdr
(&ArgStr
[1], MModReg
, False
);
if (AdrMode
!= ModNone
)
{
WAsmCode
[0] = pOrder
->Code
+ (AdrPart
<< 4);
DecodeAdr
(&ArgStr
[2], MModReg
, False
);
if (AdrMode
!= ModNone
)
SetCode
(WAsmCode
[0] + (((Word
)AdrPart
) << 8));
}
}
}
}
static void DecodeBW
(Word Index
)
{
const FixedOrder
*pOrder
= BWOrders
+ Index
;
if (OpSize
== eSymbolSizeUnknown
)
SetOpSize
(eSymbolSize16Bit
);
if (!ChkArgCnt
(2, 2));
else if ((OpSize
!= eSymbolSize8Bit
) && (OpSize
!= eSymbolSize16Bit
)) WrError
(ErrNum_InvOpSize
);
else
{
DecodeAdr
(&ArgStr
[1], MModReg
, False
);
if (AdrMode
!= ModNone
)
{
WAsmCode
[0] = pOrder
->Code
+ OpSize
+ (AdrPart
<< 4);
DecodeAdr
(&ArgStr
[2], MModReg
, False
);
if (AdrMode
!= ModNone
)
SetCode
(WAsmCode
[0] + (((Word
)AdrPart
) << 8));
}
}
}
static void DecodeMAC
(Word Code
)
{
UNUSED
(Code
);
if (OpSize
== eSymbolSizeUnknown
)
SetOpSize
(eSymbolSize16Bit
);
if (!ChkArgCnt
(2, 2));
else if ((OpSize
!= eSymbolSize16Bit
) && (OpSize
!= eSymbolSize32Bit
)) WrError
(ErrNum_InvOpSize
);
else if ((OpSize
== eSymbolSize32Bit
) && !ChkMinCPU
(CPU7600
));
else
{
DecodeAdr
(&ArgStr
[1], MModPostInc
, False
);
if (AdrMode
!= ModNone
)
{
WAsmCode
[0] = 0x000f + (AdrPart
<< 4) + (((Word
)2 - OpSize
) << 14);
DecodeAdr
(&ArgStr
[2], MModPostInc
, False
);
if (AdrMode
!= ModNone
)
SetCode
(WAsmCode
[0] + (((Word
)AdrPart
) << 8));
}
}
}
static void DecodeADD
(Word Code
)
{
UNUSED
(Code
);
if (!ChkArgCnt
(2, 2));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
DecodeAdr
(&ArgStr
[2], MModReg
, False
);
if (AdrMode
!= ModNone
)
{
Word HReg
= AdrPart
;
OpSize
= eSymbolSize32Bit
;
DecodeAdr
(&ArgStr
[1], MModReg
| MModImm
, True
);
switch (AdrMode
)
{
case ModReg
:
SetCode
(0x300c + (((Word
)HReg
) << 8) + (AdrPart
<< 4));
break;
case ModImm
:
SetCode
(0x7000 + AdrPart
+ (((Word
)HReg
) << 8));
break;
}
}
}
}
static void DecodeCMPEQ
(Word Code
)
{
UNUSED
(Code
);
if (!ChkArgCnt
(2, 2));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
DecodeAdr
(&ArgStr
[2], MModReg
, False
);
if (AdrMode
!= ModNone
)
{
Word HReg
= AdrPart
;
OpSize
= eSymbolSize32Bit
;
DecodeAdr
(&ArgStr
[1], MModReg
| MModImm
, True
);
switch (AdrMode
)
{
case ModReg
:
SetCode
(0x3000 + (((Word
)HReg
) << 8) + (AdrPart
<< 4));
break;
case ModImm
:
if (HReg
!= 0) WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0x8800 + AdrPart
);
break;
}
}
}
}
static void DecodeLog
(Word Code
)
{
Word HReg
;
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[2], MModReg
| MModGBRR0
, False
);
switch (AdrMode
)
{
case ModReg
:
if (*AttrPart.
str.
p_str && (OpSize
!= eSymbolSize32Bit
)) WrError
(ErrNum_InvOpSize
);
else
{
OpSize
= eSymbolSize32Bit
;
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[1], MModReg
| MModImm
, False
);
switch (AdrMode
)
{
case ModReg
:
SetCode
(0x2008 + Code
+ (((Word
)HReg
) << 8) + (AdrPart
<< 4));
break;
case ModImm
:
if (HReg
!= 0) WrError
(ErrNum_InvAddrMode
);
else
SetCode
(0xc800 + (Code
<< 8) + AdrPart
);
break;
}
}
break;
case ModGBRR0
:
DecodeAdr
(&ArgStr
[1], MModImm
, False
);
if (AdrMode
!= ModNone
)
SetCode
(0xcc00 + (Code
<< 8) + AdrPart
);
break;
}
}
}
static void DecodeTRAPA
(Word Code
)
{
UNUSED
(Code
);
if (!ChkArgCnt
(1, 1));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
OpSize
= eSymbolSize8Bit
;
DecodeAdr
(&ArgStr
[1], MModImm
, False
);
if (AdrMode
== ModImm
)
SetCode
(0xc300 + AdrPart
);
ChkDelayed
();
}
}
static void DecodeBT_BF
(Word Code
)
{
if (!ChkArgCnt
(1, 1));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if ((Code
& 0x400) && !ChkMinCPU
(CPU7600
));
else
{
Boolean OK
;
tSymbolFlags Flags
;
LongInt AdrLong
;
DelayedAdr
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], Int32
, &OK
, &Flags
);
AdrLong
= DelayedAdr
- (EProgCounter
() + 4);
if (OK
)
{
if (Odd
(AdrLong
)) WrError
(ErrNum_DistIsOdd
);
else if (((AdrLong
< -256) || (AdrLong
> 254)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
SetCode
(Code
+ ((AdrLong
>> 1) & 0xff));
if (Code
& 0x400)
CurrDelayed
= True
;
ChkDelayed
();
}
}
}
}
static void DecodeBRA_BSR
(Word Code
)
{
if (!ChkArgCnt
(1, 1));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
Boolean OK
;
tSymbolFlags Flags
;
LongInt AdrLong
;
DelayedAdr
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], Int32
, &OK
, &Flags
);
AdrLong
= DelayedAdr
- (EProgCounter
() + 4);
if (OK
)
{
if (Odd
(AdrLong
)) WrError
(ErrNum_DistIsOdd
);
else if (((AdrLong
< -4096) || (AdrLong
> 4094)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
SetCode
(Code
+ ((AdrLong
>> 1) & 0xfff));
CurrDelayed
= True
;
ChkDelayed
();
}
}
}
}
static void DecodeJSR_JMP
(Word Code
)
{
if (!ChkArgCnt
(1, 1));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
DecodeAdr
(&ArgStr
[1], MModIReg
, False
);
if (AdrMode
!= ModNone
)
{
SetCode
(Code
+ (AdrPart
<< 8));
CurrDelayed
= True
;
DelayedAdr
= 0x7fffffff;
ChkDelayed
();
}
}
}
static void DecodeDCT_DCF
(Word Cond
)
{
char *pos
;
int z
;
if (!DSPAvail
)
{
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
return;
}
/* strip off DSP condition */
if (!ChkArgCnt
(1, ArgCntMax
))
return;
pos
= FirstBlank
(ArgStr
[1].
str.
p_str);
if (!pos
)
{
StrCompCopy
(&OpPart
, &ArgStr
[1]);
for (z
= 1; z
< ArgCnt
; z
++)
StrCompCopy
(&ArgStr
[z
], &ArgStr
[z
+ 1]);
ArgCnt
--;
}
else
StrCompSplitLeft
(&ArgStr
[1], &OpPart
, pos
);
UNUSED
(Cond
);
}
static LargeInt ltorg_16
(const as_literal_t
*p_lit
, tStrComp
*p_name
)
{
LargeInt ret
;
SetMaxCodeLen
(CodeLen
+ 2);
WAsmCode
[CodeLen
>> 1] = p_lit
->value
;
ret
= EProgCounter
() + CodeLen
;
EnterIntSymbol
(p_name
, ret
, ActPC
, False
);
CodeLen
+= 2;
return ret
;
}
static LargeInt ltorg_32
(const as_literal_t
*p_lit
, tStrComp
*p_name
)
{
LargeInt ret
;
SetMaxCodeLen
(CodeLen
+ 6);
if (((EProgCounter
() + CodeLen
) & 2) != 0)
{
WAsmCode
[CodeLen
>> 1] = 0;
CodeLen
+= 2;
}
WAsmCode
[CodeLen
>> 1] = (p_lit
->value
>> 16);
WAsmCode
[(CodeLen
>> 1) + 1] = (p_lit
->value
& 0xffff);
ret
= EProgCounter
() + CodeLen
;
EnterIntSymbol
(p_name
, ret
, ActPC
, False
);
CodeLen
+= 4;
return ret
;
}
static void DecodeLTORG
(Word Code
)
{
UNUSED
(Code
);
if (!ChkArgCnt
(0, 0));
else if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else
{
if ((EProgCounter
() & 3) == 0)
{
literals_dump
(ltorg_32
, eSymbolSize32Bit
, MomSectionHandle
, True
);
literals_dump
(ltorg_16
, eSymbolSize16Bit
, MomSectionHandle
, False
);
}
else
{
literals_dump
(ltorg_16
, eSymbolSize16Bit
, MomSectionHandle
, False
);
literals_dump
(ltorg_32
, eSymbolSize32Bit
, MomSectionHandle
, True
);
}
}
}
/*-------------------------------------------------------------------------*/
/* dynamische Belegung/Freigabe Codetabellen */
static void AddFixed
(const char *NName
, Word NCode
, Boolean NPriv
, CPUVar NMin
)
{
order_array_rsv_end
(FixedOrders
, FixedOrder
);
FixedOrders
[InstrZ
].
Priv = NPriv
;
FixedOrders
[InstrZ
].
MinCPU = NMin
;
FixedOrders
[InstrZ
].
Code = NCode
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddOneReg
(const char *NName
, Word NCode
, CPUVar NMin
, Boolean NPriv
, Boolean NDel
)
{
order_array_rsv_end
(OneRegOrders
, OneRegOrder
);
OneRegOrders
[InstrZ
].
Code = NCode
;
OneRegOrders
[InstrZ
].
MinCPU = NMin
;
OneRegOrders
[InstrZ
].
Priv = NPriv
;
OneRegOrders
[InstrZ
].
Delayed = NDel
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeOneReg
);
}
static void AddTwoReg
(const char *NName
, Word NCode
, Boolean NPriv
, CPUVar NMin
, ShortInt NDef
)
{
order_array_rsv_end
(TwoRegOrders
, TwoRegOrder
);
TwoRegOrders
[InstrZ
].
Priv = NPriv
;
TwoRegOrders
[InstrZ
].
DefSize = NDef
;
TwoRegOrders
[InstrZ
].
MinCPU = NMin
;
TwoRegOrders
[InstrZ
].
Code = NCode
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeTwoReg
);
}
static void AddMulReg
(const char *NName
, Word NCode
, CPUVar NMin
)
{
order_array_rsv_end
(MulRegOrders
, FixedMinOrder
);
MulRegOrders
[InstrZ
].
Code = NCode
;
MulRegOrders
[InstrZ
].
MinCPU = NMin
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeMulReg
);
}
static void AddBW
(const char *NName
, Word NCode
)
{
order_array_rsv_end
(BWOrders
, FixedOrder
);
BWOrders
[InstrZ
].
Code = NCode
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeBW
);
}
static void AddSReg
(const char *NName
, Word NCode
, CPUVar NMin
, Boolean NDSP
)
{
order_array_rsv_end
(RegDefs
, TRegDef
);
RegDefs
[InstrZ
].
Name = NName
;
RegDefs
[InstrZ
].
Code = NCode
;
RegDefs
[InstrZ
].
MinCPU = NMin
;
RegDefs
[InstrZ
++].
NeedsDSP = NDSP
;
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(201);
AddInstTable
(InstTable
, "MOV", 0, DecodeMOV
);
AddInstTable
(InstTable
, "MOVA", 0, DecodeMOVA
);
AddInstTable
(InstTable
, "PREF", 0, DecodePREF
);
AddInstTable
(InstTable
, "LDC", 1, DecodeLDC_STC
);
AddInstTable
(InstTable
, "STC", 0, DecodeLDC_STC
);
AddInstTable
(InstTable
, "LDS", 1, DecodeLDS_STS
);
AddInstTable
(InstTable
, "STS", 0, DecodeLDS_STS
);
AddInstTable
(InstTable
, "TAS", 0, DecodeTAS
);
AddInstTable
(InstTable
, "MAC", 0, DecodeMAC
);
AddInstTable
(InstTable
, "ADD", 0, DecodeADD
);
AddInstTable
(InstTable
, "CMP/EQ", 0, DecodeCMPEQ
);
AddInstTable
(InstTable
, "TRAPA", 0, DecodeTRAPA
);
AddInstTable
(InstTable
, "BF", 0x8b00, DecodeBT_BF
);
AddInstTable
(InstTable
, "BT", 0x8900, DecodeBT_BF
);
AddInstTable
(InstTable
, "BF/S", 0x8f00, DecodeBT_BF
);
AddInstTable
(InstTable
, "BT/S", 0x8d00, DecodeBT_BF
);
AddInstTable
(InstTable
, "BRA", 0xa000, DecodeBRA_BSR
);
AddInstTable
(InstTable
, "BSR", 0xb000, DecodeBRA_BSR
);
AddInstTable
(InstTable
, "JSR", 0x400b, DecodeJSR_JMP
);
AddInstTable
(InstTable
, "JMP", 0x402b, DecodeJSR_JMP
);
AddInstTable
(InstTable
, "DCT", 1, DecodeDCT_DCF
);
AddInstTable
(InstTable
, "DCF", 2, DecodeDCT_DCF
);
AddInstTable
(InstTable
, "LTORG", 0, DecodeLTORG
);
InstrZ
= 0;
AddFixed
("CLRT" , 0x0008, False
, CPU7000
);
AddFixed
("CLRMAC", 0x0028, False
, CPU7000
);
AddFixed
("NOP" , 0x0009, False
, CPU7000
);
AddFixed
("RTE" , 0x002b, False
, CPU7000
);
AddFixed
("SETT" , 0x0018, False
, CPU7000
);
AddFixed
("SLEEP" , 0x001b, False
, CPU7000
);
AddFixed
("RTS" , 0x000b, False
, CPU7000
);
AddFixed
("DIV0U" , 0x0019, False
, CPU7000
);
AddFixed
("BRK" , 0x0000, True
, CPU7000
);
AddFixed
("RTB" , 0x0001, True
, CPU7000
);
AddFixed
("CLRS" , 0x0048, False
, CPU7700
);
AddFixed
("SETS" , 0x0058, False
, CPU7700
);
AddFixed
("LDTLB" , 0x0038, True
, CPU7700
);
InstrZ
= 0;
AddOneReg
("MOVT" , 0x0029, CPU7000
, False
, False
);
AddOneReg
("CMP/PZ", 0x4011, CPU7000
, False
, False
);
AddOneReg
("CMP/PL", 0x4015, CPU7000
, False
, False
);
AddOneReg
("ROTL" , 0x4004, CPU7000
, False
, False
);
AddOneReg
("ROTR" , 0x4005, CPU7000
, False
, False
);
AddOneReg
("ROTCL" , 0x4024, CPU7000
, False
, False
);
AddOneReg
("ROTCR" , 0x4025, CPU7000
, False
, False
);
AddOneReg
("SHAL" , 0x4020, CPU7000
, False
, False
);
AddOneReg
("SHAR" , 0x4021, CPU7000
, False
, False
);
AddOneReg
("SHLL" , 0x4000, CPU7000
, False
, False
);
AddOneReg
("SHLR" , 0x4001, CPU7000
, False
, False
);
AddOneReg
("SHLL2" , 0x4008, CPU7000
, False
, False
);
AddOneReg
("SHLR2" , 0x4009, CPU7000
, False
, False
);
AddOneReg
("SHLL8" , 0x4018, CPU7000
, False
, False
);
AddOneReg
("SHLR8" , 0x4019, CPU7000
, False
, False
);
AddOneReg
("SHLL16", 0x4028, CPU7000
, False
, False
);
AddOneReg
("SHLR16", 0x4029, CPU7000
, False
, False
);
AddOneReg
("LDBR" , 0x0021, CPU7000
, True
, False
);
AddOneReg
("STBR" , 0x0020, CPU7000
, True
, False
);
AddOneReg
("DT" , 0x4010, CPU7600
, False
, False
);
AddOneReg
("BRAF" , 0x0023, CPU7600
, False
, True
);
AddOneReg
("BSRF" , 0x0003, CPU7600
, False
, True
);
InstrZ
= 0;
AddTwoReg
("XTRCT" , 0x200d, False
, CPU7000
, 2);
AddTwoReg
("ADDC" , 0x300e, False
, CPU7000
, 2);
AddTwoReg
("ADDV" , 0x300f, False
, CPU7000
, 2);
AddTwoReg
("CMP/HS", 0x3002, False
, CPU7000
, 2);
AddTwoReg
("CMP/GE", 0x3003, False
, CPU7000
, 2);
AddTwoReg
("CMP/HI", 0x3006, False
, CPU7000
, 2);
AddTwoReg
("CMP/GT", 0x3007, False
, CPU7000
, 2);
AddTwoReg
("CMP/STR", 0x200c, False
, CPU7000
, 2);
AddTwoReg
("DIV1" , 0x3004, False
, CPU7000
, 2);
AddTwoReg
("DIV0S" , 0x2007, False
, CPU7000
, -1);
AddTwoReg
("MULS" , 0x200f, False
, CPU7000
, 1);
AddTwoReg
("MULU" , 0x200e, False
, CPU7000
, 1);
AddTwoReg
("NEG" , 0x600b, False
, CPU7000
, 2);
AddTwoReg
("NEGC" , 0x600a, False
, CPU7000
, 2);
AddTwoReg
("SUB" , 0x3008, False
, CPU7000
, 2);
AddTwoReg
("SUBC" , 0x300a, False
, CPU7000
, 2);
AddTwoReg
("SUBV" , 0x300b, False
, CPU7000
, 2);
AddTwoReg
("NOT" , 0x6007, False
, CPU7000
, 2);
AddTwoReg
("SHAD" , 0x400c, False
, CPU7700
, 2);
AddTwoReg
("SHLD" , 0x400d, False
, CPU7700
, 2);
InstrZ
= 0;
AddMulReg
("MUL" , 0x0007, CPU7600
);
AddMulReg
("DMULU" , 0x3005, CPU7600
);
AddMulReg
("DMULS" , 0x300d, CPU7600
);
InstrZ
= 0;
AddBW
("SWAP", 0x6008); AddBW
("EXTS", 0x600e); AddBW
("EXTU", 0x600c);
InstrZ
= 0;
AddInstTable
(InstTable
, "TST", InstrZ
++, DecodeLog
);
AddInstTable
(InstTable
, "AND", InstrZ
++, DecodeLog
);
AddInstTable
(InstTable
, "XOR", InstrZ
++, DecodeLog
);
AddInstTable
(InstTable
, "OR" , InstrZ
++, DecodeLog
);
AddInstTable
(InstTable
, "REG", 0, CodeREG
);
InstrZ
= 0;
AddSReg
("MACH", 0, CPU7000
, FALSE
);
AddSReg
("MACL", 1, CPU7000
, FALSE
);
AddSReg
("PR" , 2, CPU7000
, FALSE
);
AddSReg
("DSR" , 6, CPU7000
, TRUE
);
AddSReg
("A0" , 7, CPU7000
, TRUE
);
AddSReg
("X0" , 8, CPU7000
, TRUE
);
AddSReg
("X1" , 9, CPU7000
, TRUE
);
AddSReg
("Y0" , 10, CPU7000
, TRUE
);
AddSReg
("Y1" , 11, CPU7000
, TRUE
);
AddSReg
(NULL
, 0, CPU7000
, FALSE
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(FixedOrders
);
order_array_free
(OneRegOrders
);
order_array_free
(TwoRegOrders
);
order_array_free
(MulRegOrders
);
order_array_free
(BWOrders
);
order_array_free
(RegDefs
);
}
/*-------------------------------------------------------------------------*/
static Boolean DecodeAttrPart_7000
(void)
{
if (*AttrPart.
str.
p_str)
{
if (strlen(AttrPart.
str.
p_str) != 1)
{
WrError
(ErrNum_TooLongAttr
);
return False
;
}
if (!DecodeMoto16AttrSize
(*AttrPart.
str.
p_str, &AttrPartOpSize
[0], False
))
return False
;
}
return True
;
}
static void MakeCode_7000
(void)
{
CodeLen
= 0;
DontPrint
= False
;
OpSize
= eSymbolSizeUnknown
;
/* zu ignorierendes */
if (Memo
("")) return;
/* ab hier (und weiter in der Hauptroutine) stehen die Befehle,
die Code erzeugen, deshalb wird der Merker fuer verzoegerte
Spruenge hier weiter geschaltet. */
PrevDelayed
= CurrDelayed
;
CurrDelayed
= False
;
/* Attribut verwursten */
if (*AttrPart.
str.
p_str)
SetOpSize
(AttrPartOpSize
[0]);
if (DecodeMoto16Pseudo
(OpSize
, True
))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_7000(char *pArg, TempResult *pResult)
* \brief handle built-in symbols in SH7x00
* \param pArg source argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_7000
(char *pArg
, TempResult
*pResult
)
{
Word Reg
;
if (DecodeRegCore
(pArg
, &Reg
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize32Bit
;
pResult
->Contents.
RegDescr.
Reg = Reg
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_7000
;
pResult
->Contents.
RegDescr.
compare = NULL
;
}
}
static Boolean IsDef_7000
(void)
{
return Memo
("REG");
}
static void SwitchFrom_7000
(void)
{
DeinitFields
();
}
static void SwitchTo_7000
(void)
{
TurnWords
= True
;
SetIntConstMode
(eIntConstModeMoto
);
PCSymbol
= "*";
HeaderID
= 0x6c;
NOPCode
= 0x0009;
DivideChars
= ",";
HasAttrs
= True
;
AttrChars
= ".";
ValidSegs
= 1 << SegCode
;
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 2; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = (LargeWord
)IntTypeDefs
[UInt32
].
Max;
DecodeAttrPart
= DecodeAttrPart_7000
;
MakeCode
= MakeCode_7000
;
IsDef
= IsDef_7000
;
InternSymbol
= InternSymbol_7000
;
DissectReg
= DissectReg_7000
;
SwitchFrom
= SwitchFrom_7000
;
InitFields
();
onoff_supmode_add
();
AddONOFF
("COMPLITERALS", &CompLiterals
, CompLiteralsName
, False
);
AddMoto16PseudoONOFF
(False
);
if (!onoff_test_and_set
(e_onoff_reg_dsp
))
SetFlag
(&DSPAvail
, DSPSymName
, False
);
AddONOFF
(DSPCmdName
, &DSPAvail
, DSPSymName
, False
);
CurrDelayed
= False
; PrevDelayed
= False
;
}
void code7000_init
(void)
{
CPU7000
= AddCPU
("SH7000", SwitchTo_7000
);
CPU7600
= AddCPU
("SH7600", SwitchTo_7000
);
CPU7700
= AddCPU
("SH7700", SwitchTo_7000
);
}