/* code96.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Codegenerator MCS/96-Familie */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "bpemu.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "strutil.h"
#include "code96.h"
typedef enum
{
ModNone
= -1,
ModDir
= 0,
ModInd
= 1,
ModPost
= 2,
ModIdx
= 3,
ModImm
= 4
} tAdrMode
;
#define ModNone (-1)
#define MModDir (1 << ModDir)
#define MModInd (1 << ModInd)
#define MModPost (1 << ModPost)
#define MModIdx (1 << ModIdx)
#define MModMem (MModInd | MModPost | MModIdx)
#define MModImm (1 << ModImm)
#define SFRStart 2
#define SFRStop 0x17
typedef enum
{
eForceNone
= 0,
eForceShort
= 1,
eForceLong
= 2
} tForceSize
;
static CPUVar CPU8096
, CPU80196
, CPU80196N
, CPU80296
;
static Byte AdrMode
;
static ShortInt AdrType
;
static Byte AdrVals
[4];
static ShortInt OpSize
;
static LongInt WSRVal
, WSR1Val
;
static Word WinStart
, WinStop
, WinEnd
, WinBegin
;
static Word Win1Start
, Win1Stop
, Win1Begin
, Win1End
;
static IntType MemInt
;
/*---------------------------------------------------------------------------*/
static void ChkSFR
(Word Adr
, const tStrComp
*pArg
)
{
if ((Adr
>= SFRStart
) && (Adr
<= SFRStop
))
WrStrErrorPos
(ErrNum_IOAddrNotAllowed
, pArg
);
}
static void Chk296
(Word Adr
, const tStrComp
*pArg
)
{
if ((MomCPU
== CPU80296
) && (Adr
<= 1))
WrStrErrorPos
(ErrNum_IOAddrNotAllowed
, pArg
);
}
static Boolean ChkWork
(Word
*Adr
)
{
/* Registeradresse, die von Fenstern ueberdeckt wird ? */
if ((*Adr
>= WinBegin
) && (*Adr
<= WinEnd
))
return False
;
else if ((*Adr
>= Win1Begin
) && (*Adr
<= Win1End
))
return False
;
/* Speicheradresse in Fenster ? */
else if ((*Adr
>= WinStart
) && (*Adr
<= WinStop
))
{
*Adr
= (*Adr
) - WinStart
+ WinBegin
;
return True
;
}
else if ((*Adr
>= Win1Start
) && (*Adr
<= Win1Stop
))
{
*Adr
= (*Adr
) - Win1Start
+ Win1Begin
;
return True
;
}
/* Default */
else
return (*Adr
<= 0xff);
}
static void ChkAdr
(Byte Mask
, const tStrComp
*pArg
)
{
if ((AdrType
== ModDir
) && (!(Mask
& MModDir
)))
{
AdrType
= ModInd
; /* not exactly right, but AdrMode counts */
AdrMode
= 0;
}
if ((AdrType
!= ModNone
) && (!(Mask
& (1 << AdrType
))))
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
AdrType
= ModNone
;
AdrCnt
= 0;
}
}
static int SplitForceSize
(const char *pArg
, tForceSize
*pForceSize
)
{
switch (*pArg
)
{
case '>': *pForceSize
= eForceLong
; return 1;
case '<': *pForceSize
= eForceShort
; return 1;
default: return 0;
}
}
static void DecodeAdr
(const tStrComp
*pArg
, Byte Mask
, Boolean AddrWide
)
{
LongInt AdrInt
;
LongWord AdrWord
;
Word BReg
;
Boolean OK
;
tSymbolFlags Flags
;
char *p
, *p2
;
int ArgLen
;
Byte Reg
;
LongWord OMask
;
AdrType
= ModNone
;
AdrCnt
= 0;
OMask
= (1 << OpSize
) - 1;
if (*pArg
->str.
p_str == '#')
{
switch (OpSize
)
{
case -1:
WrStrErrorPos
(ErrNum_UndefOpSizes
, pArg
);
break;
case 0:
AdrVals
[0] = EvalStrIntExpressionOffs
(pArg
, 1, Int8
, &OK
);
if (OK
)
{
AdrType
= ModImm
;
AdrCnt
= 1;
AdrMode
= 1;
}
break;
case 1:
AdrWord
= EvalStrIntExpressionOffs
(pArg
, 1, Int16
, &OK
);
if (OK
)
{
AdrType
= ModImm
;
AdrCnt
= 2;
AdrMode
= 1;
AdrVals
[0] = Lo
(AdrWord
);
AdrVals
[1] = Hi
(AdrWord
);
}
break;
}
goto chk
;
}
p
= QuotPos
(pArg
->str.
p_str, '[');
if (p
)
{
tStrComp Left
, Mid
, Right
;
StrCompSplitRef
(&Left
, &Mid
, pArg
, p
);
p2
= RQuotPos
(Mid.
str.
p_str, ']');
ArgLen
= strlen(Mid.
str.
p_str);
if (!p2
|| (p2
> Mid.
str.
p_str + ArgLen
- 1) || (p2
< Mid.
str.
p_str + ArgLen
- 2)) WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
else
{
StrCompSplitRef
(&Mid
, &Right
, &Mid
, p2
);
BReg
= EvalStrIntExpressionWithFlags
(&Mid
, Int16
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
BReg
= 0;
if (OK
)
{
if (!ChkWork
(&BReg
)) WrStrErrorPos
(ErrNum_OverRange
, &Mid
);
else
{
Reg
= Lo
(BReg
);
ChkSFR
(Reg
, &Mid
);
if (Reg
& 1) WrStrErrorPos
(ErrNum_AddrMustBeEven
, &Mid
);
else if ((strlen(Left.
str.
p_str) == 0) && !strcmp(Right.
str.
p_str, "+"))
{
AdrType
= ModPost
;
AdrMode
= 2;
AdrCnt
= 1;
AdrVals
[0] = Reg
+ 1;
}
else if (strlen(Right.
str.
p_str) != 0) WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
else if (strlen(Left.
str.
p_str) == 0)
{
AdrVals
[0] = Reg
;
AdrCnt
= 1;
if (Mask
& MModInd
)
{
AdrType
= ModInd
;
AdrMode
= 2;
AdrCnt
= 1;
}
else
{
WrStrErrorPos
(ErrNum_IndexedForIndirect
, pArg
);
AdrType
= ModIdx
;
AdrMode
= 3;
AdrVals
[AdrCnt
++] = 0;
}
}
else
{
tForceSize ForceSize
= eForceNone
;
int Offset
= SplitForceSize
(Left.
str.
p_str, &ForceSize
);
AdrInt
= EvalStrIntExpressionOffsWithFlags
(&Left
, Offset
, AddrWide
? Int24
: Int16
, &OK
, &Flags
);
if (OK
)
{
if ((AdrInt
== 0) && (Mask
& MModInd
) && !ForceSize
)
{
AdrType
= ModInd
;
AdrMode
= 2;
AdrCnt
= 1;
AdrVals
[0] = Reg
;
}
else if (AddrWide
)
{
AdrType
= ModIdx
;
AdrMode
= 3;
AdrCnt
= 4;
AdrVals
[0] = Reg
;
AdrVals
[1] = AdrInt
& 0xff;
AdrVals
[2] = (AdrInt
>> 8) & 0xff;
AdrVals
[3] = (AdrInt
>> 16) & 0xff;
}
else
{
Boolean IsShort
= (AdrInt
>= -128) && (AdrInt
<= 127);
if (!ForceSize
)
ForceSize
= IsShort
? eForceShort
: eForceLong
;
if (ForceSize
== eForceShort
)
{
if ((AdrInt
> 127) && !mSymbolQuestionable
(Flags
)) WrStrErrorPos
(ErrNum_OverRange
, &Left
);
else if ((AdrInt
< -128) && !mSymbolQuestionable
(Flags
)) WrStrErrorPos
(ErrNum_UnderRange
, &Left
);
else
{
AdrType
= ModIdx
;
AdrMode
= 3;
AdrCnt
= 2;
AdrVals
[0] = Reg
;
AdrVals
[1] = Lo
(AdrInt
);
}
}
else
{
AdrType
= ModIdx
;
AdrMode
= 3;
AdrCnt
= 3;
AdrVals
[0] = Reg
+ 1;
AdrVals
[1] = Lo
(AdrInt
);
AdrVals
[2] = Hi
(AdrInt
);
}
}
}
}
}
}
}
}
else
{
tForceSize ForceSize
= eForceNone
;
int Offset
= SplitForceSize
(pArg
->str.
p_str, &ForceSize
);
AdrWord
= EvalStrIntExpressionOffsWithFlags
(pArg
, Offset
, MemInt
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
AdrWord
&= (0xffffffff - OMask
);
if (OK
)
{
if (AdrWord
& OMask
) WrStrErrorPos
(ErrNum_NotAligned
, pArg
);
else
{
BReg
= AdrWord
& 0xffff;
if ((!(BReg
& 0xffff0000)) && ChkWork
(&BReg
) && !ForceSize
)
{
AdrType
= ModDir
;
AdrCnt
= 1;
AdrVals
[0] = Lo
(BReg
);
}
else if (AddrWide
)
{
AdrType
= ModIdx
;
AdrMode
= 3;
AdrCnt
= 4;
AdrVals
[0] = 0;
AdrVals
[1] = AdrWord
& 0xff;
AdrVals
[2] = (AdrWord
>> 8) & 0xff;
AdrVals
[3] = (AdrWord
>> 16) & 0xff;
}
else
{
Boolean IsShort
= AdrWord
>= 0xff80;
if (!ForceSize
)
ForceSize
= IsShort
? eForceShort
: eForceLong
;
if (ForceSize
== eForceShort
)
{
if (!IsShort
) WrStrErrorPos
(ErrNum_UnderRange
, pArg
);
else
{
AdrType
= ModIdx
;
AdrMode
= 3;
AdrCnt
= 2;
AdrVals
[0] = 0;
AdrVals
[1] = Lo
(AdrWord
);
}
}
else
{
AdrType
= ModIdx
;
AdrMode
= 3;
AdrCnt
= 3;
AdrVals
[0] = 1;
AdrVals
[1] = Lo
(AdrWord
);
AdrVals
[2] = Hi
(AdrWord
);
}
}
}
}
}
chk
:
ChkAdr
(Mask
, pArg
);
}
static void CalcWSRWindow
(void)
{
WSRVal
&= 0x7f;
if (WSRVal
<= 0x0f)
{
WinStart
= 0xffff;
WinStop
= 0;
WinBegin
= 0xff;
WinEnd
= 0;
}
else if (WSRVal
<= 0x1f)
{
WinBegin
= 0x80;
WinEnd
= 0xff;
WinStart
= (WSRVal
< 0x18) ? ((WSRVal
- 0x10) << 7) : ((WSRVal
+ 0x20) << 7);
WinStop
= WinStart
+ 0x7f;
}
else if (WSRVal
<= 0x3f)
{
WinBegin
= 0xc0;
WinEnd
= 0xff;
WinStart
= (WSRVal
< 0x30) ? ((WSRVal
- 0x20) << 6) : ((WSRVal
+ 0x40) << 6);
WinStop
= WinStart
+ 0x3f;
}
else if (WSRVal
<= 0x7f)
{
WinBegin
= 0xe0;
WinEnd
= 0xff;
WinStart
= (WSRVal
< 0x60) ? ((WSRVal
- 0x40) << 5) : ((WSRVal
+ 0x80) << 5);
WinStop
= WinStart
+ 0x1f;
}
if ((WinStop
> 0x1fdf) && (MomCPU
< CPU80296
))
WinStop
= 0x1fdf;
}
static void CalcWSR1Window
(void)
{
if (WSR1Val
<= 0x1f)
{
Win1Start
= 0xffff;
Win1Stop
= 0;
Win1Begin
= 0xff;
Win1End
= 0;
}
else if (WSR1Val
<= 0x3f)
{
Win1Begin
= 0x40;
Win1End
= 0x7f;
Win1Start
= (WSR1Val
< 0x30) ? ((WSR1Val
- 0x20) << 6) : ((WSR1Val
+ 0x40) << 6);
Win1Stop
= Win1Start
+ 0x3f;
}
else if (WSR1Val
<= 0x7f)
{
Win1Begin
= 0x60;
Win1End
= 0x7f;
Win1Start
= (WSR1Val
< 0x60) ? ((WSR1Val
- 0x40) << 5) : ((WSR1Val
+ 0x80) << 5);
Win1Stop
= Win1Start
+ 0x1f;
}
else
{
Win1Begin
= 0x40;
Win1End
= 0x7f;
Win1Start
= (WSR1Val
+ 0x340) << 6;
Win1Stop
= Win1Start
+ 0x3f;
}
}
static Boolean IsShortBranch
(LongInt Dist
)
{
return (Dist
>= -1024) && (Dist
<= 1023);
}
static Boolean IsByteBranch
(LongInt Dist
)
{
return (Dist
>= -128) && (Dist
<= 127);
}
static Boolean GetShort
(Word Code
, LongInt Dist
)
{
switch (Code
)
{
case 0: return True
;
case 1: return False
;
default: return IsShortBranch
(Dist
);
}
}
/*---------------------------------------------------------------------------*/
static void DecodeFixed
(Word Code
)
{
if (ChkArgCnt
(0, 0))
BAsmCode
[(CodeLen
= 1) - 1] = Code
;
}
static void DecodeALU3
(Word Code
)
{
if (ChkArgCnt
(2, 3))
{
int Start
= 0;
Boolean Special
= (Hi
(Code
) & 0x40) || False
,
DoubleDest
= (Hi
(Code
) & 0x08) || False
;
OpSize
= Hi
(Code
) & 3;
if (Hi
(Code
) & 0x80)
BAsmCode
[Start
++] = 0xfe;
BAsmCode
[Start
++] = 0x40 + (Ord
(ArgCnt
==2) << 5)
+ ((1 - OpSize
) << 4)
+ (Lo
(Code
) << 2);
DecodeAdr
(&ArgStr
[ArgCnt
], MModImm
| MModMem
, False
);
if (AdrType
!= ModNone
)
{
Boolean OK
;
BAsmCode
[Start
- 1] += AdrMode
;
memcpy(BAsmCode
+ Start
, AdrVals
, AdrCnt
);
Start
+= AdrCnt
;
if ((Special
) && (AdrMode
== 0))
ChkSFR
(AdrVals
[0], &ArgStr
[ArgCnt
]);
if (ArgCnt
== 3)
{
DecodeAdr
(&ArgStr
[2], MModDir
, False
);
OK
= (AdrType
!= ModNone
);
if (OK
)
{
BAsmCode
[Start
++] = AdrVals
[0];
if (Special
)
ChkSFR
(AdrVals
[0], &ArgStr
[2]);
}
}
else
OK
= True
;
if (OK
)
{
OpSize
+= DoubleDest
;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[Start
] = AdrVals
[0];
CodeLen
= Start
+ 1;
if (Special
)
{
ChkSFR
(AdrVals
[0], &ArgStr
[1]);
Chk296
(AdrVals
[0], &ArgStr
[1]);
}
}
}
}
}
}
static void DecodeALU2
(Word Code
)
{
if (ChkArgCnt
(2, 2))
{
int Start
= 0;
Boolean Special
= (Hi
(Code
) & 0x40) || False
,
DoubleDest
= (Hi
(Code
) & 0x08) || False
;
Byte HReg
, Mask
;
OpSize
= Hi
(Code
) & 3;
if (Hi
(Code
) & 0x80)
BAsmCode
[Start
++] = 0xfe;
HReg
= ((Hi
(Code
) & 0x20) ? 2 : 1) << 1;
BAsmCode
[Start
++] = Lo
(Code
) + ((1 - OpSize
) << HReg
);
Mask
= MModMem
| ((Hi
(Code
) & 0x20) ? MModImm
: 0);
DecodeAdr
(&ArgStr
[2], Mask
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[Start
- 1] += AdrMode
;
memcpy(BAsmCode
+ Start
, AdrVals
, AdrCnt
);
Start
+= AdrCnt
;
if ((Special
) && (AdrMode
== 0))
ChkSFR
(AdrVals
[0], &ArgStr
[2]);
OpSize
+= DoubleDest
;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[Start
] = AdrVals
[0];
CodeLen
= 1 + Start
;
if (Special
)
{
ChkSFR
(AdrVals
[0], &ArgStr
[1]);
}
}
}
}
}
static void DecodeCMPL
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80196
))
{
OpSize
= 2;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[2] = AdrVals
[0];
DecodeAdr
(&ArgStr
[2], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[1] = AdrVals
[0];
BAsmCode
[0] = 0xc5;
CodeLen
= 3;
}
}
}
}
static void DecodePUSH_POP
(Word IsPOP
)
{
OpSize
= 1;
if (ChkArgCnt
(1, 1))
{
DecodeAdr
(&ArgStr
[1], MModMem
| (IsPOP
? 0 : MModImm
), False
);
if (AdrType
!= ModNone
)
{
CodeLen
= 1 + AdrCnt
;
BAsmCode
[0] = 0xc8 + AdrMode
+ (IsPOP
<< 2);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
}
}
}
static void DecodeBMOV
(Word Code
)
{
if (ChkArgCnt
(2, 2))
{
OpSize
= 2;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[2] = AdrVals
[0];
OpSize
= 1;
DecodeAdr
(&ArgStr
[2], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[1] = AdrVals
[0];
BAsmCode
[0] = Code
;
CodeLen
= 3;
}
}
}
}
static void DecodeALU1
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean DoubleDest
= (Hi
(Code
) & 0x08) || False
;
OpSize
= (Hi
(Code
) & 3) + DoubleDest
;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
CodeLen
= 1 + AdrCnt
;
OpSize
-= DoubleDest
;
BAsmCode
[0] = Code
+ ((1 - OpSize
) << 4);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
}
}
}
static void DecodeXCH
(Word Code
)
{
Byte HReg
;
OpSize
= Hi
(Code
) & 3;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80196
))
{
DecodeAdr
(&ArgStr
[1], MModIdx
| MModDir
, False
);
switch (AdrType
)
{
case ModIdx
:
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
HReg
= AdrCnt
;
BAsmCode
[0] = (AdrMode
? 0x0b : 0x04) + ((1 - OpSize
) << 4);
DecodeAdr
(&ArgStr
[2], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[1 + HReg
] = AdrVals
[0];
CodeLen
= 2 + HReg
;
}
break;
case ModDir
:
HReg
= AdrVals
[0];
DecodeAdr
(&ArgStr
[2], MModDir
| MModIdx
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = ((AdrType
== ModIdx
) ? 0x0b : 0x04) + ((1 - OpSize
) << 4);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode
[1 + AdrCnt
] = HReg
;
CodeLen
= 2 + AdrCnt
;
}
break;
}
}
}
static void DecodeLDBZE_LDBSE
(Word Code
)
{
if (ChkArgCnt
(2, 2))
{
OpSize
= 0;
DecodeAdr
(&ArgStr
[2], MModMem
| MModImm
, False
);
if (AdrType
!= ModNone
)
{
int Start
;
BAsmCode
[0] = Code
+ AdrMode
;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
Start
= 1 + AdrCnt
;
OpSize
= 1;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[Start
] = AdrVals
[0];
CodeLen
= 1 + Start
;
}
}
}
}
static void DecodeNORML
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(2, 2))
{
OpSize
= eSymbolSize8Bit
;
DecodeAdr
(&ArgStr
[2], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[1] = AdrVals
[0];
OpSize
= eSymbolSize32Bit
;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
CodeLen
= 3;
BAsmCode
[0] = 0x0f;
BAsmCode
[2] = AdrVals
[0];
}
}
}
}
static void DecodeIDLPD
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(CPU80196
))
{
OpSize
= 0;
DecodeAdr
(&ArgStr
[1], MModImm
, False
);
if (AdrType
!= ModNone
)
{
CodeLen
= 2;
BAsmCode
[0] = 0xf6;
BAsmCode
[1] = AdrVals
[0];
}
}
}
static void DecodeShift
(Word Code
)
{
OpSize
= Hi
(Code
) & 3;
if (ChkArgCnt
(2, 2))
{
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0x08 + Lo
(Code
) + (Ord
(OpSize
== 0) << 4) + (Ord
(OpSize
== 2) << 2);
BAsmCode
[2] = AdrVals
[0];
OpSize
= 0;
DecodeAdr
(&ArgStr
[2], MModDir
| MModImm
, False
);
if (AdrType
!= ModNone
)
{
if ((AdrType
== ModImm
) && (AdrVals
[0] > 15)) WrStrErrorPos
(ErrNum_OverRange
, &ArgStr
[2]);
else if ((AdrType
== ModDir
) && (AdrVals
[0] < 16)) WrStrErrorPos
(ErrNum_UnderRange
, &ArgStr
[2]);
else
{
BAsmCode
[1] = AdrVals
[0];
CodeLen
= 3;
}
}
}
}
}
static void DecodeSKIP
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(1, 1))
{
OpSize
= 0;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
CodeLen
= 2;
BAsmCode
[0] = 0;
BAsmCode
[1] = AdrVals
[0];
}
}
}
static void DecodeELD_EST
(Word Code
)
{
OpSize
= Hi
(Code
) & 3;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80196N
))
{
DecodeAdr
(&ArgStr
[2], MModInd
| MModIdx
, True
);
if (AdrType
!= ModNone
)
{
Byte HReg
;
BAsmCode
[0] = Code
+ (AdrMode
& 1) + ((1 - OpSize
) << 1);
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
HReg
= 1 + AdrCnt
;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
== ModDir
)
{
BAsmCode
[HReg
] = AdrVals
[0];
CodeLen
= HReg
+ 1;
}
}
}
}
static void DecodeMac
(Word Code
)
{
if (ChkArgCnt
(1, 2)
&& ChkMinCPU
(CPU80296
))
{
OpSize
= 1;
BAsmCode
[0] = 0x4c + (Ord
(ArgCnt
== 1) << 5);
DecodeAdr
(&ArgStr
[ArgCnt
], MModMem
| (Hi
(Code
) ? 0 : MModImm
), False
);
if (AdrType
!= ModNone
)
{
int HReg
;
BAsmCode
[0] += AdrMode
;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
HReg
= 1 + AdrCnt
;
if (ArgCnt
== 2)
{
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
== ModDir
)
{
BAsmCode
[HReg
] = AdrVals
[0];
HReg
++;
}
}
if (AdrType
!= ModNone
)
{
BAsmCode
[HReg
] = Lo
(Code
);
CodeLen
= 1 + HReg
;
}
}
}
}
static void DecodeMVAC_MSAC
(Word Code
)
{
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPU80296
))
{
OpSize
= 2;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
== ModDir
)
{
BAsmCode
[0] = 0x0d;
BAsmCode
[2] = AdrVals
[0] + Code
;
OpSize
= 0;
DecodeAdr
(&ArgStr
[2], MModImm
| MModDir
, False
);
BAsmCode
[1] = AdrVals
[0];
switch (AdrType
)
{
case ModImm
:
if (AdrVals
[0] > 31) WrStrErrorPos
(ErrNum_OverRange
, &ArgStr
[2]);
else CodeLen
= 3;
break;
case ModDir
:
if (AdrVals
[0] < 32) WrStrErrorPos
(ErrNum_UnderRange
, &ArgStr
[2]);
else CodeLen
= 3;
}
}
}
}
static void DecodeRpt
(Word Code
)
{
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(CPU80296
))
{
OpSize
= 1;
DecodeAdr
(&ArgStr
[1], MModImm
| MModPost
| MModInd
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0x40 + AdrMode
;
memcpy(BAsmCode
+ 1, AdrVals
, AdrCnt
);
BAsmCode
[1 + AdrCnt
] = Code
;
BAsmCode
[2 + AdrCnt
] = 4;
CodeLen
= 3 + AdrCnt
;
}
}
}
static void DecodeRel
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
tSymbolFlags Flags
;
LongInt AdrInt
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], MemInt
, &OK
, &Flags
) - (EProgCounter
() + 2);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && !IsByteBranch
(AdrInt
)) WrStrErrorPos
(ErrNum_JmpDistTooBig
, &ArgStr
[1]);
else
{
CodeLen
= 2;
BAsmCode
[0] = Code
;
BAsmCode
[1] = AdrInt
& 0xff;
}
}
}
}
static void DecodeSCALL_LCALL_CALL
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
tSymbolFlags Flags
;
LongWord AdrWord
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], MemInt
, &OK
, &Flags
);
if (OK
)
{
LongInt AdrInt
= AdrWord
- (EProgCounter
() + 2);
Boolean IsShort
= GetShort
(Code
, AdrInt
);
if (IsShort
)
{
if (!mSymbolQuestionable
(Flags
) && !IsShortBranch
(AdrInt
)) WrStrErrorPos
(ErrNum_JmpDistTooBig
, &ArgStr
[1]);
else
{
CodeLen
= 2;
BAsmCode
[1] = AdrInt
& 0xff;
BAsmCode
[0] = 0x28 + ((AdrInt
& 0x700) >> 8);
}
}
else
{
CodeLen
= 3;
BAsmCode
[0] = 0xef;
AdrInt
--;
BAsmCode
[1] = Lo
(AdrInt
);
BAsmCode
[2] = Hi
(AdrInt
);
if (!mSymbolQuestionable
(Flags
) && IsShortBranch
(AdrInt
))
WrStrErrorPos
(ErrNum_ShortJumpPossible
, &ArgStr
[1]);
}
}
}
}
static void DecodeBR_LJMP_SJMP
(Word Code
)
{
OpSize
= 1;
if (!ChkArgCnt
(1, 1));
else if ((Code
== 0xff) && (QuotPos
(ArgStr
[1].
str.
p_str, '[')))
{
DecodeAdr
(&ArgStr
[1], MModInd
, False
);
if (AdrType
!= ModNone
)
{
CodeLen
= 2;
BAsmCode
[0] = 0xe3;
BAsmCode
[1] = AdrVals
[0];
}
}
else
{
Boolean OK
;
tSymbolFlags Flags
;
LongWord AdrWord
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], MemInt
, &OK
, &Flags
);
if (OK
)
{
LongInt AdrInt
= AdrWord
- (EProgCounter
() + 2);
Boolean IsShort
= GetShort
(Code
, AdrInt
);
if (IsShort
)
{
if (!mSymbolQuestionable
(Flags
) && !IsShortBranch
(AdrInt
)) WrStrErrorPos
(ErrNum_JmpDistTooBig
, &ArgStr
[1]);
else
{
CodeLen
= 2;
BAsmCode
[1] = AdrInt
& 0xff;
BAsmCode
[0] = 0x20 + ((AdrInt
& 0x700) >> 8);
}
}
else
{
CodeLen
= 3;
BAsmCode
[0] = 0xe7;
AdrInt
--;
BAsmCode
[1] = Lo
(AdrInt
);
BAsmCode
[2] = Hi
(AdrInt
);
if (!mSymbolQuestionable
(Flags
) && IsShortBranch
(AdrInt
))
WrStrErrorPos
(ErrNum_ShortJumpPossible
, &ArgStr
[1]);
}
}
}
}
static void DecodeTIJMP
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(3, 3)
&& ChkMinCPU
(CPU80196
))
{
OpSize
= 1;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[3] = AdrVals
[0];
DecodeAdr
(&ArgStr
[2], MModDir
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[1] = AdrVals
[0];
OpSize
= 0;
DecodeAdr
(&ArgStr
[3], MModImm
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[2] = AdrVals
[0];
BAsmCode
[0] = 0xe2;
CodeLen
= 4;
}
}
}
}
}
static void DecodeDJNZ_DJNZW
(Word Size
)
{
if (ChkArgCnt
(2, 2)
&& (!Size
|| ChkMinCPU
(CPU80196
)))
{
OpSize
= Size
;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
Boolean OK
;
tSymbolFlags Flags
;
LongInt AdrInt
;
BAsmCode
[0] = 0xe0 + OpSize
;
BAsmCode
[1] = AdrVals
[0];
AdrInt
= EvalStrIntExpressionWithFlags
(&ArgStr
[2], MemInt
, &OK
, &Flags
) - (EProgCounter
() + 3);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && !IsByteBranch
(AdrInt
)) WrStrErrorPos
(ErrNum_JmpDistTooBig
, &ArgStr
[2]);
else
{
CodeLen
= 3;
BAsmCode
[2] = AdrInt
& 0xff;
}
}
}
}
}
static void DecodeJBC_JBS
(Word Code
)
{
if (ChkArgCnt
(3, 3))
{
Boolean OK
;
BAsmCode
[0] = Code
+ EvalStrIntExpression
(&ArgStr
[2], UInt3
, &OK
);
if (OK
)
{
OpSize
= 0;
DecodeAdr
(&ArgStr
[1], MModDir
, False
);
if (AdrType
!= ModNone
)
{
LongInt AdrInt
;
tSymbolFlags Flags
;
BAsmCode
[1] = AdrVals
[0];
AdrInt
= EvalStrIntExpressionWithFlags
(&ArgStr
[3], MemInt
, &OK
, &Flags
) - (EProgCounter
() + 3);
if (OK
)
{
if (!mSymbolQuestionable
(Flags
) && !IsByteBranch
(AdrInt
)) WrStrErrorPos
(ErrNum_JmpDistTooBig
, &ArgStr
[3]);
else
{
CodeLen
= 3;
BAsmCode
[2] = AdrInt
& 0xff;
}
}
}
}
}
}
static void DecodeECALL
(Word Code
)
{
UNUSED
(Code
);
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(CPU80196N
))
{
Boolean OK
;
LongInt AdrInt
= EvalStrIntExpression
(&ArgStr
[1], MemInt
, &OK
) - (EProgCounter
() + 4);
if (OK
)
{
BAsmCode
[0] = 0xf1;
BAsmCode
[1] = AdrInt
& 0xff;
BAsmCode
[2] = (AdrInt
>> 8) & 0xff;
BAsmCode
[3] = (AdrInt
>> 16) & 0xff;
CodeLen
= 4;
}
}
}
static void DecodeEJMP_EBR
(Word Code
)
{
UNUSED
(Code
);
OpSize
= 1;
if (!ChkArgCnt
(1, 1));
else if (!ChkMinCPU
(CPU80196N
));
else if (*ArgStr
[1].
str.
p_str == '[')
{
DecodeAdr
(&ArgStr
[1], MModInd
, False
);
if (AdrType
!= ModNone
)
{
BAsmCode
[0] = 0xe3;
BAsmCode
[1] = AdrVals
[0] + 1;
CodeLen
= 2;
}
}
else
{
Boolean OK
;
LongInt AdrInt
= EvalStrIntExpression
(&ArgStr
[1], MemInt
, &OK
) - (EProgCounter
() + 4);
if (OK
)
{
BAsmCode
[0] = 0xe6;
BAsmCode
[1] = AdrInt
& 0xff;
BAsmCode
[2] = (AdrInt
>> 8) & 0xff;
BAsmCode
[3] = (AdrInt
>> 16) & 0xff;
CodeLen
= 4;
}
}
}
/*---------------------------------------------------------------------------*/
static void AddSize
(const char *NName
, Word NCode
, InstProc Proc
, Word SizeMask
)
{
int l
;
char SizeName
[20];
if (SizeMask
& 2)
AddInstTable
(InstTable
, NName
, 0x0100 | NCode
, Proc
);
l
= as_snprintf
(SizeName
, sizeof(SizeName
), "%sB", NName
);
if (SizeMask
& 1)
AddInstTable
(InstTable
, SizeName
, 0x0000 | NCode
, Proc
);
if (SizeMask
& 4)
{
SizeName
[l
- 1] = 'L';
AddInstTable
(InstTable
, SizeName
, 0x0200 | NCode
, Proc
);
}
}
static void AddFixed
(const char *NName
, Byte NCode
, CPUVar NMin
, CPUVar NMax
)
{
if ((MomCPU
>= NMin
) && (MomCPU
<= NMax
))
AddInstTable
(InstTable
, NName
, NCode
, DecodeFixed
);
}
static void AddALU3
(const char *NName
, Word NCode
)
{
AddSize
(NName
, NCode
, DecodeALU3
, 3);
}
static void AddALU2
(const char *NName
, Word NCode
)
{
AddSize
(NName
, NCode
, DecodeALU2
, 3);
}
static void AddALU1
(const char *NName
, Word NCode
)
{
AddSize
(NName
, NCode
, DecodeALU1
, 3);
}
static void AddRel
(const char *NName
, Byte NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeRel
);
}
static void AddMac
(const char *NName
, Word NCode
, Boolean NRel
)
{
AddInstTable
(InstTable
, NName
, NCode
| (NRel
? 0x100 : 0), DecodeMac
);
}
static void AddRpt
(const char *NName
, Byte NCode
)
{
AddInstTable
(InstTable
, NName
, NCode
, DecodeRpt
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(207);
SetDynamicInstTable
(InstTable
);
AddInstTable
(InstTable
, "CMPL", 0, DecodeCMPL
);
AddInstTable
(InstTable
, "PUSH", 0, DecodePUSH_POP
);
AddInstTable
(InstTable
, "POP" , 1, DecodePUSH_POP
);
if (MomCPU
>= CPU80196
)
{
AddInstTable
(InstTable
, "BMOV", 0xc1, DecodeBMOV
);
AddInstTable
(InstTable
, "BMOVI", 0xcd, DecodeBMOV
);
}
if (MomCPU
>= CPU80196N
)
AddInstTable
(InstTable
, "EBMOVI", 0xe4, DecodeBMOV
);
AddSize
("XCH", 0, DecodeXCH
, 3);
AddInstTable
(InstTable
, "LDBZE", 0xac, DecodeLDBZE_LDBSE
);
AddInstTable
(InstTable
, "LDBSE", 0xbc, DecodeLDBZE_LDBSE
);
AddInstTable
(InstTable
, "NORML", 0, DecodeNORML
);
AddInstTable
(InstTable
, "IDLPD", 0, DecodeIDLPD
);
AddSize
("SHR", 0, DecodeShift
, 7);
AddSize
("SHL", 1, DecodeShift
, 7);
AddSize
("SHRA", 2, DecodeShift
, 7);
AddInstTable
(InstTable
, "SKIP", 0, DecodeSKIP
);
AddSize
("ELD", 0xe8, DecodeELD_EST
, 3);
AddSize
("EST", 0x1c, DecodeELD_EST
, 3);
AddInstTable
(InstTable
, "MVAC", 1, DecodeMVAC_MSAC
);
AddInstTable
(InstTable
, "MSAC", 3, DecodeMVAC_MSAC
);
AddInstTable
(InstTable
, "CALL", 0xff, DecodeSCALL_LCALL_CALL
);
AddInstTable
(InstTable
, "LCALL", 1, DecodeSCALL_LCALL_CALL
);
AddInstTable
(InstTable
, "SCALL", 0, DecodeSCALL_LCALL_CALL
);
AddInstTable
(InstTable
, "BR", 0xff, DecodeBR_LJMP_SJMP
);
AddInstTable
(InstTable
, "LJMP", 1, DecodeBR_LJMP_SJMP
);
AddInstTable
(InstTable
, "SJMP", 0, DecodeBR_LJMP_SJMP
);
AddInstTable
(InstTable
, "TIJMP", 0, DecodeTIJMP
);
AddInstTable
(InstTable
, "DJNZ", 0, DecodeDJNZ_DJNZW
);
AddInstTable
(InstTable
, "DJNZW", 1, DecodeDJNZ_DJNZW
);
AddInstTable
(InstTable
, "JBC", 0x30, DecodeJBC_JBS
);
AddInstTable
(InstTable
, "JBS", 0x38, DecodeJBC_JBS
);
AddInstTable
(InstTable
, "ECALL", 0, DecodeECALL
);
AddInstTable
(InstTable
, "EJMP", 0, DecodeEJMP_EBR
);
AddInstTable
(InstTable
, "EBR", 0, DecodeEJMP_EBR
);
AddFixed
("CLRC" , 0xf8, CPU8096
, CPU80296
);
AddFixed
("CLRVT", 0xfc, CPU8096
, CPU80296
);
AddFixed
("DI" , 0xfa, CPU8096
, CPU80296
);
AddFixed
("DPTS" , 0xec, CPU80196
, CPU80196N
);
AddFixed
("EI" , 0xfb, CPU8096
, CPU80296
);
AddFixed
("EPTS" , 0xed, CPU80196
, CPU80196N
);
AddFixed
("NOP" , 0xfd, CPU8096
, CPU80296
);
AddFixed
("POPA" , 0xf5, CPU80196
, CPU80296
);
AddFixed
("POPF" , 0xf3, CPU8096
, CPU80296
);
AddFixed
("PUSHA", 0xf4, CPU80196
, CPU80296
);
AddFixed
("PUSHF", 0xf2, CPU8096
, CPU80296
);
AddFixed
("RET" , 0xf0, CPU8096
, CPU80296
);
AddFixed
("RST" , 0xff, CPU8096
, CPU80296
);
AddFixed
("SETC" , 0xf9, CPU8096
, CPU80296
);
AddFixed
("TRAP" , 0xf7, CPU8096
, CPU80296
);
AddFixed
("RETI" , 0xe5, CPU80196N
, CPU80296
);
AddALU3
("ADD" , 0x0001);
AddALU3
("AND" , 0x0000);
AddALU3
("MUL" , 0xc803);
AddALU3
("MULU", 0x4803);
AddALU3
("SUB" , 0x0002);
AddALU2
("ADDC", 0x20a4);
AddALU2
("CMP" , 0x2088);
AddALU2
("DIV" , 0xe88c);
AddALU2
("DIVU", 0x688c);
AddALU2
("LD" , 0x20a0);
AddALU2
("OR" , 0x2080);
AddALU2
("ST" , 0x00c0);
AddALU2
("SUBC", 0x20a8);
AddALU2
("XOR" , 0x2084);
AddALU1
("CLR", 0x0001);
AddALU1
("DEC", 0x0005);
AddALU1
("EXT", 0x8806);
AddALU1
("INC", 0x0007);
AddALU1
("NEG", 0x0003);
AddALU1
("NOT", 0x0002);
AddRel
("JC" , 0xdb);
AddRel
("JE" , 0xdf);
AddRel
("JGE" , 0xd6);
AddRel
("JGT" , 0xd2);
AddRel
("JH" , 0xd9);
AddRel
("JLE" , 0xda);
AddRel
("JLT" , 0xde);
AddRel
("JNC" , 0xd3);
AddRel
("JNE" , 0xd7);
AddRel
("JNH" , 0xd1);
AddRel
("JNST" , 0xd0);
AddRel
("JNV" , 0xd5);
AddRel
("JNVT" , 0xd4);
AddRel
("JST" , 0xd8);
AddRel
("JV" , 0xdd);
AddRel
("JVT" , 0xdc);
AddMac
("MAC" , 0x00, False
); AddMac
("SMAC" , 0x01, False
);
AddMac
("MACR" , 0x04, True
); AddMac
("SMACR" , 0x05, True
);
AddMac
("MACZ" , 0x08, False
); AddMac
("SMACZ" , 0x09, False
);
AddMac
("MACRZ" , 0x0c, True
); AddMac
("SMACRZ", 0x0d, True
);
AddRpt
("RPT" , 0x00); AddRpt
("RPTNST" , 0x10); AddRpt
("RPTNH" , 0x11);
AddRpt
("RPTGT" , 0x12); AddRpt
("RPTNC" , 0x13); AddRpt
("RPTNVT" , 0x14);
AddRpt
("RPTNV" , 0x15); AddRpt
("RPTGE" , 0x16); AddRpt
("RPTNE" , 0x17);
AddRpt
("RPTST" , 0x18); AddRpt
("RPTH" , 0x19); AddRpt
("RPTLE" , 0x1a);
AddRpt
("RPTC" , 0x1b); AddRpt
("RPTVT" , 0x1c); AddRpt
("RPTV" , 0x1d);
AddRpt
("RPTLT" , 0x1e); AddRpt
("RPTE" , 0x1f); AddRpt
("RPTI" , 0x20);
AddRpt
("RPTINST", 0x30); AddRpt
("RPTINH" , 0x31); AddRpt
("RPTIGT" , 0x32);
AddRpt
("RPTINC" , 0x33); AddRpt
("RPTINVT", 0x34); AddRpt
("RPTINV" , 0x35);
AddRpt
("RPTIGE" , 0x36); AddRpt
("RPTINE" , 0x37); AddRpt
("RPTIST" , 0x38);
AddRpt
("RPTIH" , 0x39); AddRpt
("RPTILE" , 0x3a); AddRpt
("RPTIC" , 0x3b);
AddRpt
("RPTIVT" , 0x3c); AddRpt
("RPTIV" , 0x3d); AddRpt
("RPTILT" , 0x3e);
AddRpt
("RPTIE" , 0x3f);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
}
/*-------------------------------------------------------------------------*/
static void MakeCode_96
(void)
{
CodeLen
= 0;
DontPrint
= False
;
OpSize
= -1;
/* zu ignorierendes */
if (Memo
(""))
return;
/* Pseudoanweisungen */
if (DecodeIntelPseudo
(False
))
return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static void InitCode_96
(void)
{
WSRVal
= 0; CalcWSRWindow
();
WSR1Val
= 0; CalcWSR1Window
();
}
static Boolean IsDef_96
(void)
{
return False
;
}
static void SwitchFrom_96
(void)
{
DeinitFields
();
}
static ASSUMERec ASSUME96s
[] =
{
{"WSR" , &WSRVal
, 0, 0xff, 0x00, CalcWSRWindow
},
{"WSR1", &WSR1Val
, 0, 0xbf, 0x00, CalcWSR1Window
},
};
static void SwitchTo_96
(void)
{
TurnWords
= False
;
SetIntConstMode
(eIntConstModeIntel
);
PCSymbol
= "$";
HeaderID
= 0x39;
NOPCode
= 0xfd;
DivideChars
= ",";
HasAttrs
= False
;
ValidSegs
= 1 << SegCode
;
Grans
[SegCode
] = 1;
ListGrans
[SegCode
] = 1;
SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = (MomCPU
>= CPU80196N
) ? 0xffffffl
: 0xffff;
MakeCode
= MakeCode_96
;
IsDef
= IsDef_96
;
SwitchFrom
= SwitchFrom_96
;
MemInt
= (MomCPU
>= CPU80196N
) ? UInt24
: UInt16
;
if (MomCPU
>= CPU80196
)
{
pASSUMERecs
= ASSUME96s
;
ASSUMERecCnt
= (MomCPU
>= CPU80296
) ? (sizeof(ASSUME96s
) / sizeof(*ASSUME96s
)) : 1;
}
InitFields
();
}
void code96_init
(void)
{
CPU8096
= AddCPU
("8096" , SwitchTo_96
);
CPU80196
= AddCPU
("80196" , SwitchTo_96
);
CPU80196N
= AddCPU
("80196N", SwitchTo_96
);
CPU80296
= AddCPU
("80296" , SwitchTo_96
);
AddInitPassProc
(InitCode_96
);
}