Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* code78k3.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator 78K3-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "headids.h"
#include "errmsg.h"
#include "code78k3.h"
/*-------------------------------------------------------------------------*/
enum
{
ModNone
= -1,
ModImm
= 0,
ModReg8
= 1,
ModReg16
= 2,
ModMem
= 3,
ModShort
= 4,
ModSFR
= 5,
ModAbs
= 6,
ModShortIndir
= 7,
ModSP
= 8,
ModSTBC
= 9,
ModWDM
= 10
};
#define MModImm (1 << ModImm)
#define MModReg8 (1 << ModReg8)
#define MModReg16 (1 << ModReg16)
#define MModMem (1 << ModMem)
#define MModShort (1 << ModShort)
#define MModSFR (1 << ModSFR)
#define MModAbs (1 << ModAbs)
#define MModShortIndir (1 << ModShortIndir)
#define MModSP (1 << ModSP)
#define MModSTBC (1 << ModSTBC)
#define MModWDM (1 << ModWDM)
#define PSWLAddr 0xfffe
#define PSWHAddr 0xffff
/*-------------------------------------------------------------------------*/
static CPUVar CPU78310
;
typedef struct
{
ShortInt Mode
, Val
;
Byte Vals
[3];
tSymbolFlags ValSymFlags
;
Boolean ForceLong
, ForceRel
;
int Cnt
;
} tAdrResult
;
static ShortInt OpSize
;
static Boolean AssumeByte
;
static LongInt Reg_RSS
;
/*-------------------------------------------------------------------------*/
/* address decoders */
static Byte AccReg8
(void)
{
return Reg_RSS
? 5 : 1;
}
static Byte BReg8
(void)
{
return Reg_RSS
? 7 : 3;
}
static Byte CReg8
(void)
{
return Reg_RSS
? 6 : 2;
}
static Byte AccReg16
(void)
{
return Reg_RSS
? 2 : 0;
}
static Boolean SetOpSize
(ShortInt NewSize
)
{
if (OpSize
< 0)
{
OpSize
= NewSize
;
return True
;
}
else if (OpSize
!= NewSize
)
{
WrError
(ErrNum_ConfOpSizes
);
return False
;
}
else
return True
;
}
static ShortInt DecodeReg8
(const char *pAsc
)
{
ShortInt Result
= -1;
switch (strlen(pAsc
))
{
case 1:
{
static const char Reg8Names
[9] = "XACBEDLH";
const char *pPos
= strchr(Reg8Names
, as_toupper
(*pAsc
));
if (pPos
)
{
Result
= pPos
- Reg8Names
;
/* E/D/L/H maps to R12..R15 */
if (Result
>= 4)
Result
+= 8;
/* X/A/C/B maps to R4..7 if RSS=1 */
else if (Reg_RSS
)
Result
+= 4;
}
break;
}
case 2:
{
if ((toupper(pAsc
[0]) == 'R') && isdigit(pAsc
[1]))
Result
= pAsc
[1] - '0';
break;
}
case 3:
{
static const char Reg8Names
[][4] = { "VPL", "VPH", "UPL", "UPH", "R10", "R11", "R12", "R13", "R14", "R15", "" };
int z
;
for (z
= 0; *Reg8Names
[z
]; z
++)
if (!as_strcasecmp
(pAsc
, Reg8Names
[z
]))
{
/* map to 8..11 resp. 10..15 */
Result
= (z
> 4) ? z
+ 6 : z
+ 8;
break;
}
}
}
return Result
;
}
static ShortInt DecodeReg16
(const char *pAsc
)
{
ShortInt Result
= -1;
switch (strlen(pAsc
))
{
case 2:
{
static const char Reg16Names
[][3] = { "AX", "BC", "VP", "UP", "DE", "HL", "" };
int z
;
for (z
= 0; *Reg16Names
[z
]; z
++)
if (!as_strcasecmp
(Reg16Names
[z
], pAsc
))
{
Result
= ((z
>= 2) || Reg_RSS
) ? z
+ 2 : z
;
break;
}
break;
}
case 3:
{
if ((toupper(pAsc
[0]) == 'R') && (toupper(pAsc
[1]) == 'P')
&& (pAsc
[2] >= '0') && (pAsc
[2] <= '7'))
Result
= pAsc
[2] - '0';
break;
}
}
return Result
;
}
static ShortInt DecodeIndReg16
(const char *pAsc
)
{
int l
= strlen(pAsc
);
char Copy
[10];
if ((l
< 2) || (l
> 5) || (*pAsc
!= '[') || (pAsc
[l
-1] != ']'))
return -1;
memcpy(Copy
, pAsc
+ 1, l
- 2); Copy
[l
- 2] = '\0';
l
= DecodeReg16
(Copy
);
return l
;
}
static ShortInt DecodeRegBank
(const char *pAsc
)
{
if ((strlen(pAsc
) == 3)
&& (toupper(pAsc
[0]) == 'R') && (toupper(pAsc
[1]) == 'B')
&& (pAsc
[2] >= '0') && (pAsc
[2] <= '7'))
return pAsc
[2] - '0';
else
return -1;
}
static void ExecAssumeByte
(void)
{
if ((OpSize
== -1) && AssumeByte
)
{
SetOpSize
(0);
AssumeByte
= False
;
}
}
static ShortInt DecodeAdr
(const tStrComp
*pArg
, Word Mask
, tAdrResult
*pResult
)
{
Boolean OK
;
Word WordOp
;
int ArgLen
;
unsigned Offset
;
pResult
->Mode
= ModNone
;
pResult
->Cnt
= 0;
pResult
->ForceLong
=
pResult
->ForceRel
= False
;
/* immediate ? */
if (*pArg
->str.
p_str == '#')
{
ExecAssumeByte
();
switch (OpSize
)
{
case 0:
pResult
->Vals
[0] = EvalStrIntExpressionOffs
(pArg
, 1, Int8
, &OK
);
if (OK
)
{
pResult
->Cnt
= 1;
pResult
->Mode
= ModImm
;
}
break;
case 1:
WordOp
= EvalStrIntExpressionOffs
(pArg
, 1, Int16
, &OK
);
if (OK
)
{
pResult
->Vals
[0] = Lo
(WordOp
);
pResult
->Vals
[1] = Hi
(WordOp
);
pResult
->Cnt
= 2;
pResult
->Mode
= ModImm
;
}
break;
default:
WrError
(ErrNum_UndefOpSizes
);
}
goto AdrFound
;
}
/* 8 bit registers? */
if ((pResult
->Val
= DecodeReg8
(pArg
->str.
p_str)) >= 0)
{
pResult
->Mode
= ModReg8
;
SetOpSize
(0);
goto AdrFound
;
}
if (!as_strcasecmp
(pArg
->str.
p_str, "STBC"))
{
pResult
->Mode
= ModSTBC
;
SetOpSize
(0);
goto AdrFound
;
}
if (!as_strcasecmp
(pArg
->str.
p_str, "WDM"))
{
pResult
->Mode
= ModWDM
;
SetOpSize
(0);
goto AdrFound
;
}
/* 16 bit registers? */
if ((pResult
->Val
= DecodeReg16
(pArg
->str.
p_str)) >= 0)
{
pResult
->Mode
= ModReg16
;
SetOpSize
(1);
goto AdrFound
;
}
if (!as_strcasecmp
(pArg
->str.
p_str, "SP"))
{
pResult
->Mode
= ModSP
;
SetOpSize
(1);
goto AdrFound
;
}
/* memory-indirect addressing? */
ArgLen
= strlen(pArg
->str.
p_str);
if ((ArgLen
>= 2) && (pArg
->str.
p_str[ArgLen
- 1] == ']'))
{
tStrComp Arg
;
char *pStart
;
StrCompRefRight
(&Arg
, pArg
, 0);
/* remove ']' */
StrCompShorten
(&Arg
, 1);
pStart
= RQuotPos
(Arg.
str.
p_str, '[');
if (!pStart
)
{
WrError
(ErrNum_BrackErr
);
goto AdrFound
;
}
/* purely indirect? */
if (pStart
== Arg.
str.
p_str)
{
static const char Modes
[][5] = { "DE+", "HL+", "DE-", "HL-", "DE", "HL", "VP", "UP",
"RP6+", "RP7+", "RP6-", "RP7-", "RP6", "RP7", "RP4", "RP5" };
unsigned z
;
char *pSep
, Save
;
tStrComp Base
, Remainder
;
/* skip '[' */
StrCompIncRefLeft
(&Arg
, 1);
/* simple expression without displacement? */
for (z
= 0; z
< sizeof(Modes
) / sizeof(*Modes
); z
++)
if (!as_strcasecmp
(Arg.
str.
p_str, Modes
[z
]))
{
pResult
->Mode
= ModMem
; pResult
->Val
= 0x16;
pResult
->Vals
[0] = z
% (sizeof(Modes
) / sizeof(*Modes
) / 2);
pResult
->Cnt
= 1;
goto AdrFound
;
}
/* no -> extract base register. Its name ends with the first non-letter,
which either means +/- or a blank */
for (pSep
= Arg.
str.
p_str; *pSep
; pSep
++)
if (!as_isalpha
(*pSep
))
break;
/* decode base register. SP is not otherwise handled. */
Save
= StrCompSplitRef
(&Base
, &Remainder
, &Arg
, pSep
);
if (!as_strcasecmp
(Base.
str.
p_str, "SP"))
pResult
->Vals
[0] = 1;
else
{
int tmp
;
tmp
= DecodeReg16
(Base.
str.
p_str);
switch (tmp
)
{
case -1: pResult
->Vals
[0] = 0xff; break; /* no register */
case 4: pResult
->Vals
[0] = 4; break; /* VP */
case 5: pResult
->Vals
[0] = 3; break; /* UP */
case 6: pResult
->Vals
[0] = 0; break; /* DE */
case 7: pResult
->Vals
[0] = 2; break; /* HL */
default:
WrStrErrorPos
(ErrNum_InvReg
, &Base
);
goto AdrFound
;
}
}
*pSep
= Save
;
/* no base register detected: purely indirect */
if (0xff == pResult
->Vals
[0])
{
tSymbolFlags Flags
;
WordOp
= EvalStrIntExpressionWithFlags
(&Arg
, UInt16
, &OK
, &Flags
);
if (OK
)
{
if (mFirstPassUnknown
(Flags
))
WordOp
= 0xfe20;
if (ChkRange
(WordOp
, 0xfe20, 0xff1f))
{
pResult
->Mode
= ModShortIndir
;
pResult
->Vals
[0] = Lo
(WordOp
);
}
}
goto AdrFound
;
}
/* Now that we have the base, prepare displacement. May
be an 8/16-bit register in certain combinations, or a number: */
if (*pSep
== '+')
{
int tmp
;
tmp
= DecodeReg8
(pSep
+ 1);
if (tmp
== -1); /* no reg at all */
else if ((tmp
== AccReg8
()) /* A */
|| (tmp
== BReg8
())) /* B */
{
if (pResult
->Vals
[0] == 0) /* DE+A/B */
{
pResult
->Mode
= ModMem
; pResult
->Val
= 0x17;
pResult
->Cnt
= 1; pResult
->Vals
[0] = tmp
& 2;
goto AdrFound
;
}
else if (pResult
->Vals
[0] == 2) /* HL+A/B */
{
pResult
->Mode
= ModMem
; pResult
->Val
= 0x17;
pResult
->Cnt
= 1; pResult
->Vals
[0] = tmp
;
goto AdrFound
;
}
else
WrError
(ErrNum_InvAddrMode
);
goto AdrFound
;
}
else
{
WrError
(ErrNum_InvAddrMode
);
goto AdrFound
;
}
tmp
= DecodeReg16
(pSep
+ 1);
switch (tmp
)
{
case -1: /* no reg at all */
break;
case 6: /* DE */
case 7: /* HL */
if (pResult
->Vals
[0] == 4) /* VP+DE/HL */
{
pResult
->Mode
= ModMem
; pResult
->Val
= 0x17;
pResult
->Cnt
= 1; pResult
->Vals
[0] = tmp
- 2;
goto AdrFound
;
}
/* fall-through */
default:
WrError
(ErrNum_InvAddrMode
);
goto AdrFound
;
}
}
/* it's a number: put a fake 0 in front so displacement expression evaluates correctly! */
if (pSep
> Arg.
str.
p_str)
pSep
--;
*pSep
= '0';
pResult
->Vals
[1] = EvalStrIntExpressionOffs
(&Arg
, pSep
- Arg.
str.
p_str, Int8
, &OK
);
if (OK
)
{
pResult
->Mode
= ModMem
; pResult
->Val
= 0x06;
pResult
->Cnt
= 2;
goto AdrFound
;
}
}
/* no -> with outer displacement */
else
{
int tmp
;
tStrComp Disp
, Reg
;
/* split displacement + register */
StrCompSplitRef
(&Disp
, &Reg
, &Arg
, pStart
);
/* handle base register */
tmp
= DecodeReg8
(Reg.
str.
p_str);
if ((tmp
== AccReg8
()) /* A */
|| (tmp
== BReg8
())) /* B */
{
pResult
->Vals
[0] = tmp
& 3;
}
else if (tmp
== -1)
{
tmp
= DecodeReg16
(Reg.
str.
p_str);
if (tmp
>= 6) /* DE/HL */
{
pResult
->Vals
[0] = (tmp
- 6) << 1;
}
else
{
WrStrErrorPos
(ErrNum_InvReg
, &Reg
);
goto AdrFound
;
}
}
else
{
WrStrErrorPos
(ErrNum_InvReg
, &Reg
);
goto AdrFound
;
}
/* compute displacement */
WordOp
= EvalStrIntExpression
(&Disp
, Int16
, &OK
);
if (OK
)
{
pResult
->Mode
= ModMem
; pResult
->Val
= 0x0a;
pResult
->Vals
[1] = Lo
(WordOp
); pResult
->Vals
[2] = Hi
(WordOp
);
pResult
->Cnt
= 3;
goto AdrFound
;
}
}
}
/* OK, nothing but absolute left...exclamation mark enforces 16-bit addressing,
dollar sign relative addressing. Relative flag is only a hint to the individual
instruction decoders and not used in this context. */
Offset
= 0;
if (pArg
->str.
p_str[Offset
] == '!')
{
pResult
->ForceLong
= True
;
Offset
++;
}
else if (pArg
->str.
p_str[Offset
] == '$')
{
pResult
->ForceRel
= True
;
Offset
++;
}
WordOp
= EvalStrIntExpressionOffsWithFlags
(pArg
, Offset
, UInt16
, &OK
, &pResult
->ValSymFlags
);
if (OK
)
{
if ((Mask
& MModShort
) && (!pResult
->ForceLong
) && ((WordOp
>= 0xfe20) && (WordOp
<= 0xff1f)))
{
pResult
->Mode
= ModShort
; pResult
->Cnt
= 1;
pResult
->Vals
[0] = Lo
(WordOp
);
}
else if ((Mask
& MModSFR
) && (!pResult
->ForceLong
) && (Hi
(WordOp
) == 0xff))
{
pResult
->Mode
= ModSFR
; pResult
->Cnt
= 1;
pResult
->Vals
[0] = Lo
(WordOp
);
}
else
{
pResult
->Mode
= ModAbs
; pResult
->Cnt
= 2;
pResult
->Vals
[0] = Lo
(WordOp
);
pResult
->Vals
[1] = Hi
(WordOp
);
}
}
AdrFound
:
if ((pResult
->Mode
!= ModNone
) && (!(Mask
& (1 << pResult
->Mode
))))
{
WrError
(ErrNum_InvAddrMode
);
pResult
->Mode
= ModNone
; pResult
->Cnt
= 0;
}
return pResult
->Mode
;
}
static void AppendDisp
(const tStrComp
*pArg
)
{
Boolean OK
;
LongInt Dist
;
tSymbolFlags Flags
;
Dist
= EvalStrIntExpressionOffsWithFlags
(pArg
, !!(*pArg
->str.
p_str == '$'), UInt16
, &OK
, &Flags
) - (EProgCounter
() + CodeLen
+ 1);
if (!mSymbolQuestionable
(Flags
) && ((Dist
< -128) || (Dist
> 127)))
{
WrError
(ErrNum_JmpDistTooBig
);
CodeLen
= 0;
}
else
BAsmCode
[CodeLen
++] = Dist
& 0xff;
}
static Boolean ChkAcc
(tStrComp
*pArg
)
{
tAdrResult AdrResult
;
if (DecodeAdr
(pArg
, OpSize
? MModReg16
: MModReg8
, &AdrResult
) == ModNone
)
return False
;
if (((OpSize
) && (AdrResult.
Val != AccReg16
()))
|| ((!OpSize
) && (AdrResult.
Val != AccReg8
())))
{
WrError
(ErrNum_InvAddrMode
);
return False
;
}
return True
;
}
static Boolean DecodeBitAdr
(const tStrComp
*pArg
, LongWord
*pResult
)
{
char *pSplit
;
Boolean OK
;
pSplit
= RQuotPos
(pArg
->str.
p_str, '.');
if (pSplit
)
{
tStrComp RegArg
, BitArg
;
StrCompSplitRef
(&RegArg
, &BitArg
, pArg
, pSplit
);
*pResult
= EvalStrIntExpression
(&BitArg
, UInt3
, &OK
) << 8;
if (OK
)
{
tAdrResult AdrResult
;
switch (DecodeAdr
(&RegArg
, MModReg8
| MModSFR
| MModShort
, &AdrResult
))
{
case ModReg8
:
if ((AdrResult.
Val != AccReg8
()) && (AdrResult.
Val != AccReg8
() - 1))
{
WrStrErrorPos
(ErrNum_InvReg
, &RegArg
);
OK
= FALSE
;
}
else
*pResult
|= (((LongWord
)(AdrResult.
Val & 1)) << 11) | 0x00030000;
break;
case ModSFR
:
switch (AdrResult.
Vals[0])
{
case PSWLAddr
& 0xff:
*pResult
|= 0x00020000;
break;
case PSWHAddr
& 0xff:
*pResult
|= 0x00020800;
break;
default:
*pResult
|= 0x01080800 | *AdrResult.
Vals;
break;
}
break;
case ModShort
:
*pResult
|= 0x01080000 | *AdrResult.
Vals;
break;
default:
OK
= FALSE
;
}
}
}
else
*pResult
= EvalStrIntExpression
(pArg
, UInt32
, &OK
);
return OK
;
}
/*-------------------------------------------------------------------------*/
/* Instruction Decoders */
static void DecodeFixed
(Word Index
)
{
if (ChkArgCnt
(0, 0))
BAsmCode
[CodeLen
++] = Lo
(Index
);
}
static void DecodeMOV
(Word Is16
)
{
if (Is16
)
SetOpSize
(1);
if (ChkArgCnt
(2, 2))
{
tAdrResult DestAdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModReg16
| MModSP
| MModShort
| MModSFR
| (Is16
? 0 : (MModReg8
| MModSTBC
| MModWDM
| MModAbs
| MModShortIndir
| MModMem
)), &DestAdrResult
))
{
case ModReg8
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModImm
| MModReg8
| ((DestAdrResult.
Val == AccReg8
()) ? (MModMem
| MModAbs
| MModShort
| MModSFR
| MModShortIndir
) : 0), &SrcAdrResult
))
{
case ModImm
:
if (DestAdrResult.
Val >= 8) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0xb8 | DestAdrResult.
Val;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
}
break;
case ModReg8
:
if (SrcAdrResult.
Val >= 8) WrError
(ErrNum_InvAddrMode
);
else if (DestAdrResult.
Val == AccReg8
())
BAsmCode
[CodeLen
++] = 0xd0 | SrcAdrResult.
Val;
else
{
BAsmCode
[CodeLen
++] = 0x24;
BAsmCode
[CodeLen
++] = (DestAdrResult.
Val << 4) | SrcAdrResult.
Val;
}
break;
case ModMem
:
if ((SrcAdrResult.
Val == 0x16) && (SrcAdrResult.
Vals[0] <= 5))
BAsmCode
[CodeLen
++] = 0x58 | SrcAdrResult.
Vals[0];
else
{
BAsmCode
[CodeLen
++] = 0x00 | SrcAdrResult.
Val;
BAsmCode
[CodeLen
++] = 0x00 | (SrcAdrResult.
Vals[0] << 4);
memcpy(BAsmCode
+ CodeLen
, SrcAdrResult.
Vals + 1, SrcAdrResult.
Cnt - 1);
CodeLen
+= SrcAdrResult.
Cnt - 1;
}
break;
case ModAbs
:
BAsmCode
[CodeLen
++] = 0x09;
BAsmCode
[CodeLen
++] = 0xf0;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x20;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSFR
:
BAsmCode
[CodeLen
++] = 0x10;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModShortIndir
:
BAsmCode
[CodeLen
++] = 0x18;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModSTBC
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModImm
, &SrcAdrResult
))
{
case ModImm
:
BAsmCode
[CodeLen
++] = 0x09;
BAsmCode
[CodeLen
++] = 0x44;
BAsmCode
[CodeLen
++] = 0xff - SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModWDM
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModImm
, &SrcAdrResult
))
{
case ModImm
:
BAsmCode
[CodeLen
++] = 0x09;
BAsmCode
[CodeLen
++] = 0x42;
BAsmCode
[CodeLen
++] = 0xff - SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModReg16
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg16
| MModImm
| ((DestAdrResult.
Val == AccReg16
()) ? (MModShort
| MModSFR
| MModSP
) : 0), &SrcAdrResult
))
{
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x24;
BAsmCode
[CodeLen
++] = 0x08 | (DestAdrResult.
Val << 5) | SrcAdrResult.
Val;
break;
case ModImm
:
BAsmCode
[CodeLen
++] = 0x60 | DestAdrResult.
Val;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x1c;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSFR
:
BAsmCode
[CodeLen
++] = 0x11;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSP
:
BAsmCode
[CodeLen
++] = 0x11;
BAsmCode
[CodeLen
++] = 0xfc;
break;
}
break;
}
case ModSP
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg16
| MModImm
, &SrcAdrResult
))
{
case ModReg16
:
if (SrcAdrResult.
Val != AccReg16
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x13;
BAsmCode
[CodeLen
++] = 0xfc;
}
break;
case ModImm
:
BAsmCode
[CodeLen
++] = 0x0b;
BAsmCode
[CodeLen
++] = 0xfc;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
}
break;
}
case ModShort
:
{
tAdrResult SrcAdrResult
;
AssumeByte
= (OpSize
== -1);
switch (DecodeAdr
(&ArgStr
[2], MModImm
| MModShort
| MModReg8
| MModReg16
, &SrcAdrResult
))
{
case ModImm
:
BAsmCode
[CodeLen
++] = OpSize
? 0x0c : 0x3a;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
if (OpSize
)
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
case ModShort
:
ExecAssumeByte
();
BAsmCode
[CodeLen
++] = (OpSize
== 1) ? 0x3c : 0x38;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
break;
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x22;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
case ModReg16
:
if (SrcAdrResult.
Val != AccReg16
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x1a;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
}
break;
}
case ModSFR
:
{
tAdrResult SrcAdrResult
;
AssumeByte
= (OpSize
== -1);
switch (DecodeAdr
(&ArgStr
[2], MModImm
| MModReg8
| MModReg16
, &SrcAdrResult
))
{
case ModImm
:
BAsmCode
[CodeLen
++] = OpSize
? 0x0b : 0x2b;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
if (OpSize
)
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x12;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
case ModReg16
:
if (SrcAdrResult.
Val != AccReg16
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x13;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
}
break;
}
case ModMem
:
{
tAdrResult SrcAdrResult
;
SetOpSize
(0);
switch (DecodeAdr
(&ArgStr
[2], MModImm
| MModReg8
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else if ((DestAdrResult.
Val == 0x16) && (DestAdrResult.
Vals[0] <= 5))
BAsmCode
[CodeLen
++] = 0x50 | DestAdrResult.
Vals[0];
else
{
BAsmCode
[CodeLen
++] = 0x00 | DestAdrResult.
Val;
BAsmCode
[CodeLen
++] = 0x80 | (DestAdrResult.
Vals[0] << 4);
memcpy(BAsmCode
+ CodeLen
, DestAdrResult.
Vals + 1, DestAdrResult.
Cnt - 1);
CodeLen
+= DestAdrResult.
Cnt - 1;
}
break;
/* ModImm? */
}
break;
}
case ModAbs
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x09;
BAsmCode
[CodeLen
++] = 0xf1;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[1];
}
break;
}
break;
}
case ModShortIndir
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x19;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
}
break;
}
}
}
}
static void DecodeXCH
(Word Is16
)
{
if (Is16
)
SetOpSize
(1);
if (ChkArgCnt
(2, 2))
{
tAdrResult DestAdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModReg16
| MModShort
| MModSFR
| (Is16
? 0 : (MModReg8
| MModShortIndir
| MModMem
)), &DestAdrResult
))
{
case ModReg8
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
| ((DestAdrResult.
Val == AccReg8
()) ? (MModMem
| MModShort
| MModShortIndir
| MModSFR
) : 0), &SrcAdrResult
))
{
case ModReg8
:
if ((DestAdrResult.
Val == AccReg8
()) && (SrcAdrResult.
Val < 8))
BAsmCode
[CodeLen
++] = 0xd8 | SrcAdrResult.
Val;
else if ((SrcAdrResult.
Val == AccReg8
()) && (DestAdrResult.
Val < 8))
BAsmCode
[CodeLen
++] = 0xd8 | DestAdrResult.
Val;
else if (DestAdrResult.
Val < 8)
{
BAsmCode
[CodeLen
++] = 0x25;
BAsmCode
[CodeLen
++] = 0x00 | (SrcAdrResult.
Val << 4) | DestAdrResult.
Val;
}
else if (SrcAdrResult.
Val < 8)
{
BAsmCode
[CodeLen
++] = 0x25;
BAsmCode
[CodeLen
++] = 0x00 | (DestAdrResult.
Val << 4) | SrcAdrResult.
Val;
}
else
WrError
(ErrNum_InvRegPair
);
break;
case ModMem
:
BAsmCode
[CodeLen
++] = 0x00 | SrcAdrResult.
Val;
BAsmCode
[CodeLen
++] = 0x04 | (SrcAdrResult.
Vals[0] << 4);
memcpy(BAsmCode
+ CodeLen
, SrcAdrResult.
Vals + 1, SrcAdrResult.
Cnt - 1);
CodeLen
+= SrcAdrResult.
Cnt - 1;
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x21;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSFR
:
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = 0x21;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModShortIndir
:
BAsmCode
[CodeLen
++] = 0x23;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModReg16
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg16
| ((DestAdrResult.
Val == AccReg16
()) ? (MModShort
| MModSFR
) : 0), &SrcAdrResult
))
{
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x25;
BAsmCode
[CodeLen
++] = 0x08 | (DestAdrResult.
Val << 5) | SrcAdrResult.
Val;
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSFR
:
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModShort
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
| MModReg16
| MModShort
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x21;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
case ModReg16
:
if (SrcAdrResult.
Val != AccReg16
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
case ModShort
:
BAsmCode
[CodeLen
++] = (OpSize
== 1) ? 0x2a : 0x39;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
break;
}
break;
}
case ModSFR
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
| MModReg16
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = 0x21;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
case ModReg16
:
if (SrcAdrResult.
Val != AccReg16
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
}
break;
}
case ModMem
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x00 | DestAdrResult.
Val;
BAsmCode
[CodeLen
++] = 0x04 | (DestAdrResult.
Vals[0] << 4);
memcpy(BAsmCode
+ CodeLen
, DestAdrResult.
Vals + 1, DestAdrResult.
Cnt - 1);
CodeLen
+= DestAdrResult.
Cnt - 1;
}
break;
}
break;
}
case ModShortIndir
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x23;
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
}
break;
}
break;
}
}
}
}
static void DecodeALU
(Word Props
)
{
const Byte Code8
= (Props
>> 0) & 15,
Code16
= (Props
>> 4) & 15,
Code16Reg
= (Props
>> 8) & 15;
const Boolean Is16
= (Props
& 0x8000) || False
,
May16
= (Props
& 0x4000) || False
;
if (Is16
)
SetOpSize
(1);
if (ChkArgCnt
(2, 2))
{
tAdrResult DestAdrResult
;
switch (DecodeAdr
(&ArgStr
[1],
MModShort
| MModSFR
| (May16
? MModReg16
: 0)
| (Is16
? 0 : (MModReg8
| MModMem
)), &DestAdrResult
))
{
case ModReg8
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
| ((DestAdrResult.
Val == AccReg8
()) ? (MModShort
| MModSFR
| MModMem
| MModImm
) : 0), &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val >= 8) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x88 | Code8
;
BAsmCode
[CodeLen
++] = (DestAdrResult.
Val << 4) | SrcAdrResult.
Val;
}
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x98 | Code8
;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSFR
:
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = 0x98 | Code8
;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModMem
:
BAsmCode
[CodeLen
++] = 0x00 | SrcAdrResult.
Val;
BAsmCode
[CodeLen
++] = 0x08 | Code8
| (SrcAdrResult.
Vals[0] << 4);
memcpy(BAsmCode
+ CodeLen
, SrcAdrResult.
Vals + 1, SrcAdrResult.
Cnt - 1);
CodeLen
+= SrcAdrResult.
Cnt - 1;
break;
case ModImm
:
BAsmCode
[CodeLen
++] = 0xa8 | Code8
;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModReg16
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg16
| ((DestAdrResult.
Val == AccReg16
()) ? (MModShort
| MModImm
| MModSFR
) : 0), &SrcAdrResult
))
{
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x88 | Code16Reg
;
BAsmCode
[CodeLen
++] = 0x08 | (DestAdrResult.
Val << 5) | SrcAdrResult.
Val;
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x10 | Code16
;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModSFR
:
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = 0x1d | Code16
;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
case ModImm
:
BAsmCode
[CodeLen
++] = 0x20 | Code16
;
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
break;
}
break;
}
case ModShort
:
{
tAdrResult SrcAdrResult
;
AssumeByte
= (OpSize
== -1);
switch (DecodeAdr
(&ArgStr
[2], MModShort
| MModImm
, &SrcAdrResult
))
{
case ModShort
:
BAsmCode
[CodeLen
++] = OpSize
? (0x30 | Code16
) : (0x78 | Code8
);
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
break;
case ModImm
:
BAsmCode
[CodeLen
++] = OpSize
? (0x00 | Code16
) : (0x68 | Code8
);
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
if (OpSize
)
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
}
break;
}
case ModSFR
:
{
tAdrResult SrcAdrResult
;
AssumeByte
= (OpSize
== -1);
switch (DecodeAdr
(&ArgStr
[2], MModImm
, &SrcAdrResult
))
{
case ModImm
:
BAsmCode
[CodeLen
++] = 0x01;
BAsmCode
[CodeLen
++] = OpSize
? (0x00 | Code16
) : (0x68 | Code8
);
BAsmCode
[CodeLen
++] = DestAdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[0];
if (OpSize
)
BAsmCode
[CodeLen
++] = SrcAdrResult.
Vals[1];
break;
}
break;
}
case ModMem
:
{
tAdrResult SrcAdrResult
;
switch (DecodeAdr
(&ArgStr
[2], MModReg8
, &SrcAdrResult
))
{
case ModReg8
:
if (SrcAdrResult.
Val != AccReg8
()) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x00 | DestAdrResult.
Val;
BAsmCode
[CodeLen
++] = 0x88 | Code8
| (DestAdrResult.
Vals[0] << 4);
memcpy(BAsmCode
+ CodeLen
, DestAdrResult.
Vals + 1, DestAdrResult.
Cnt - 1);
CodeLen
+= DestAdrResult.
Cnt - 1;
}
break;
}
break;
}
}
}
}
static void DecodeMULDIV
(Word Props
)
{
if (ChkArgCnt
(1, 1))
{
tAdrResult AdrResult
;
if (Props
& 0x8000)
SetOpSize
(1);
switch (DecodeAdr
(&ArgStr
[1], MModReg16
| ((OpSize
== 1) ? 0 : MModReg8
), &AdrResult
))
{
case ModReg8
:
if (AdrResult.
Val > 7) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0x08 | ((Props
<< 4) & 0xf0) | AdrResult.
Val;
}
break;
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0x08 | (Props
& 0xf0) | AdrResult.
Val;
break;
}
}
}
static void DecodeINCDEC
(Word Props
)
{
const Byte Code
= Props
& 1;
if (ChkArgCnt
(1, 1))
{
tAdrResult AdrResult
;
if (Props
& 2)
SetOpSize
(1);
switch (DecodeAdr
(&ArgStr
[1], MModShort
| MModReg16
| MModSP
| ((OpSize
== 1) ? 0 : MModReg8
), &AdrResult
))
{
case ModReg8
:
if (AdrResult.
Val > 7) WrError
(ErrNum_InvAddrMode
);
else
BAsmCode
[CodeLen
++] = 0xc0 | AdrResult.
Val | (Code
<< 3);
break;
case ModReg16
:
if (AdrResult.
Val < 4) WrError
(ErrNum_InvAddrMode
);
else
BAsmCode
[CodeLen
++] = 0x40 | AdrResult.
Val | (Code
<< 3);
break;
case ModSP
:
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0xc8 | Code
;
break;
case ModShort
:
if (OpSize
== 1)
{
BAsmCode
[CodeLen
++] = 0x07;
BAsmCode
[CodeLen
++] = 0xe8 | Code
;
}
else
BAsmCode
[CodeLen
++] = 0x26 | Code
;
BAsmCode
[CodeLen
++] = AdrResult.
Vals[0];
break;
}
}
}
static void DecodeShift
(Word Props
)
{
Boolean OK
;
Byte Shift
;
tAdrResult AdrResult
;
if (!ChkArgCnt
(2, 2))
return;
Shift
= EvalStrIntExpression
(&ArgStr
[2], UInt3
, &OK
);
if (!OK
)
return;
if (Props
& 0x8000)
SetOpSize
(1);
switch (DecodeAdr
(&ArgStr
[1], ((OpSize
!= 1) ? MModReg8
: 0) | ((Props
& 0x4000) ? MModReg16
: 0), &AdrResult
))
{
case ModReg8
:
if (AdrResult.
Val > 7) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x30 | (Props
& 1);
BAsmCode
[CodeLen
++] = (Props
& 0xf0) | AdrResult.
Val | (Shift
<< 3);
}
break;
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x30 | (Props
& 1);
BAsmCode
[CodeLen
++] = ((Props
& 0xf00) >> 4) | AdrResult.
Val | (Shift
<< 3);
break;
}
}
static void DecodeROLROR4
(Word Code
)
{
ShortInt Reg
;
if (!ChkArgCnt
(1, 1));
else if ((Reg
= DecodeIndReg16
(ArgStr
[1].
str.
p_str)) < 0) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = Code
| Reg
;
}
}
static void DecodeBIT
(Word Index
)
{
LongWord Result
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 1)
&& DecodeBitAdr
(&ArgStr
[1], &Result
))
EnterIntSymbol
(&LabPart
, Result
, SegNone
, False
);
}
static void DecodeMOV1
(Word Index
)
{
LongWord Bit
;
int ArgPos
;
UNUSED
(Index
);
if (ChkArgCnt
(2, 2))
{
if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "CY"))
ArgPos
= 2;
else if (!as_strcasecmp
(ArgStr
[2].
str.
p_str, "CY"))
ArgPos
= 1;
else
{
WrError
(ErrNum_InvAddrMode
);
return;
}
if (DecodeBitAdr
(&ArgStr
[ArgPos
], &Bit
))
{
BAsmCode
[CodeLen
++] = 0x00 | ((Bit
>> 16) & 0xff);
BAsmCode
[CodeLen
++] = ((2 - ArgPos
) << 4) | ((Bit
>> 8) & 0xff);
if (Bit
& 0x1000000)
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
}
}
static void DecodeANDOR1
(Word Index
)
{
LongWord Bit
;
if (!ChkArgCnt
(2, 2));
else if (as_strcasecmp
(ArgStr
[1].
str.
p_str, "CY")) WrError
(ErrNum_InvAddrMode
);
else
{
tStrComp
*pArg
, BitArg
;
pArg
= &ArgStr
[2];
if (*pArg
->str.
p_str == '/')
{
StrCompRefRight
(&BitArg
, pArg
, 1);
pArg
= &BitArg
;
Index
|= 0x10;
}
if (DecodeBitAdr
(pArg
, &Bit
))
{
BAsmCode
[CodeLen
++] = 0x00 | ((Bit
>> 16) & 0xff);
BAsmCode
[CodeLen
++] = Index
| ((Bit
>> 8) & 0xff);
if (Bit
& 0x1000000)
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
}
}
static void DecodeXOR1
(Word Index
)
{
LongWord Bit
;
UNUSED
(Index
);
if (!ChkArgCnt
(2, 2));
else if (as_strcasecmp
(ArgStr
[1].
str.
p_str, "CY")) WrError
(ErrNum_InvAddrMode
);
else
{
if (DecodeBitAdr
(&ArgStr
[2], &Bit
))
{
BAsmCode
[CodeLen
++] = 0x00 | ((Bit
>> 16) & 0xff);
BAsmCode
[CodeLen
++] = 0x60 | ((Bit
>> 8) & 0xff);
if (Bit
& 0x1000000)
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
}
}
static void DecodeBit1
(Word Index
)
{
LongWord Bit
;
UNUSED
(Index
);
if (!ChkArgCnt
(1, 1));
else if (!as_strcasecmp
(ArgStr
[1].
str.
p_str, "CY"))
{
BAsmCode
[CodeLen
++] = 0x40 | (9 - (Index
>> 4));
}
else if (DecodeBitAdr
(&ArgStr
[1], &Bit
))
{
if ((Index
>= 0x80) && ((Bit
& 0xfffff800) == 0x01080000))
{
BAsmCode
[CodeLen
++] = (0x130 - Index
) | ((Bit
>> 8) & 7);
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
else
{
BAsmCode
[CodeLen
++] = 0x00 | ((Bit
>> 16) & 0xff);
BAsmCode
[CodeLen
++] = Index
| ((Bit
>> 8) & 0xff);
if (Bit
& 0x1000000)
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
}
}
static void DecodeCALL
(Word Code
)
{
ShortInt Reg
;
UNUSED
(Code
);
if (!ChkArgCnt
(1, 1));
else if ((Reg
= DecodeIndReg16
(ArgStr
[1].
str.
p_str)) >= 0)
{
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0x78 | Reg
;
}
else
{
tAdrResult AdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModAbs
| MModReg16
, &AdrResult
))
{
case ModAbs
:
BAsmCode
[CodeLen
++] = 0x28;
BAsmCode
[CodeLen
++] = AdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = AdrResult.
Vals[1];
break;
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0x58 | AdrResult.
Val;
break;
}
}
}
static void DecodeCALLF
(Word Index
)
{
Word AdrWord
;
Boolean OK
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 1))
{
tSymbolFlags Flags
;
AdrWord
= EvalStrIntExpressionOffsWithFlags
(&ArgStr
[1], !!(*ArgStr
[1].
str.
p_str == '!'), UInt12
, &OK
, &Flags
);
if (OK
)
{
if (mFirstPassUnknown
(Flags
))
AdrWord
|= 0x800;
if (AdrWord
< 0x800) WrError
(ErrNum_UnderRange
);
else
{
BAsmCode
[CodeLen
++] = 0x90 | (Hi
(AdrWord
) & 7);
BAsmCode
[CodeLen
++] = Lo
(AdrWord
);
}
}
}
}
static void DecodeCALLT
(Word Index
)
{
Word AdrWord
;
Boolean OK
;
int l
;
UNUSED
(Index
);
if (ChkArgCnt
(1, 1))
{
l
= strlen(ArgStr
[1].
str.
p_str);
if ((*ArgStr
[1].
str.
p_str != '[') || (ArgStr
[1].
str.
p_str[l
- 1] != ']')) WrError
(ErrNum_InvAddrMode
);
else
{
tStrComp Arg
;
tSymbolFlags Flags
;
StrCompRefRight
(&Arg
, &ArgStr
[1], 1);
StrCompShorten
(&Arg
, 1);
AdrWord
= EvalStrIntExpressionWithFlags
(&Arg
, UInt7
, &OK
, &Flags
);
if (OK
)
{
if (mFirstPassUnknown
(Flags
))
AdrWord
= 0x40;
if (ChkRange
(AdrWord
, 0x40, 0x7e))
{
if (AdrWord
& 1) WrError
(ErrNum_AddrMustBeEven
);
else
{
BAsmCode
[CodeLen
++] = 0xe0 | ((AdrWord
- 0x40) >> 1);
}
}
}
}
}
}
static void DecodePUSHPOP
(Word Code
)
{
Boolean IsU
= (Code
& 2) || False
;
ShortInt Reg
;
if (ChkArgCnt
(1, ArgCntMax
))
{
Word Mask
= 0, ThisMask
;
int z
;
for (z
= 1; z
<= ArgCnt
; z
++)
{
/* special case, either bit 5 or separate instruction */
if (!as_strcasecmp
(ArgStr
[z
].
str.
p_str, "PSW"))
ThisMask
= IsU
? 0x20 : 0x100;
/* user stack ptr itself cannot be pushed onto user stack */
else if (((Reg
= DecodeReg16
(ArgStr
[z
].
str.
p_str)) < 0)
|| (IsU
&& (Reg
== 5)))
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[z
]);
return;
}
else
ThisMask
= 1 << Reg
;
/* register already named? */
if (Mask
& ThisMask
)
{
WrStrErrorPos
(ErrNum_InvRegList
, &ArgStr
[z
]);
return;
}
else
Mask
|= ThisMask
;
}
/* cannot mix separate PSW and other registers in one instruction */
if (Lo
(Mask
) && Hi
(Mask
)) WrError
(ErrNum_InvRegList
);
else if (Hi
(Mask
))
BAsmCode
[CodeLen
++] = Hi
(Code
);
else
{
BAsmCode
[CodeLen
++] = Lo
(Code
);
BAsmCode
[CodeLen
++] = Lo
(Mask
);
}
}
}
static void DecodeBR
(Word Code
)
{
ShortInt Reg
;
UNUSED
(Code
);
if (!ChkArgCnt
(1, 1));
else if ((Reg
= DecodeIndReg16
(ArgStr
[1].
str.
p_str)) >= 0)
{
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0x68 | Reg
;
}
else
{
tAdrResult AdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModAbs
| MModReg16
, &AdrResult
))
{
case ModReg16
:
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0x48 | AdrResult.
Val;
break;
case ModAbs
:
{
Word AbsAddr
= (((Word
)AdrResult.
Vals[1]) << 8) | AdrResult.
Vals[0];
Integer Dist
= AbsAddr
- (EProgCounter
() + 2);
Boolean DistOK
= (Dist
>= -128) && (Dist
< 127);
if (AdrResult.
ForceRel && !DistOK
) WrError
(ErrNum_JmpDistTooBig
);
else if (AdrResult.
ForceLong || !DistOK
)
{
BAsmCode
[CodeLen
++] = 0x14;
BAsmCode
[CodeLen
++] = AdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = AdrResult.
Vals[1];
}
else
{
BAsmCode
[CodeLen
++] = 0x14;
BAsmCode
[CodeLen
++] = Dist
& 0xff;
}
break;
}
}
}
}
static void DecodeBranch
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
if (Hi
(Code
))
BAsmCode
[CodeLen
++] = Hi
(Code
);
BAsmCode
[CodeLen
++] = Lo
(Code
);
AppendDisp
(&ArgStr
[1]);
}
}
static void DecodeBrBit
(Word Index
)
{
LongWord Bit
;
UNUSED
(Index
);
if (!ChkArgCnt
(2, 2));
else if (DecodeBitAdr
(&ArgStr
[1], &Bit
))
{
if ((Bit
& 0xfffff800) == 0x01080000)
{
if (Index
== 0x80)
{
BAsmCode
[CodeLen
++] = 0x70 | ((Bit
>> 8) & 7);
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
else
{
BAsmCode
[CodeLen
++] = 0x00 | ((Bit
>> 16) & 0xff);
BAsmCode
[CodeLen
++] = (0x130 - Index
) | ((Bit
>> 8) & 0xff);
if (Bit
& 0x1000000)
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
}
else
{
BAsmCode
[CodeLen
++] = 0x00 | ((Bit
>> 16) & 0xff);
BAsmCode
[CodeLen
++] = (0x130 - Index
) | ((Bit
>> 8) & 0xff);
if (Bit
& 0x1000000)
BAsmCode
[CodeLen
++] = Bit
& 0xff;
}
AppendDisp
(&ArgStr
[2]);
}
}
static void DecodeDBNZ
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(2, 2))
{
tAdrResult AdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModReg8
| MModShort
, &AdrResult
))
{
case ModReg8
:
if ((AdrResult.
Val != CReg8
()) && (AdrResult.
Val != BReg8
())) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
BAsmCode
[CodeLen
++] = 0x30 | (AdrResult.
Val & 3);
break;
case ModShort
:
BAsmCode
[CodeLen
++] = 0x3b;
BAsmCode
[CodeLen
++] = AdrResult.
Vals[0];
break;
default:
return;
}
AppendDisp
(&ArgStr
[2]);
}
}
static void DecodeBRKCS
(Word Code
)
{
ShortInt Bank
;
UNUSED
(Code
);
if (!ChkArgCnt
(1, 1));
else if ((Bank
= DecodeRegBank
(ArgStr
[1].
str.
p_str)) < 0) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
{
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0xd8 | Bank
;
}
}
static void DecodeRETCS
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(1, 1))
{
tAdrResult AdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModAbs
, &AdrResult
))
{
case ModAbs
:
BAsmCode
[CodeLen
++] = 0x29;
BAsmCode
[CodeLen
++] = AdrResult.
Vals[0];
BAsmCode
[CodeLen
++] = AdrResult.
Vals[1];
break;
}
}
}
static void DecodeString1
(Word Code
)
{
UNUSED
(Code
);
SetOpSize
(0);
if (!ChkArgCnt
(2, 2));
else if (ChkAcc
(&ArgStr
[2]))
{
tAdrResult AdrResult
;
switch (DecodeAdr
(&ArgStr
[1], MModMem
, &AdrResult
))
{
case ModMem
:
if ((AdrResult.
Val != 0x16) || (AdrResult.
Vals[0] & 13)) WrError
(ErrNum_InvAddrMode
);
else
{
BAsmCode
[CodeLen
++] = 0x15;
BAsmCode
[CodeLen
++] = Code
| ((AdrResult.
Vals[0] & 2) << 3);
}
break;
}
}
}
static void DecodeString2
(Word Code
)
{
tAdrResult SrcAdrResult
, DestAdrResult
;
UNUSED
(Code
);
if (!ChkArgCnt
(2, 2))
return;
if (DecodeAdr
(&ArgStr
[1], MModMem
, &DestAdrResult
) != ModMem
)
return;
if ((DestAdrResult.
Val != 0x16) || (DestAdrResult.
Vals[0] & 5)) /* [DE-] or [DE+] */
{
WrError
(ErrNum_InvAddrMode
);
return;
}
if (DecodeAdr
(&ArgStr
[2], MModMem
, &SrcAdrResult
) != ModMem
)
return;
if ((SrcAdrResult.
Val != 0x16)
|| ((SrcAdrResult.
Vals[0] & 5) != 1) /* [HL-] or [HL+] */
|| ((DestAdrResult.
Vals[0] ^ SrcAdrResult.
Vals[0]) & 2)) /* match [DE+] with [HL+] and [DE-] with [HL-] */
{
WrError
(ErrNum_InvAddrMode
);
return;
}
BAsmCode
[CodeLen
++] = 0x15;
BAsmCode
[CodeLen
++] = Code
| ((SrcAdrResult.
Vals[0] & 2) << 3);
}
static void DecodeSEL
(Word Code
)
{
ShortInt Bank
= 0;
UNUSED
(Code
);
if (!ChkArgCnt
(1, 2));
else if ((Bank
= DecodeRegBank
(ArgStr
[1].
str.
p_str)) < 0) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else if ((ArgCnt
== 2) && (as_strcasecmp
(ArgStr
[2].
str.
p_str, "ALT"))) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[2]);
{
BAsmCode
[CodeLen
++] = 0x05;
BAsmCode
[CodeLen
++] = 0xa8 | Bank
| ((ArgCnt
- 1) << 4);
}
}
/*-------------------------------------------------------------------------*/
/* dynamic code table handling */
static void AddFixed
(const char *NName
, Word NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeFixed
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(201);
AddInstTable
(InstTable
, "MOV", 0, DecodeMOV
);
AddInstTable
(InstTable
, "MOVW", 1, DecodeMOV
);
AddInstTable
(InstTable
, "XCH", 0, DecodeXCH
);
AddInstTable
(InstTable
, "XCHW", 1, DecodeXCH
);
AddInstTable
(InstTable
, "ADD", 0x40d0, DecodeALU
);
AddInstTable
(InstTable
, "ADDW", 0xc0d0, DecodeALU
);
AddInstTable
(InstTable
, "ADDC", 0x0001, DecodeALU
);
AddInstTable
(InstTable
, "SUB", 0x42e2, DecodeALU
);
AddInstTable
(InstTable
, "SUBW", 0xc2e2, DecodeALU
);
AddInstTable
(InstTable
, "SUBC", 0x0003, DecodeALU
);
AddInstTable
(InstTable
, "AND", 0x0004, DecodeALU
);
AddInstTable
(InstTable
, "OR", 0x0006, DecodeALU
);
AddInstTable
(InstTable
, "XOR", 0x0005, DecodeALU
);
AddInstTable
(InstTable
, "CMP", 0x47f7, DecodeALU
);
AddInstTable
(InstTable
, "CMPW", 0xc7f7, DecodeALU
);
AddInstTable
(InstTable
, "MULU", 0x0020, DecodeMULDIV
);
AddInstTable
(InstTable
, "DIVU", 0x00e1, DecodeMULDIV
);
AddInstTable
(InstTable
, "MULUW", 0x8020, DecodeMULDIV
);
AddInstTable
(InstTable
, "DIVUX", 0x80e1, DecodeMULDIV
);
AddInstTable
(InstTable
, "INC", 0, DecodeINCDEC
);
AddInstTable
(InstTable
, "INCW", 2, DecodeINCDEC
);
AddInstTable
(InstTable
, "DEC", 1, DecodeINCDEC
);
AddInstTable
(InstTable
, "DECW", 3, DecodeINCDEC
);
AddInstTable
(InstTable
, "ROR", 0x0040, DecodeShift
);
AddInstTable
(InstTable
, "ROL", 0x0041, DecodeShift
);
AddInstTable
(InstTable
, "RORC", 0x0000, DecodeShift
);
AddInstTable
(InstTable
, "ROLC", 0x0001, DecodeShift
);
AddInstTable
(InstTable
, "SHR", 0x4c80, DecodeShift
);
AddInstTable
(InstTable
, "SHL", 0x4c81, DecodeShift
);
AddInstTable
(InstTable
, "SHRW", 0xcc80, DecodeShift
);
AddInstTable
(InstTable
, "SHLW", 0xcc81, DecodeShift
);
AddInstTable
(InstTable
, "ROL4", 0x88, DecodeROLROR4
);
AddInstTable
(InstTable
, "ROR4", 0x98, DecodeROLROR4
);
AddFixed
("ADJ4", 0x0004);
AddInstTable
(InstTable
, "MOV1", 0, DecodeMOV1
);
AddInstTable
(InstTable
, "AND1", 0x20, DecodeANDOR1
);
AddInstTable
(InstTable
, "OR1" , 0x40, DecodeANDOR1
);
AddInstTable
(InstTable
, "XOR1" , 0, DecodeXOR1
);
AddInstTable
(InstTable
, "SET1", 0x80, DecodeBit1
);
AddInstTable
(InstTable
, "CLR1", 0x90, DecodeBit1
);
AddInstTable
(InstTable
, "NOT1", 0x70, DecodeBit1
);
AddInstTable
(InstTable
, "CALL", 0, DecodeCALL
);
AddInstTable
(InstTable
, "CALLF", 0, DecodeCALLF
);
AddInstTable
(InstTable
, "CALLT", 0, DecodeCALLT
);
AddFixed
("BRK", 0x005e);
AddFixed
("RET", 0x0056);
AddFixed
("RETI", 0x0057);
AddInstTable
(InstTable
, "PUSH", 0x4935, DecodePUSHPOP
);
AddInstTable
(InstTable
, "PUSHU", 0x0037, DecodePUSHPOP
);
AddInstTable
(InstTable
, "POP", 0x4834, DecodePUSHPOP
);
AddInstTable
(InstTable
, "POPU", 0x0036, DecodePUSHPOP
);
AddInstTable
(InstTable
, "BR", 0, DecodeBR
);
AddInstTable
(InstTable
, "BC", 0x83, DecodeBranch
);
AddInstTable
(InstTable
, "BL", 0x83, DecodeBranch
);
AddInstTable
(InstTable
, "BNC", 0x82, DecodeBranch
);
AddInstTable
(InstTable
, "BNL", 0x82, DecodeBranch
);
AddInstTable
(InstTable
, "BZ", 0x81, DecodeBranch
);
AddInstTable
(InstTable
, "BE", 0x81, DecodeBranch
);
AddInstTable
(InstTable
, "BNZ", 0x80, DecodeBranch
);
AddInstTable
(InstTable
, "BNE", 0x80, DecodeBranch
);
AddInstTable
(InstTable
, "BV", 0x85, DecodeBranch
);
AddInstTable
(InstTable
, "BPE", 0x85, DecodeBranch
);
AddInstTable
(InstTable
, "BNV", 0x84, DecodeBranch
);
AddInstTable
(InstTable
, "BPO", 0x84, DecodeBranch
);
AddInstTable
(InstTable
, "BN", 0x87, DecodeBranch
);
AddInstTable
(InstTable
, "BP", 0x86, DecodeBranch
);
AddInstTable
(InstTable
, "BGT",0x07fb, DecodeBranch
);
AddInstTable
(InstTable
, "BGE",0x07f9, DecodeBranch
);
AddInstTable
(InstTable
, "BLT",0x07f8, DecodeBranch
);
AddInstTable
(InstTable
, "BLE",0x07fa, DecodeBranch
);
AddInstTable
(InstTable
, "BH", 0x07fd, DecodeBranch
);
AddInstTable
(InstTable
, "BNH",0x07fc, DecodeBranch
);
AddInstTable
(InstTable
, "BT" , 0x80, DecodeBrBit
);
AddInstTable
(InstTable
, "BF" , 0x90, DecodeBrBit
);
AddInstTable
(InstTable
, "BTCLR" , 0x60, DecodeBrBit
);
AddInstTable
(InstTable
, "BFSET" , 0x70, DecodeBrBit
);
AddInstTable
(InstTable
, "DBNZ", 0, DecodeDBNZ
);
AddInstTable
(InstTable
, "BRKCS", 0, DecodeBRKCS
);
AddInstTable
(InstTable
, "RETCS", 0, DecodeRETCS
);
AddInstTable
(InstTable
, "MOVM", 0x00, DecodeString1
);
AddInstTable
(InstTable
, "XCHM", 0x01, DecodeString1
);
AddInstTable
(InstTable
, "CMPME", 0x04, DecodeString1
);
AddInstTable
(InstTable
, "CMPMNE", 0x05, DecodeString1
);
AddInstTable
(InstTable
, "CMPMC", 0x07, DecodeString1
);
AddInstTable
(InstTable
, "CMPMNC", 0x06, DecodeString1
);
AddInstTable
(InstTable
, "MOVBK", 0x20, DecodeString2
);
AddInstTable
(InstTable
, "XCHBK", 0x21, DecodeString2
);
AddInstTable
(InstTable
, "CMPBKE", 0x24, DecodeString2
);
AddInstTable
(InstTable
, "CMPBKNE", 0x25, DecodeString2
);
AddInstTable
(InstTable
, "CMPBKC", 0x27, DecodeString2
);
AddInstTable
(InstTable
, "CMPBKNC", 0x26, DecodeString2
);
AddFixed
("SWRS", 0x43);
AddInstTable
(InstTable
, "SEL", 0, DecodeSEL
);
AddFixed
("NOP", 0x00);
AddFixed
("EI", 0x4b);
AddFixed
("DI", 0x4a);
AddInstTable
(InstTable
, "BIT", 0, DecodeBIT
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
}
/*-------------------------------------------------------------------------*/
/* interface to common layer */
static void MakeCode_78K3
(void)
{
CodeLen
= 0; DontPrint
= False
; OpSize
= -1;
AssumeByte
= False
;
/* zu ignorierendes */
if (Memo
(""))
return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo
(False
))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_78K3
(void)
{
return Memo
("BIT");
}
static void InternSymbol_78K3
(char *pAsc
, TempResult
*pErg
)
{
if (!as_strcasecmp
(pAsc
, "PSWL"))
as_tempres_set_int
(pErg
, PSWLAddr
);
else if (!as_strcasecmp
(pAsc
, "PSWH"))
as_tempres_set_int
(pErg
, PSWHAddr
);
}
static void SwitchFrom_78K3
(void)
{
DeinitFields
();
}
static void SwitchTo_78K3
(void)
{
static const ASSUMERec ASSUME78K3s
[] =
{
{"RSS" , &Reg_RSS
, 0, 0x1, 0x0, NULL
},
};
const TFamilyDescr
*pDescr
;
pDescr
= FindFamilyByName
("78K3");
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
PCSymbol
= "PC";
HeaderID
= pDescr
->Id
;
NOPCode
= 0x00;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= 1 << SegCode
;
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = 0xffff;
pASSUMERecs
= ASSUME78K3s
;
ASSUMERecCnt
= sizeof(ASSUME78K3s
) / sizeof(ASSUME78K3s
[0]);
MakeCode
= MakeCode_78K3
;
IsDef
= IsDef_78K3
;
InternSymbol
= InternSymbol_78K3
;
SwitchFrom
= SwitchFrom_78K3
; InitFields
();
}
void code78k3_init
(void)
{
CPU78310
= AddCPU
("78310", SwitchTo_78K3
);
}