/* codez8.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator Zilog Z8 */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "nls.h"
#include "strutil.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmstructs.h"
#include "asmitree.h"
#include "asmallg.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "headids.h"
#include "errmsg.h"
#include "codez8.h"
typedef enum
{
eCoreNone
= 0,
eCoreZ8NMOS
= 1 << 0,
eCoreZ8CMOS
= 1 << 1,
eCoreSuper8
= 1 << 2,
eCoreZ8Encore
= 1 << 3,
eCoreAll
= eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
} tCoreFlags
;
typedef struct
{
const char *pName
;
Word Code
;
tCoreFlags CoreFlags
;
} BaseOrder
;
typedef struct
{
Word Code
;
tCoreFlags CoreFlags
;
Boolean Is16
;
} ALU1Order
;
typedef struct
{
const char *Name
;
Byte Code
;
} Condition
;
#ifdef __cplusplus
# include "codez8.hpp"
#endif
typedef struct
{
const char *pName
;
tCoreFlags CoreFlags
;
Word WorkOfs
;
Word RAMEnd
, SFRStart
;
} tCPUProps
;
#define LongWorkOfs 0xee0 /* ditto with 12-bit-addresses */
#define EXTPREFIX 0x1f
#define mIsSuper8() (pCurrCPUProps->CoreFlags & eCoreSuper8)
#define mIsZ8Encore() (pCurrCPUProps->CoreFlags & eCoreZ8Encore)
/* CAUTION: ModIReg and ModIRReg are mutually exclusive
ModReg and ModRReg are mutually exclusive */
enum
{
ModNone
= -1,
ModWReg
= 0, /* working register R0..R15, 'r' */
ModReg
= 1, /* general register 'R' */
ModRReg
= 2, /* general register pair 'RR' (must be even) */
ModIWReg
= 3, /* indirect working register @R0...@R15 'Ir' */
ModIReg
= 4, /* indirect general register 'IR' */
ModImm
= 5, /* immediate value 'IM' */
ModWRReg
= 6, /* working register pair 'rr' (must be even) */
ModIWRReg
= 7, /* indirect working register pair 'Irr' (must be even) */
ModIRReg
= 8, /* indirect general register pair 'IRR' (must be even) */
ModInd
= 9,
ModXReg
= 10,
ModIndRR
= 11,
ModIndRR16
= 12,
ModWeird
= 13,
ModDA
= 14
};
#define MModWReg (1 << ModWReg)
#define MModReg (1 << ModReg)
#define MModRReg (1 << ModRReg)
#define MModIWReg (1 << ModIWReg)
#define MModIReg (1 << ModIReg)
#define MModImm (1 << ModImm)
#define MModWRReg (1 << ModWRReg)
#define MModIWRReg (1 << ModIWRReg)
#define MModIRReg (1 << ModIRReg)
#define MModInd (1 << ModInd)
#define MModXReg (1 << ModXReg)
#define MModIndRR (1 << ModIndRR)
#define MModIndRR16 (1 << ModIndRR16)
#define MModWeird (1 << ModWeird)
#define MModDA (1 << ModDA)
static ShortInt AdrType
, OpSize
;
static Byte AdrVal
;
static Word AdrWVal
;
static LongInt AdrIndex
;
static BaseOrder
*FixedOrders
;
static BaseOrder
*ALU2Orders
;
static BaseOrder
*ALUXOrders
;
static ALU1Order
*ALU1Orders
;
static Condition
*Conditions
;
static int CondCnt
, TrueCond
;
static const tCPUProps
*pCurrCPUProps
;
static LongInt RPVal
, RP0Val
, RP1Val
;
static IntType RegSpaceType
;
/*--------------------------------------------------------------------------*/
/* address expression decoding routines */
/*!------------------------------------------------------------------------
* \fn IsWRegCore(const char *pArg, Byte *pResult)
* \brief Is argument a working register? (Rn, n=0..15)
* \param pArg argument
* \param pResult resulting register number if it is
* \return True if it is
* ------------------------------------------------------------------------ */
static Boolean IsWRegCore
(const char *pArg
, Byte
*pResult
)
{
if ((strlen(pArg
) < 2) || (as_toupper
(*pArg
) != 'R')) return False
;
else
{
Boolean OK
;
*pResult
= ConstLongInt
(pArg
+ 1, &OK
, 10);
return OK
&& (*pResult
<= 15);
}
}
/*!------------------------------------------------------------------------
* \fn IsWReg(const tStrComp *pArg, Byte *pResult, Boolean MustBeReg)
* \brief Is argument a working register (Rn, n=0..15) or register alias?
* \param pArg argument
* \param pResult resulting register number if it is
* \param MustBeReg expecting register?
* \return reg eval result
* ------------------------------------------------------------------------ */
static Boolean IsWReg
(const tStrComp
*pArg
, Byte
*pResult
, Boolean MustBeReg
)
{
tRegDescr RegDescr
;
tEvalResult EvalResult
;
tRegEvalResult RegEvalResult
;
if (IsWRegCore
(pArg
->str.
p_str, pResult
))
return True
;
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize8Bit
, MustBeReg
);
*pResult
= RegDescr.
Reg;
return RegEvalResult
;
}
/*!------------------------------------------------------------------------
* \fn IsWRRegCore(const char *pArg, Byte *pResult)
* \brief Is argument a working register pair? (RRn, n=0..15)
* \param pArg argument
* \param pResult resulting value if it is
* \return True if it is
* ------------------------------------------------------------------------ */
static Boolean IsWRRegCore
(const char *pArg
, Byte
*pResult
)
{
if ((strlen(pArg
) < 3) || as_strncasecmp
(pArg
, "RR", 2)) return False
;
else
{
Boolean OK
;
*pResult
= ConstLongInt
(pArg
+ 2, &OK
, 10);
return OK
&& (*pResult
<= 15);
}
}
#if 0
/*!------------------------------------------------------------------------
* \fn IsWRReg(const tStrComp *pArg, Byte *pResult, Boolean MustBeReg)
* \brief Is argument a working register pair (RRn, n=0..15) or register pair alias?
* \param pArg argument
* \param pResult resulting value if it is
* \param MustBeReg expecting register?
* \return reg eval result
* ------------------------------------------------------------------------ */
static Boolean IsWRReg
(const tStrComp
*pArg
, Byte
*pResult
, Boolean MustBeReg
)
{
tRegDescr RegDescr
;
tEvalResult EvalResult
;
tRegEvalResult RegEvalResult
;
if (IsWRRegCore
(pArg
->str.
p_str, pResult
))
return True
;
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSize16Bit
, MustBeReg
);
*pResult
= RegDescr.
Reg;
return RegEvalResult
;
}
#endif
/*!------------------------------------------------------------------------
* \fn IsWRegOrWRReg(const tStrComp *pArg, Byte *pResult, tSymbolSize *pSize, Boolean MustBeReg)
* \brief Is argument a working register (pair) ((R)Rn, n=0..15) or register (pair) alias?
* \param pArg argument
* \param pResult resulting value if it is
* \param pSize register size if it is
* \param MustBeReg expecting register?
* \return reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult IsWRegOrWRReg
(const tStrComp
*pArg
, Byte
*pResult
, tSymbolSize
*pSize
, Boolean MustBeReg
)
{
tEvalResult EvalResult
;
tRegEvalResult RegEvalResult
;
if (IsWRegCore
(pArg
->str.
p_str, pResult
))
{
EvalResult.
DataSize = eSymbolSize8Bit
;
RegEvalResult
= eIsReg
;
}
else if (IsWRRegCore
(pArg
->str.
p_str, pResult
))
{
EvalResult.
DataSize = eSymbolSize16Bit
;
RegEvalResult
= eIsReg
;
}
else
{
tRegDescr RegDescr
;
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSizeUnknown
, MustBeReg
);
*pResult
= RegDescr.
Reg;
}
if ((eIsReg
== RegEvalResult
) && (EvalResult.
DataSize == eSymbolSize16Bit
) && (*pResult
& 1))
{
WrStrErrorPos
(ErrNum_AddrMustBeEven
, pArg
);
RegEvalResult
= MustBeReg
? eIsNoReg
: eRegAbort
;
}
*pSize
= EvalResult.
DataSize;
return RegEvalResult
;
}
/*!------------------------------------------------------------------------
* \fn DissectReg_Z8(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - Z8 variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_Z8
(char *pDest
, size_t DestSize
, tRegInt Value
, tSymbolSize InpSize
)
{
switch (InpSize
)
{
case eSymbolSize8Bit
:
as_snprintf
(pDest
, DestSize
, "R%u", (unsigned)Value
);
break;
case eSymbolSize16Bit
:
as_snprintf
(pDest
, DestSize
, "RR%u", (unsigned)Value
);
break;
default:
as_snprintf
(pDest
, DestSize
, "%d-%u", (int)InpSize
, (unsigned)Value
);
}
}
/*!------------------------------------------------------------------------
* \fn CorrMode8(Word Mask, ShortInt Old, ShortInt New)
* \brief upgrade from working reg mode to gen. reg mode if necessary & possible?
* \param Mask bit mask of allowed addressing modes
* \param Old currently selected (working reg) mode
* \param New possible new mode
* \return True if converted
* ------------------------------------------------------------------------ */
static Boolean CorrMode8
(Word Mask
, ShortInt Old
, ShortInt New
)
{
if ((AdrType
== Old
) && ((Mask
& (1 << Old
)) == 0) && ((Mask
& (1 << New
)) != 0))
{
AdrType
= New
;
AdrVal
+= pCurrCPUProps
->WorkOfs
;
return True
;
}
else
return False
;
}
/*!------------------------------------------------------------------------
* \fn Boolean CorrMode12(Word Mask, ShortInt Old, ShortInt New)
* \brief upgrade from working reg mode to ext. reg (12 bit) mode if necessary & possible?
* \param Mask bit mask of allowed addressing modes
* \param Old currently selected (working reg) mode
* \param New possible new mode
* \return True if converted
* ------------------------------------------------------------------------ */
static Boolean CorrMode12
(Word Mask
, ShortInt Old
, ShortInt New
)
{
if ((AdrType
== Old
) && ((Mask
& (1 << Old
)) == 0) && ((Mask
& (1 << New
)) != 0))
{
AdrType
= New
;
AdrWVal
= AdrVal
+ LongWorkOfs
;
return True
;
}
else
return False
;
}
/*!------------------------------------------------------------------------
* \fn ChkAdr(Word Mask, const tStrComp *pArg)
* \brief check for validity of decoded addressing mode
* \param Mask bit mask of allowed addressing modes
* \param pArg original expression
* \return true if OK
* ------------------------------------------------------------------------ */
static Boolean ChkAdr
(Word Mask
, const tStrComp
*pArg
)
{
CorrMode8
(Mask
, ModWReg
, ModReg
);
CorrMode12
(Mask
, ModWReg
, ModXReg
);
CorrMode8
(Mask
, ModIWReg
, ModIReg
);
if ((AdrType
!= ModNone
) && !(Mask
& (1 << AdrType
)))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
); AdrType
= ModNone
;
return False
;
}
return True
;
}
/*!------------------------------------------------------------------------
* \fn IsWRegAddress(Word Address, Byte *pWorkReg)
* \brief check whether data address is accessible as work register
* \param Address data address in 8/12 bit data space
* \param pWorkReg resulting work register # if yes
* \param FirstPassUnknown flag about questionable value
* \return true if accessible as work register
* ------------------------------------------------------------------------ */
static Boolean ChkInRange
(Word Address
, Word Base
, Word Length
, Byte
*pOffset
)
{
if ((Address
>= Base
) && (Address
< Base
+ Length
))
{
*pOffset
= Address
- Base
;
return True
;
}
return False
;
}
static Boolean IsWRegAddress
(Word Address
, Byte
*pWorkReg
)
{
if (mIsSuper8
())
{
if ((RP0Val
<= 0xff) && ChkInRange
(Address
, RP0Val
& 0xf8, 8, pWorkReg
))
return True
;
if ((RP1Val
<= 0xff) && ChkInRange
(Address
, RP1Val
& 0xf8, 8, pWorkReg
))
{
*pWorkReg
+= 8;
return True
;
}
}
else if (mIsZ8Encore
())
{
if ((RPVal
<= 0xff) && ChkInRange
(Address
, (RPVal
& 0xf0) | ((RPVal
& 0x0f) << 8), 16, pWorkReg
))
return True
;
}
else
{
if ((RPVal
<= 0xff) && ChkInRange
(Address
, RPVal
& 0xf0, 16, pWorkReg
))
return True
;
}
return False
;
}
/*!------------------------------------------------------------------------
* \fn IsRegAddress(Word Address)
* \brief check whether data address is accessible via 8-bit address
* \param Address data address in 8/12 bit data space
* \return true if accessible via 8-bit address
* ------------------------------------------------------------------------ */
static Boolean IsRegAddress
(Word Address
)
{
/* simple Z8 does not support 12 bit register addresses, so
always force this to TRUE for it */
if (!(pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
))
return TRUE
;
return ((RPVal
<= 0xff)
&& (Hi
(Address
) == (RPVal
& 15)));
}
/*!------------------------------------------------------------------------
* \fn DecodeAdr(const tStrComp *pArg, Word Mask)
* \brief decode address expression
* \param pArg expression in source code
* \param Mask bit mask of allowed modes
* \return True if successfully decoded to an allowed mode
* ------------------------------------------------------------------------ */
int GetForceLen
(const char *pArg
)
{
int Result
= 0;
while ((Result
< 2) && (pArg
[Result
] == '>'))
Result
++;
return Result
;
}
static ShortInt IsWRegWithRP
(const tStrComp
*pComp
, Byte
*pResult
, Word Mask16Modes
, Word Mask8Modes
)
{
tEvalResult EvalResult
;
Word Address
;
tSymbolSize Size
;
switch (IsWRegOrWRReg
(pComp
, pResult
, &Size
, False
))
{
case eIsReg
:
return Size
;
case eIsNoReg
:
break;
case eRegAbort
:
return eSymbolSizeUnknown
;
}
/* It's neither Rn nor RRn. Since an address by itself has no
operand size, only one mode may be allowed to keep things
unambiguous: */
if (Mask16Modes
&& Mask8Modes
)
{
WrStrErrorPos
(ErrNum_InvReg
, pComp
);
return eSymbolSizeUnknown
;
}
Address
= EvalStrIntExpressionWithResult
(pComp
, UInt8
, &EvalResult
);
if (!EvalResult.
OK)
return eSymbolSizeUnknown
;
/* if (mFirstPassUnknown(EvalResult.Flags)) ... */
if (Mask16Modes
&& IsWRegAddress
(Address
, pResult
))
{
if (mFirstPassUnknown
(EvalResult.
Flags)) *pResult
&= ~
1;
if (*pResult
& 1)
{
WrStrErrorPos
(ErrNum_AddrMustBeEven
, pComp
);
return eSymbolSizeUnknown
;
}
return eSymbolSize16Bit
;
}
if (Mask8Modes
&& IsWRegAddress
(Address
, pResult
))
return eSymbolSize8Bit
;
WrStrErrorPos
(ErrNum_InvReg
, pComp
);
return eSymbolSizeUnknown
;
}
static Boolean DecodeAdr
(const tStrComp
*pArg
, Word Mask
)
{
Boolean OK
;
tEvalResult EvalResult
;
char *p
;
int ForceLen
, l
;
tSymbolSize Size
;
if (!mIsSuper8
() && !mIsZ8Encore
())
Mask
&= ~MModIndRR
;
if (!mIsSuper8
())
Mask
&= ~MModIndRR16
;
if (!mIsZ8Encore
())
Mask
&= ~
(MModXReg
| MModWeird
);
AdrType
= ModNone
;
/* immediate ? */
if (*pArg
->str.
p_str == '#')
{
switch (OpSize
)
{
case eSymbolSize8Bit
:
AdrVal
= EvalStrIntExpressionOffs
(pArg
, 1, Int8
, &OK
);
break;
case eSymbolSize16Bit
:
AdrWVal
= EvalStrIntExpressionOffs
(pArg
, 1, Int16
, &OK
);
break;
default:
OK
= False
;
}
if (OK
) AdrType
= ModImm
;
return ChkAdr
(Mask
, pArg
);
}
/* Register ? */
switch (IsWRegOrWRReg
(pArg
, &AdrVal
, &Size
, False
))
{
case eIsReg
:
AdrType
= (Size
== eSymbolSize16Bit
) ? ModWRReg
: ModWReg
;
return ChkAdr
(Mask
, pArg
);
case eIsNoReg
:
break;
case eRegAbort
:
return False
;
}
/* treat absolute address as register? */
if (*pArg
->str.
p_str == '!')
{
AdrWVal
= EvalStrIntExpressionOffsWithResult
(pArg
, 1, UInt16
, &EvalResult
);
if (EvalResult.
OK)
{
if (!mFirstPassUnknown
(EvalResult.
Flags) && !IsWRegAddress
(AdrWVal
, &AdrVal
))
WrError
(ErrNum_InAccPage
);
AdrType
= ModWReg
;
return ChkAdr
(Mask
, pArg
);
}
return False
;
}
/* indirekte Konstrukte ? */
if (*pArg
->str.
p_str == '@')
{
tStrComp Comp
;
tRegEvalResult RegEvalResult
;
StrCompRefRight
(&Comp
, pArg
, 1);
if ((strlen(Comp.
str.
p_str) >= 6) && (!as_strncasecmp
(Comp.
str.
p_str, ".RR", 3)) && (IsIndirect
(Comp.
str.
p_str + 3)))
{
AdrVal
= EvalStrIntExpressionOffsWithResult
(&Comp
, 3, Int8
, &EvalResult
);
if (EvalResult.
OK)
{
AdrType
= ModWeird
;
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
}
else if ((RegEvalResult
= IsWRegOrWRReg
(&Comp
, &AdrVal
, &Size
, False
)) != eIsNoReg
)
{
if (RegEvalResult
== eRegAbort
)
return False
;
AdrType
= (Size
== eSymbolSize16Bit
) ? ModIWRReg
: ModIWReg
;
}
else
{
/* Trying to do a working register optimization at this place is
extremely tricky since an expression like @<address> has no
inherent operand size (8/16 bit). So the optimization IRR->Irr
will only be allowed if IR is not allowed, or Irr is the only
mode allowed: */
Word ModeMask
= Mask
& (MModIRReg
| MModIWRReg
| MModIReg
| MModIWReg
);
if (ModeMask
== (MModIWReg
| MModIWRReg
))
{
WrStrErrorPos
(ErrNum_UndefRegSize
, &Comp
);
return False
;
}
AdrWVal
= EvalStrIntExpressionOffsWithResult
(&Comp
, ForceLen
= GetForceLen
(pArg
->str.
p_str), Int8
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
if (!(ModeMask
& MModIReg
) || (ModeMask
== MModIWRReg
))
{
if (mFirstPassUnknown
(EvalResult.
Flags)) AdrWVal
&= ~
1;
if (AdrWVal
& 1) WrStrErrorPos
(ErrNum_AddrMustBeEven
, &Comp
);
else if ((Mask
& MModIWRReg
) && (ForceLen
<= 0) && IsWRegAddress
(AdrWVal
, &AdrVal
))
AdrType
= ModIWRReg
;
else
{
AdrVal
= AdrWVal
;
AdrType
= ModIRReg
;
}
}
else
{
if ((Mask
& MModIWReg
) && (ForceLen
<= 0) && IsWRegAddress
(AdrWVal
, &AdrVal
))
AdrType
= ModIWReg
;
else
{
AdrVal
= AdrWVal
;
AdrType
= ModIReg
;
}
}
}
}
return ChkAdr
(Mask
, pArg
);
}
/* indiziert ? */
l
= strlen(pArg
->str.
p_str);
if ((l
> 4) && (pArg
->str.
p_str[l
- 1] == ')'))
{
tStrComp Left
, Right
;
StrCompRefRight
(&Right
, pArg
, 0);
StrCompShorten
(&Right
, 1);
p
= RQuotPos
(pArg
->str.
p_str, '(');
if (!p
)
{
WrStrErrorPos
(ErrNum_BrackErr
, pArg
);
return False
;
}
StrCompSplitRef
(&Left
, &Right
, &Right
, p
);
switch (IsWRegWithRP
(&Right
, &AdrVal
, Mask
& (MModIndRR
| MModIndRR16
), Mask
& MModInd
))
{
case eSymbolSize8Bit
:
/* We are operating on a single base register and therefore in a 8-bit address space.
So we may allow both a signed or unsigned displacements since addresses will wrap
around anyway: */
AdrIndex
= EvalStrIntExpressionWithResult
(&Left
, Int8
, &EvalResult
);
if (EvalResult.
OK)
{
AdrType
= ModInd
; ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
return ChkAdr
(Mask
, pArg
);
case eSymbolSize16Bit
:
/* 16 bit index only allowed if index register is not zero */
AdrIndex
= EvalStrIntExpressionWithResult
(&Left
, ((Mask
& MModIndRR16
) && (AdrVal
!= 0)) ? Int16
: SInt8
, &EvalResult
);
if (EvalResult.
OK)
{
if ((Mask
& MModIndRR
) && RangeCheck
(AdrIndex
, SInt8
))
AdrType
= ModIndRR
;
else
AdrType
= ModIndRR16
;
/* TODO: differentiate LDC/LDE */
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
return ChkAdr
(Mask
, pArg
);
default:
return False
;
}
}
/* simple direct address ? */
AdrWVal
= EvalStrIntExpressionOffsWithResult
(pArg
, ForceLen
= GetForceLen
(pArg
->str.
p_str),
(Mask
& MModDA
) ? UInt16
: RegSpaceType
, &EvalResult
);
if (EvalResult.
OK)
{
if (Mask
& MModDA
)
{
AdrType
= ModDA
;
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
}
else
{
if (mFirstPassUnknown
(EvalResult.
Flags) && !(Mask
& ModXReg
))
AdrWVal
= Lo
(AdrWVal
) | ((RPVal
& 15) << 8);
if (IsWRegAddress
(AdrWVal
, &AdrVal
) && (Mask
& MModWReg
) && (ForceLen
<= 0))
{
AdrType
= ModWReg
;
}
else if (IsRegAddress
(AdrWVal
) && (Mask
& (MModReg
| MModRReg
)) && (ForceLen
<= 1))
{
if (Mask
& MModRReg
)
{
if (mFirstPassUnknown
(EvalResult.
Flags))
AdrWVal
&= ~
1;
if (AdrWVal
& 1)
{
WrStrErrorPos
(ErrNum_AddrMustBeEven
, pArg
);
return False
;
}
AdrType
= ModRReg
;
}
else
AdrType
= ModReg
;
AdrVal
= Lo
(AdrWVal
);
}
else
AdrType
= ModXReg
;
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
}
return ChkAdr
(Mask
, pArg
);
}
else
return False
;
}
static int DecodeCond
(const tStrComp
*pArg
)
{
int z
;
NLS_UpString
(pArg
->str.
p_str);
for (z
= 0; z
< CondCnt
; z
++)
if (strcmp(Conditions
[z
].
Name, pArg
->str.
p_str) == 0)
break;
if (z
>= CondCnt
)
WrStrErrorPos
(ErrNum_UndefCond
, pArg
);
return z
;
}
static Boolean ChkCoreFlags
(tCoreFlags CoreFlags
)
{
if (pCurrCPUProps
->CoreFlags
& CoreFlags
)
return True
;
WrStrErrorPos
(ErrNum_InstructionNotSupported
, &OpPart
);
return False
;
}
/*--------------------------------------------------------------------------*/
/* Bit Symbol Handling */
/*
* Compact representation of bits and bit fields in symbol table:
* bits 0..2: (start) bit position
* bits 3...10/14: register address in SFR space (256B/4KB)
*/
/*!------------------------------------------------------------------------
* \fn EvalBitPosition(const char *pBitArg, Boolean *pOK, ShortInt OpSize)
* \brief evaluate constant bit position, with bit range depending on operand size
* \param pBitArg bit position argument
* \param pOK returns True if OK
* \param OpSize operand size (0 -> 8 bits)
* \return bit position as number
* ------------------------------------------------------------------------ */
static Byte EvalBitPosition
(const tStrComp
*pBitArg
, Boolean
*pOK
, ShortInt OpSize
)
{
switch (OpSize
)
{
case eSymbolSize8Bit
:
return EvalStrIntExpressionOffs
(pBitArg
, !!(*pBitArg
->str.
p_str == '#'), UInt3
, pOK
);
default:
WrStrErrorPos
(ErrNum_InvOpSize
, pBitArg
);
*pOK
= False
;
return 0;
}
}
/*!------------------------------------------------------------------------
* \fn AssembleBitSymbol(Byte BitPos, ShortInt OpSize, Word Address)
* \brief build the compact internal representation of a bit field symbol
* \param BitPos bit position in word
* \param Width width of bit field
* \param OpSize operand size (0..2)
* \param Address register address
* \return compact representation
* ------------------------------------------------------------------------ */
static LongWord AssembleBitSymbol
(Byte BitPos
, ShortInt OpSize
, Word Address
)
{
UNUSED
(OpSize
);
return BitPos
| (((LongWord
)Address
& 0xfff) << 3);
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, ShortInt OpSize)
* \brief encode a bit symbol, address & bit position separated
* \param pResult resulting encoded bit
* \param pRegArg register argument
* \param pBitArg bit argument
* \param OpSize register size (0 = 8 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg2
(LongWord
*pResult
, const tStrComp
*pRegArg
, const tStrComp
*pBitArg
, ShortInt OpSize
)
{
Boolean OK
;
LongWord Addr
;
Byte BitPos
;
BitPos
= EvalBitPosition
(pBitArg
, &OK
, OpSize
);
if (!OK
)
return False
;
/* all I/O registers reside in the first 256/4K byte of the address space */
DecodeAdr
(pRegArg
, MModWReg
| (mIsZ8Encore
() ? MModXReg
: MModReg
));
switch (AdrType
)
{
case ModXReg
:
Addr
= AdrWVal
;
break;
case ModWReg
:
Addr
= AdrVal
+ pCurrCPUProps
->WorkOfs
;
break;
case ModReg
:
Addr
= AdrVal
;
break;
default:
return False
;
}
*pResult
= AssembleBitSymbol
(BitPos
, OpSize
, Addr
);
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg(LongWord *pResult, int Start, int Stop, ShortInt OpSize)
* \brief encode a bit symbol from instruction argument(s)
* \param pResult resulting encoded bit
* \param Start first argument
* \param Stop last argument
* \param OpSize register size (0 = 8 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg
(LongWord
*pResult
, int Start
, int Stop
, ShortInt OpSize
)
{
*pResult
= 0;
/* Just one argument -> parse as bit argument */
if (Start
== Stop
)
{
tEvalResult EvalResult
;
*pResult
= EvalStrIntExpressionWithResult
(&ArgStr
[Start
],
mIsZ8Encore
() ? UInt15
: UInt11
,
&EvalResult
);
if (EvalResult.
OK)
ChkSpace
(SegBData
, EvalResult.
AddrSpaceMask);
return EvalResult.
OK;
}
/* register & bit position are given as separate arguments */
else if (Stop
== Start
+ 1)
return DecodeBitArg2
(pResult
, &ArgStr
[Start
], &ArgStr
[Stop
], OpSize
);
/* other # of arguments not allowed */
else
{
WrError
(ErrNum_WrongArgCnt
);
return False
;
}
}
/*!------------------------------------------------------------------------
* \fn ExpandZ8Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
* \brief expands bit definition when a structure is instantiated
* \param pVarName desired symbol name
* \param pStructElem element definition
* \param Base base address of instantiated structure
* ------------------------------------------------------------------------ */
static void ExpandZ8Bit
(const tStrComp
*pVarName
, const struct sStructElem
*pStructElem
, LargeWord Base
)
{
LongWord Address
= Base
+ pStructElem
->Offset
;
if (pInnermostNamedStruct
)
{
PStructElem pElem
= CloneStructElem
(pVarName
, pStructElem
);
if (!pElem
)
return;
pElem
->Offset
= Address
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElem
);
}
else
{
if (!ChkRange
(Address
, 0, 0x7ff)
|| !ChkRange
(pStructElem
->BitPos
, 0, 7))
return;
PushLocHandle
(-1);
EnterIntSymbol
(pVarName
, AssembleBitSymbol
(pStructElem
->BitPos
, eSymbolSize8Bit
, Address
), SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
/*!------------------------------------------------------------------------
* \fn DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos, ShortInt *pOpSize)
* \brief transform compact represenation of bit (field) symbol into components
* \param BitSymbol compact storage
* \param pAddress (I/O) register address
* \param pBitPos (start) bit position
* \param pWidth pWidth width of bit field, always one for individual bit
* \param pOpSize returns register size (0 for 8 bits)
* \return constant True
* ------------------------------------------------------------------------ */
static Boolean DissectBitSymbol
(LongWord BitSymbol
, Word
*pAddress
, Byte
*pBitPos
, ShortInt
*pOpSize
)
{
*pAddress
= (BitSymbol
>> 3) & 0xfff;
*pBitPos
= BitSymbol
& 7;
*pOpSize
= eSymbolSize8Bit
;
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeWRBitArg(int StartArg, int EndArg, Byte *pResult)
* \brief decode bit argument in working register
* \param StartArg 1st argument
* \param EndArg last argument
* \param pResult resulting encoded bit
* \return TRUE if successfully decoded
* ------------------------------------------------------------------------ */
static Boolean DecodeWRBitArg
(int StartArg
, int EndArg
, Byte
*pResult
)
{
LongWord Result
;
Word Address
;
Byte BitPos
;
ShortInt OpSize
;
if (!DecodeBitArg
(&Result
, StartArg
, EndArg
, eSymbolSize8Bit
))
return False
;
(void)DissectBitSymbol
(Result
, &Address
, &BitPos
, &OpSize
);
if ((Address
< pCurrCPUProps
->WorkOfs
) || (Address
>= pCurrCPUProps
->WorkOfs
+ 16))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[StartArg
]);
return False
;
}
*pResult
= ((Address
& 15) << 3) | BitPos
;
return True
;
}
/*!------------------------------------------------------------------------
* \fn DissectBit_Z8(char *pDest, size_t DestSize, LargeWord Inp)
* \brief dissect compact storage of bit (field) into readable form for listing
* \param pDest destination for ASCII representation
* \param DestSize destination buffer size
* \param Inp compact storage
* ------------------------------------------------------------------------ */
static void DissectBit_Z8
(char *pDest
, size_t DestSize
, LargeWord Inp
)
{
Byte BitPos
;
Word Address
;
ShortInt OpSize
;
DissectBitSymbol
(Inp
, &Address
, &BitPos
, &OpSize
);
UNUSED
(OpSize
);
UNUSED
(DestSize
);
if ((Address
>= pCurrCPUProps
->WorkOfs
) && (Address
<= pCurrCPUProps
->WorkOfs
+ 15))
as_snprintf
(pDest
, DestSize
, "%c%u", HexStartCharacter
+ ('r' - 'a'), (unsigned)(Address
& 15));
else
SysString
(pDest
, DestSize
, Address
, ListRadixBase
,
mIsZ8Encore
() ? 3 : 2, (16 == ListRadixBase
) && (IntConstMode
== eIntConstModeIntel
),
HexStartCharacter
, SplitByteCharacter
);
as_snprcatf
(pDest
, DestSize
, ".%u", (unsigned)BitPos
);
}
/*--------------------------------------------------------------------------*/
/* Instruction Decoders */
static void DecodeFixed
(Word Index
)
{
BaseOrder
*pOrder
= FixedOrders
+ Index
;
if (ChkArgCnt
(0, 0)
&& ChkCoreFlags
(pOrder
->CoreFlags
))
{
CodeLen
= 1;
BAsmCode
[0] = pOrder
->Code
;
}
}
static void DecodeALU2
(Word Index
)
{
BaseOrder
*pOrder
= ALU2Orders
+ Index
;
Byte Save
;
int l
= 0;
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(pOrder
->CoreFlags
))
{
if (Hi
(pOrder
->Code
))
BAsmCode
[l
++] = Hi
(pOrder
->Code
);
DecodeAdr
(&ArgStr
[1], MModReg
| MModWReg
| ((pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0 : MModIReg
));
switch (AdrType
)
{
case ModReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg
| MModImm
);
switch (AdrType
)
{
case ModReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 4;
BAsmCode
[l
++] = AdrVal
;
BAsmCode
[l
++] = Save
;
CodeLen
= l
;
break;
case ModIReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 5;
BAsmCode
[l
++] = AdrVal
;
BAsmCode
[l
++] = Save
;
CodeLen
= l
;
break;
case ModImm
:
BAsmCode
[l
++] = pOrder
->Code
+ 6;
BAsmCode
[l
++] = Save
;
BAsmCode
[l
++] = AdrVal
;
CodeLen
= l
;
break;
}
break;
case ModWReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
| MModReg
| MModIWReg
| MModIReg
| MModImm
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 2;
BAsmCode
[l
++] = (Save
<< 4) + AdrVal
;
CodeLen
= l
;
break;
case ModReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 4;
BAsmCode
[l
++] = AdrVal
;
BAsmCode
[l
++] = pCurrCPUProps
->WorkOfs
+ Save
;
CodeLen
= l
;
break;
case ModIWReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 3;
BAsmCode
[l
++] = (Save
<< 4) + AdrVal
;
CodeLen
= l
;
break;
case ModIReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 5;
BAsmCode
[l
++] = AdrVal
;
BAsmCode
[l
++] = pCurrCPUProps
->WorkOfs
+ Save
;
CodeLen
= l
;
break;
case ModImm
:
BAsmCode
[l
++] = pOrder
->Code
+ 6;
BAsmCode
[l
++] = Save
+ pCurrCPUProps
->WorkOfs
;
BAsmCode
[l
++] = AdrVal
;
CodeLen
= l
;
break;
}
break;
case ModIReg
:
Save
= AdrVal
;
if (DecodeAdr
(&ArgStr
[2], MModImm
))
{
BAsmCode
[l
++] = pOrder
->Code
+ 7;
BAsmCode
[l
++] = Save
;
BAsmCode
[l
++] = AdrVal
;
CodeLen
= l
;
}
break;
}
}
}
static void DecodeALUX
(Word Index
)
{
BaseOrder
*pOrder
= ALUXOrders
+ Index
;
int l
= 0;
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(pOrder
->CoreFlags
))
{
if (Hi
(pOrder
->Code
))
BAsmCode
[l
++] = Hi
(pOrder
->Code
);
if (DecodeAdr
(&ArgStr
[1], MModXReg
))
{
BAsmCode
[l
+ 3] = Lo
(AdrWVal
);
BAsmCode
[l
+ 2] = Hi
(AdrWVal
) & 15;
DecodeAdr
(&ArgStr
[2], MModXReg
| MModImm
);
switch (AdrType
)
{
case ModXReg
:
BAsmCode
[l
+ 0] = pOrder
->Code
;
BAsmCode
[l
+ 1] = AdrWVal
>> 4;
BAsmCode
[l
+ 2] |= (AdrWVal
& 15) << 4;
CodeLen
= l
+ 4;
break;
case ModImm
:
BAsmCode
[l
+ 0] = pOrder
->Code
+ 1;
BAsmCode
[l
+ 1] = AdrVal
;
CodeLen
= l
+ 4;
break;
}
}
}
}
static void DecodeALU1
(Word Index
)
{
ALU1Order
*pOrder
= ALU1Orders
+ Index
;
int l
= 0;
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(pOrder
->CoreFlags
))
{
if (Hi
(pOrder
->Code
))
BAsmCode
[l
++] = Hi
(pOrder
->Code
);
DecodeAdr
(&ArgStr
[1], (pOrder
->Is16
? (MModWRReg
| MModRReg
) : MModReg
) | MModIReg
);
switch (AdrType
)
{
case ModReg
:
case ModRReg
:
BAsmCode
[l
++] = pOrder
->Code
;
BAsmCode
[l
++] = AdrVal
;
CodeLen
= l
;
break;
case ModWRReg
:
BAsmCode
[l
++] = pOrder
->Code
;
BAsmCode
[l
++] = pCurrCPUProps
->WorkOfs
+ AdrVal
;
CodeLen
= l
;
break;
case ModIReg
:
BAsmCode
[l
++] = pOrder
->Code
+ 1;
BAsmCode
[l
++] = AdrVal
;
CodeLen
= l
;
break;
}
}
}
static void DecodeLD
(Word Index
)
{
Word Save
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModReg
| MModWReg
| MModIReg
| MModIWReg
| MModInd
);
switch (AdrType
)
{
case ModReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModReg
| MModWReg
| MModIReg
| MModImm
);
switch (AdrType
)
{
case ModReg
: /* Super8 OK */
BAsmCode
[0] = 0xe4;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
case ModWReg
:
if (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
)
{
BAsmCode
[0] = 0xe4;
BAsmCode
[1] = AdrVal
+ pCurrCPUProps
->WorkOfs
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
}
else /** non-eZ8 **/ /* Super8 OK */
{
BAsmCode
[0] = (AdrVal
<< 4) + 9;
BAsmCode
[1] = Save
;
CodeLen
= 2;
}
break;
case ModIReg
: /* Super8 OK */
BAsmCode
[0] = 0xe5;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
case ModImm
: /* Super8 OK */
BAsmCode
[0] = 0xe6;
BAsmCode
[1] = Save
;
BAsmCode
[2] = AdrVal
;
CodeLen
= 3;
break;
}
break;
case ModWReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
| MModReg
| MModIWReg
| MModIReg
| MModImm
| MModInd
);
switch (AdrType
)
{
case ModWReg
:
if (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
)
{
BAsmCode
[0] = 0xe4;
BAsmCode
[1] = AdrVal
+ pCurrCPUProps
->WorkOfs
;
BAsmCode
[2] = Save
+ pCurrCPUProps
->WorkOfs
;
CodeLen
= 3;
}
else /** non-eZ8 */ /* Super8 OK */
{
BAsmCode
[0] = (Save
<< 4) + 8;
BAsmCode
[1] = AdrVal
+ pCurrCPUProps
->WorkOfs
;
CodeLen
= 2;
}
break;
case ModReg
:
if (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
)
{
BAsmCode
[0] = 0xe4;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
+ pCurrCPUProps
->WorkOfs
;
CodeLen
= 3;
}
else /** non-eZ8 **/ /* Super8 OK */
{
BAsmCode
[0] = (Save
<< 4) + 8;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
}
break;
case ModIWReg
:
/* is C7 r,IR or r,ir? */
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0xc7 : 0xe3;
BAsmCode
[1] = (Save
<< 4) + AdrVal
;
CodeLen
= 2;
break;
case ModIReg
: /* Super8 OK */
BAsmCode
[0] = 0xe5;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = pCurrCPUProps
->WorkOfs
+ Save
;
CodeLen
= 3;
break;
case ModImm
: /* Super8 OK */
BAsmCode
[0] = (Save
<< 4) + 12;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModInd
:
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0x87 : 0xc7;
BAsmCode
[1] = (Save
<< 4) + AdrVal
;
BAsmCode
[2] = AdrIndex
;
CodeLen
= 3;
break;
}
break;
case ModIReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModReg
| MModImm
);
switch (AdrType
)
{
case ModReg
: /* Super8 OK */
BAsmCode
[0] = 0xf5;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
case ModImm
:
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0xd6 : 0xe7;
BAsmCode
[1] = Save
;
BAsmCode
[2] = AdrVal
;
CodeLen
= 3;
break;
}
break;
case ModIWReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
| MModReg
| MModImm
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0xd7 : 0xf3;
BAsmCode
[1] = (Save
<< 4) + AdrVal
;
CodeLen
= 2;
break;
case ModReg
: /* Super8 OK */
BAsmCode
[0] = 0xf5;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = pCurrCPUProps
->WorkOfs
+ Save
;
CodeLen
= 3;
break;
case ModImm
:
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0xd6 : 0xe7;
BAsmCode
[1] = pCurrCPUProps
->WorkOfs
+ Save
;
BAsmCode
[2] = AdrVal
;
CodeLen
= 3;
break;
}
break;
case ModInd
:
Save
= AdrVal
;
if (DecodeAdr
(&ArgStr
[2], MModWReg
))
{
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreSuper8
) ? 0x97 : 0xd7;
BAsmCode
[1] = (AdrVal
<< 4) + Save
;
BAsmCode
[2] = AdrIndex
;
CodeLen
= 3;
}
break;
}
}
}
static void DecodeLDCE
(Word Code
)
{
Byte Save
, Super8Add
= mIsSuper8
() && !!(Code
== 0x82);
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
))
{
LongWord DestMask
= MModWReg
| MModIWRReg
, SrcMask
;
if ((pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
) && (Code
== 0xc2))
DestMask
|= MModIWReg
;
if (mIsSuper8
())
DestMask
|= MModIndRR
| MModIndRR16
| MModDA
;
DecodeAdr
(&ArgStr
[1], DestMask
);
switch (AdrType
)
{
case ModWReg
:
SrcMask
= MModIWRReg
;
if (pCurrCPUProps
->CoreFlags
& eCoreSuper8
)
SrcMask
|= MModIndRR
| MModIndRR16
| MModDA
;
Save
= AdrVal
; DecodeAdr
(&ArgStr
[2], SrcMask
);
switch (AdrType
)
{
case ModIWRReg
:
BAsmCode
[0] = mIsSuper8
() ? 0xc3 : Code
;
BAsmCode
[1] = (Save
<< 4) | AdrVal
| Super8Add
;
CodeLen
= 2;
break;
case ModDA
:
BAsmCode
[0] = 0xa7;
BAsmCode
[1] = (Save
<< 4) | Super8Add
;
BAsmCode
[2] = Lo
(AdrWVal
);
BAsmCode
[3] = Hi
(AdrWVal
);
CodeLen
= 4;
break;
case ModIndRR
:
BAsmCode
[0] = 0xe7;
BAsmCode
[1] = (Save
<< 4) | AdrVal
| Super8Add
;
BAsmCode
[2] = Lo
(AdrIndex
);
CodeLen
= 3;
break;
case ModIndRR16
:
BAsmCode
[0] = 0xa7;
BAsmCode
[1] = (Save
<< 4) | AdrVal
| Super8Add
;
BAsmCode
[2] = Lo
(AdrIndex
);
BAsmCode
[3] = Hi
(AdrIndex
);
CodeLen
= 4;
break;
}
break;
case ModIWReg
:
Save
= AdrVal
; DecodeAdr
(&ArgStr
[2], MModIWRReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0xc5;
BAsmCode
[1] = (Save
<< 4) | AdrVal
;
CodeLen
= 2;
}
break;
case ModIWRReg
:
Save
= AdrVal
; DecodeAdr
(&ArgStr
[2], MModWReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = mIsSuper8
() ? 0xd3 : Code
+ 0x10;
BAsmCode
[1] = (AdrVal
<< 4) | Save
| Super8Add
;
CodeLen
= 2;
}
break;
case ModDA
: /* Super8 only */
BAsmCode
[2] = Lo
(AdrWVal
);
BAsmCode
[3] = Hi
(AdrWVal
);
DecodeAdr
(&ArgStr
[2], MModWReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0xb7;
BAsmCode
[1] = (AdrVal
<< 4) | Super8Add
;
CodeLen
= 4;
}
break;
case ModIndRR
: /* Super8 only */
BAsmCode
[2] = Lo
(AdrIndex
);
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0xf7;
BAsmCode
[1] = (AdrVal
<< 4) | Save
| Super8Add
;
CodeLen
= 3;
}
break;
case ModIndRR16
: /* Super8 only */
BAsmCode
[2] = Lo
(AdrIndex
);
BAsmCode
[3] = Hi
(AdrIndex
);
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0xb7;
BAsmCode
[1] = (AdrVal
<< 4) | Save
| Super8Add
;
CodeLen
= 4;
}
break;
}
}
}
static void DecodeLDCEI
(Word Index
)
{
Byte Save
;
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModIWReg
| MModIWRReg
);
switch (AdrType
)
{
case ModIWReg
:
Save
= AdrVal
; DecodeAdr
(&ArgStr
[2], MModIWRReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = Index
;
BAsmCode
[1] = (Save
<< 4) + AdrVal
;
CodeLen
= 2;
}
break;
case ModIWRReg
:
Save
= AdrVal
; DecodeAdr
(&ArgStr
[2], MModIWReg
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = Index
+ 0x10;
BAsmCode
[1] = (AdrVal
<< 4) + Save
;
CodeLen
= 2;
}
break;
}
}
}
static void DecodeLDCEDI
(Word Code
)
{
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreSuper8
)
&& DecodeAdr
(&ArgStr
[1], MModWReg
))
{
BAsmCode
[0] = Lo
(Code
);
BAsmCode
[1] = AdrVal
<< 4;
DecodeAdr
(&ArgStr
[2], MModIWRReg
);
if (AdrType
== ModIWRReg
)
{
BAsmCode
[1] |= AdrVal
| Hi
(Code
);
CodeLen
= 2;
}
}
}
static void DecodeLDCEPDI
(Word Code
)
{
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreSuper8
)
&& DecodeAdr
(&ArgStr
[1], MModIWRReg
))
{
BAsmCode
[0] = Lo
(Code
);
BAsmCode
[1] = AdrVal
| Hi
(Code
);
DecodeAdr
(&ArgStr
[2], MModWReg
);
if (AdrType
== ModWReg
)
{
BAsmCode
[1] |= AdrVal
<< 4;
CodeLen
= 2;
}
}
}
static void DecodeINC
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModWReg
| MModReg
| MModIReg
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = (AdrVal
<< 4) + 0x0e;
CodeLen
= 1;
break;
case ModReg
:
BAsmCode
[0] = 0x20;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModIReg
:
BAsmCode
[0] = 0x21;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
static void DecodeJR
(Word Index
)
{
Integer AdrInt
;
int z
;
tEvalResult EvalResult
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 2)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
))
{
z
= (ArgCnt
== 1) ? TrueCond
: DecodeCond
(&ArgStr
[1]);
if (z
< CondCnt
)
{
AdrInt
= EvalStrIntExpressionWithResult
(&ArgStr
[ArgCnt
], Int16
, &EvalResult
) - (EProgCounter
() + 2);
if (EvalResult.
OK)
{
if (!mSymbolQuestionable
(EvalResult.
Flags)
&& ((AdrInt
> 127) || (AdrInt
< -128))) WrError
(ErrNum_JmpDistTooBig
);
else
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
BAsmCode
[0] = (Conditions
[z
].
Code << 4) + 0x0b;
BAsmCode
[1] = Lo
(AdrInt
);
CodeLen
= 2;
}
}
}
}
}
static void DecodeDJNZ
(Word Index
)
{
Integer AdrInt
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
)
&& DecodeAdr
(&ArgStr
[1], MModWReg
))
{
AdrInt
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], Int16
, &OK
, &Flags
) - (EProgCounter
() + 2);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
)
&& ((AdrInt
> 127) || (AdrInt
< -128))) WrError
(ErrNum_JmpDistTooBig
);
else
{
BAsmCode
[0] = (AdrVal
<< 4) + 0x0a;
BAsmCode
[1] = Lo
(AdrInt
);
CodeLen
= 2;
}
}
}
}
static void DecodeCPIJNE
(Word Code
)
{
if (ChkArgCnt
(3, 3)
&& ChkCoreFlags
(eCoreSuper8
)
&& DecodeAdr
(&ArgStr
[1], MModWReg
))
{
BAsmCode
[1] = AdrVal
& 0x0f;
DecodeAdr
(&ArgStr
[2], MModIWReg
);
if (AdrType
!= ModNone
)
{
Boolean OK
;
tSymbolFlags Flags
;
Integer AdrInt
= EvalStrIntExpressionWithFlags
(&ArgStr
[3], Int16
, &OK
, &Flags
) - (EProgCounter
() + 3);
BAsmCode
[1] |= AdrVal
<< 4;
if (OK
)
{
if (!mSymbolQuestionable
(Flags
)
&& ((AdrInt
> 127) || (AdrInt
< -128))) WrError
(ErrNum_JmpDistTooBig
);
else
{
BAsmCode
[0] = Code
;
BAsmCode
[2] = Lo
(AdrInt
);
CodeLen
= 3;
}
}
}
}
}
static void DecodeCALL
(Word Index
)
{
Boolean IsSuper8
= !!(pCurrCPUProps
->CoreFlags
& eCoreSuper8
);
UNUSED
(Index
);
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModIWRReg
| MModIRReg
| MModDA
| (IsSuper8
? MModImm
: 0));
switch (AdrType
)
{
case ModIWRReg
:
BAsmCode
[0] = IsSuper8
? 0xf4 : 0xd4;
BAsmCode
[1] = pCurrCPUProps
->WorkOfs
+ AdrVal
;
CodeLen
= 2;
break;
case ModIRReg
:
BAsmCode
[0] = IsSuper8
? 0xf4 : 0xd4;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
case ModDA
:
BAsmCode
[0] = IsSuper8
? 0xf6 : 0xd6;
BAsmCode
[1] = Hi
(AdrWVal
);
BAsmCode
[2] = Lo
(AdrWVal
);
CodeLen
= 3;
break;
case ModImm
:
BAsmCode
[0] = 0xd4;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
static void DecodeJP
(Word Index
)
{
int z
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 2)
&& ChkCoreFlags
(eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
))
{
z
= (ArgCnt
== 1) ? TrueCond
: DecodeCond
(&ArgStr
[1]);
if (z
< CondCnt
)
{
DecodeAdr
(&ArgStr
[ArgCnt
], MModIWRReg
| MModIRReg
| MModDA
);
switch (AdrType
)
{
case ModIWRReg
:
if (z
!= TrueCond
) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
) ? 0xc4 : 0x30;
BAsmCode
[1] = pCurrCPUProps
->WorkOfs
+ AdrVal
;
CodeLen
= 2;
}
break;
case ModIRReg
:
if (z
!= TrueCond
) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
) ? 0xc4 : 0x30;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
}
break;
case ModDA
:
BAsmCode
[0] = (Conditions
[z
].
Code << 4) + 0x0d;
BAsmCode
[1] = Hi
(AdrWVal
);
BAsmCode
[2] = Lo
(AdrWVal
);
CodeLen
= 3;
break;
}
}
}
}
static void DecodeSRP
(Word Code
)
{
Boolean Valid
;
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
((Hi
(Code
) ? eCoreNone
: (eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreZ8Encore
)) | eCoreSuper8
)
&& DecodeAdr
(&ArgStr
[1], MModImm
))
{
if (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
|| Memo
("RDR"))
Valid
= True
;
else
{
Byte MuteMask
= Hi
(Code
) ? 7 : 15;
Valid
= (((AdrVal
& MuteMask
) == 0) && ((AdrVal
<= pCurrCPUProps
->RAMEnd
) || (AdrVal
>= pCurrCPUProps
->SFRStart
)));
}
if (!Valid
) WrError
(ErrNum_InvRegisterPointer
);
BAsmCode
[0] = (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
) ? 0x01 : Lo
(Code
);
BAsmCode
[1] = AdrVal
| Hi
(Code
);
CodeLen
= 2;
}
}
static void DecodeStackExt
(Word Index
)
{
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(eCoreZ8Encore
)
&& DecodeAdr
(&ArgStr
[1], MModXReg
))
{
BAsmCode
[0] = Index
;
BAsmCode
[1] = AdrWVal
>> 4;
BAsmCode
[2] = (AdrWVal
& 15) << 4;
CodeLen
= 3;
}
}
static void DecodeStackDI
(Word Code
)
{
int MemIdx
= ((Code
>> 4) & 15) - 7;
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreSuper8
))
{
Byte Reg
;
DecodeAdr
(&ArgStr
[3 - MemIdx
], MModReg
| MModWReg
);
Reg
= (AdrType
== ModWReg
) ? AdrVal
+ pCurrCPUProps
->WorkOfs
: AdrVal
;
if (AdrType
!= ModNone
)
{
DecodeAdr
(&ArgStr
[MemIdx
], MModIReg
| MModIWReg
);
if (AdrType
== ModIWReg
)
AdrVal
+= pCurrCPUProps
->WorkOfs
;
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = Code
;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Reg
;
CodeLen
= 3;
}
}
}
}
static void DecodeTRAP
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(eCoreZ8Encore
)
&& DecodeAdr
(&ArgStr
[1], MModImm
))
{
BAsmCode
[0] = 0xf2;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
}
}
static void DecodeBSWAP
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(eCoreZ8Encore
)
&& DecodeAdr
(&ArgStr
[1], MModReg
))
{
BAsmCode
[0] = 0xd5;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
}
}
static void DecodeMULT
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(1, 1)
&& ChkCoreFlags
(eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModWRReg
| MModReg
);
switch (AdrType
)
{
case ModWRReg
:
BAsmCode
[0] = 0xf4;
BAsmCode
[1] = AdrVal
+ pCurrCPUProps
->WorkOfs
;
CodeLen
= 2;
break;
case ModReg
:
BAsmCode
[0] = 0xf4;
BAsmCode
[1] = AdrVal
;
CodeLen
= 2;
break;
}
}
}
static void DecodeMULT_DIV
(Word Code
)
{
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreSuper8
)
&& DecodeAdr
(&ArgStr
[1], MModWRReg
| MModRReg
))
{
BAsmCode
[2] = (AdrType
== ModWRReg
) ? AdrVal
+ pCurrCPUProps
->WorkOfs
: AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
| MModReg
| MModIReg
| MModImm
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = Code
;
BAsmCode
[1] = AdrVal
+ pCurrCPUProps
->WorkOfs
;
CodeLen
= 3;
break;
case ModReg
:
BAsmCode
[0] = Code
;
BAsmCode
[1] = AdrVal
;
CodeLen
= 3;
break;
case ModIReg
:
BAsmCode
[0] = Code
+ 1;
BAsmCode
[1] = AdrVal
;
CodeLen
= 3;
break;
case ModImm
:
BAsmCode
[0] = Code
+ 2;
BAsmCode
[1] = AdrVal
;
CodeLen
= 3;
break;
}
}
}
static void DecodeLDX
(Word Index
)
{
Word Save
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModWReg
| MModIWReg
| MModReg
| MModIReg
| MModIWRReg
| MModIndRR
| MModXReg
| MModWeird
);
switch (AdrType
)
{
case ModWReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModXReg
| MModIndRR
| MModImm
);
switch (AdrType
)
{
case ModXReg
:
Save
+= LongWorkOfs
;
BAsmCode
[0] = 0xe8;
BAsmCode
[1] = AdrWVal
>> 4;
BAsmCode
[2] = ((AdrWVal
& 15) << 4) | (Hi
(Save
) & 15);
BAsmCode
[3] = Lo
(Save
);
CodeLen
= 4;
break;
case ModIndRR
:
BAsmCode
[0] = 0x88;
BAsmCode
[1] = (Save
<< 4) | AdrVal
;
BAsmCode
[2] = AdrIndex
;
CodeLen
= 3;
break;
case ModImm
:
BAsmCode
[0] = 0xe9;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Hi
(LongWorkOfs
| Save
);
BAsmCode
[3] = Lo
(LongWorkOfs
| Save
);
CodeLen
= 4;
break;
}
break;
case ModIWReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModXReg
);
switch (AdrType
)
{
case ModXReg
:
BAsmCode
[0] = 0x85;
BAsmCode
[1] = (Save
<< 4) | (Hi
(AdrWVal
) & 15);
BAsmCode
[2] = Lo
(AdrWVal
);
CodeLen
= 3;
break;
}
break;
case ModReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModIReg
);
switch (AdrType
)
{
case ModIReg
:
BAsmCode
[0] = 0x86;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
}
break;
case ModIReg
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModReg
| MModWeird
);
switch (AdrType
)
{
case ModReg
:
BAsmCode
[0] = 0x96;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
case ModWeird
:
BAsmCode
[0] = 0x87;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
}
break;
case ModIWRReg
:
Save
= pCurrCPUProps
->WorkOfs
+ AdrVal
;
DecodeAdr
(&ArgStr
[2], MModReg
);
switch (AdrType
)
{
case ModReg
:
BAsmCode
[0] = 0x96;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
}
break;
case ModIndRR
:
BAsmCode
[2] = AdrIndex
;
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = 0x89;
BAsmCode
[1] = (Save
<< 4) | AdrVal
;
CodeLen
= 3;
break;
}
break;
case ModXReg
:
Save
= AdrWVal
;
DecodeAdr
(&ArgStr
[2], MModWReg
| MModIWReg
| MModXReg
| MModImm
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = 0x94;
BAsmCode
[1] = (AdrVal
<< 4) | (Hi
(Save
) & 15);
BAsmCode
[2] = Lo
(Save
);
CodeLen
= 3;
break;
case ModIWReg
:
BAsmCode
[0] = 0x95;
BAsmCode
[1] = (AdrVal
<< 4) | (Hi
(Save
) & 15);
BAsmCode
[2] = Lo
(Save
);
CodeLen
= 3;
break;
case ModXReg
:
BAsmCode
[0] = 0xe8;
BAsmCode
[1] = AdrWVal
>> 4;
BAsmCode
[2] = ((AdrWVal
& 15) << 4) | (Hi
(Save
) & 15);
BAsmCode
[3] = Lo
(Save
);
CodeLen
= 4;
break;
case ModImm
:
BAsmCode
[0] = 0xe9;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = (Hi
(Save
) & 15);
BAsmCode
[3] = Lo
(Save
);
CodeLen
= 4;
break;
}
break;
case ModWeird
:
Save
= AdrVal
;
DecodeAdr
(&ArgStr
[2], MModIReg
);
switch (AdrType
)
{
case ModIReg
:
BAsmCode
[0] = 0x97;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Save
;
CodeLen
= 3;
break;
}
break;
}
}
}
static void DecodeLDW
(Word Code
)
{
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreSuper8
))
{
DecodeAdr
(&ArgStr
[1], MModRReg
| MModWRReg
);
if (AdrType
!= ModNone
)
{
Byte Dest
= (AdrType
== ModRReg
) ? AdrVal
: AdrVal
+ pCurrCPUProps
->WorkOfs
;
OpSize
= eSymbolSize16Bit
;
DecodeAdr
(&ArgStr
[2], MModRReg
| MModWRReg
| MModIReg
| MModImm
);
switch (AdrType
)
{
case ModWRReg
:
case ModRReg
:
BAsmCode
[0] = Code
;
BAsmCode
[1] = (AdrType
== ModRReg
) ? AdrVal
: AdrVal
+ pCurrCPUProps
->WorkOfs
;
BAsmCode
[2] = Dest
;
CodeLen
= 3;
break;
case ModIReg
:
BAsmCode
[0] = Code
+ 1;
BAsmCode
[1] = AdrVal
;
BAsmCode
[2] = Dest
;
CodeLen
= 3;
break;
case ModImm
:
BAsmCode
[0] = Code
+ 2;
BAsmCode
[1] = Dest
;
BAsmCode
[2] = Hi
(AdrWVal
);
BAsmCode
[3] = Lo
(AdrWVal
);
CodeLen
= 4;
break;
}
}
}
}
static void DecodeLDWX
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8Encore
)
&& DecodeAdr
(&ArgStr
[1], MModXReg
))
{
BAsmCode
[0] = 0x1f;
BAsmCode
[1] = 0xe8;
BAsmCode
[3] = Hi
(AdrWVal
);
BAsmCode
[4] = Lo
(AdrWVal
);
if (DecodeAdr
(&ArgStr
[2], MModXReg
))
{
BAsmCode
[2] = AdrWVal
>> 4;
BAsmCode
[3] |= (AdrWVal
& 0x0f) << 4;
CodeLen
= 5;
}
}
}
static void DecodeLEA
(Word Index
)
{
Byte Save
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkCoreFlags
(eCoreZ8Encore
))
{
DecodeAdr
(&ArgStr
[1], MModWReg
| MModWRReg
);
switch (AdrType
)
{
case ModWReg
:
Save
= AdrVal
;
if (DecodeAdr
(&ArgStr
[2], MModInd
))
{
BAsmCode
[0] = 0x98;
BAsmCode
[1] = (Save
<< 4) | AdrVal
;
BAsmCode
[2] = AdrIndex
;
CodeLen
= 3;
}
break;
case ModWRReg
:
Save
= AdrVal
;
if (DecodeAdr
(&ArgStr
[2], MModIndRR
))
{
BAsmCode
[0] = 0x99;
BAsmCode
[1] = (Save
<< 4) | AdrVal
;
BAsmCode
[2] = AdrIndex
;
CodeLen
= 3;
}
break;
}
}
}
static void DecodeBIT
(Word Index
)
{
Boolean OK
;
UNUSED
(Index
);
if (ChkArgCnt
(3, 3)
&& ChkCoreFlags
(eCoreZ8Encore
))
{
BAsmCode
[1] = EvalStrIntExpression
(&ArgStr
[1], UInt1
, &OK
) << 7;
if (OK
)
{
BAsmCode
[1] |= EvalStrIntExpression
(&ArgStr
[2], UInt3
, &OK
) << 4;
if (OK
)
{
DecodeAdr
(&ArgStr
[3], MModWReg
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = 0xe2;
BAsmCode
[1] |= AdrVal
;
CodeLen
= 2;
break;
}
}
}
}
}
static void DecodeBit
(Word Index
)
{
Boolean OK
;
if (ChkCoreFlags
(eCoreZ8Encore
))
switch (ArgCnt
)
{
case 1:
{
LongWord BitArg
;
ShortInt OpSize
= eSymbolSize8Bit
;
if (DecodeBitArg
(&BitArg
, 1, 1, OpSize
))
{
Word Address
;
Byte BitPos
;
(void)DissectBitSymbol
(BitArg
, &Address
, &BitPos
, &OpSize
);
if ((Address
& 0xff0) == pCurrCPUProps
->WorkOfs
)
{
BAsmCode
[0] = 0xe2;
BAsmCode
[1] = Index
| (BitPos
<< 4) | (Address
& 15);
CodeLen
= 2;
}
else /* -> ANDX,ORX ER,IM */
{
BAsmCode
[0] = Index
? 0x49 : 0x59;
BAsmCode
[1] = Index
? (1 << BitPos
) : ~
(1 << BitPos
);
BAsmCode
[2] = Hi
(Address
);
BAsmCode
[3] = Lo
(Address
);
CodeLen
= 4;
}
}
break;
}
case 2:
BAsmCode
[1] = EvalStrIntExpression
(&ArgStr
[1], UInt3
, &OK
);
if (OK
)
{
DecodeAdr
(&ArgStr
[2], MModWReg
| MModXReg
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = 0xe2;
BAsmCode
[1] = (BAsmCode
[1] << 4) | Index
| AdrVal
;
CodeLen
= 2;
break;
case ModXReg
: /* -> ANDX,ORX ER,IM */
BAsmCode
[0] = Index
? 0x49 : 0x59;
BAsmCode
[1] = Index
? (1 << BAsmCode
[1]) : ~
(1 << BAsmCode
[1]);
BAsmCode
[2] = Hi
(AdrWVal
);
BAsmCode
[3] = Lo
(AdrWVal
);
CodeLen
= 4;
break;
}
}
break;
default:
(void)ChkArgCnt
(1, 2);
}
}
static void DecodeBTJCore
(Word Index
, int ArgOffset
)
{
int TmpCodeLen
= 0;
switch (ArgCnt
- ArgOffset
)
{
case 2:
{
LongWord BitArg
;
ShortInt OpSize
= eSymbolSize8Bit
;
if (DecodeBitArg
(&BitArg
, 1 + ArgOffset
, 1 + ArgOffset
, OpSize
))
{
Word Address
;
Byte BitPos
;
(void)DissectBitSymbol
(BitArg
, &Address
, &BitPos
, &OpSize
);
if ((Address
& 0xff0) == pCurrCPUProps
->WorkOfs
)
{
BAsmCode
[0] = 0xf6;
BAsmCode
[1] = (Address
& 15) | (BitPos
<< 4);
TmpCodeLen
= 2;
}
else
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
}
break;
}
case 3:
{
Boolean OK
;
BAsmCode
[1] = EvalStrIntExpression
(&ArgStr
[1 + ArgOffset
], UInt3
, &OK
) << 4;
if (OK
)
{
DecodeAdr
(&ArgStr
[2 + ArgOffset
], MModWReg
| MModIWReg
);
switch (AdrType
)
{
case ModWReg
:
BAsmCode
[0] = 0xf6;
BAsmCode
[1] |= AdrVal
;
TmpCodeLen
= 2;
break;
case ModIWReg
:
BAsmCode
[0] = 0xf7;
BAsmCode
[1] |= AdrVal
;
TmpCodeLen
= 2;
break;
}
}
break;
}
default:
(void)ChkArgCnt
(3, 4);
}
if (TmpCodeLen
> 0)
{
tEvalResult EvalResult
;
Integer AdrInt
= EvalStrIntExpressionWithResult
(&ArgStr
[ArgCnt
], Int16
, &EvalResult
) - (EProgCounter
() + TmpCodeLen
+ 1);
BAsmCode
[1] |= Index
;
if (EvalResult.
OK)
{
if (!mSymbolQuestionable
(EvalResult.
Flags)
&& ((AdrInt
> 127) || (AdrInt
< -128))) WrError
(ErrNum_JmpDistTooBig
);
else
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
BAsmCode
[TmpCodeLen
] = Lo
(AdrInt
);
CodeLen
= TmpCodeLen
+ 1;
}
}
}
}
static void DecodeBTJ
(Word Index
)
{
if (ChkCoreFlags
(eCoreZ8Encore
)
&& ChkArgCnt
(3, 4))
{
Boolean OK
;
Index
= EvalStrIntExpression
(&ArgStr
[1], UInt1
, &OK
) << 7;
if (OK
)
DecodeBTJCore
(Index
, 1);
}
}
static void DecodeBtj
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 3)
&& ChkCoreFlags
(eCoreZ8Encore
))
DecodeBTJCore
(Index
, 0);
}
static void DecodeBit1
(Word Code
)
{
if (ChkArgCnt
(1, 2)
&& ChkCoreFlags
(eCoreSuper8
)
&& DecodeWRBitArg
(1, ArgCnt
, &BAsmCode
[1]))
{
BAsmCode
[1] = (BAsmCode
[1] << 1) | Hi
(Code
);
BAsmCode
[0] = Lo
(Code
);
CodeLen
= 2;
}
}
static void DecodeBit2
(Word Code
)
{
if (ChkCoreFlags
(eCoreSuper8
))
{
LongWord BitValue
;
Byte Reg
;
switch (ArgCnt
)
{
case 3:
{
int BitStart
, BitEnd
, RegIdx
;
if ((*ArgStr
[2].
str.
p_str == '#') && Hi
(Code
))
{
BitStart
= 1;
BitEnd
= 2;
RegIdx
= 3;
BAsmCode
[1] = 0x01;
}
else
{
BitStart
= 2;
BitEnd
= 3;
RegIdx
= 1;
BAsmCode
[1] = 0x00;
}
DecodeAdr
(&ArgStr
[RegIdx
], MModWReg
); Reg
= AdrVal
;
if ((AdrType
== ModWReg
) && DecodeBitArg2
(&BitValue
, &ArgStr
[BitStart
], &ArgStr
[BitEnd
], eSymbolSize8Bit
));
else
return;
break;
}
case 2:
{
if ((IsWReg
(&ArgStr
[1], &Reg
, False
) == eIsReg
)
&& DecodeBitArg
(&BitValue
, 2, 2, eSymbolSize8Bit
))
{
BAsmCode
[1] = 0x00;
}
else if ((IsWReg
(&ArgStr
[2], &Reg
, False
) == eIsReg
)
&& DecodeBitArg
(&BitValue
, 1, 1, eSymbolSize8Bit
)
&& Hi
(Code
))
{
BAsmCode
[1] = 0x01;
}
else
{
WrError
(ErrNum_InvAddrMode
);
return;
}
break;
}
default:
(void)ChkArgCnt
(2, 3);
return;
}
CodeLen
= 3;
BAsmCode
[0] = Lo
(Code
);
BAsmCode
[1] |= (Reg
<< 4) | ((BitValue
& 7) << 1);
BAsmCode
[2] = BitValue
>> 3;
CodeLen
= 3;
}
}
static void DecodeBitRel
(Word Code
)
{
if (ChkArgCnt
(2, 3)
&& ChkCoreFlags
(eCoreSuper8
)
&& DecodeWRBitArg
(2, ArgCnt
, &BAsmCode
[1]))
{
tEvalResult EvalResult
;
Integer AdrInt
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt16
, &EvalResult
) - (EProgCounter
() + 3);
if (EvalResult.
OK)
{
if (!mSymbolQuestionable
(EvalResult.
Flags)
&& ((AdrInt
> 127) || (AdrInt
< -128))) WrError
(ErrNum_JmpDistTooBig
);
else
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
BAsmCode
[0] = Lo
(Code
);
BAsmCode
[1] = (BAsmCode
[1] << 1) | Hi
(Code
);
BAsmCode
[2] = Lo
(AdrInt
);
CodeLen
= 3;
}
}
}
}
static void DecodeSFR
(Word Code
)
{
UNUSED
(Code
);
CodeEquate
(SegData
, 0, mIsZ8Encore
() ? 0xfff : 0xff);
}
static void DecodeDEFBIT
(Word Code
)
{
LongWord BitSpec
;
UNUSED
(Code
);
/* if in structure definition, add special element to structure */
if (ActPC
== StructSeg
)
{
Boolean OK
;
Byte BitPos
;
PStructElem pElement
;
if (!ChkArgCnt
(2, 2))
return;
BitPos
= EvalBitPosition
(&ArgStr
[2], &OK
, eSymbolSize8Bit
);
if (!OK
)
return;
pElement
= CreateStructElem
(&LabPart
);
if (!pElement
)
return;
pElement
->pRefElemName
= as_strdup
(ArgStr
[1].
str.
p_str);
pElement
->OpSize
= eSymbolSize8Bit
;
pElement
->BitPos
= BitPos
;
pElement
->ExpandFnc
= ExpandZ8Bit
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElement
);
}
else
{
if (DecodeBitArg
(&BitSpec
, 1, ArgCnt
, eSymbolSize8Bit
))
{
*ListLine
= '=';
DissectBit_Z8
(ListLine
+ 1, STRINGSIZE
- 3, BitSpec
);
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, BitSpec
, SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
}
/*--------------------------------------------------------------------------*/
/* Instruction Table Buildup/Teardown */
static void AddFixed
(const char *NName
, Word Code
, tCoreFlags CoreFlags
)
{
order_array_rsv_end
(FixedOrders
, BaseOrder
);
FixedOrders
[InstrZ
].
Code = Code
;
FixedOrders
[InstrZ
].
CoreFlags = CoreFlags
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddALU2
(const char *NName
, Word Code
, tCoreFlags CoreFlags
)
{
order_array_rsv_end
(ALU2Orders
, BaseOrder
);
ALU2Orders
[InstrZ
].
Code = Code
;
ALU2Orders
[InstrZ
].
CoreFlags = CoreFlags
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeALU2
);
}
static void AddALUX
(const char *NName
, Word Code
, tCoreFlags CoreFlags
)
{
order_array_rsv_end
(ALUXOrders
, BaseOrder
);
ALUXOrders
[InstrZ
].
Code = Code
;
ALUXOrders
[InstrZ
].
CoreFlags = CoreFlags
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeALUX
);
}
static void AddALU1
(const char *NName
, Word Code
, tCoreFlags CoreFlags
, Boolean Is16
)
{
order_array_rsv_end
(ALU1Orders
, ALU1Order
);
ALU1Orders
[InstrZ
].
Code = Code
;
ALU1Orders
[InstrZ
].
CoreFlags = CoreFlags
;
ALU1Orders
[InstrZ
].
Is16 = Is16
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeALU1
);
}
static void AddCondition
(const char *NName
, Byte NCode
)
{
order_array_rsv_end
(Conditions
, Condition
);
Conditions
[InstrZ
].
Name = NName
;
Conditions
[InstrZ
++].
Code = NCode
;
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(201);
InstrZ
= 0;
AddFixed
("CCF" , 0xef , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("DI" , 0x8f , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("EI" , 0x9f , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("HALT" , 0x7f , eCoreZ8CMOS
| eCoreZ8Encore
);
AddFixed
("IRET" , 0xbf , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("NOP" , NOPCode
, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("RCF" , 0xcf , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("RET" , 0xaf , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("SCF" , 0xdf , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddFixed
("STOP" , 0x6f , eCoreZ8CMOS
| eCoreZ8Encore
);
AddFixed
("ATM" , 0x2f , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreZ8Encore
);
AddFixed
("BRK" , 0x00 , eCoreZ8Encore
);
AddFixed
("WDH" , 0x4f , eCoreZ8NMOS
| eCoreZ8CMOS
);
AddFixed
("WDT" , 0x5f , eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreZ8Encore
);
AddFixed
("ENTER", 0x1f , eCoreSuper8
);
AddFixed
("EXIT" , 0x2f , eCoreSuper8
);
AddFixed
("NEXT" , 0x0f , eCoreSuper8
);
AddFixed
("SB0" , 0x4f , eCoreSuper8
);
AddFixed
("SB1" , 0x5f , eCoreSuper8
);
AddFixed
("WFI" , 0x3f , eCoreSuper8
);
InstrZ
= 0;
AddALU2
("ADD" , 0x0000, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("ADC" , 0x0010, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("SUB" , 0x0020, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("SBC" , 0x0030, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("OR" , 0x0040, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("AND" , 0x0050, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("TCM" , 0x0060, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("TM" , 0x0070, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("CP" , 0x00a0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("XOR" , 0x00b0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
);
AddALU2
("CPC" , (EXTPREFIX
<< 8) | 0xa0, eCoreZ8Encore
);
InstrZ
= 0;
AddALUX
("ADDX", 0x0008, eCoreZ8Encore
);
AddALUX
("ADCX", 0x0018, eCoreZ8Encore
);
AddALUX
("SUBX", 0x0028, eCoreZ8Encore
);
AddALUX
("SBCX", 0x0038, eCoreZ8Encore
);
AddALUX
("ORX" , 0x0048, eCoreZ8Encore
);
AddALUX
("ANDX", 0x0058, eCoreZ8Encore
);
AddALUX
("TCMX", 0x0068, eCoreZ8Encore
);
AddALUX
("TMX" , 0x0078, eCoreZ8Encore
);
AddALUX
("CPX" , 0x00a8, eCoreZ8Encore
);
AddALUX
("XORX", 0x00b8, eCoreZ8Encore
);
AddALUX
("CPCX", (EXTPREFIX
<< 8) | 0xa8, eCoreZ8Encore
);
InstrZ
= 0;
AddALU1
("DEC" , (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
) ? 0x0030 : 0x0000, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("RLC" , 0x0010, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("DA" , 0x0040, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("POP" , 0x0050, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("COM" , 0x0060, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("PUSH", 0x0070, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("DECW", 0x0080, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, True
);
AddALU1
("RL" , 0x0090, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("INCW", 0x00a0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, True
);
AddALU1
("CLR" , 0x00b0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("RRC" , 0x00c0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("SRA" , 0x00d0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("RR" , 0x00e0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("SWAP", 0x00f0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreSuper8
| eCoreZ8Encore
, False
);
AddALU1
("SRL" , (EXTPREFIX
<< 8) | 0xc0, eCoreZ8NMOS
| eCoreZ8CMOS
| eCoreZ8Encore
, False
);
InstrZ
= 0;
AddCondition
("F" , 0); TrueCond
= InstrZ
; AddCondition
("T" , 8);
AddCondition
("C" , 7); AddCondition
("NC" ,15);
AddCondition
("Z" , 6); AddCondition
("NZ" ,14);
AddCondition
("MI" , 5); AddCondition
("PL" ,13);
AddCondition
("OV" , 4); AddCondition
("NOV",12);
AddCondition
("EQ" , 6); AddCondition
("NE" ,14);
AddCondition
("LT" , 1); AddCondition
("GE" , 9);
AddCondition
("LE" , 2); AddCondition
("GT" ,10);
AddCondition
("ULT", 7); AddCondition
("UGE",15);
AddCondition
("ULE", 3); AddCondition
("UGT",11);
CondCnt
= InstrZ
;
AddInstTable
(InstTable
, "LD", 0, DecodeLD
);
AddInstTable
(InstTable
, "LDX", 0, DecodeLDX
);
AddInstTable
(InstTable
, "LDW", 0xc4, DecodeLDW
);
AddInstTable
(InstTable
, "LDWX", 0, DecodeLDWX
);
AddInstTable
(InstTable
, "LDC", 0xc2, DecodeLDCE
);
AddInstTable
(InstTable
, "LDE", 0x82, DecodeLDCE
);
if (mIsSuper8
())
{
AddInstTable
(InstTable
, "LDCI", 0x00e3, DecodeLDCEDI
);
AddInstTable
(InstTable
, "LDEI", 0x01e3, DecodeLDCEDI
);
}
else
{
AddInstTable
(InstTable
, "LDCI", 0xc3, DecodeLDCEI
);
AddInstTable
(InstTable
, "LDEI", 0x83, DecodeLDCEI
);
}
AddInstTable
(InstTable
, "LDCD", 0x00e2, DecodeLDCEDI
);
AddInstTable
(InstTable
, "LDED", 0x01e2, DecodeLDCEDI
);
AddInstTable
(InstTable
, "LDCPD", 0x00f2, DecodeLDCEPDI
);
AddInstTable
(InstTable
, "LDEPD", 0x01f2, DecodeLDCEPDI
);
AddInstTable
(InstTable
, "LDCPI", 0x00f3, DecodeLDCEPDI
);
AddInstTable
(InstTable
, "LDEPI", 0x01f3, DecodeLDCEPDI
);
AddInstTable
(InstTable
, "INC", 0, DecodeINC
);
AddInstTable
(InstTable
, "JR", 0, DecodeJR
);
AddInstTable
(InstTable
, "JP", 0, DecodeJP
);
AddInstTable
(InstTable
, "CALL", 0, DecodeCALL
);
AddInstTable
(InstTable
, "SRP", 0x0031, DecodeSRP
);
AddInstTable
(InstTable
, "SRP0", 0x0231, DecodeSRP
);
AddInstTable
(InstTable
, "SRP1", 0x0131, DecodeSRP
);
AddInstTable
(InstTable
, "RDR", 0x01d5, DecodeSRP
);
AddInstTable
(InstTable
, "DJNZ", 0, DecodeDJNZ
);
AddInstTable
(InstTable
, "LEA", 0, DecodeLEA
);
AddInstTable
(InstTable
, "POPX" , 0xd8, DecodeStackExt
);
AddInstTable
(InstTable
, "PUSHX", 0xc8, DecodeStackExt
);
AddInstTable
(InstTable
, "POPUD", 0x92, DecodeStackDI
);
AddInstTable
(InstTable
, "POPUI", 0x93, DecodeStackDI
);
AddInstTable
(InstTable
, "PUSHUD", 0x82, DecodeStackDI
);
AddInstTable
(InstTable
, "PUSHUI", 0x83, DecodeStackDI
);
AddInstTable
(InstTable
, "TRAP" , 0, DecodeTRAP
);
AddInstTable
(InstTable
, "BSWAP", 0, DecodeBSWAP
);
if (mIsSuper8
())
AddInstTable
(InstTable
, "MULT" , 0x84, DecodeMULT_DIV
);
else
AddInstTable
(InstTable
, "MULT" , 0, DecodeMULT
);
AddInstTable
(InstTable
, "DIV" , 0x94, DecodeMULT_DIV
);
AddInstTable
(InstTable
, "BIT", 0, DecodeBIT
);
AddInstTable
(InstTable
, "BCLR", 0x00, DecodeBit
);
AddInstTable
(InstTable
, "BSET", 0x80, DecodeBit
);
AddInstTable
(InstTable
, "BTJ", 0, DecodeBTJ
);
AddInstTable
(InstTable
, "BTJZ", 0x00, DecodeBtj
);
AddInstTable
(InstTable
, "BTJNZ", 0x80, DecodeBtj
);
AddInstTable
(InstTable
, "CPIJNE", 0xd2, DecodeCPIJNE
);
AddInstTable
(InstTable
, "CPIJE", 0xc2, DecodeCPIJNE
);
AddInstTable
(InstTable
, "BITC", 0x0057, DecodeBit1
);
AddInstTable
(InstTable
, "BITR", 0x0077, DecodeBit1
);
AddInstTable
(InstTable
, "BITS", 0x0177, DecodeBit1
);
AddInstTable
(InstTable
, "BAND", 0x0167, DecodeBit2
);
AddInstTable
(InstTable
, "BOR", 0x0107, DecodeBit2
);
AddInstTable
(InstTable
, "BXOR", 0x0127, DecodeBit2
);
AddInstTable
(InstTable
, "LDB", 0x0147, DecodeBit2
);
AddInstTable
(InstTable
, "BCP", 0x0017, DecodeBit2
);
AddInstTable
(InstTable
, "BTJRF",0x0037, DecodeBitRel
);
AddInstTable
(InstTable
, "BTJRT",0x0137, DecodeBitRel
);
AddInstTable
(InstTable
, "SFR", 0, DecodeSFR
);
AddInstTable
(InstTable
, "REG", 0, CodeREG
);
AddInstTable
(InstTable
, "DEFBIT", 0, DecodeDEFBIT
);
}
static void DeinitFields
(void)
{
order_array_free
(FixedOrders
);
order_array_free
(ALU2Orders
);
order_array_free
(ALU1Orders
);
order_array_free
(ALUXOrders
);
order_array_free
(Conditions
);
DestroyInstTable
(InstTable
);
}
/*---------------------------------------------------------------------*/
/*!------------------------------------------------------------------------
* \fn InternSymbol_Z8(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on Z8
* \param pArg source code argument
* \param pResult result buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_Z8
(char *pArg
, TempResult
*pResult
)
{
Byte RegNum
;
if (IsWRegCore
(pArg
, &RegNum
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize8Bit
;
pResult
->Contents.
RegDescr.
Reg = RegNum
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_Z8
;
pResult
->Contents.
RegDescr.
compare = NULL
;
}
else if (IsWRRegCore
(pArg
, &RegNum
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= eSymbolSize16Bit
;
pResult
->Contents.
RegDescr.
Reg = RegNum
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_Z8
;
pResult
->Contents.
RegDescr.
compare = NULL
;
}
}
static void MakeCode_Z8
(void)
{
CodeLen
= 0; DontPrint
= False
; OpSize
= eSymbolSize8Bit
;
/* zu ignorierendes */
if (Memo
("")) return;
/* Pseudo Instructions */
if (DecodeIntelPseudo
(True
))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static void InitCode_Z8
(void)
{
RPVal
= 0;
}
static Boolean IsDef_Z8
(void)
{
return (Memo
("SFR") || Memo
("REG") || Memo
("DEFBIT"));
}
static void SwitchFrom_Z8
(void)
{
DeinitFields
();
}
static void AdaptRP01
(void)
{
/* SRP on Super8 sets RP0 & RP1. Act similar for ASSUME on Super8: */
if (RPVal
>= 0x100)
RP0Val
= RP1Val
= RPVal
;
else
{
RP0Val
= RPVal
;
RP1Val
= RPVal
+ 8;
}
}
#define ASSUMEeZ8Count 1
#define ASSUMESuper8Count 3
static ASSUMERec ASSUMEeZ8s
[] =
{
{"RP" , &RPVal
, 0, 0xff, 0x100, AdaptRP01
},
{"RP0" , &RP0Val
, 0, 0xff, 0x100, NULL
},
{"RP1" , &RP1Val
, 0, 0xff, 0x100, NULL
}
};
/*!------------------------------------------------------------------------
* \fn SwitchTo_Z8(void *pUser)
* \brief prepare to assemble code for this target
* \param pUser CPU properties
* ------------------------------------------------------------------------ */
static void SwitchTo_Z8
(void *pUser
)
{
const TFamilyDescr
*pDescr
;
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
pCurrCPUProps
= (const tCPUProps
*)pUser
;
if (mIsSuper8
())
pDescr
= FindFamilyByName
("Super8");
else if (mIsZ8Encore
())
pDescr
= FindFamilyByName
("eZ8");
else
pDescr
= FindFamilyByName
("Z8");
PCSymbol
= "$"; HeaderID
= pDescr
->Id
;
NOPCode
= mIsZ8Encore
() ? 0x0f : 0xff;
DivideChars
= ","; HasAttrs
= False
;
ValidSegs
= (1 << SegCode
) | (1 << SegData
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = 0xffff;
Grans
[SegData
] = 1; ListGrans
[SegData
] = 1; SegInits
[SegData
] = 0;
if (pCurrCPUProps
->CoreFlags
& eCoreZ8Encore
)
{
RegSpaceType
= UInt12
;
SegLimits
[SegData
] = 0xfff;
ValidSegs
|= 1 << SegXData
;
Grans
[SegXData
] = 1; ListGrans
[SegXData
] = 1; SegInits
[SegXData
] = 0;
SegLimits
[SegXData
] = 0xffff;
}
else
{
RegSpaceType
= UInt8
;
SegLimits
[SegData
] = 0xff;
}
pASSUMERecs
= ASSUMEeZ8s
;
ASSUMERecCnt
= mIsSuper8
() ? ASSUMESuper8Count
: ASSUMEeZ8Count
;
MakeCode
= MakeCode_Z8
;
IsDef
= IsDef_Z8
;
InternSymbol
= InternSymbol_Z8
;
DissectReg
= DissectReg_Z8
;
DissectBit
= DissectBit_Z8
;
SwitchFrom
= SwitchFrom_Z8
;
InitFields
();
}
/*!------------------------------------------------------------------------
* \fn codez8_init(void)
* \brief register target to AS
* ------------------------------------------------------------------------ */
static const tCPUProps CPUProps
[] =
{
{ "Z8601" , eCoreZ8NMOS
, 0xe0, 0x7f, 0xf0 },
{ "Z8603" , eCoreZ8NMOS
, 0xe0, 0x7f, 0xf0 },
{ "Z86C03" , eCoreZ8CMOS
, 0xe0, 0x3f, 0xf0 },
{ "Z86E03" , eCoreZ8CMOS
, 0xe0, 0x3f, 0xf0 },
/*{ "Z8604" , eCoreZ8 , 0xe0, 0x7f, 0xf0 },*/
{ "Z86C06" , eCoreZ8CMOS
, 0xe0, 0x7f, 0xf0 },
{ "Z86E06" , eCoreZ8CMOS
, 0xe0, 0x7f, 0xf0 },
{ "Z86C08" , eCoreZ8CMOS
, 0xe0, 0x7f, 0xf0 },
{ "Z86C30" , eCoreZ8CMOS
, 0xe0, 0xef, 0xf0 },
{ "Z86C21" , eCoreZ8CMOS
, 0xe0, 0xef, 0xf0 },
{ "Z86E21" , eCoreZ8CMOS
, 0xe0, 0xef, 0xf0 },
{ "Z86C31" , eCoreZ8CMOS
, 0xe0, 0x7f, 0xf0 },
{ "Z86C32" , eCoreZ8CMOS
, 0xe0, 0xef, 0xf0 },
{ "Z86C40" , eCoreZ8CMOS
, 0xe0, 0xef, 0xf0 },
{ "Z88C00" , eCoreSuper8
, 0xc0, 0xbf, 0xe0 },
{ "Z88C01" , eCoreSuper8
, 0xc0, 0xbf, 0xe0 },
{ "eZ8" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F0113" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F011A" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0123" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F012A" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0130" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0131" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0213" , eCoreZ8Encore
, 0xee0, 0x1ff, 0xf00 },
{ "Z8F021A" , eCoreZ8Encore
, 0xee0, 0x1ff, 0xf00 },
{ "Z8F0223" , eCoreZ8Encore
, 0xee0, 0x1ff, 0xf00 },
{ "Z8F022A" , eCoreZ8Encore
, 0xee0, 0x1ff, 0xf00 },
{ "Z8F0230" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0231" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0411" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0412" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0413" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F041A" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0421" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0422" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0423" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F042A" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0430" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0431" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0811" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0812" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0813" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F081A" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0821" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0822" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0823" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F082A" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F0830" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0831" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F0880" , eCoreZ8Encore
, 0xee0, 0x3ff, 0xf00 },
{ "Z8F1232" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F1233" , eCoreZ8Encore
, 0xee0, 0xff, 0xf00 },
{ "Z8F1621" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F1622" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F1680" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F1681" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F1682" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F2421" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F2422" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F2480" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F3221" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F3222" , eCoreZ8Encore
, 0xee0, 0x7ff, 0xf00 },
{ "Z8F3281" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F3282" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F4821" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F4822" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F4823" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6081" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6082" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6421" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6422" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6423" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6481" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ "Z8F6482" , eCoreZ8Encore
, 0xee0, 0xeff, 0xf00 },
{ NULL
, eCoreNone
, 0x00, 0x00, 0x000 }
};
void codez8_init
(void)
{
const tCPUProps
*pRun
;
for (pRun
= CPUProps
; pRun
->pName
; pRun
++)
(void)AddCPUUser
(pRun
->pName
, SwitchTo_Z8
, (void*)pRun
, NULL
);
AddInitPassProc
(InitCode_Z8
);
}