/* code51.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator fuer MCS-51/252 Prozessoren */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "asmrelocs.h"
#include "asmlist.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "asmitree.h"
#include "codevars.h"
#include "fileformat.h"
#include "errmsg.h"
#include "intformat.h"
#include "code51.h"
/*-------------------------------------------------------------------------*/
/* Daten */
typedef struct
{
CPUVar MinCPU
;
Word Code
;
} FixedOrder
;
enum
{
ModNone
= -1,
ModReg
= 1,
ModIReg8
= 2,
ModIReg
= 3,
ModInd
= 5,
ModImm
= 7,
ModImmEx
= 8,
ModDir8
= 9,
ModDir16
= 10,
ModAcc
= 11,
ModBit51
= 12,
ModBit251
= 13
};
#define MModReg (1 << ModReg)
#define MModIReg8 (1 << ModIReg8)
#define MModIReg (1 << ModIReg)
#define MModInd (1 << ModInd)
#define MModImm (1 << ModImm)
#define MModImmEx (1 << ModImmEx)
#define MModDir8 (1 << ModDir8)
#define MModDir16 (1 << ModDir16)
#define MModAcc (1 << ModAcc)
#define MModBit51 (1 << ModBit51)
#define MModBit251 (1 << ModBit251)
#define MMod51 (MModReg | MModIReg8 | MModImm | MModAcc | MModDir8)
#define MMod251 (MModIReg | MModInd | MModImmEx | MModDir16)
#define AccReg 11
#define DPXValue 14
#define SPXValue 15
static FixedOrder
*FixedOrders
;
static FixedOrder
*AccOrders
;
static FixedOrder
*CondOrders
;
static FixedOrder
*BCondOrders
;
static Byte AdrVals
[5];
static Byte AdrPart
, AdrSize
;
static ShortInt AdrMode
,OpSize
;
static Boolean MinOneIs0
;
static Boolean SrcMode
;
static CPUVar CPU87C750
, CPU8051
, CPU8052
, CPU80C320
,
CPU80501
, CPU80502
, CPU80504
, CPU80515
, CPU80517
,
CPU80C390
,
CPU80251
, CPU80251T
;
static PRelocEntry AdrRelocInfo
, BackupAdrRelocInfo
;
static LongWord AdrOffset
, AdrRelocType
,
BackupAdrOffset
, BackupAdrRelocType
;
/*-------------------------------------------------------------------------*/
/* Adressparser */
static void SetOpSize
(ShortInt NewSize
)
{
if (OpSize
== -1)
OpSize
= NewSize
;
else if (OpSize
!= NewSize
)
{
WrError
(ErrNum_ConfOpSizes
);
AdrMode
= ModNone
;
AdrCnt
= 0;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeRegCore(const char *pAsc, tRegInt *pValue, tSymbolSize *pSize)
* \brief check whether argument describes a CPU register
* \param pAsc argument
* \param pValue resulting register # if yes
* \param pSize resulting register size if yes
* \return true if yes
* ------------------------------------------------------------------------ */
static Boolean DecodeRegCore
(const char *pAsc
, tRegInt
*pValue
, tSymbolSize
*pSize
)
{
static Byte Masks
[3] = { 0, 1, 3 };
const char *Start
;
int alen
= strlen(pAsc
);
Boolean IO
;
if (!as_strcasecmp
(pAsc
, "DPX"))
{
*pValue
= DPXValue
;
*pSize
= eSymbolSize32Bit
;
return True
;
}
if (!as_strcasecmp
(pAsc
, "SPX"))
{
*pValue
= SPXValue
;
*pSize
= eSymbolSize32Bit
;
return True
;
}
if ((alen
>= 2) && (as_toupper
(*pAsc
) == 'R'))
{
Start
= pAsc
+ 1;
*pSize
= eSymbolSize8Bit
;
}
else if ((MomCPU
>= CPU80251
) && (alen
>= 3) && (as_toupper
(*pAsc
) == 'W') && (as_toupper
(pAsc
[1]) == 'R'))
{
Start
= pAsc
+ 2;
*pSize
= eSymbolSize16Bit
;
}
else if ((MomCPU
>= CPU80251
) && (alen
>= 3) && (as_toupper
(*pAsc
) == 'D') && (as_toupper
(pAsc
[1]) == 'R'))
{
Start
= pAsc
+ 2;
*pSize
= eSymbolSize32Bit
;
}
else
return False
;
*pValue
= ConstLongInt
(Start
, &IO
, 10);
if (!IO
) return False
;
else if (*pValue
& Masks
[*pSize
]) return False
;
else
{
*pValue
>>= *pSize
;
switch (*pSize
)
{
case eSymbolSize8Bit
:
return ((*pValue
< 8) || ((MomCPU
>= CPU80251
) && (*pValue
< 16)));
case eSymbolSize16Bit
:
return (*pValue
< 16);
case eSymbolSize32Bit
:
return ((*pValue
< 8) || (*pValue
== DPXValue
) || (*pValue
== SPXValue
));
default:
return False
;
}
}
}
/*!------------------------------------------------------------------------
* \fn DissectReg_51(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
* \brief dissect register symbols - 80(2)51 variant
* \param pDest destination buffer
* \param DestSize destination buffer size
* \param Value numeric register value
* \param InpSize register size
* ------------------------------------------------------------------------ */
static void DissectReg_51
(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
, "WR%u", (unsigned)Value
<< 1);
break;
case eSymbolSize32Bit
:
if (SPXValue
== Value
)
strmaxcpy
(pDest
, "SPX", DestSize
);
else if (DPXValue
== Value
)
strmaxcpy
(pDest
, "DPX", DestSize
);
else
as_snprintf
(pDest
, DestSize
, "DR%u", (unsigned)Value
<< 2);
break;
default:
as_snprintf
(pDest
, DestSize
, "%d-%u", (int)InpSize
, (unsigned)Value
);
}
}
/*!------------------------------------------------------------------------
* \fn DecodeReg(const tStrComp *pArg, Byte *pValue, tSymbolSize *pSize, Boolean MustBeReg)
* \brief check whether argument is a CPU register or user-defined register alias
* \param pArg argument
* \param pValue resulting register # if yes
* \param pSize resulting register size if yes
* \param MustBeReg operand must be a register
* \return reg eval result
* ------------------------------------------------------------------------ */
static tRegEvalResult DecodeReg
(const tStrComp
*pArg
, Byte
*pValue
, tSymbolSize
*pSize
, Boolean MustBeReg
)
{
tRegDescr RegDescr
;
tEvalResult EvalResult
;
tRegEvalResult RegEvalResult
;
if (DecodeRegCore
(pArg
->str.
p_str, &RegDescr.
Reg, pSize
))
{
*pValue
= RegDescr.
Reg;
return eIsReg
;
}
RegEvalResult
= EvalStrRegExpressionAsOperand
(pArg
, &RegDescr
, &EvalResult
, eSymbolSizeUnknown
, MustBeReg
);
*pValue
= RegDescr.
Reg;
*pSize
= EvalResult.
DataSize;
return RegEvalResult
;
}
static void SaveAdrRelocs
(LongWord Type
, LongWord Offset
)
{
AdrOffset
= Offset
;
AdrRelocType
= Type
;
AdrRelocInfo
= LastRelocs
;
LastRelocs
= NULL
;
}
static void SaveBackupAdrRelocs
(void)
{
BackupAdrOffset
= AdrOffset
;
BackupAdrRelocType
= AdrRelocType
;
BackupAdrRelocInfo
= AdrRelocInfo
;
AdrRelocInfo
= NULL
;
}
static void TransferAdrRelocs
(LongWord Offset
)
{
TransferRelocs2
(AdrRelocInfo
, ProgCounter
() + AdrOffset
+ Offset
, AdrRelocType
);
AdrRelocInfo
= NULL
;
}
static void TransferBackupAdrRelocs
(LargeWord Offset
)
{
TransferRelocs2
(BackupAdrRelocInfo
, ProgCounter
() + BackupAdrOffset
+ Offset
, BackupAdrRelocType
);
AdrRelocInfo
= NULL
;
}
static void DecodeAdr
(tStrComp
*pArg
, Word Mask
)
{
Boolean OK
, FirstFlag
;
tEvalResult EvalResult
;
tSymbolSize HSize
;
Word H16
;
LongWord H32
;
tStrComp SegComp
, AddrComp
, *pAddrComp
;
int SegType
;
char Save
= '\0', *pSegSepPos
;
Word ExtMask
;
AdrMode
= ModNone
; AdrCnt
= 0;
ExtMask
= MMod251
& Mask
;
if (MomCPU
< CPU80251
) Mask
&= MMod51
;
if (!*pArg
->str.
p_str)
return;
if (!as_strcasecmp
(pArg
->str.
p_str, "A"))
{
if (!(Mask
& MModAcc
))
{
AdrMode
= ModReg
;
AdrPart
= AccReg
;
}
else
AdrMode
= ModAcc
;
SetOpSize
(0);
goto chk
;
}
if (*pArg
->str.
p_str == '#')
{
tStrComp Comp
;
StrCompRefRight
(&Comp
, pArg
, 1);
if ((OpSize
== -1) && (MinOneIs0
)) OpSize
= 0;
switch (OpSize
)
{
case -1:
WrError
(ErrNum_UndefOpSizes
);
break;
case 0:
AdrVals
[0] = EvalStrIntExpression
(&Comp
, Int8
, &OK
);
if (OK
)
{
AdrMode
= ModImm
;
AdrCnt
= 1;
SaveAdrRelocs
(RelocTypeB8
, 0);
}
break;
case 1:
H16
= EvalStrIntExpression
(&Comp
, Int16
, &OK
);
if (OK
)
{
AdrVals
[0] = Hi
(H16
);
AdrVals
[1] = Lo
(H16
);
AdrMode
= ModImm
;
AdrCnt
= 2;
SaveAdrRelocs
(RelocTypeB16
, 0);
}
break;
case 2:
H32
= EvalStrIntExpressionWithResult
(&Comp
, Int32
, &EvalResult
);
if (mFirstPassUnknown
(EvalResult.
Flags))
H32
&= 0xffff;
if (EvalResult.
OK)
{
AdrVals
[1] = H32
& 0xff;
AdrVals
[0] = (H32
>> 8) & 0xff;
H32
>>= 16;
if (H32
== 0)
AdrMode
= ModImm
;
else if ((H32
== 1) || (H32
== 0xffff))
AdrMode
= ModImmEx
;
else
WrError
(ErrNum_UndefOpSizes
);
if (AdrMode
!= ModNone
)
AdrCnt
= 2;
SaveAdrRelocs
(RelocTypeB16
, 0);
}
break;
case 3:
H32
= EvalStrIntExpression
(&Comp
, Int24
, &OK
);
if (OK
)
{
AdrVals
[0] = (H32
>> 16) & 0xff;
AdrVals
[1] = (H32
>> 8) & 0xff;
AdrVals
[2] = H32
& 0xff;
AdrCnt
= 3;
AdrMode
= ModImm
;
SaveAdrRelocs
(RelocTypeB24
, 0);
}
break;
}
goto chk
;
}
switch (DecodeReg
(pArg
, &AdrPart
, &HSize
, False
))
{
case eIsReg
:
if ((MomCPU
>= CPU80251
) && ((Mask
& MModReg
) == 0))
AdrMode
= ((HSize
== 0) && (AdrPart
== AccReg
)) ? ModAcc
: ModReg
;
else
AdrMode
= ModReg
;
SetOpSize
(HSize
);
goto chk
;
case eIsNoReg
:
break;
case eRegAbort
:
return;
}
if (*pArg
->str.
p_str == '@')
{
tStrComp IndirComp
;
char *PPos
, *MPos
;
StrCompRefRight
(&IndirComp
, pArg
, 1);
PPos
= strchr(IndirComp.
str.
p_str, '+');
MPos
= strchr(IndirComp.
str.
p_str, '-');
if ((MPos
) && ((MPos
< PPos
) || (!PPos
)))
PPos
= MPos
;
if (PPos
)
{
Save
= *PPos
;
*PPos
= '\0';
IndirComp.
Pos.
Len = PPos
- IndirComp.
str.
p_str;
}
switch (DecodeReg
(&IndirComp
, &AdrPart
, &HSize
, False
))
{
case eIsReg
:
{
if (!PPos
)
{
H32
= 0;
OK
= True
;
}
else
{
tStrComp DispComp
;
*PPos
= Save
;
StrCompRefRight
(&DispComp
, &IndirComp
, PPos
- IndirComp.
str.
p_str + !!(Save
== '+'));
H32
= EvalStrIntExpression
(&DispComp
, SInt16
, &OK
);
}
if (OK
)
switch (HSize
)
{
case eSymbolSize8Bit
:
if ((AdrPart
>1) || (H32
!= 0)) WrError
(ErrNum_InvAddrMode
);
else
AdrMode
= ModIReg8
;
break;
case eSymbolSize16Bit
:
if (H32
== 0)
{
AdrMode
= ModIReg
;
AdrSize
= 0;
}
else
{
AdrMode
= ModInd
;
AdrSize
= 0;
AdrVals
[1] = H32
& 0xff;
AdrVals
[0] = (H32
>> 8) & 0xff;
AdrCnt
= 2;
}
break;
case eSymbolSize32Bit
:
if (H32
== 0)
{
AdrMode
= ModIReg
;
AdrSize
= 2;
}
else
{
AdrMode
= ModInd
;
AdrSize
= 2;
AdrVals
[1] = H32
& 0xff;
AdrVals
[0] = (H32
>> 8) & 0xff;
AdrCnt
= 2;
}
break;
default:
break;
}
break;
}
case eIsNoReg
:
WrStrErrorPos
(ErrNum_InvReg
, &IndirComp
);
break;
case eRegAbort
:
/* will go to function end anyway after restoring separator */
break;
}
if (PPos
)
*PPos
= Save
;
goto chk
;
}
FirstFlag
= False
;
SegType
= -1;
pSegSepPos
= QuotPos
(pArg
->str.
p_str, ':');
if (pSegSepPos
)
{
StrCompSplitRef
(&SegComp
, &AddrComp
, pArg
, pSegSepPos
);
if (MomCPU
< CPU80251
)
{
WrError
(ErrNum_InvAddrMode
);
return;
}
else
{
if (!as_strcasecmp
(SegComp.
str.
p_str, "S"))
SegType
= -2;
else
{
SegType
= EvalStrIntExpressionWithResult
(&SegComp
, UInt8
, &EvalResult
);
if (!EvalResult.
OK)
return;
if (mFirstPassUnknown
(EvalResult.
Flags))
FirstFlag
= True
;
}
}
pAddrComp
= &AddrComp
;
}
else
pAddrComp
= pArg
;
switch (SegType
)
{
case -2:
H32
= EvalStrIntExpressionWithResult
(pAddrComp
, UInt9
, &EvalResult
);
ChkSpace
(SegIO
, EvalResult.
AddrSpaceMask);
if (mFirstPassUnknown
(EvalResult.
Flags))
H32
= (H32
& 0xff) | 0x80;
break;
case -1:
H32
= EvalStrIntExpressionWithResult
(pAddrComp
, UInt24
, &EvalResult
);
break;
default:
H32
= EvalStrIntExpressionWithResult
(pAddrComp
, UInt16
, &EvalResult
);
}
if (mFirstPassUnknown
(EvalResult.
Flags))
FirstFlag
= True
;
if (!EvalResult.
OK)
return;
if ((SegType
== -2) || ((SegType
== -1) && (EvalResult.
AddrSpaceMask & (1 << SegIO
))))
{
if (ChkRange
(H32
, 0x80, 0xff))
{
SaveAdrRelocs
(RelocTypeB8
, 0);
AdrMode
= ModDir8
;
AdrVals
[0] = H32
& 0xff;
AdrCnt
= 1;
}
}
else
{
if (SegType
>= 0)
H32
+= ((LongWord
)SegType
) << 16;
if (FirstFlag
)
H32
&= ((MomCPU
< CPU80251
) || ((Mask
& ModDir16
) == 0)) ? 0xff : 0xffff;
if (((H32
< 128) || ((H32
< 256) && (MomCPU
< CPU80251
))) && ((Mask
& MModDir8
) != 0))
{
if (MomCPU
< CPU80251
)
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
SaveAdrRelocs
(RelocTypeB8
, 0);
AdrMode
= ModDir8
;
AdrVals
[0] = H32
&0xff;
AdrCnt
= 1;
}
else if ((MomCPU
< CPU80251
) || (H32
> 0xffff)) WrError
(ErrNum_AdrOverflow
);
else
{
AdrMode
= ModDir16
;
AdrCnt
= 2;
AdrVals
[1] = H32
& 0xff;
AdrVals
[0] = (H32
>> 8) & 0xff;
}
}
chk
:
if ((AdrMode
!= ModNone
) && ((Mask
& (1 << AdrMode
)) == 0))
{
if (ExtMask
& (1 << AdrMode
))
(void)ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
);
else
WrError
(ErrNum_InvAddrMode
);
AdrCnt
= 0;
AdrMode
= ModNone
;
}
}
static void DissectBit_251
(char *pDest
, size_t DestSize
, LargeWord Inp
)
{
as_snprintf
(pDest
, DestSize
, "%~02.*u%s.%u",
ListRadixBase
, (unsigned)(Inp
& 0xff), GetIntConstIntelSuffix
(ListRadixBase
),
(unsigned)(Inp
>> 24));
}
static ShortInt DecodeBitAdr
(tStrComp
*pArg
, LongInt
*Erg
, Boolean MayShorten
)
{
tEvalResult EvalResult
;
char *pPos
, Save
= '\0';
tStrComp RegPart
, BitPart
;
pPos
= RQuotPos
(pArg
->str.
p_str, '.');
if (pPos
)
Save
= StrCompSplitRef
(&RegPart
, &BitPart
, pArg
, pPos
);
if (MomCPU
< CPU80251
)
{
if (!pPos
)
{
*Erg
= EvalStrIntExpressionWithResult
(pArg
, UInt8
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegBData
, EvalResult.
AddrSpaceMask);
return ModBit51
;
}
else
return ModNone
;
}
else
{
*Erg
= EvalStrIntExpressionWithResult
(&RegPart
, UInt8
, &EvalResult
);
if (mFirstPassUnknown
(EvalResult.
Flags))
*Erg
= 0x20;
*pPos
= Save
;
if (!EvalResult.
OK) return ModNone
;
else
{
ChkSpace
(SegData
, EvalResult.
AddrSpaceMask);
Save
= EvalStrIntExpressionWithResult
(&BitPart
, UInt3
, &EvalResult
);
if (!EvalResult.
OK) return ModNone
;
else
{
if (*Erg
> 0x7f)
{
if ((*Erg
) & 7)
WrError
(ErrNum_NotBitAddressable
);
}
else
{
if (((*Erg
) & 0xe0) != 0x20)
WrError
(ErrNum_NotBitAddressable
);
*Erg
= (*Erg
- 0x20) << 3;
}
*Erg
+= Save
;
return ModBit51
;
}
}
}
}
else
{
if (!pPos
)
{
static const LongWord ValidBits
= 0x070000fful
;
*Erg
= EvalStrIntExpressionWithResult
(pArg
, Int32
, &EvalResult
);
if (mFirstPassUnknown
(EvalResult.
Flags))
*Erg
&= ValidBits
;
if (*Erg
& ~ValidBits
)
{
WrError
(ErrNum_InvBitPos
);
EvalResult.
OK = False
;
}
}
else
{
DecodeAdr
(&RegPart
, MModDir8
);
*pPos
= Save
;
if (AdrMode
== ModNone
)
EvalResult.
OK = False
;
else
{
*Erg
= EvalStrIntExpressionWithResult
(&BitPart
, UInt3
, &EvalResult
) << 24;
if (EvalResult.
OK)
(*Erg
) += AdrVals
[0];
}
}
if (!EvalResult.
OK)
return ModNone
;
else if (MayShorten
)
{
if (((*Erg
) & 0x87) == 0x80)
{
*Erg
= ((*Erg
) & 0xf8) + ((*Erg
) >> 24);
return ModBit51
;
}
else if (((*Erg
) & 0xf0) == 0x20)
{
*Erg
= (((*Erg
) & 0x0f) << 3) + ((*Erg
) >> 24);
return ModBit51
;
}
else
return ModBit251
;
}
else
return ModBit251
;
}
}
static Boolean Chk504
(LongInt Adr
)
{
return ((MomCPU
== CPU80504
) && ((Adr
& 0x7ff) == 0x7fe));
}
static Boolean NeedsPrefix
(Word Opcode
)
{
return (((Opcode
&0x0f) >= 6) && ((SrcMode
!= 0) != ((Hi
(Opcode
) != 0) != 0)));
}
static void PutCode
(Word Opcode
)
{
if (((Opcode
&0x0f) < 6) || ((SrcMode
!= 0) != ((Hi
(Opcode
) == 0) != 0)))
{
BAsmCode
[0] = Lo
(Opcode
);
CodeLen
= 1;
}
else
{
BAsmCode
[0] = 0xa5;
BAsmCode
[1] = Lo
(Opcode
);
CodeLen
= 2;
}
}
static Boolean IsCarry
(const char *pArg
)
{
return (!as_strcasecmp
(pArg
, "C")) || (!as_strcasecmp
(pArg
, "CY"));
}
/*-------------------------------------------------------------------------*/
/* Einzelfaelle */
static void DecodeMOV
(Word Index
)
{
LongInt AdrLong
;
Byte HSize
, HReg
;
Integer AdrInt
;
UNUSED
(Index
);
if (!ChkArgCnt
(2, 2));
else if (IsCarry
(ArgStr
[1].
str.
p_str))
{
switch (DecodeBitAdr
(&ArgStr
[2], &AdrLong
, True
))
{
case ModBit51
:
PutCode
(0xa2);
BAsmCode
[CodeLen
] = AdrLong
& 0xff;
CodeLen
++;
break;
case ModBit251
:
PutCode
(0x1a9);
BAsmCode
[CodeLen
] = 0xa0 + (AdrLong
>> 24);
BAsmCode
[CodeLen
+ 1] = AdrLong
& 0xff;
CodeLen
+=2;
break;
}
}
else if ((!as_strcasecmp
(ArgStr
[2].
str.
p_str, "C")) || (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "CY")))
{
switch (DecodeBitAdr
(&ArgStr
[1], &AdrLong
, True
))
{
case ModBit51
:
PutCode
(0x92);
BAsmCode
[CodeLen
] = AdrLong
& 0xff;
CodeLen
++;
break;
case ModBit251
:
PutCode
(0x1a9);
BAsmCode
[CodeLen
] = 0x90 + (AdrLong
>> 24);
BAsmCode
[CodeLen
+ 1] = AdrLong
& 0xff;
CodeLen
+=2;
break;
}
}
else if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "DPTR"))
{
SetOpSize
((MomCPU
== CPU80C390
) ? 3 : 1);
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
PutCode
(0x90);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
TransferAdrRelocs
(CodeLen
);
CodeLen
+= AdrCnt
;
break;
}
}
else
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModReg
| MModIReg8
| MModIReg
| MModInd
| MModDir8
| MModDir16
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModIReg
| MModInd
| MModDir8
| MModDir16
| MModImm
);
switch (AdrMode
)
{
case ModReg
:
if ((AdrPart
< 8) && (!SrcMode
))
PutCode
(0xe8 + AdrPart
);
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x17c);
BAsmCode
[CodeLen
++] = (AccReg
<< 4) + AdrPart
;
}
break;
case ModIReg8
:
PutCode
(0xe6 + AdrPart
);
break;
case ModIReg
:
PutCode
(0x17e);
BAsmCode
[CodeLen
++] = (AdrPart
<< 4) + 0x09 + AdrSize
;
BAsmCode
[CodeLen
++] = (AccReg
<< 4);
break;
case ModInd
:
PutCode
(0x109 + (AdrSize
<< 4));
BAsmCode
[CodeLen
++] = (AccReg
<< 4) + AdrPart
;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
case ModDir8
:
PutCode
(0xe5);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModDir16
:
PutCode
(0x17e);
BAsmCode
[CodeLen
++] = (AccReg
<< 4) + 0x03;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
case ModImm
:
PutCode
(0x74);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
case ModReg
:
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModIReg
| MModInd
| MModDir8
| MModDir16
| MModImm
| MModImmEx
);
switch (AdrMode
)
{
case ModReg
:
if ((OpSize
== 0) && (AdrPart
== AccReg
) && (HReg
< 8))
PutCode
(0xf8 + HReg
);
else if ((OpSize
== 0) && (HReg
== AccReg
) && (AdrPart
< 8))
PutCode
(0xe8 + AdrPart
);
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x17c + OpSize
);
if (OpSize
== 2)
BAsmCode
[CodeLen
- 1]++;
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
}
break;
case ModIReg8
:
if ((OpSize
!= 0) || (HReg
!= AccReg
)) WrError
(ErrNum_InvAddrMode
);
else
PutCode
(0xe6 + AdrPart
);
break;
case ModIReg
:
if (OpSize
== 0)
{
PutCode
(0x17e);
BAsmCode
[CodeLen
++] = (AdrPart
<< 4) + 0x09 + AdrSize
;
BAsmCode
[CodeLen
++] = HReg
<< 4;
}
else if (OpSize
== 1)
{
PutCode
(0x10b);
BAsmCode
[CodeLen
++] = (AdrPart
<< 4) + 0x08 + AdrSize
;
BAsmCode
[CodeLen
++] = HReg
<< 4;
}
else
WrError
(ErrNum_InvAddrMode
);
break;
case ModInd
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x109 + (AdrSize
<< 4) + (OpSize
<< 6));
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
case ModDir8
:
if ((OpSize
== 0) && (HReg
== AccReg
))
{
PutCode
(0xe5);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else if ((OpSize
== 0) && (HReg
< 8) && (!SrcMode
))
{
PutCode
(0xa8 + HReg
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x17e);
BAsmCode
[CodeLen
++] = 0x01 + (HReg
<< 4) + (OpSize
<< 2);
if (OpSize
== 2)
BAsmCode
[CodeLen
- 1] += 4;
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
break;
case ModDir16
:
PutCode
(0x17e);
BAsmCode
[CodeLen
++] = 0x03 + (HReg
<< 4) + (OpSize
<< 2);
if (OpSize
== 2)
BAsmCode
[CodeLen
- 1] += 4;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
case ModImm
:
if ((OpSize
== 0) && (HReg
== AccReg
))
{
PutCode
(0x74);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else if ((OpSize
== 0) && (HReg
< 8) && (!SrcMode
))
{
PutCode
(0x78 + HReg
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x17e);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
case ModImmEx
:
PutCode
(0x17e);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = 0x0c + (HReg
<< 4);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
}
break;
case ModIReg8
:
SetOpSize
(0); HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModAcc
| MModDir8
| MModImm
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(0xf6 + HReg
);
break;
case ModDir8
:
PutCode
(0xa6 + HReg
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModImm
:
PutCode
(0x76 + HReg
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
case ModIReg
:
HReg
= AdrPart
; HSize
= AdrSize
;
DecodeAdr
(&ArgStr
[2], MModReg
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
== 0)
{
PutCode
(0x17a);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + 0x09 + HSize
;
BAsmCode
[CodeLen
++] = AdrPart
<< 4;
}
else if (OpSize
== 1)
{
PutCode
(0x11b);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + 0x08 + HSize
;
BAsmCode
[CodeLen
++] = AdrPart
<< 4;
}
else
WrError
(ErrNum_InvAddrMode
);
}
break;
case ModInd
:
HReg
= AdrPart
; HSize
= AdrSize
;
AdrInt
= (((Word
)AdrVals
[0]) << 8) + AdrVals
[1];
DecodeAdr
(&ArgStr
[2], MModReg
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x119 + (HSize
<< 4) + (OpSize
<< 6));
BAsmCode
[CodeLen
++] = (AdrPart
<< 4) + HReg
;
BAsmCode
[CodeLen
++] = Hi
(AdrInt
);
BAsmCode
[CodeLen
++] = Lo
(AdrInt
);
}
}
break;
case ModDir8
:
MinOneIs0
= True
;
HReg
= AdrVals
[0];
SaveBackupAdrRelocs
();
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModDir8
| MModImm
);
switch (AdrMode
)
{
case ModReg
:
if ((OpSize
== 0) && (AdrPart
== AccReg
))
{
PutCode
(0xf5);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
}
else if ((OpSize
== 0) && (AdrPart
< 8) && (!SrcMode
))
{
PutCode
(0x88 + AdrPart
);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
}
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x17a);
BAsmCode
[CodeLen
++] = 0x01 + (AdrPart
<< 4) + (OpSize
<< 2);
if (OpSize
== 2)
BAsmCode
[CodeLen
- 1] += 4;
BAsmCode
[CodeLen
++] = HReg
;
}
break;
case ModIReg8
:
PutCode
(0x86 + AdrPart
);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
break;
case ModDir8
:
PutCode
(0x85);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
break;
case ModImm
:
PutCode
(0x75);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
case ModDir16
:
AdrInt
= (((Word
)AdrVals
[0]) << 8) + AdrVals
[1];
DecodeAdr
(&ArgStr
[2], MModReg
);
switch (AdrMode
)
{
case ModReg
:
PutCode
(0x17a);
BAsmCode
[CodeLen
++] = 0x03 + (AdrPart
<< 4) + (OpSize
<< 2);
if (OpSize
== 2) BAsmCode
[CodeLen
- 1] += 4;
BAsmCode
[CodeLen
++] = Hi
(AdrInt
);
BAsmCode
[CodeLen
++] = Lo
(AdrInt
);
break;
}
break;
}
}
}
static void DecodeLogic
(Word Index
)
{
Byte HReg
;
LongInt AdrLong
;
int z
;
/* Index: ORL=0 ANL=1 XRL=2 */
if (!ChkArgCnt
(2, 2));
else if (IsCarry
(ArgStr
[1].
str.
p_str))
{
if (Index
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
Boolean InvFlag
;
ShortInt Result
;
HReg
= Index
<< 4;
InvFlag
= *ArgStr
[2].
str.
p_str == '/';
if (InvFlag
)
{
tStrComp Comp
;
StrCompRefRight
(&Comp
, &ArgStr
[2], 1);
Result
= DecodeBitAdr
(&Comp
, &AdrLong
, True
);
}
else
Result
= DecodeBitAdr
(&ArgStr
[2], &AdrLong
, True
);
switch (Result
)
{
case ModBit51
:
PutCode
((InvFlag
) ? 0xa0 + HReg
: 0x72 + HReg
);
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
break;
case ModBit251
:
PutCode
(0x1a9);
BAsmCode
[CodeLen
++] = ((InvFlag
) ? 0xe0 : 0x70) + HReg
+ (AdrLong
>> 24);
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
break;
}
}
}
else
{
z
= (Index
<< 4) + 0x40;
DecodeAdr
(&ArgStr
[1], MModAcc
| MModReg
| MModDir8
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModIReg
| MModDir8
| MModDir16
| MModImm
);
switch (AdrMode
)
{
case ModReg
:
if ((AdrPart
< 8) && (!SrcMode
)) PutCode
(z
+ 8 + AdrPart
);
else
{
PutCode
(z
+ 0x10c);
BAsmCode
[CodeLen
++] = AdrPart
+ (AccReg
<< 4);
}
break;
case ModIReg8
:
PutCode
(z
+ 6 + AdrPart
);
break;
case ModIReg
:
PutCode
(z
+ 0x10e);
BAsmCode
[CodeLen
++] = 0x09 + AdrSize
+ (AdrPart
<< 4);
BAsmCode
[CodeLen
++] = AccReg
<< 4;
break;
case ModDir8
:
PutCode
(z
+ 0x05);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModDir16
:
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = 0x03 + (AccReg
<< 4);
memcpy(BAsmCode
+CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
case ModImm
:
PutCode
(z
+ 0x04);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
case ModReg
:
if (MomCPU
< CPU80251
) WrError
(ErrNum_InvAddrMode
);
else
{
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModIReg
| MModDir8
| MModDir16
| MModImm
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(z
+ 0x10c + OpSize
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
}
break;
case ModIReg8
:
if ((OpSize
!= 0) || (HReg
!= AccReg
)) WrError
(ErrNum_InvAddrMode
);
else
PutCode
(z
+ 0x06 + AdrPart
);
break;
case ModIReg
:
if (OpSize
!= 0) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = 0x09 + AdrSize
+ (AdrPart
<< 4);
BAsmCode
[CodeLen
++] = HReg
<< 4;
}
break;
case ModDir8
:
if ((OpSize
== 0) && (HReg
== AccReg
))
{
PutCode
(0x05 + z
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2) + 1;
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
break;
case ModDir16
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2) + 3;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
case ModImm
:
if ((OpSize
== 0) && (HReg
== AccReg
))
{
PutCode
(0x04 + z
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2);
TransferAdrRelocs
(CodeLen
);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
}
}
break;
case ModDir8
:
HReg
= AdrVals
[0];
SaveBackupAdrRelocs
();
SetOpSize
(0);
DecodeAdr
(&ArgStr
[2], MModAcc
| MModImm
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(z
+ 0x02);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
break;
case ModImm
:
PutCode
(z
+ 0x03);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
}
}
}
static void DecodeMOVC
(Word Index
)
{
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
if (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "@A+DPTR"))
PutCode
(0x93);
else if (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "@A+PC"))
PutCode
(0x83);
else
WrError
(ErrNum_InvAddrMode
);
break;
}
}
}
static void DecodeMOVH
(Word Index
)
{
Byte HReg
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80251
))
{
DecodeAdr
(&ArgStr
[1], MModReg
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
!= 2) WrError
(ErrNum_InvAddrMode
);
else
{
HReg
= AdrPart
;
OpSize
--;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
PutCode
(0x17a);
BAsmCode
[CodeLen
++] = 0x0c + (HReg
<< 4);
TransferAdrRelocs
(CodeLen
);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
}
}
break;
}
}
}
static void DecodeMOVZS
(Word Index
)
{
Byte HReg
;
int z
;
UNUSED
(Index
);
z
= Ord
(Memo
("MOVS")) << 4;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80251
))
{
DecodeAdr
(&ArgStr
[1], MModReg
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
!= 1) WrError
(ErrNum_InvAddrMode
);
else
{
HReg
= AdrPart
;
OpSize
--;
DecodeAdr
(&ArgStr
[2], MModReg
);
switch (AdrMode
)
{
case ModReg
:
PutCode
(0x10a + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
break;
}
}
break;
}
}
}
static void DecodeMOVX
(Word Index
)
{
int z
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
z
= 0;
if ((!as_strcasecmp
(ArgStr
[2].
str.
p_str, "A")) || ((MomCPU
>= CPU80251
) && (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "R11"))))
{
z
= 0x10;
strcpy(ArgStr
[2].
str.
p_str, ArgStr
[1].
str.
p_str);
strmaxcpy
(ArgStr
[1].
str.
p_str, "A", STRINGSIZE
);
}
if ((as_strcasecmp
(ArgStr
[1].
str.
p_str, "A")) && ((MomCPU
< CPU80251
) || (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "R11")))) WrError
(ErrNum_InvAddrMode
);
else if (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "@DPTR"))
PutCode
(0xe0 + z
);
else
{
DecodeAdr
(&ArgStr
[2], MModIReg8
);
switch (AdrMode
)
{
case ModIReg8
:
PutCode
(0xe2 + AdrPart
+ z
);
break;
}
}
}
}
static void DecodeStack
(Word Index
)
{
int z
;
/* Index: PUSH=0 POP=1 PUSHW=2 */
z
= (Index
& 1) << 4;
if (ChkArgCnt
(1, 1))
{
if (*ArgStr
[1].
str.
p_str == '#')
SetOpSize
(Ord
(Index
== 2));
DecodeAdr
(&ArgStr
[1], MModDir8
| MModReg
| ((z
== 0x10) ? 0 : MModImm
));
switch (AdrMode
)
{
case ModDir8
:
PutCode
(0xc0 + z
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModReg
:
if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x1ca + z
);
BAsmCode
[CodeLen
++] = 0x08 + (AdrPart
<< 4) + OpSize
+ (Ord
(OpSize
== 2));
}
break;
case ModImm
:
if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x1ca);
BAsmCode
[CodeLen
++] = 0x02 + (OpSize
<< 2);
TransferAdrRelocs
(CodeLen
);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
}
}
}
static void DecodeXCH
(Word Index
)
{
Byte HReg
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModReg
| MModIReg8
| MModDir8
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModDir8
);
switch (AdrMode
)
{
case ModReg
:
if (AdrPart
> 7) WrError
(ErrNum_InvAddrMode
);
else
PutCode
(0xc8 + AdrPart
);
break;
case ModIReg8
:
PutCode
(0xc6 + AdrPart
);
break;
case ModDir8
:
PutCode
(0xc5);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
case ModReg
:
if ((OpSize
!= 0) || (AdrPart
> 7)) WrError
(ErrNum_InvAddrMode
);
else
{
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(0xc8 + HReg
);
break;
}
}
break;
case ModIReg8
:
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(0xc6 + HReg
);
break;
}
break;
case ModDir8
:
HReg
= AdrVals
[0]; SaveBackupAdrRelocs
();
DecodeAdr
(&ArgStr
[2], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(0xc5);
TransferBackupAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = HReg
;
break;
}
break;
}
}
}
static void DecodeXCHD
(Word Index
)
{
Byte HReg
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModIReg8
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModIReg8
);
switch (AdrMode
)
{
case ModIReg8
:
PutCode
(0xd6 + AdrPart
);
break;
}
break;
case ModIReg8
:
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(0xd6 + HReg
);
break;
}
break;
}
}
}
#define RelocTypeABranch11 (11 | RelocFlagBig | RelocFlagPage | (5 << 8) | (3 << 12)) | (0 << 16)
#define RelocTypeABranch19 (19 | RelocFlagBig | RelocFlagPage | (5 << 8) | (3 << 12)) | (0 << 16)
static void DecodeABranch
(Word Index
)
{
/* Index: AJMP = 0 ACALL = 1 */
if (ChkArgCnt
(1, 1))
{
tEvalResult EvalResult
;
LongInt AdrLong
= EvalStrIntExpressionWithResult
(&ArgStr
[1], Int24
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
if (MomCPU
== CPU80C390
)
{
if (ChkSamePage
(EProgCounter
() + 3, AdrLong
, 19, EvalResult.
Flags))
{
PutCode
(0x01 + (Index
<< 4) + (((AdrLong
>> 16) & 7) << 5));
BAsmCode
[CodeLen
++] = Hi
(AdrLong
);
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
TransferRelocs
(ProgCounter
() - 3, RelocTypeABranch19
);
}
}
else
{
if (!ChkSamePage
(EProgCounter
(), AdrLong
, 11, EvalResult.
Flags));
else if (Chk504
(EProgCounter
())) WrError
(ErrNum_NotOnThisAddress
);
else
{
PutCode
(0x01 + (Index
<< 4) + ((Hi
(AdrLong
) & 7) << 5));
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
TransferRelocs
(ProgCounter
() - 2, RelocTypeABranch11
);
}
}
}
}
}
static void DecodeLBranch
(Word Index
)
{
/* Index: LJMP=0 LCALL=1 */
if (!ChkArgCnt
(1, 1));
else if (!ChkMinCPU
(CPU8051
));
else if (*ArgStr
[1].
str.
p_str == '@')
{
DecodeAdr
(&ArgStr
[1], MModIReg
);
switch (AdrMode
)
{
case ModIReg
:
if (AdrSize
!= 0) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x189 + (Index
<< 4));
BAsmCode
[CodeLen
++] = 0x04 + (AdrPart
<< 4);
}
break;
}
}
else
{
tEvalResult EvalResult
;
LongInt AdrLong
= EvalStrIntExpressionWithResult
(&ArgStr
[1], (MomCPU
< CPU80C390
) ? Int16
: Int24
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
if (MomCPU
== CPU80C390
)
{
PutCode
(0x02 + (Index
<< 4));
BAsmCode
[CodeLen
++] = (AdrLong
>> 16) & 0xff;
BAsmCode
[CodeLen
++] = (AdrLong
>> 8) & 0xff;
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
TransferRelocs
(ProgCounter
() + 1, RelocTypeB24
);
}
else
{
if ((MomCPU
>= CPU80251
) && !ChkSamePage
(EProgCounter
() + 3, AdrLong
, 16, EvalResult.
Flags));
else
{
PutCode
(0x02 + (Index
<< 4));
BAsmCode
[CodeLen
++] = (AdrLong
>> 8) & 0xff;
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
TransferRelocs
(ProgCounter
() + 1, RelocTypeB16
);
}
}
}
}
}
static void DecodeEBranch
(Word Index
)
{
/* Index: AJMP=0 ACALL=1 */
if (!ChkArgCnt
(1, 1));
else if (!ChkMinCPU
(CPU80251
));
else if (*ArgStr
[1].
str.
p_str == '@')
{
DecodeAdr
(&ArgStr
[1], MModIReg
);
switch (AdrMode
)
{
case ModIReg
:
if (AdrSize
!= 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x189 + (Index
<< 4));
BAsmCode
[CodeLen
++] = 0x08 + (AdrPart
<< 4);
}
break;
}
}
else
{
tEvalResult EvalResult
;
LongInt AdrLong
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt24
, &EvalResult
);
if (EvalResult.
OK)
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
PutCode
(0x18a + (Index
<< 4));
BAsmCode
[CodeLen
++] = (AdrLong
>> 16) & 0xff;
BAsmCode
[CodeLen
++] = (AdrLong
>> 8) & 0xff;
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
}
}
static void DecodeJMP
(Word Index
)
{
LongInt AdrLong
, Dist
;
Boolean OK
;
UNUSED
(Index
);
if (!ChkArgCnt
(1, 1));
else if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "@A+DPTR"))
PutCode
(0x73);
else if (*ArgStr
[1].
str.
p_str == '@')
{
DecodeAdr
(&ArgStr
[1], MModIReg
);
switch (AdrMode
)
{
case ModIReg
:
PutCode
(0x189);
BAsmCode
[CodeLen
++] = 0x04 + (AdrSize
<< 1) + (AdrPart
<< 4);
break;
}
}
else
{
AdrLong
= EvalStrIntExpression
(&ArgStr
[1], UInt24
, &OK
);
if (OK
)
{
Dist
= AdrLong
- (EProgCounter
() + 2);
if ((Dist
<=127) && (Dist
>= -128))
{
PutCode
(0x80);
BAsmCode
[CodeLen
++] = Dist
& 0xff;
}
else if ((!Chk504
(EProgCounter
())) && ((AdrLong
>> 11) == ((((long)EProgCounter
()) + 2) >> 11)))
{
PutCode
(0x01 + ((Hi
(AdrLong
) & 7) << 5));
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
}
else if (MomCPU
< CPU8051
) WrError
(ErrNum_JmpTargOnDiffPage
);
else if (((((long)EProgCounter
()) + 3) >> 16) == (AdrLong
>> 16))
{
PutCode
(0x02);
BAsmCode
[CodeLen
++] = Hi
(AdrLong
);
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
}
else if (MomCPU
< CPU80251
) WrError
(ErrNum_JmpTargOnDiffPage
);
else
{
PutCode
(0x18a);
BAsmCode
[CodeLen
++] = (AdrLong
>> 16) & 0xff;
BAsmCode
[CodeLen
++] = (AdrLong
>> 8) & 0xff;
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
}
}
}
static void DecodeCALL
(Word Index
)
{
LongInt AdrLong
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Index
);
if (!ChkArgCnt
(1, 1));
else if (*ArgStr
[1].
str.
p_str == '@')
{
DecodeAdr
(&ArgStr
[1], MModIReg
);
switch (AdrMode
)
{
case ModIReg
:
PutCode
(0x199);
BAsmCode
[CodeLen
++] = 0x04 + (AdrSize
<< 1) + (AdrPart
<< 4);
break;
}
}
else
{
AdrLong
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], UInt24
, &OK
, &Flags
);
if (OK
)
{
if ((!Chk504
(EProgCounter
())) && ((AdrLong
>> 11) == ((((long)EProgCounter
()) + 2) >> 11)))
{
PutCode
(0x11 + ((Hi
(AdrLong
) & 7) << 5));
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
}
else if (MomCPU
< CPU8051
) WrError
(ErrNum_JmpTargOnDiffPage
);
else if (ChkSamePage
(AdrLong
, EProgCounter
() + 3, 16, Flags
))
{
PutCode
(0x12);
BAsmCode
[CodeLen
++] = Hi
(AdrLong
);
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
}
}
}
}
static void DecodeDJNZ
(Word Index
)
{
LongInt AdrLong
;
Boolean OK
;
tSymbolFlags Flags
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
AdrLong
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], UInt24
, &OK
, &Flags
);
SubPCRefReloc
();
if (OK
)
{
DecodeAdr
(&ArgStr
[1], MModReg
| MModDir8
);
switch (AdrMode
)
{
case ModReg
:
if ((OpSize
!= 0) || (AdrPart
> 7)) WrError
(ErrNum_InvAddrMode
);
else
{
AdrLong
-= EProgCounter
() + 2 + Ord
(NeedsPrefix
(0xd8 + AdrPart
));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0xd8 + AdrPart
);
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
}
break;
case ModDir8
:
AdrLong
-= EProgCounter
() + 3 + Ord
(NeedsPrefix
(0xd5));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0xd5);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
BAsmCode
[CodeLen
++] = Lo
(AdrLong
);
}
break;
}
}
}
}
static void DecodeCJNE
(Word Index
)
{
LongInt AdrLong
;
Boolean OK
;
tSymbolFlags Flags
;
Byte HReg
;
UNUSED
(Index
);
if (ChkArgCnt
(3, 3))
{
AdrLong
= EvalStrIntExpressionWithFlags
(&ArgStr
[3], UInt24
, &OK
, &Flags
);
SubPCRefReloc
();
if (OK
)
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModIReg8
| MModReg
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModDir8
| MModImm
);
switch (AdrMode
)
{
case ModDir8
:
AdrLong
-= EProgCounter
() + 3 + Ord
(NeedsPrefix
(0xb5));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0xb5);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
break;
case ModImm
:
AdrLong
-= EProgCounter
() + 3 + Ord
(NeedsPrefix
(0xb5));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0xb4);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
break;
}
break;
case ModReg
:
if ((OpSize
!= 0) || (AdrPart
> 7)) WrError
(ErrNum_InvAddrMode
);
else
{
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
AdrLong
-= EProgCounter
() + 3 + Ord
(NeedsPrefix
(0xb8 + HReg
));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0xb8 + HReg
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
break;
}
}
break;
case ModIReg8
:
HReg
= AdrPart
; SetOpSize
(0);
DecodeAdr
(&ArgStr
[2], MModImm
);
switch (AdrMode
)
{
case ModImm
:
AdrLong
-= EProgCounter
() + 3 + Ord
(NeedsPrefix
(0xb6 + HReg
));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(Flags
)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0xb6 + HReg
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
break;
}
break;
}
}
}
}
static void DecodeADD
(Word Index
)
{
Byte HReg
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModReg
);
switch (AdrMode
)
{
case ModAcc
:
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir8
| MModDir16
| MModIReg8
| MModIReg
| MModReg
);
switch (AdrMode
)
{
case ModImm
:
PutCode
(0x24);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModDir8
:
PutCode
(0x25);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModDir16
:
PutCode
(0x12e);
BAsmCode
[CodeLen
++] = (AccReg
<< 4) + 3;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, 2);
CodeLen
+= 2;
break;
case ModIReg8
:
PutCode
(0x26 + AdrPart
);
break;
case ModIReg
:
PutCode
(0x12e);
BAsmCode
[CodeLen
++] = 0x09 + AdrSize
+ (AdrPart
<< 4);
BAsmCode
[CodeLen
++] = AccReg
<< 4;
break;
case ModReg
:
if ((AdrPart
< 8) && (!SrcMode
)) PutCode
(0x28 + AdrPart
);
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x12c);
BAsmCode
[CodeLen
++] = AdrPart
+ (AccReg
<< 4);
}
break;
}
break;
case ModReg
:
if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModImm
| MModReg
| MModDir8
| MModDir16
| MModIReg8
| MModIReg
);
switch (AdrMode
)
{
case ModImm
:
if ((OpSize
== 0) && (HReg
== AccReg
))
{
PutCode
(0x24);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else
{
PutCode
(0x12e);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
case ModReg
:
PutCode
(0x12c + OpSize
);
if (OpSize
== 2) BAsmCode
[CodeLen
- 1]++;
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
break;
case ModDir8
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else if ((OpSize
== 0) && (HReg
== AccReg
))
{
PutCode
(0x25);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
else
{
PutCode
(0x12e);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2) + 1;
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
break;
case ModDir16
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x12e);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2) + 3;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
case ModIReg8
:
if ((OpSize
!= 0) || (HReg
!= AccReg
)) WrError
(ErrNum_InvAddrMode
);
else PutCode
(0x26 + AdrPart
);
break;
case ModIReg
:
if (OpSize
!= 0) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x12e);
BAsmCode
[CodeLen
++] = 0x09 + AdrSize
+ (AdrPart
<< 4);
BAsmCode
[CodeLen
++] = HReg
<< 4;
}
break;
}
}
break;
}
}
}
static void DecodeSUBCMP
(Word Index
)
{
int z
;
Byte HReg
;
/* Index: SUB=0 CMP=1 */
z
= 0x90 + (Index
<< 5);
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80251
))
{
DecodeAdr
(&ArgStr
[1], MModReg
);
switch (AdrMode
)
{
case ModReg
:
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModImm
| MModReg
| MModDir8
| MModDir16
| MModIReg
| (Index
? MModImmEx
: 0));
switch (AdrMode
)
{
case ModImm
:
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2);
TransferAdrRelocs
(CodeLen
);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
case ModImmEx
:
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + 0x0c;
TransferAdrRelocs
(CodeLen
);
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
break;
case ModReg
:
PutCode
(0x10c + z
+ OpSize
);
if (OpSize
== 2)
BAsmCode
[CodeLen
- 1]++;
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
break;
case ModDir8
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2) + 1;
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
break;
case ModDir16
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + (OpSize
<< 2) + 3;
memcpy(BAsmCode
+ CodeLen
, AdrVals
, AdrCnt
);
CodeLen
+= AdrCnt
;
}
break;
case ModIReg
:
if (OpSize
!= 0) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = 0x09 + AdrSize
+ (AdrPart
<< 4);
BAsmCode
[CodeLen
++] = HReg
<< 4;
}
break;
}
break;
}
}
}
static void DecodeADDCSUBB
(Word Index
)
{
Byte HReg
;
/* Index: ADDC=0 SUBB=1 */
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
HReg
= 0x30 + (Index
*0x60);
DecodeAdr
(&ArgStr
[2], MModReg
| MModIReg8
| MModDir8
| MModImm
);
switch (AdrMode
)
{
case ModReg
:
if (AdrPart
> 7) WrError
(ErrNum_InvAddrMode
);
else
PutCode
(HReg
+ 0x08 + AdrPart
);
break;
case ModIReg8
:
PutCode
(HReg
+ 0x06 + AdrPart
);
break;
case ModDir8
:
PutCode
(HReg
+ 0x05);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
case ModImm
:
PutCode
(HReg
+ 0x04);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
break;
}
break;
}
}
}
static void DecodeINCDEC
(Word Index
)
{
Byte HReg
;
int z
;
Boolean OK
;
tSymbolFlags Flags
;
/* Index: INC=0 DEC=1 */
z
= Index
<< 4;
if (!ChkArgCnt
(1, 2));
else if ((ArgCnt
== 2) && (*ArgStr
[2].
str.
p_str != '#')) WrError
(ErrNum_InvAddrMode
);
else
{
if (1 == ArgCnt
)
{
HReg
= 1;
OK
= True
;
Flags
= eSymbolFlag_None
;
}
else
HReg
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[2], 1, UInt3
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
HReg
= 1;
if (OK
)
{
OK
= True
;
if (HReg
== 1)
HReg
= 0;
else if (HReg
== 2)
HReg
= 1;
else if (HReg
== 4)
HReg
= 2;
else
OK
= False
;
if (!OK
) WrError
(ErrNum_OverRange
);
else if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "DPTR"))
{
if (Index
== 1) WrError
(ErrNum_InvAddrMode
);
else if (HReg
!= 0) WrError
(ErrNum_OverRange
);
else
PutCode
(0xa3);
}
else
{
DecodeAdr
(&ArgStr
[1], MModAcc
| MModReg
| MModDir8
| MModIReg8
);
switch (AdrMode
)
{
case ModAcc
:
if (HReg
== 0)
PutCode
(0x04 + z
);
else if (MomCPU
< CPU80251
) WrError
(ErrNum_OverRange
);
else
{
PutCode
(0x10b + z
);
BAsmCode
[CodeLen
++] = (AccReg
<< 4) + HReg
;
}
break;
case ModReg
:
if ((OpSize
== 0) && (AdrPart
== AccReg
) && (HReg
== 0))
PutCode
(0x04 + z
);
else if ((AdrPart
< 8) && (OpSize
== 0) && (HReg
== 0) && (!SrcMode
))
PutCode
(0x08 + z
+ AdrPart
);
else if (ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
))
{
PutCode
(0x10b + z
);
BAsmCode
[CodeLen
++] = (AdrPart
<< 4) + (OpSize
<< 2) + HReg
;
if (OpSize
== 2)
BAsmCode
[CodeLen
- 1] += 4;
}
break;
case ModDir8
:
if (HReg
!= 0) WrError
(ErrNum_OverRange
);
else
{
PutCode
(0x05 + z
);
TransferAdrRelocs
(CodeLen
);
BAsmCode
[CodeLen
++] = AdrVals
[0];
}
break;
case ModIReg8
:
if (HReg
!= 0) WrError
(ErrNum_OverRange
);
else
PutCode
(0x06 + z
+ AdrPart
);
break;
}
}
}
}
}
static void DecodeMULDIV
(Word Index
)
{
int z
;
Byte HReg
;
/* Index: DIV=0 MUL=1 */
z
= Index
<< 5;
if (!ChkArgCnt
(1, 2));
else if (ArgCnt
== 1)
{
if (as_strcasecmp
(ArgStr
[1].
str.
p_str, "AB")) WrError
(ErrNum_InvAddrMode
);
else
PutCode
(0x84 + z
);
}
else
{
DecodeAdr
(&ArgStr
[1], MModReg
);
switch (AdrMode
)
{
case ModReg
:
HReg
= AdrPart
;
DecodeAdr
(&ArgStr
[2], MModReg
);
switch (AdrMode
)
{
case ModReg
:
if (!ChkMinCPUExt
(CPU80251
, ErrNum_AddrModeNotSupported
));
else if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x18c + z
+ OpSize
);
BAsmCode
[CodeLen
++] = (HReg
<< 4) + AdrPart
;
}
break;
}
break;
}
}
}
static void DecodeBits
(Word Index
)
{
LongInt AdrLong
;
int z
;
/* Index: CPL=0 CLR=1 SETB=2 */
z
= Index
<< 4;
if (!ChkArgCnt
(1, 1));
else if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "A"))
{
if (Memo
("SETB")) WrError
(ErrNum_InvAddrMode
);
else
PutCode
(0xf4 - z
);
}
else if (IsCarry
(ArgStr
[1].
str.
p_str))
PutCode
(0xb3 + z
);
else
switch (DecodeBitAdr
(&ArgStr
[1], &AdrLong
, True
))
{
case ModBit51
:
PutCode
(0xb2 + z
);
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
break;
case ModBit251
:
PutCode
(0x1a9);
BAsmCode
[CodeLen
++] = 0xb0 + z
+ (AdrLong
>> 24);
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
break;
}
}
static void DecodeShift
(Word Index
)
{
int z
;
/* Index: SRA=0 SRL=1 SLL=3 */
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(CPU80251
))
{
z
= Index
<< 4;
DecodeAdr
(&ArgStr
[1], MModReg
);
switch (AdrMode
)
{
case ModReg
:
if (OpSize
== 2) WrError
(ErrNum_InvAddrMode
);
else
{
PutCode
(0x10e + z
);
BAsmCode
[CodeLen
++] = (AdrPart
<< 4) + (OpSize
<< 2);
}
break;
}
}
}
static void DecodeCond
(Word Index
)
{
FixedOrder
*FixedZ
= CondOrders
+ Index
;
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(FixedZ
->MinCPU
))
{
tEvalResult EvalResult
;
LongInt AdrLong
= EvalStrIntExpressionWithResult
(&ArgStr
[1], UInt24
, &EvalResult
);
SubPCRefReloc
();
if (EvalResult.
OK)
{
AdrLong
-= EProgCounter
() + 2 + Ord
(NeedsPrefix
(FixedZ
->Code
));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(EvalResult.
Flags)) WrError
(ErrNum_JmpDistTooBig
);
else
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
PutCode
(FixedZ
->Code
);
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
}
}
}
static void DecodeBCond
(Word Index
)
{
FixedOrder
*FixedZ
= BCondOrders
+ Index
;
LongInt AdrLong
, BitLong
;
tEvalResult EvalResult
;
if (ChkArgCnt
(2, 2))
{
AdrLong
= EvalStrIntExpressionWithResult
(&ArgStr
[2], UInt24
, &EvalResult
);
SubPCRefReloc
();
if (EvalResult.
OK)
{
ChkSpace
(SegCode
, EvalResult.
AddrSpaceMask);
switch (DecodeBitAdr
(&ArgStr
[1], &BitLong
, True
))
{
case ModBit51
:
AdrLong
-= EProgCounter
() + 3 + Ord
(NeedsPrefix
(FixedZ
->Code
));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(EvalResult.
Flags)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(FixedZ
->Code
);
BAsmCode
[CodeLen
++] = BitLong
& 0xff;
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
break;
case ModBit251
:
AdrLong
-= EProgCounter
() + 4 + Ord
(NeedsPrefix
(0x1a9));
if (((AdrLong
< -128) || (AdrLong
> 127)) && !mSymbolQuestionable
(EvalResult.
Flags)) WrError
(ErrNum_JmpDistTooBig
);
else
{
PutCode
(0x1a9);
BAsmCode
[CodeLen
++] = FixedZ
->Code
+ (BitLong
>> 24);
BAsmCode
[CodeLen
++] = BitLong
& 0xff;
BAsmCode
[CodeLen
++] = AdrLong
& 0xff;
}
break;
}
}
}
}
static void DecodeAcc
(Word Index
)
{
FixedOrder
*FixedZ
= AccOrders
+ Index
;
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(FixedZ
->MinCPU
))
{
DecodeAdr
(&ArgStr
[1], MModAcc
);
switch (AdrMode
)
{
case ModAcc
:
PutCode
(FixedZ
->Code
);
break;
}
}
}
static void DecodeFixed
(Word Index
)
{
FixedOrder
*FixedZ
= FixedOrders
+ Index
;
if (ChkArgCnt
(0, 0)
&& ChkMinCPU
(FixedZ
->MinCPU
))
PutCode
(FixedZ
->Code
);
}
static void DecodeSFR
(Word Index
)
{
Word AdrByte
;
Boolean OK
;
tSymbolFlags Flags
;
as_addrspace_t DSeg
;
UNUSED
(Index
);
if (!ChkArgCnt
(1, 1));
else if (Memo
("SFRB") && !ChkMaxCPU
(CPU80C390
));
else
{
AdrByte
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], (MomCPU
>= CPU80251
) ? UInt9
: UInt8
, &OK
, &Flags
);
if (OK
&& !mFirstPassUnknown
(Flags
))
{
PushLocHandle
(-1);
DSeg
= (MomCPU
>= CPU80251
) ? SegIO
: SegData
;
EnterIntSymbol
(&LabPart
, AdrByte
, DSeg
, False
);
if (MakeUseList
)
{
if (AddChunk
(SegChunks
+ DSeg
, AdrByte
, 1, False
))
WrError
(ErrNum_Overlap
);
}
if (Memo
("SFRB"))
{
Byte BitStart
;
if (AdrByte
> 0x7f)
{
if ((AdrByte
& 7) != 0) WrError
(ErrNum_NotBitAddressable
);
BitStart
= AdrByte
;
}
else
{
if ((AdrByte
& 0xe0) != 0x20) WrError
(ErrNum_NotBitAddressable
);
BitStart
= (AdrByte
- 0x20) << 3;
}
if (MakeUseList
)
if (AddChunk
(SegChunks
+ SegBData
, BitStart
, 8, False
)) WrError
(ErrNum_Overlap
);
as_snprintf
(ListLine
, STRINGSIZE
, "=%~02.*u%s-%~02.*u%s",
ListRadixBase
, (unsigned)BitStart
, GetIntConstIntelSuffix
(ListRadixBase
),
ListRadixBase
, (unsigned)BitStart
+ 7, GetIntConstIntelSuffix
(ListRadixBase
));
}
else
as_snprintf
(ListLine
, STRINGSIZE
, "=%~02.*u%s",
ListRadixBase
, (unsigned)AdrByte
, GetIntConstIntelSuffix
(ListRadixBase
));
PopLocHandle
();
}
}
}
static void DecodeBIT
(Word Index
)
{
LongInt AdrLong
;
UNUSED
(Index
);
if (!ChkArgCnt
(1, 1));
else if (MomCPU
>= CPU80251
)
{
if (DecodeBitAdr
(&ArgStr
[1], &AdrLong
, False
) == ModBit251
)
{
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, AdrLong
, SegBData
, False
);
PopLocHandle
();
*ListLine
= '=';
DissectBit_251
(ListLine
+ 1, STRINGSIZE
- 1, AdrLong
);
}
}
else
{
if (DecodeBitAdr
(&ArgStr
[1], &AdrLong
, False
) == ModBit51
)
{
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, AdrLong
, SegBData
, False
);
PopLocHandle
();
as_snprintf
(ListLine
, STRINGSIZE
, "=%~02.*u%s",
ListRadixBase
, (unsigned)AdrLong
, GetIntConstIntelSuffix
(ListRadixBase
));
}
}
}
static void DecodePORT
(Word Index
)
{
UNUSED
(Index
);
if (ChkMinCPU
(CPU80251
))
CodeEquate
(SegIO
, 0, 0x1ff);
}
/*-------------------------------------------------------------------------*/
/* dynamische Codetabellenverwaltung */
static void AddFixed
(const char *NName
, Word NCode
, CPUVar NCPU
)
{
order_array_rsv_end
(FixedOrders
, FixedOrder
);
FixedOrders
[InstrZ
].
Code = NCode
;
FixedOrders
[InstrZ
].
MinCPU = NCPU
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeFixed
);
}
static void AddAcc
(const char *NName
, Word NCode
, CPUVar NCPU
)
{
order_array_rsv_end
(AccOrders
, FixedOrder
);
AccOrders
[InstrZ
].
Code = NCode
;
AccOrders
[InstrZ
].
MinCPU = NCPU
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeAcc
);
}
static void AddCond
(const char *NName
, Word NCode
, CPUVar NCPU
)
{
order_array_rsv_end
(CondOrders
, FixedOrder
);
CondOrders
[InstrZ
].
Code = NCode
;
CondOrders
[InstrZ
].
MinCPU = NCPU
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeCond
);
}
static void AddBCond
(const char *NName
, Word NCode
, CPUVar NCPU
)
{
order_array_rsv_end
(BCondOrders
, FixedOrder
);
BCondOrders
[InstrZ
].
Code = NCode
;
BCondOrders
[InstrZ
].
MinCPU = NCPU
;
AddInstTable
(InstTable
, NName
, InstrZ
++, DecodeBCond
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(203);
AddInstTable
(InstTable
, "MOV" , 0, DecodeMOV
);
AddInstTable
(InstTable
, "ANL" , 1, DecodeLogic
);
AddInstTable
(InstTable
, "ORL" , 0, DecodeLogic
);
AddInstTable
(InstTable
, "XRL" , 2, DecodeLogic
);
AddInstTable
(InstTable
, "MOVC" , 0, DecodeMOVC
);
AddInstTable
(InstTable
, "MOVH" , 0, DecodeMOVH
);
AddInstTable
(InstTable
, "MOVZ" , 0, DecodeMOVZS
);
AddInstTable
(InstTable
, "MOVS" , 0, DecodeMOVZS
);
AddInstTable
(InstTable
, "MOVX" , 0, DecodeMOVX
);
AddInstTable
(InstTable
, "POP" , 1, DecodeStack
);
AddInstTable
(InstTable
, "PUSH" , 0, DecodeStack
);
AddInstTable
(InstTable
, "PUSHW", 2, DecodeStack
);
AddInstTable
(InstTable
, "XCH" , 0, DecodeXCH
);
AddInstTable
(InstTable
, "XCHD" , 0, DecodeXCHD
);
AddInstTable
(InstTable
, "AJMP" , 0, DecodeABranch
);
AddInstTable
(InstTable
, "ACALL", 1, DecodeABranch
);
AddInstTable
(InstTable
, "LJMP" , 0, DecodeLBranch
);
AddInstTable
(InstTable
, "LCALL", 1, DecodeLBranch
);
AddInstTable
(InstTable
, "EJMP" , 0, DecodeEBranch
);
AddInstTable
(InstTable
, "ECALL", 1, DecodeEBranch
);
AddInstTable
(InstTable
, "JMP" , 0, DecodeJMP
);
AddInstTable
(InstTable
, "CALL" , 0, DecodeCALL
);
AddInstTable
(InstTable
, "DJNZ" , 0, DecodeDJNZ
);
AddInstTable
(InstTable
, "CJNE" , 0, DecodeCJNE
);
AddInstTable
(InstTable
, "ADD" , 0, DecodeADD
);
AddInstTable
(InstTable
, "SUB" , 0, DecodeSUBCMP
);
AddInstTable
(InstTable
, "CMP" , 1, DecodeSUBCMP
);
AddInstTable
(InstTable
, "ADDC" , 0, DecodeADDCSUBB
);
AddInstTable
(InstTable
, "SUBB" , 1, DecodeADDCSUBB
);
AddInstTable
(InstTable
, "INC" , 0, DecodeINCDEC
);
AddInstTable
(InstTable
, "DEC" , 1, DecodeINCDEC
);
AddInstTable
(InstTable
, "MUL" , 1, DecodeMULDIV
);
AddInstTable
(InstTable
, "DIV" , 0, DecodeMULDIV
);
AddInstTable
(InstTable
, "CLR" , 1, DecodeBits
);
AddInstTable
(InstTable
, "CPL" , 0, DecodeBits
);
AddInstTable
(InstTable
, "SETB" , 2, DecodeBits
);
AddInstTable
(InstTable
, "SRA" , 0, DecodeShift
);
AddInstTable
(InstTable
, "SRL" , 1, DecodeShift
);
AddInstTable
(InstTable
, "SLL" , 3, DecodeShift
);
AddInstTable
(InstTable
, "SFR" , 0, DecodeSFR
);
AddInstTable
(InstTable
, "SFRB" , 1, DecodeSFR
);
AddInstTable
(InstTable
, "BIT" , 0, DecodeBIT
);
AddInstTable
(InstTable
, "PORT" , 0, DecodePORT
);
InstrZ
= 0;
AddFixed
("NOP" , 0x0000, CPU87C750
);
AddFixed
("RET" , 0x0022, CPU87C750
);
AddFixed
("RETI", 0x0032, CPU87C750
);
AddFixed
("ERET", 0x01aa, CPU80251
);
AddFixed
("TRAP", 0x01b9, CPU80251
);
InstrZ
= 0;
AddAcc
("DA" , 0x00d4, CPU87C750
);
AddAcc
("RL" , 0x0023, CPU87C750
);
AddAcc
("RLC" , 0x0033, CPU87C750
);
AddAcc
("RR" , 0x0003, CPU87C750
);
AddAcc
("RRC" , 0x0013, CPU87C750
);
AddAcc
("SWAP", 0x00c4, CPU87C750
);
InstrZ
= 0;
AddCond
("JC" , 0x0040, CPU87C750
);
AddCond
("JE" , 0x0168, CPU80251
);
AddCond
("JG" , 0x0138, CPU80251
);
AddCond
("JLE" , 0x0128, CPU80251
);
AddCond
("JNC" , 0x0050, CPU87C750
);
AddCond
("JNE" , 0x0178, CPU80251
);
AddCond
("JNZ" , 0x0070, CPU87C750
);
AddCond
("JSG" , 0x0118, CPU80251
);
AddCond
("JSGE", 0x0158, CPU80251
);
AddCond
("JSL" , 0x0148, CPU80251
);
AddCond
("JSLE", 0x0108, CPU80251
);
AddCond
("JZ" , 0x0060, CPU87C750
);
AddCond
("SJMP", 0x0080, CPU87C750
);
InstrZ
= 0;
AddBCond
("JB" , 0x0020, CPU87C750
);
AddBCond
("JBC", 0x0010, CPU87C750
);
AddBCond
("JNB", 0x0030, CPU87C750
);
AddInstTable
(InstTable
, "REG" , 0, CodeREG
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(FixedOrders
);
order_array_free
(AccOrders
);
order_array_free
(CondOrders
);
order_array_free
(BCondOrders
);
}
/*-------------------------------------------------------------------------*/
/* Instruktionsdecoder */
static void MakeCode_51
(void)
{
CodeLen
= 0;
DontPrint
= False
;
OpSize
= -1;
MinOneIs0
= False
;
/* zu ignorierendes */
if (*OpPart.
str.
p_str == '\0') return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo
(TargetBigEndian
))
return;
/* suchen */
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_51
(void)
{
switch (*OpPart.
str.
p_str)
{
case 'B':
return Memo
("BIT");
case 'S':
if (Memo
("SFR")) return True
;
if (MomCPU
>= CPU80251
) return False
;
return Memo
("SFRB");
case 'P':
return (MomCPU
>= CPU80251
) ? Memo
("PORT") : False
;
case 'R':
return Memo
("REG");
default:
return False
;
}
}
/*!------------------------------------------------------------------------
* \fn InternSymbol_51(char *pArg, TempResult *pResult)
* \brief handle built-in symbols on 80x51
* \param pArg source argument
* \param pResult destination buffer
* ------------------------------------------------------------------------ */
static void InternSymbol_51
(char *pArg
, TempResult
*pResult
)
{
tRegInt Erg
;
tSymbolSize Size
;
if (DecodeRegCore
(pArg
, &Erg
, &Size
))
{
pResult
->Typ
= TempReg
;
pResult
->DataSize
= (tSymbolSize
)Size
;
pResult
->Contents.
RegDescr.
Reg = Erg
;
pResult
->Contents.
RegDescr.
Dissect = DissectReg_51
;
pResult
->Contents.
RegDescr.
compare = NULL
;
}
}
static void SwitchTo_51
(void)
{
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
PCSymbol
= "$";
HeaderID
= 0x31;
NOPCode
= 0x00;
DivideChars
= ",";
HasAttrs
= False
;
/* C251 is entirely different... */
if (MomCPU
>= CPU80251
)
{
ValidSegs
= (1 << SegCode
) | (1 << SegIO
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = 0xffffffl
;
Grans
[SegIO
] = 1; ListGrans
[SegIO
] = 1; SegInits
[SegIO
] = 0;
SegLimits
[SegIO
] = 0x1ff;
DissectBit
= DissectBit_251
;
}
/* rest of the pack... */
else
{
ValidSegs
=(1 << SegCode
) | (1 << SegData
) | (1 << SegIData
) | (1 << SegXData
) | (1 << SegBData
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
if (MomCPU
== CPU80C390
)
SegLimits
[SegCode
] = 0xffffff;
else if (MomCPU
== CPU87C750
)
SegLimits
[SegCode
] = 0x7ff;
else
SegLimits
[SegCode
] = 0xffff;
Grans
[SegXData
] = 1; ListGrans
[SegXData
] = 1; SegInits
[SegXData
] = 0;
if (MomCPU
== CPU80C390
)
SegLimits
[SegXData
] = 0xffffff;
else
SegLimits
[SegXData
] = 0xffff;
Grans
[SegData
] = 1; ListGrans
[SegData
] = 1; SegInits
[SegData
] = 0x30;
SegLimits
[SegData
] = 0xff;
Grans
[SegIData
] = 1; ListGrans
[SegIData
] = 1; SegInits
[SegIData
] = 0x80;
SegLimits
[SegIData
] = 0xff;
Grans
[SegBData
] = 1; ListGrans
[SegBData
] = 1; SegInits
[SegBData
] = 0;
SegLimits
[SegBData
] = 0xff;
}
MakeCode
= MakeCode_51
;
IsDef
= IsDef_51
;
InternSymbol
= InternSymbol_51
;
DissectReg
= DissectReg_51
;
InitFields
();
SwitchFrom
= DeinitFields
;
if (!onoff_test_and_set
(e_onoff_reg_srcmode
))
SetFlag
(&SrcMode
, SrcModeSymName
, False
);
AddONOFF
(SrcModeCmdName
, &SrcMode
, SrcModeSymName
, False
);
onoff_bigendian_add
();
}
void code51_init
(void)
{
CPU87C750
= AddCPU
("87C750", SwitchTo_51
);
CPU8051
= AddCPU
("8051" , SwitchTo_51
);
CPU8052
= AddCPU
("8052" , SwitchTo_51
);
CPU80C320
= AddCPU
("80C320", SwitchTo_51
);
CPU80501
= AddCPU
("80C501", SwitchTo_51
);
CPU80502
= AddCPU
("80C502", SwitchTo_51
);
CPU80504
= AddCPU
("80C504", SwitchTo_51
);
CPU80515
= AddCPU
("80515" , SwitchTo_51
);
CPU80517
= AddCPU
("80517" , SwitchTo_51
);
CPU80C390
= AddCPU
("80C390", SwitchTo_51
);
CPU80251
= AddCPU
("80C251", SwitchTo_51
);
CPU80251T
= AddCPU
("80C251T", SwitchTo_51
);
}