/* code68s12z.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS */
/* */
/* Code Generator NXP S12Z */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include "strutil.h"
#include "bpemu.h"
#include "asmdef.h"
#include "asmpars.h"
#include "asmsub.h"
#include "asmallg.h"
#include "asmitree.h"
#include "asmstructs.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "codevars.h"
#include "errmsg.h"
#include "headids.h"
#include "codes12z.h"
typedef enum
{
AdrModeNone
= -1,
AdrModeReg
= 0,
AdrModeAReg
= 1,
AdrModeImm
= 2,
AdrModeMemReg
= 3
} tAdrMode
;
typedef enum
{
eIndirModeNone
,
eIndirModePar
,
eIndirModeSquare
} tIndirMode
;
typedef enum
{
eIncModeNone
,
eIncModePreInc
,
eIncModePostInc
,
eIncModePreDec
,
eIncModePostDec
} tIncMode
;
#define MModeReg (1 << AdrModeReg)
#define MModeAReg (1 << AdrModeAReg)
#define MModeImm (1 << AdrModeImm)
#define MModeMemReg (1 << AdrModeMemReg)
#define OpSizeBitPos8 ((tSymbolSize)16)
#define OpSizeBitPos16 ((tSymbolSize)17)
#define OpSizeBitPos32 ((tSymbolSize)18)
#define OpSizeShiftCount ((tSymbolSize)19)
typedef struct
{
tAdrMode Mode
;
Byte Arg
, Vals
[4], ShiftLSB
;
unsigned ValCnt
;
} tAdrVals
;
static tSymbolSize OpSize
, OpSize2
;
static const tSymbolSize RegSizes
[16] =
{
eSymbolSize16Bit
, eSymbolSize16Bit
, /* D2/D3 */
eSymbolSize16Bit
, eSymbolSize16Bit
, /* D4/D5 */
eSymbolSize8Bit
, eSymbolSize8Bit
, /* D0/D1 */
eSymbolSize32Bit
, eSymbolSize32Bit
, /* D6/D7 */
eSymbolSize24Bit
, eSymbolSize24Bit
, /* X/Y */
eSymbolSize24Bit
, eSymbolSizeUnknown
, /* S/- */
eSymbolSize8Bit
, eSymbolSize8Bit
, /* CCH/CCL */
eSymbolSize16Bit
, eSymbolSizeUnknown
, /* CCR/- */
};
/*--------------------------------------------------------------------------*/
/* Helper Functions */
static void PutCode
(Word Code
)
{
if (Hi
(Code
))
BAsmCode
[CodeLen
++] = Hi
(Code
);
BAsmCode
[CodeLen
++] = Lo
(Code
);
}
static void AppendAdrVals
(const tAdrVals
*pVals
)
{
memcpy(BAsmCode
+ CodeLen
, pVals
->Vals
, pVals
->ValCnt
);
CodeLen
+= pVals
->ValCnt
;
}
static Boolean DecodeRegStr
(const char *pArg
, Byte
*pRes
)
{
if ((strlen(pArg
) == 2)
&& (toupper(*pArg
) == 'D')
&& ((pArg
[1] >= '0') && (pArg
[1] <= '7')))
{
static const Byte RegCodes
[8] = { 4, 5, 0, 1, 2, 3, 6, 7 };
*pRes
= RegCodes
[pArg
[1] - '0'];
return True
;
}
else
return False
;
}
static Boolean DecodeAdrRegStr
(const char *pArg
, Byte
*pRes
)
{
static const char Regs
[4][3] = { "X", "Y", "S", "PC" };
unsigned z
;
for (z
= 0; z
< 4; z
++)
if (!as_strcasecmp
(pArg
, Regs
[z
]))
{
*pRes
= z
;
return True
;
}
return False
;
}
static Boolean DecodeRegArg
(int ArgNum
, Byte
*pRes
, Byte Mask
)
{
Boolean Result
= DecodeRegStr
(ArgStr
[ArgNum
].
str.
p_str, pRes
);
if (!Result
|| !((Mask
>> *pRes
) & 1))
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[ArgNum
]);
return Result
;
}
static Boolean DecodeAdrRegArg
(int ArgNum
, Byte
*pRes
, Byte Mask
)
{
Boolean Result
= DecodeAdrRegStr
(ArgStr
[ArgNum
].
str.
p_str, pRes
);
if (!Result
|| !((Mask
>> *pRes
) & 1))
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[ArgNum
]);
return Result
;
}
static Boolean DecodeGenRegArg
(int ArgNum
, Byte
*pRes
)
{
if (DecodeRegStr
(ArgStr
[ArgNum
].
str.
p_str, pRes
))
return True
;
else if (DecodeAdrRegStr
(ArgStr
[ArgNum
].
str.
p_str, pRes
) && (*pRes
!= 3))
{
*pRes
+= 8;
return True
;
}
else if (!as_strcasecmp
(ArgStr
[ArgNum
].
str.
p_str, "CCH"))
{
*pRes
= 12;
return True
;
}
else if (!as_strcasecmp
(ArgStr
[ArgNum
].
str.
p_str, "CCL"))
{
*pRes
= 13;
return True
;
}
else if (!as_strcasecmp
(ArgStr
[ArgNum
].
str.
p_str, "CCW"))
{
*pRes
= 14;
return True
;
}
else
return False
;
}
static Boolean ShortImm
(LongInt Value
, ShortInt OpSize
, Byte
*pShortValue
, Byte
*pShiftLSB
)
{
if (OpSize
== OpSizeShiftCount
)
{
if ((Value
>= 0) && (Value
<= 31))
{
*pShortValue
= (Value
>> 1 & 15);
*pShiftLSB
= Value
& 1;
return True
;
}
else
return False
;
}
else if (OpSize
< OpSizeBitPos8
)
{
if (Value
== -1)
{
*pShortValue
= 0;
return True
;
}
else if ((Value
>= 1) && (Value
<= 15))
{
*pShortValue
= Value
;
return True
;
}
else if (((Value
== (LongInt
)0xff) && (OpSize
== 0))
|| ((Value
== (LongInt
)0xffff) && (OpSize
== 1))
|| ((Value
== (LongInt
)0xffffff) && (OpSize
== eSymbolSize24Bit
))
|| ((Value
== (LongInt
)0xffffffff) && (OpSize
== 2)))
{
*pShortValue
= 0;
return True
;
}
else
return False
;
}
else
return False
;
}
static unsigned OpSizeByteLen
(ShortInt OpSize
)
{
switch (OpSize
)
{
case -1: return 0;
case 1: return 2;
case 2: return 4;
case eSymbolSize24Bit
: return 3;
default: return 1;
}
}
static void ResetAdrVals
(tAdrVals
*pVals
)
{
pVals
->Mode
= AdrModeNone
;
pVals
->Arg
= 0;
pVals
->ValCnt
= 0;
pVals
->ShiftLSB
= 0;
}
static Boolean IsIncDec
(char ch
, char *pRes
)
{
*pRes
= ((ch
== '+') || (ch
== '-')) ? ch
: '\0';
return !!*pRes
;
}
static void CopyIndirect
(tStrComp
*pDest
, const tStrComp
*pSrc
)
{
pDest
->Pos.
Len = strmemcpy
(pDest
->str.
p_str, STRINGSIZE
, pSrc
->str.
p_str + 1, strlen(pSrc
->str.
p_str) - 2);
pDest
->Pos.
StartCol = pSrc
->Pos.
StartCol + 1;
}
static Boolean DecodeAdr
(int ArgIndex
, unsigned ModeMask
, tAdrVals
*pVals
)
{
String CompStr
;
tStrComp Comp
;
int l
;
tIndirMode IndirMode
;
LargeWord Address
;
Boolean OK
;
ResetAdrVals
(pVals
);
StrCompMkTemp
(&Comp
, CompStr
, sizeof(CompStr
));
/* simple register: */
if (DecodeRegStr
(ArgStr
[ArgIndex
].
str.
p_str, &pVals
->Arg
))
{
if (ModeMask
& MModeReg
)
pVals
->Mode
= AdrModeReg
;
else
{
pVals
->Mode
= AdrModeMemReg
;
pVals
->Arg
|= 0xb8;
}
goto done
;
}
if (DecodeAdrRegStr
(ArgStr
[ArgIndex
].
str.
p_str, &pVals
->Arg
))
{
pVals
->Mode
= AdrModeAReg
;
goto done
;
}
/* immediate: */
if (*ArgStr
[ArgIndex
].
str.
p_str == '#')
{
Boolean OK
;
LongInt Value
;
/* avoid returning AdrModeMemReg if immediate is forbidden */
if (!(ModeMask
&MModeImm
))
goto error
;
switch ((int)OpSize
)
{
case eSymbolSize8Bit
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, Int8
, &OK
);
break;
case eSymbolSize16Bit
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, Int16
, &OK
);
break;
case eSymbolSize32Bit
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, Int32
, &OK
);
break;
case eSymbolSize24Bit
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, Int24
, &OK
);
break;
case OpSizeBitPos8
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, UInt3
, &OK
);
break;
case OpSizeBitPos16
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, UInt4
, &OK
);
break;
case OpSizeBitPos32
:
case OpSizeShiftCount
:
Value
= EvalStrIntExpressionOffs
(&ArgStr
[ArgIndex
], 1, UInt5
, &OK
);
break;
default:
WrStrErrorPos
(ErrNum_UndefOpSizes
, &ArgStr
[ArgIndex
]);
goto done
;
}
if ((ModeMask
& MModeMemReg
) && (ShortImm
(Value
, OpSize
, &pVals
->Arg
, &pVals
->ShiftLSB
)))
{
pVals
->Mode
= AdrModeMemReg
;
pVals
->Arg
|= 0x70;
}
else
{
pVals
->Mode
= AdrModeImm
;
if (OpSize
== eSymbolSize32Bit
)
pVals
->Vals
[pVals
->ValCnt
++] = (Value
>> 24) & 0xff;
if ((OpSize
== eSymbolSize32Bit
) || (OpSize
== eSymbolSize24Bit
))
pVals
->Vals
[pVals
->ValCnt
++] = (Value
>> 16) & 0xff;
if ((OpSize
!= eSymbolSize8Bit
) && (OpSize
< OpSizeBitPos8
))
pVals
->Vals
[pVals
->ValCnt
++] = (Value
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = Value
& 0xff;
}
goto done
;
}
/* indirect () []: */
l
= strlen(ArgStr
[ArgIndex
].
str.
p_str);
if (IsIndirect
(ArgStr
[ArgIndex
].
str.
p_str))
IndirMode
= eIndirModePar
;
else if ((l
>= 2) && (ArgStr
[ArgIndex
].
str.
p_str[0] == '[') && (ArgStr
[ArgIndex
].
str.
p_str[l
- 1] == ']'))
IndirMode
= eIndirModeSquare
;
else
IndirMode
= eIndirModeNone
;
if (IndirMode
)
{
char *pSep
, IncChar
;
LongInt DispAcc
= 0;
Byte DataReg
= 0, AdrReg
= 0, AdrIncReg
= 0;
Boolean AdrRegPresent
= False
, DataRegPresent
= False
, HasDisp
= False
;
tIncMode IncMode
= eIncModeNone
;
tStrComp Right
, RunComp
;
CopyIndirect
(&Comp
, &ArgStr
[ArgIndex
]);
StrCompRefRight
(&RunComp
, &Comp
, 0);
/* split into components */
while (True
)
{
pSep
= QuotPos
(RunComp.
str.
p_str, ',');
if (pSep
)
StrCompSplitRef
(&RunComp
, &Right
, &RunComp
, pSep
);
/* remove leading/trailing spaces */
KillPrefBlanksStrCompRef
(&RunComp
);
KillPostBlanksStrComp
(&RunComp
);
l
= strlen(RunComp.
str.
p_str);
if (DecodeRegStr
(RunComp.
str.
p_str, &DataReg
))
{
if (DataRegPresent
)
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &RunComp
);
goto done
;
}
DataRegPresent
= True
;
}
else if (DecodeAdrRegStr
(RunComp.
str.
p_str, &AdrReg
))
{
if (AdrRegPresent
)
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &RunComp
);
goto done
;
}
AdrRegPresent
= True
;
}
else if (IsIncDec
(*RunComp.
str.
p_str, &IncChar
) && DecodeAdrRegStr
(RunComp.
str.
p_str + 1, &AdrIncReg
))
{
if (IncMode
)
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &RunComp
);
goto done
;
}
IncMode
= (IncChar
== '+') ? eIncModePreInc
: eIncModePreDec
;
}
else if (IsIncDec
(Comp.
str.
p_str[l
- 1], &IncChar
))
{
RunComp.
str.
p_str[l
- 1] = '\0';
if (!DecodeAdrRegStr
(RunComp.
str.
p_str, &AdrIncReg
))
{
WrStrErrorPos
(ErrNum_InvReg
, &RunComp
);
goto done
;
}
if (IncMode
)
{
WrStrErrorPos
(ErrNum_InvAddrMode
, &RunComp
);
goto done
;
}
IncMode
= (IncChar
== '+') ? eIncModePostInc
: eIncModePostDec
;
}
else
{
Boolean OK
;
LongInt Val
= EvalStrIntExpression
(&RunComp
, Int24
, &OK
);
if (!OK
)
goto done
;
DispAcc
+= Val
;
HasDisp
= True
;
}
if (pSep
)
RunComp
= Right
;
else
break;
}
/* pre/pos in/decrement */
if ((IndirMode
== eIndirModePar
) && IncMode
&& !DispAcc
&& !AdrRegPresent
&& !DataRegPresent
)
{
switch (AdrIncReg
)
{
case 0:
case 1:
pVals
->Arg
= 0xc3 | (AdrIncReg
<< 4);
if ((IncMode
== eIncModePostInc
) || (IncMode
== eIncModePreInc
))
pVals
->Arg
|= 0x20;
if ((IncMode
== eIncModePostInc
) || (IncMode
== eIncModePostDec
))
pVals
->Arg
|= 0x04;
pVals
->Mode
= AdrModeMemReg
;
break;
case 2:
if (IncMode
== eIncModePreDec
)
{
pVals
->Arg
= 0xfb;
pVals
->Mode
= AdrModeMemReg
;
}
else if (IncMode
== eIncModePostInc
)
{
pVals
->Arg
= 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
else
goto error
;
break;
default:
goto error
;
}
}
/* (disp,XYSP) */
else if ((IndirMode
== eIndirModePar
) && AdrRegPresent
&& !DataRegPresent
&& !IncMode
)
{
if ((AdrReg
== 3) && (HasDisp
))
DispAcc
-= EProgCounter
();
if ((DispAcc
>= 0) && (DispAcc
<= 15) && (AdrReg
!= 3))
{
pVals
->Arg
= 0x40 | (AdrReg
<< 4) | (DispAcc
& 15);
pVals
->Mode
= AdrModeMemReg
;
}
else if (RangeCheck
(DispAcc
, SInt9
))
{
pVals
->Arg
= 0xc0 | (AdrReg
<< 4) | ((DispAcc
>> 8) & 1);
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
else
{
pVals
->Arg
= 0xc2 | (AdrReg
<< 4);
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 16) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
}
/* (Dn,XYS) */
else if ((IndirMode
== eIndirModePar
) && AdrRegPresent
&& DataRegPresent
&& !IncMode
&& !DispAcc
)
{
if (AdrReg
== 3)
goto error
;
else
{
pVals
->Arg
= 0x88 | (AdrReg
<< 4) | DataReg
;
pVals
->Mode
= AdrModeMemReg
;
}
}
/* (disp,Dn) */
else if ((IndirMode
== eIndirModePar
) && !AdrRegPresent
&& DataRegPresent
&& !IncMode
)
{
if (RangeCheck
(DispAcc
, UInt18
))
{
pVals
->Arg
= 0x80 | DataReg
| ((DispAcc
>> 12) & 0x30);
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
else
{
pVals
->Arg
= 0xe8 | DataReg
;
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 16) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
}
/* [Dn,XY] */
else if ((IndirMode
== eIndirModeSquare
) && AdrRegPresent
&& DataRegPresent
&& !IncMode
&& !DispAcc
)
{
if (AdrReg
>= 2)
goto error
;
else
{
pVals
->Arg
= 0xc8 | (AdrReg
<< 4) | DataReg
;
pVals
->Mode
= AdrModeMemReg
;
}
}
/* [disp,XYSP] */
else if ((IndirMode
== eIndirModeSquare
) && AdrRegPresent
&& !DataRegPresent
&& !IncMode
)
{
if ((AdrReg
== 3) && (HasDisp
))
DispAcc
-= EProgCounter
();
if (RangeCheck
(DispAcc
, SInt9
))
{
pVals
->Arg
= 0xc4 | (AdrReg
<< 4) | ((DispAcc
>> 8) & 1);
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
else
{
pVals
->Arg
= 0xc6 | (AdrReg
<< 4);
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 16) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
}
/* [disp] */
else if ((IndirMode
== eIndirModeSquare
) && !AdrRegPresent
&& !DataRegPresent
&& !IncMode
)
{
pVals
->Arg
= 0xfe;
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 16) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = (DispAcc
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = DispAcc
& 0xff;
pVals
->Mode
= AdrModeMemReg
;
}
else
goto error
;
goto done
;
}
/* absolute: */
Address
= EvalStrIntExpression
(&ArgStr
[ArgIndex
], UInt24
, &OK
);
if (OK
)
{
if (RangeCheck
(Address
, UInt14
))
{
pVals
->Arg
= 0x00 | ((Address
>> 8) & 0x3f);
pVals
->Vals
[pVals
->ValCnt
++] = Address
& 0xff;
}
else if (RangeCheck
(Address
, UInt18
))
{
pVals
->Arg
= 0xf8 | ((Address
>> 16) & 1) | ((Address
>> 15) & 4);
pVals
->Vals
[pVals
->ValCnt
++] = (Address
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = Address
& 0xff;
}
else
{
pVals
->Arg
= 0xfa;
pVals
->Vals
[pVals
->ValCnt
++] = (Address
>> 16) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = (Address
>> 8) & 0xff;
pVals
->Vals
[pVals
->ValCnt
++] = Address
& 0xff;
}
pVals
->Mode
= AdrModeMemReg
;
}
done
:
if ((pVals
->Mode
!= AdrModeNone
) && !((ModeMask
>> pVals
->Mode
) & 1))
{
ResetAdrVals
(pVals
);
goto error
;
}
return (pVals
->Mode
!= AdrModeNone
);
error
:
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[ArgIndex
]);
return False
;
}
static Boolean IsImmediate
(const tAdrVals
*pVals
, ShortInt OpSize
, Byte
*pImmVal
)
{
switch (pVals
->Mode
)
{
case AdrModeImm
:
*pImmVal
= pVals
->Vals
[pVals
->ValCnt
- 1];
return True
;
case AdrModeMemReg
:
if ((pVals
->Arg
& 0xf0) == 0x70)
{
*pImmVal
= pVals
->Arg
& 15;
if (OpSize
== OpSizeShiftCount
)
*pImmVal
= (*pImmVal
<< 1) | pVals
->ShiftLSB
;
else if (!*pImmVal
&& (OpSize
< OpSizeBitPos8
))
*pImmVal
= 0xff;
return True
;
}
/* else fall-through */
default:
*pImmVal
= 0;
return False
;
}
}
static void ChangeImmediate
(tAdrVals
*pVals
, ShortInt OpSize
, Byte ImmVal
)
{
unsigned z
;
pVals
->Mode
= AdrModeImm
;
pVals
->Arg
= 0;
pVals
->ValCnt
= OpSizeByteLen
(OpSize
);
pVals
->Vals
[pVals
->ValCnt
- 1] = ImmVal
;
for (z
= 1; z
< pVals
->ValCnt
; z
++)
pVals
->Vals
[z
] = (ImmVal
& 0x80) ? 0xff : 0x00;
}
static Boolean IsReg
(const tAdrVals
*pVals
, Byte
*pReg
)
{
switch (pVals
->Mode
)
{
case AdrModeReg
:
*pReg
= pVals
->Arg
;
return True
;
case AdrModeMemReg
:
if ((pVals
->Arg
& 0xf8) == 0xb8)
{
*pReg
= pVals
->Arg
& 7;
return True
;
}
/* else fall-through */
default:
*pReg
= 0;
return False
;
}
}
static Boolean SetOpSize
(tSymbolSize NewOpSize
)
{
if ((OpSize
== NewOpSize
) || (OpSize
== eSymbolSizeUnknown
))
{
OpSize
= NewOpSize
;
return True
;
}
else
{
char Str
[30];
as_snprintf
(Str
, sizeof(Str
), "%d -> %d", (int)OpSize
, (int)NewOpSize
);
WrXError
(ErrNum_ConfOpSizes
, Str
);
return False
;
}
}
static Boolean SizeCode2
(ShortInt ThisOpSize
, Byte
*pSizeCode
)
{
switch (ThisOpSize
)
{
case eSymbolSize8Bit
: *pSizeCode
= 0; break;
case eSymbolSize16Bit
: *pSizeCode
= 1; break;
case eSymbolSize24Bit
: *pSizeCode
= 2; break;
case eSymbolSize32Bit
: *pSizeCode
= 3; break;
default: return False
;
}
return True
;
}
static Boolean DecodeImmBitField
(tStrComp
*pArg
, Word
*pResult
)
{
char *pSplit
= strchr(pArg
->str.
p_str, ':'), Save
;
tStrComp Left
, Right
;
Boolean OK
;
tSymbolFlags Flags
;
if (!pSplit
)
{
WrError
(ErrNum_InvBitPos
);
return False
;
}
Save
= StrCompSplitRef
(&Left
, &Right
, pArg
, pSplit
);
*pResult
= EvalStrIntExpressionWithFlags
(&Left
, UInt6
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
))
*pResult
&= 31;
*pSplit
= Save
;
if (!OK
|| !ChkRange
(*pResult
, 1, 32))
return False
;
*pResult
= (*pResult
<< 5) | (EvalStrIntExpression
(&Right
, UInt5
, &OK
) & 31);
return OK
;
}
/*--------------------------------------------------------------------------*/
/* Bit Symbol Handling */
/*
* Compact representation of bits and bit fields in symbol table:
* bits 0..2/3/4: (start) bit position
* bits 3/4/5...14/15/16: register address in I/O space (first 4K)
* bits 20/21: register size (0/1/2/3 for 8/16/32/24 bits)
* bits 24..28: length of bit field minus one (0 for individual bit)
*/
/*!------------------------------------------------------------------------
* \fn AssembleBitfieldSymbol(Byte BitPos, Byte Width, ShortInt OpSize, Word Address)
* \brief build the compact internal representation of a bit field symbol
* \param BitPos bit position in word
* \param Width width of bit field
* \param OpSize operand size (0..2)
* \param Address register address
* \return compact representation
* ------------------------------------------------------------------------ */
static LongWord AssembleBitfieldSymbol
(Byte BitPos
, Byte Width
, ShortInt OpSize
, Word Address
)
{
LongWord CodeOpSize
= (OpSize
== eSymbolSize24Bit
) ? 3 : OpSize
;
int AddrShift
= (OpSize
== eSymbolSize24Bit
) ? 5 : (3 + OpSize
);
return BitPos
| (((LongWord
)Address
& 0xfff) << AddrShift
)
| (CodeOpSize
<< 20)
| (((LongWord
)(Width
- 1) & 31) << 24);
}
/*!------------------------------------------------------------------------
* \fn AssembleBitSymbol(Byte BitPos, ShortInt OpSize, Word Address)
* \brief build the compact internal representation of a bit symbol
* \param BitPos bit position in word
* \param OpSize operand size (0..2)
* \param Address register address
* \return compact representation
* ------------------------------------------------------------------------ */
static LongWord AssembleBitSymbol
(Byte BitPos
, ShortInt OpSize
, Word Address
)
{
return AssembleBitfieldSymbol
(BitPos
, 1, OpSize
, Address
);
}
/*!------------------------------------------------------------------------
* \fn EvalBitPosition(const char *pBitArg, Boolean *pOK, ShortInt OpSize)
* \brief evaluate constant bit position, with bit range depending on operand size
* \param pBitArg bit position argument
* \param pOK returns True if OK
* \param OpSize operand size (0,1,2 -> 8,16,32 bits)
* \return bit position as number
* ------------------------------------------------------------------------ */
static Byte EvalBitPosition
(const tStrComp
*pBitArg
, Boolean
*pOK
, ShortInt OpSize
)
{
switch (OpSize
)
{
case eSymbolSize8Bit
:
return EvalStrIntExpression
(pBitArg
, UInt3
, pOK
);
case eSymbolSize16Bit
:
return EvalStrIntExpression
(pBitArg
, UInt4
, pOK
);
case eSymbolSize24Bit
:
{
Byte Result
;
tSymbolFlags Flags
;
Result
= EvalStrIntExpressionWithFlags
(pBitArg
, UInt5
, pOK
, &Flags
);
if (!*pOK
)
return Result
;
if (mFirstPassUnknown
(Flags
))
Result
&= 15;
*pOK
= ChkRange
(Result
, 0, 23);
return Result
;
}
case eSymbolSize32Bit
:
return EvalStrIntExpression
(pBitArg
, UInt5
, pOK
);
default:
WrError
(ErrNum_InvOpSize
);
*pOK
= False
;
return 0;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, ShortInt OpSize)
* \brief encode a bit symbol, address & bit position separated
* \param pResult resulting encoded bit
* \param pRegArg register argument
* \param pBitArg bit argument
* \param OpSize register size (0/1/2 = 8/16/32 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg2
(LongWord
*pResult
, const tStrComp
*pRegArg
, const tStrComp
*pBitArg
, ShortInt OpSize
)
{
Boolean OK
;
tSymbolFlags Flags
;
LongWord Addr
;
Byte BitPos
;
BitPos
= EvalBitPosition
(pBitArg
, &OK
, OpSize
);
if (!OK
)
return False
;
/* all I/O registers reside in the first 4K of the address space */
Addr
= EvalStrIntExpressionWithFlags
(pRegArg
, UInt12
, &OK
, &Flags
);
if (!OK
)
return False
;
*pResult
= AssembleBitSymbol
(BitPos
, OpSize
, Addr
);
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeBitfieldArg2(LongWord *pResult, const tStrComp *pRegArg, tStrComp *pBitArg, ShortInt OpSize)
* \brief encode a bit field symbol, address & bit position separated
* \param pResult resulting encoded bit
* \param pRegArg register argument
* \param pBitArg bit argument
* \param OpSize register size (0/1/2 = 8/16/32 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitfieldArg2
(LongWord
*pResult
, const tStrComp
*pRegArg
, tStrComp
*pBitArg
, ShortInt OpSize
)
{
Boolean OK
;
LongWord Addr
;
Word BitSpec
;
if (!DecodeImmBitField
(pBitArg
, &BitSpec
))
return False
;
/* all I/O registers reside in the first 4K of the address space */
Addr
= EvalStrIntExpression
(pRegArg
, UInt12
, &OK
);
if (!OK
)
return False
;
*pResult
= AssembleBitfieldSymbol
(BitSpec
& 31, (BitSpec
>> 5) & 31, OpSize
, Addr
);
return True
;
}
/*!------------------------------------------------------------------------
* \fn DecodeBitArg(LongWord *pResult, int Start, int Stop, ShortInt OpSize)
* \brief encode a bit symbol from instruction argument(s)
* \param pResult resulting encoded bit
* \param Start first argument
* \param Stop last argument
* \param OpSize register size (0/1/2 = 8/16/32 bit)
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitArg
(LongWord
*pResult
, int Start
, int Stop
, ShortInt OpSize
)
{
*pResult
= 0;
/* Just one argument -> parse as bit argument */
if (Start
== Stop
)
{
tEvalResult EvalResult
;
*pResult
= EvalStrIntExpressionWithResult
(&ArgStr
[Start
], UInt32
, &EvalResult
);
if (EvalResult.
OK)
ChkSpace
(SegBData
, EvalResult.
AddrSpaceMask);
return EvalResult.
OK;
}
/* register & bit position are given as separate arguments */
else if (Stop
== Start
+ 1)
return DecodeBitArg2
(pResult
, &ArgStr
[Start
], &ArgStr
[Stop
], OpSize
);
/* other # of arguments not allowed */
else
{
WrError
(ErrNum_WrongArgCnt
);
return False
;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeBitfieldArg(LongWord *pResult, int Start, int Stop, ShortInt OpSize)
* \brief encode a bit symbol from instruction argument(s)
* \param pResult resulting encoded bit
* \param Start first argument
* \param Stop last argument
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean DecodeBitfieldArg
(LongWord
*pResult
, int Start
, int Stop
, ShortInt OpSize
)
{
*pResult
= 0;
/* Just one argument -> parse as bit field argument */
if (Start
== Stop
)
{
tEvalResult EvalResult
;
*pResult
= EvalStrIntExpressionWithResult
(&ArgStr
[Start
], UInt32
, &EvalResult
);
if (EvalResult.
OK)
ChkSpace
(SegBData
, EvalResult.
AddrSpaceMask);
return EvalResult.
OK;
}
/* register & bit position are given as separate arguments */
else if (Stop
== Start
+ 1)
return DecodeBitfieldArg2
(pResult
, &ArgStr
[Start
], &ArgStr
[Stop
], OpSize
);
/* other # of arguments not allowed */
else
{
WrError
(ErrNum_WrongArgCnt
);
return False
;
}
}
/*!------------------------------------------------------------------------
* \fn DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos, Byte *pWidth, tSymbolSize *pOpSize)
* \brief transform compact represenation of bit (field) symbol into components
* \param BitSymbol compact storage
* \param pAddress (I/O) register address
* \param pBitPos (start) bit position
* \param pWidth pWidth width of bit field, always one for individual bit
* \param pOpSize returns register size (0/1/2 for 8/16/32 bits)
* \return constant True
* ------------------------------------------------------------------------ */
static Boolean DissectBitSymbol
(LongWord BitSymbol
, Word
*pAddress
, Byte
*pBitPos
, Byte
*pWidth
, tSymbolSize
*pOpSize
)
{
*pOpSize
= (tSymbolSize
)((BitSymbol
>> 20) & 3);
switch (*pOpSize
)
{
case eSymbolSize8Bit
:
*pAddress
= (BitSymbol
>> 3) & 0xfff;
*pBitPos
= BitSymbol
& 7;
break;
case eSymbolSize16Bit
:
*pAddress
= (BitSymbol
>> 4) & 0xfff;
*pBitPos
= BitSymbol
& 15;
break;
case 3:
*pOpSize
= eSymbolSize24Bit
;
/* fall-through */
case eSymbolSize32Bit
:
*pAddress
= (BitSymbol
>> 5) & 0xfff;
*pBitPos
= BitSymbol
& 31;
default:
break;
}
*pWidth
= 1 + ((BitSymbol
>> 24) & 31);
return True
;
}
/*!------------------------------------------------------------------------
* \fn DissectBit_S12Z(char *pDest, size_t DestSize, LargeWord Inp)
* \brief dissect compact storage of bit (field) into readable form for listing
* \param pDest destination for ASCII representation
* \param DestSize destination buffer size
* \param Inp compact storage
* ------------------------------------------------------------------------ */
static void DissectBit_S12Z
(char *pDest
, size_t DestSize
, LargeWord Inp
)
{
Byte BitPos
, BitWidth
;
Word Address
;
tSymbolSize OpSize
;
char Attribute
;
DissectBitSymbol
(Inp
, &Address
, &BitPos
, &BitWidth
, &OpSize
);
Attribute
= (OpSize
== eSymbolSize24Bit
) ? 'p' : "bwl"[OpSize
];
if (BitWidth
> 1)
as_snprintf
(pDest
, DestSize
, "$%x(%c).%u:%u", (unsigned)Address
, Attribute
, (unsigned)BitWidth
, (unsigned)BitPos
);
else
as_snprintf
(pDest
, DestSize
, "$%x(%c).%u", (unsigned)Address
, Attribute
, (unsigned)BitPos
);
}
/*!------------------------------------------------------------------------
* \fn ExpandS12ZBit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
* \brief expands bit definition when a structure is instantiated
* \param pVarName desired symbol name
* \param pStructElem element definition
* \param Base base address of instantiated structure
* ------------------------------------------------------------------------ */
static void ExpandS12ZBit
(const tStrComp
*pVarName
, const struct sStructElem
*pStructElem
, LargeWord Base
)
{
LongWord Address
= Base
+ pStructElem
->Offset
;
if (pInnermostNamedStruct
)
{
PStructElem pElem
= CloneStructElem
(pVarName
, pStructElem
);
if (!pElem
)
return;
pElem
->Offset
= Address
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElem
);
}
else
{
ShortInt OpSize
= (pStructElem
->OpSize
< 0) ? 0 : pStructElem
->OpSize
;
if (!ChkRange
(Address
, 0, 0xfff)
|| !ChkRange
(pStructElem
->BitPos
, 0, (8 << OpSize
) - 1))
return;
PushLocHandle
(-1);
EnterIntSymbol
(pVarName
, AssembleBitSymbol
(pStructElem
->BitPos
, OpSize
, Address
), SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
/*!------------------------------------------------------------------------
* \fn ExpandS12ZBitfield(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
* \brief expands bit field definition when a structure is instantiated
* \param pVarName desired symbol name
* \param pStructElem element definition
* \param Base base address of instantiated structure
* ------------------------------------------------------------------------ */
static void ExpandS12ZBitfield
(const tStrComp
*pVarName
, const struct sStructElem
*pStructElem
, LargeWord Base
)
{
LongWord Address
= Base
+ pStructElem
->Offset
;
if (pInnermostNamedStruct
)
{
PStructElem pElem
= CloneStructElem
(pVarName
, pStructElem
);
if (!pElem
)
return;
pElem
->Offset
= Address
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElem
);
}
else
{
ShortInt OpSize
= (pStructElem
->OpSize
< 0) ? 0 : pStructElem
->OpSize
;
if (!ChkRange
(Address
, 0, 0xfff)
|| !ChkRange
(pStructElem
->BitPos
, 0, (8 << OpSize
) - 1)
|| !ChkRange
(pStructElem
->BitPos
+ pStructElem
->BitWidthM1
, 0, (8 << OpSize
) - 1))
return;
PushLocHandle
(-1);
EnterIntSymbol
(pVarName
, AssembleBitfieldSymbol
(pStructElem
->BitPos
, pStructElem
->BitWidthM1
+ 1, OpSize
, Address
), SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
/*--------------------------------------------------------------------------*/
/* Instruction Decoders */
static void DecodeFixed
(Word Code
)
{
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(0, 0))
PutCode
(Code
);
}
static Boolean DecodeBranchCore
(int ArgIndex
)
{
Boolean OK
;
tSymbolFlags Flags
;
LongInt ShortDist
, LongDist
;
/* manual says distance is relative to start of next instruction */
ShortDist
= EvalStrIntExpressionWithFlags
(&ArgStr
[ArgIndex
], UInt24
, &OK
, &Flags
) - (EProgCounter
() + CodeLen
+ 1);
if (!OK
)
return False
;
LongDist
= ShortDist
- 1;
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= ((ShortDist
<= 63) && (ShortDist
>= -64)) ? eSymbolSizeFloat32Bit
: eSymbolSize32Bit
;
switch (OpSize
)
{
case eSymbolSize32Bit
:
if (!mSymbolQuestionable
(Flags
) && !RangeCheck
(LongDist
, SInt15
))
{
WrError
(ErrNum_JmpDistTooBig
);
return False
;
}
else
{
BAsmCode
[CodeLen
++] = 0x80 | ((LongDist
>> 7) & 0x7f);
BAsmCode
[CodeLen
++] = LongDist
& 0xff;
}
break;
case eSymbolSizeFloat32Bit
:
if (!mSymbolQuestionable
(Flags
) && !RangeCheck
(ShortDist
, SInt7
))
{
WrError
(ErrNum_JmpDistTooBig
);
return False
;
}
else
{
BAsmCode
[CodeLen
++] = ShortDist
& 0x7f;
}
break;
default:
WrStrErrorPos
(ErrNum_InvOpSize
, &AttrPart
);
return False
;
}
return True
;
}
static void DecodeBranch
(Word Code
)
{
if (!ChkArgCnt
(1, 1))
return;
PutCode
(Code
);
if (!DecodeBranchCore
(1))
CodeLen
= 0;
}
static void DecodeReg
(Word Code
)
{
Byte Reg
;
if (ChkArgCnt
(1, 1)
&& DecodeRegArg
(1, &Reg
, 0xff)
&& SetOpSize
(RegSizes
[Reg
]))
PutCode
(Code
| Reg
);
}
static void DecodeTwoReg
(Word Code
)
{
Byte SrcReg
, DestReg
;
/* TODO: what is the operand order (source/dest)? The manual is
unclear about this. Assuming source is first argument, similar to TFR: */
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2)
&& DecodeRegArg
(2, &DestReg
, 0xff)
&& DecodeRegArg
(1, &SrcReg
, 0xff))
{
PutCode
(Code
);
BAsmCode
[CodeLen
++] = DestReg
| (SrcReg
<< 4);
}
}
static void DecodeRegMemImm
(Word Code
)
{
Byte Reg
;
tAdrVals AdrVals
;
if (ChkArgCnt
(2, 2)
&& DecodeRegArg
(1, &Reg
, 0xff)
&& SetOpSize
(RegSizes
[Reg
])
&& DecodeAdr
(2, MModeImm
| MModeMemReg
, &AdrVals
))
{
if (AdrVals.
Mode == AdrModeImm
)
PutCode
(Code
| Reg
);
else
{
PutCode
((Code
+ 0x10) | Reg
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
}
AppendAdrVals
(&AdrVals
);
}
}
static void DecodeSUB
(Word Code
)
{
Byte Reg
;
tAdrVals AdrVals
;
if (ArgCnt
== 3)
{
if (DecodeRegArg
(1, &Reg
, 1 << 6)
&& DecodeAdrRegArg
(2, &Reg
, 3)
&& DecodeAdrRegArg
(3, &Reg
, 1 << (1 - Reg
)))
{
BAsmCode
[CodeLen
++] = 0xfe - Reg
;
}
}
else if (ChkArgCnt
(2, 3)
&& DecodeRegArg
(1, &Reg
, 0xff)
&& SetOpSize
(RegSizes
[Reg
])
&& DecodeAdr
(2, MModeImm
| MModeMemReg
, &AdrVals
))
{
if (AdrVals.
Mode == AdrModeImm
)
PutCode
(Code
| Reg
);
else
{
PutCode
((Code
+ 0x10) | Reg
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
}
AppendAdrVals
(&AdrVals
);
}
}
static void DecodeCMP
(Word Code
)
{
if (ChkArgCnt
(2, 2))
{
Byte Reg
;
tAdrVals AdrVals
;
DecodeAdr
(1, MModeReg
| MModeAReg
, &AdrVals
);
Reg
= AdrVals.
Arg;
switch (AdrVals.
Mode)
{
case AdrModeReg
:
if (SetOpSize
(RegSizes
[Reg
])
&& DecodeAdr
(2, MModeImm
| MModeMemReg
, &AdrVals
))
{
if (AdrVals.
Mode == AdrModeImm
)
PutCode
(Code
| Reg
);
else
{
PutCode
((Code
+ 0x10) | Reg
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
}
AppendAdrVals
(&AdrVals
);
}
break;
case AdrModeAReg
:
if (Reg
== 3) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else if (SetOpSize
(eSymbolSize24Bit
))
{
DecodeAdr
(2, MModeImm
| MModeMemReg
| MModeAReg
, &AdrVals
);
switch (AdrVals.
Mode)
{
case AdrModeImm
:
PutCode
((Reg
== 2) ? 0x1b04 : (0xe8 | Reg
));
AppendAdrVals
(&AdrVals
);
break;
case AdrModeMemReg
:
PutCode
((Reg
== 2) ? 0x1b02 : (0xf8 | Reg
));
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
break;
case AdrModeAReg
:
if (Reg
!= 0) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else if (AdrVals.
Arg != 1) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[2]);
else
PutCode
(0xfc);
break;
default:
break;
}
}
break;
default:
break;
}
}
}
static void DecodeImm8
(Word Code
)
{
tAdrVals AdrVals
;
if (ChkArgCnt
(1, 1) && SetOpSize
(eSymbolSize8Bit
) && DecodeAdr
(1, MModeImm
, &AdrVals
))
{
PutCode
(Code
);
AppendAdrVals
(&AdrVals
);
}
}
static void DecodeShift
(Word Code
)
{
if (ChkArgCnt
(2,3))
{
tAdrVals CntAdrVals
, OpAdrVals
;
tSymbolSize SaveOpSize
;
Boolean IsASL
= (Code
== 0xc0),
IsASR
= (Code
== 0x80);
Boolean ImmediateCnt
, DestIsReg
;
Byte ImmCnt
, SizeCode
, OpReg
, DestReg
;
/* force operand size to 5 bits for count */
SaveOpSize
= OpSize
;
OpSize
= OpSizeShiftCount
;
if (!DecodeAdr
(ArgCnt
, MModeImm
| MModeMemReg
| MModeReg
, &CntAdrVals
))
return;
ImmediateCnt
= IsImmediate
(&CntAdrVals
, OpSize
, &ImmCnt
);
OpSize
= SaveOpSize
;
/* source or source-and-dest operand */
if (!DecodeAdr
(ArgCnt
- 1, MModeMemReg
| MModeReg
, &OpAdrVals
))
return;
/* operand size not yet set - then set from source */
if (IsReg
(&OpAdrVals
, &OpReg
))
SetOpSize
(RegSizes
[OpReg
]);
if (OpSize
< 0)
{
WrError
(ErrNum_UndefOpSizes
);
return;
}
else if (!SizeCode2
(OpSize
, &SizeCode
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
/* for three args, destination is always a register */
if (ArgCnt
== 3)
{
/* dest reg does not set operand size - opsize is from src
operand which may be memory */
if (!DecodeRegArg
(1, &DestReg
, 0xff))
return;
DestIsReg
= True
;
}
else
DestIsReg
= IsReg
(&OpAdrVals
, &DestReg
);
/* REG-REG-OPR1/2/3 only allowed with ASL: convert to (REG-)OPR1/2/3-OPR1/2/3 for other instructions,
unless count is immediate: */
if (!IsASL
&& DestIsReg
&& (OpAdrVals.
Mode == AdrModeReg
) && !ImmediateCnt
&& (CntAdrVals.
Mode == AdrModeMemReg
))
{
OpAdrVals.
Mode = AdrModeMemReg
;
OpAdrVals.
Arg |= 0xb8;
}
/* REG-REG */
if (DestIsReg
&& (OpAdrVals.
Mode == AdrModeReg
) && (CntAdrVals.
Mode == AdrModeReg
))
{
BAsmCode
[CodeLen
++] = 0x10 | DestReg
;
BAsmCode
[CodeLen
++] = Code
| (IsASL
? 0x10 : 0x20) | OpAdrVals.
Arg;
BAsmCode
[CodeLen
++] = 0xb8 | CntAdrVals.
Arg;
}
/* REG-IMM with n=1..2 */
else if (DestIsReg
&& (OpAdrVals.
Mode == AdrModeReg
) && ImmediateCnt
&& (ImmCnt
>= 1) && (ImmCnt
<= 2))
{
BAsmCode
[CodeLen
++] = (IsASR
? 0x00 : 0x10) | DestReg
;
BAsmCode
[CodeLen
++] = Code
| (IsASR
? 0x10 : 0x00) | ((ImmCnt
- 1) << 3) | OpAdrVals.
Arg;
}
/* REG-IMM with arbitrary n */
else if (DestIsReg
&& (OpAdrVals.
Mode == AdrModeReg
) && ImmediateCnt
)
{
BAsmCode
[CodeLen
++] = 0x10 | DestReg
;
BAsmCode
[CodeLen
++] = Code
| (IsASL
? 0x00 : 0x10) | ((ImmCnt
& 1) << 3) | OpAdrVals.
Arg;
BAsmCode
[CodeLen
++] = 0x70 | ((ImmCnt
>> 1) & 7);
}
/* REG-OPR1/2/3 - ASL only */
else if (IsASL
&& DestIsReg
&& (OpAdrVals.
Mode == AdrModeReg
) && (CntAdrVals.
Mode == AdrModeMemReg
))
{
BAsmCode
[CodeLen
++] = 0x10 | DestReg
;
BAsmCode
[CodeLen
++] = Code
| (CntAdrVals.
ShiftLSB << 3) | OpAdrVals.
Arg;
BAsmCode
[CodeLen
++] = CntAdrVals.
Arg;
AppendAdrVals
(&CntAdrVals
);
}
/* (REG-)OPR1/2/3-IMM with n=1..2 */
else if (DestIsReg
&& ImmediateCnt
&& (ImmCnt
>= 1) && (ImmCnt
<= 2))
{
BAsmCode
[CodeLen
++] = 0x10 | DestReg
;
BAsmCode
[CodeLen
++] = Code
| 0x20 | ((ImmCnt
- 1) << 3) | SizeCode
;
BAsmCode
[CodeLen
++] = OpAdrVals.
Arg;
AppendAdrVals
(&OpAdrVals
);
}
/* (REG-)OPR1/2/3-IMM with arbitrary n */
else if (DestIsReg
&& ImmediateCnt
&& (OpAdrVals.
Mode == AdrModeMemReg
))
{
BAsmCode
[CodeLen
++] = 0x10 | DestReg
;
BAsmCode
[CodeLen
++] = Code
| 0x30 | ((ImmCnt
& 1) << 3) | SizeCode
;
BAsmCode
[CodeLen
++] = OpAdrVals.
Arg;
AppendAdrVals
(&OpAdrVals
);
BAsmCode
[CodeLen
++] = 0x70 | ((ImmCnt
>> 1) & 0x0f);
}
/* (REG-)OPR1/2/3-OPR1/2/3 */
else if (DestIsReg
&& (OpAdrVals.
Mode == AdrModeMemReg
) && (CntAdrVals.
Mode == AdrModeMemReg
))
{
BAsmCode
[CodeLen
++] = 0x10 | DestReg
;
BAsmCode
[CodeLen
++] = Code
| 0x30 | (CntAdrVals.
ShiftLSB << 3) | SizeCode
;
BAsmCode
[CodeLen
++] = OpAdrVals.
Arg;
AppendAdrVals
(&OpAdrVals
);
BAsmCode
[CodeLen
++] = CntAdrVals.
Arg;
AppendAdrVals
(&CntAdrVals
);
}
/* (src-)OPR/1/2/3-IMM (n=1..2) */
else if ((OpAdrVals.
Mode == AdrModeMemReg
) && ImmediateCnt
&& (ImmCnt
>= 1) && (ImmCnt
<= 2))
{
BAsmCode
[CodeLen
++] = 0x10;
BAsmCode
[CodeLen
++] = Code
| 0x34 | ((ImmCnt
- 1) << 3) | SizeCode
;
BAsmCode
[CodeLen
++] = OpAdrVals.
Arg;
AppendAdrVals
(&OpAdrVals
);
}
else
WrError
(ErrNum_InvAddrMode
);
}
}
static void DecodeBit
(Word Code
)
{
tSymbolSize SaveOpSize
;
tAdrVals PosAdrVals
, OpAdrVals
;
Byte ImmPos
, ImmWidth
, SizeCode
, OpReg
;
Boolean ImmediatePos
;
if (!ChkArgCnt
(1, 2))
return;
/* bit operand: */
if (1 == ArgCnt
)
{
LongWord BitArg
;
tSymbolSize ThisOpSize
;
Word Address
;
if (DecodeBitArg
(&BitArg
, 1, 1, OpSize
)
&& DissectBitSymbol
(BitArg
, &Address
, &ImmPos
, &ImmWidth
, &ThisOpSize
)
&& SetOpSize
(ThisOpSize
))
{
/* TODO: warn if ImmWidth != 1 */
if (!SizeCode2
(OpSize
, &SizeCode
) || (SizeCode
== 2))
{
WrError
(ErrNum_InvOpSize
);
return;
}
ImmediatePos
= True
;
OpAdrVals.
Mode = AdrModeMemReg
;
OpAdrVals.
Arg = Hi
(Address
);
OpAdrVals.
Vals[0] = Lo
(Address
);
OpAdrVals.
ValCnt = 1;
}
else
return;
OpReg
= 0;
}
/* other operand */
else
{
if (!DecodeAdr
(1, MModeMemReg
| MModeReg
, &OpAdrVals
))
return;
/* operand size not yet set - then set from source */
if (IsReg
(&OpAdrVals
, &OpReg
))
SetOpSize
(RegSizes
[OpReg
]);
if (OpSize
< 0)
{
WrError
(ErrNum_UndefOpSizes
);
return;
}
else if (!SizeCode2
(OpSize
, &SizeCode
) || (SizeCode
== 2))
{
WrError
(ErrNum_InvOpSize
);
return;
}
/* force operand size to 3/4/5 bits for bit position */
SaveOpSize
= OpSize
;
OpSize
= OpSizeBitPos8
+ OpSize
;
if (!DecodeAdr
(2, MModeImm
| MModeReg
, &PosAdrVals
))
return;
ImmediatePos
= IsImmediate
(&PosAdrVals
, OpSize
, &ImmPos
);
OpSize
= SaveOpSize
;
}
switch (OpAdrVals.
Mode)
{
case AdrModeReg
:
BAsmCode
[CodeLen
++] = Code
;
if (ImmediatePos
)
BAsmCode
[CodeLen
++] = (ImmPos
<< 3) | OpReg
;
else
{
BAsmCode
[CodeLen
++] = 0x81 | (PosAdrVals.
Arg << 4);
BAsmCode
[CodeLen
++] = 0xb8 | OpReg
;
}
break;
case AdrModeMemReg
:
BAsmCode
[CodeLen
++] = Code
;
if (ImmediatePos
)
{
BAsmCode
[CodeLen
] = 0x80 | ((ImmPos
& 7) << 4);
if (OpSize
>= eSymbolSize16Bit
)
BAsmCode
[CodeLen
] |= (1 << SizeCode
) | ((ImmPos
>> 3) & SizeCode
);
CodeLen
++;
}
else
BAsmCode
[CodeLen
++] = 0x81 | (PosAdrVals.
Arg << 4) | (SizeCode
<< 2);
BAsmCode
[CodeLen
++] = OpAdrVals.
Arg;
AppendAdrVals
(&OpAdrVals
);
break;
default:
break;
}
}
static void DecodeBitField
(Word Code
)
{
if (!ChkArgCnt
(2, 3))
return;
/* if two arguments, bit field is symbolic and is
- the destination (first arg) for BFINS
- the source (second arg) for BFEXT */
if (2 == ArgCnt
)
{
LongWord BitfieldArg
;
Byte Reg
, ImmPos
, ImmWidth
, SizeCode
;
Word FieldSpec
, Address
;
tSymbolSize ThisOpSize
;
int RegArg
= (Code
== 0x80) ? 2 : 1;
if (DecodeRegArg
(RegArg
, &Reg
, 0xff)
&& DecodeBitfieldArg
(&BitfieldArg
, 3 - RegArg
, 3 - RegArg
, OpSize
)
&& DissectBitSymbol
(BitfieldArg
, &Address
, &ImmPos
, &ImmWidth
, &ThisOpSize
)
&& SetOpSize
(ThisOpSize
)
&& SizeCode2
(OpSize
, &SizeCode
))
{
FieldSpec
= ImmPos
| ((ImmWidth
< 32) ? ((Word
)ImmWidth
<< 5) : 0);
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = 0x08 | Reg
;
BAsmCode
[CodeLen
++] = (Code
? 0xf0: 0x60) | (SizeCode
<< 2) | Hi
(FieldSpec
);
BAsmCode
[CodeLen
++] = Lo
(FieldSpec
);
BAsmCode
[CodeLen
++] = Hi
(Address
);
BAsmCode
[CodeLen
++] = Lo
(Address
);
}
}
else
{
Byte ParamReg
, SizeCode
;
Word ParamImm
;
tAdrVals SrcAdrVals
, DestAdrVals
;
if (*ArgStr
[3].
str.
p_str == '#')
{
tStrComp Field
;
StrCompRefRight
(&Field
, &ArgStr
[3], 1);
if (!DecodeImmBitField
(&Field
, &ParamImm
))
return;
ParamReg
= 16; /* immediate flag */
}
/* only D2...D5 allowed as parameter */
else if (!DecodeRegStr
(ArgStr
[3].
str.
p_str, &ParamReg
) || (ParamReg
>= 4))
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[3]);
return;
}
DecodeAdr
(2, MModeReg
| MModeImm
| MModeMemReg
, &SrcAdrVals
);
switch (SrcAdrVals.
Mode)
{
case AdrModeReg
:
DecodeAdr
(1, MModeReg
| MModeMemReg
, &DestAdrVals
);
switch (DestAdrVals.
Mode)
{
case AdrModeReg
:
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = 0x08 | DestAdrVals.
Arg;
if (16 == ParamReg
)
{
BAsmCode
[CodeLen
++] = Code
| 0x20 | (SrcAdrVals.
Arg << 2) | Hi
(ParamImm
);
BAsmCode
[CodeLen
++] = Lo
(ParamImm
);
}
else
BAsmCode
[CodeLen
++] = Code
| (SrcAdrVals.
Arg << 2) | ParamReg
;
break;
case AdrModeMemReg
:
if (OpSize
== eSymbolSizeUnknown
) WrError
(ErrNum_UndefOpSizes
);
else if (!SizeCode2
(OpSize
, &SizeCode
)) WrError
(ErrNum_InvOpSize
);
else
{
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = 0x08 | SrcAdrVals.
Arg;
if (16 == ParamReg
)
{
BAsmCode
[CodeLen
++] = Code
| 0x70 | (SizeCode
<< 2) | Hi
(ParamImm
);
BAsmCode
[CodeLen
++] = Lo
(ParamImm
);
}
else
BAsmCode
[CodeLen
++] = Code
| 0x50 | (SizeCode
<< 2) | ParamReg
;
BAsmCode
[CodeLen
++] = DestAdrVals.
Arg;
AppendAdrVals
(&DestAdrVals
);
}
break;
default:
break;
}
break;
case AdrModeMemReg
:
DecodeAdr
(1, MModeReg
, &DestAdrVals
);
switch (DestAdrVals.
Mode)
{
case AdrModeReg
:
if (OpSize
== eSymbolSizeUnknown
) WrError
(ErrNum_UndefOpSizes
);
else if (!SizeCode2
(OpSize
, &SizeCode
)) WrError
(ErrNum_InvOpSize
);
else
{
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = 0x08 | DestAdrVals.
Arg;
if (16 == ParamReg
)
{
BAsmCode
[CodeLen
++] = Code
| 0x60 | (SizeCode
<< 2) | Hi
(ParamImm
);
BAsmCode
[CodeLen
++] = Lo
(ParamImm
);
}
else
BAsmCode
[CodeLen
++] = Code
| 0x40 | (SizeCode
<< 2) | ParamReg
;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
AppendAdrVals
(&SrcAdrVals
);
}
break;
default:
break;
}
break;
case AdrModeImm
: /* immediate only allowed for short immediate in MemReg op */
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
break;
default:
break;
}
}
}
static void DecodeBitRel
(Word Code
)
{
if (!ChkArgCnt
(3, 3))
return;
ArgCnt
--;
DecodeBit
(Code
);
if (!CodeLen
)
return;
/* operand size attribute is consumed by bit operand */
OpSize
= eSymbolSizeUnknown
;
if (!DecodeBranchCore
(3))
CodeLen
= 0;
}
static void DecodeCLR
(Word Code
)
{
tAdrVals AdrVals
;
UNUSED
(Code
);
if (ChkArgCnt
(1, 1) && DecodeAdr
(1, MModeReg
| MModeAReg
| MModeMemReg
, &AdrVals
))
{
switch (AdrVals.
Mode)
{
case AdrModeReg
:
if (SetOpSize
(RegSizes
[AdrVals.
Arg]))
PutCode
(0x0038 | AdrVals.
Arg);
break;
case AdrModeAReg
:
if (!SetOpSize
(eSymbolSize24Bit
));
else if (AdrVals.
Arg > 1) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
PutCode
(0x009a | AdrVals.
Arg);
break;
case AdrModeMemReg
:
{
Byte SizeCode
;
if (OpSize
== eSymbolSizeUnknown
) WrError
(ErrNum_UndefOpSizes
);
else if (!SizeCode2
(OpSize
, &SizeCode
)) WrError
(ErrNum_InvOpSize
);
else
{
BAsmCode
[CodeLen
++] = 0xbc | SizeCode
;
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
}
break;
}
default:
break;
}
}
}
static void DecodeCOM_NEG
(Word Code
)
{
tAdrVals AdrVals
;
Byte OpReg
, SizeCode
;
if (!ChkArgCnt
(1, 1))
return;
DecodeAdr
(1, MModeMemReg
, &AdrVals
);
/* operand size not yet set - then set from (register) op */
if (IsReg
(&AdrVals
, &OpReg
))
{
if (!SetOpSize
(RegSizes
[OpReg
]))
return;
}
if (OpSize
== eSymbolSizeUnknown
)
{
WrError
(ErrNum_UndefOpSizes
);
return;
}
if (!SizeCode2
(OpSize
, &SizeCode
) || (OpSize
== eSymbolSize24Bit
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
PutCode
(Code
| SizeCode
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
}
static void DecodeDBcc
(Word Code
)
{
tAdrVals AdrVals
;
Byte OpReg
, SizeCode
;
if (!ChkArgCnt
(2, 2))
return;
DecodeAdr
(1, MModeReg
| MModeAReg
| MModeMemReg
, &AdrVals
);
if (IsReg
(&AdrVals
, &OpReg
))
{
if (!SetOpSize
(RegSizes
[OpReg
]))
return;
}
else if (AdrVals.
Mode == AdrModeAReg
)
{
if (!SetOpSize
(eSymbolSize24Bit
))
return;
}
if (OpSize
== eSymbolSizeUnknown
)
{
WrError
(ErrNum_UndefOpSizes
);
return;
}
if (!SizeCode2
(OpSize
, &SizeCode
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
switch (AdrVals.
Mode)
{
case AdrModeReg
:
PutCode
(Code
| AdrVals.
Arg);
break;
case AdrModeAReg
:
if (AdrVals.
Arg > 1) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else
PutCode
(Code
| 0x0008 | AdrVals.
Arg);
break;
case AdrModeMemReg
:
PutCode
(Code
| 0x000c | SizeCode
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
break;
default:
break;
}
if (CodeLen
> 0)
{
/* operand size attribute consumed by operand */
OpSize
= eSymbolSizeUnknown
;
if (!DecodeBranchCore
(2))
CodeLen
= 0;
}
}
static void DecodeINC_DEC
(Word Code
)
{
tAdrVals AdrVals
;
if (ChkArgCnt
(1, 1) && DecodeAdr
(1, MModeReg
| MModeMemReg
, &AdrVals
))
{
switch (AdrVals.
Mode)
{
case AdrModeReg
:
if (SetOpSize
(RegSizes
[AdrVals.
Arg]))
PutCode
(Code
+ AdrVals.
Arg);
break;
case AdrModeMemReg
:
{
Byte SizeCode
;
if (OpSize
== eSymbolSizeUnknown
) WrError
(ErrNum_UndefOpSizes
);
else if (!SizeCode2
(OpSize
, &SizeCode
) || (OpSize
== eSymbolSize24Bit
)) WrError
(ErrNum_UndefOpSizes
);
else
{
BAsmCode
[CodeLen
++] = (Code
+ 0x6c) | SizeCode
;
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
}
break;
}
default:
break;
}
}
}
static void DecodeDIV_MOD
(Word Code
)
{
tAdrVals DividentAdrVals
, DivisorAdrVals
;
Byte DividentSizeCode
, DivisorSizeCode
, DestReg
, DivisorReg
;
Word EffCode
, LoCode
;
EffCode
= Hi
(Code
) | ((Lo
(Code
) & 0x01) ? 0x1b00 : 0x0000);
LoCode
= Lo
(Code
) & 0x80;
/* destination is always a register */
if (!ChkArgCnt
(3, 3) || !DecodeRegArg
(1, &DestReg
, 0xff))
return;
DecodeAdr
(2, MModeImm
| MModeReg
| MModeMemReg
, &DividentAdrVals
);
switch (DividentAdrVals.
Mode)
{
case AdrModeReg
:
DecodeAdr
(3, MModeImm
| MModeReg
| MModeMemReg
, &DivisorAdrVals
);
switch (DivisorAdrVals.
Mode)
{
case AdrModeReg
:
PutCode
(EffCode
| DestReg
);
BAsmCode
[CodeLen
++] = LoCode
| (DividentAdrVals.
Arg << 3) | DivisorAdrVals.
Arg;
break;
case AdrModeImm
:
if (!SizeCode2
(OpSize
, &DivisorSizeCode
) || (OpSize
== eSymbolSize24Bit
)) WrError
(ErrNum_UndefOpSizes
);
else
{
PutCode
(EffCode
| DestReg
);
BAsmCode
[CodeLen
++] = LoCode
| 0x44 | (DividentAdrVals.
Arg << 3) | DivisorSizeCode
;
AppendAdrVals
(&DivisorAdrVals
);
}
break;
case AdrModeMemReg
:
if (!SizeCode2
(OpSize
, &DivisorSizeCode
) || (OpSize
== eSymbolSize24Bit
)) WrError
(ErrNum_UndefOpSizes
);
else
{
PutCode
(EffCode
| DestReg
);
BAsmCode
[CodeLen
++] = LoCode
| 0x40 | (DividentAdrVals.
Arg << 3) | DivisorSizeCode
;
BAsmCode
[CodeLen
++] = DivisorAdrVals.
Arg;
AppendAdrVals
(&DivisorAdrVals
);
}
break;
default:
break;
}
break;
case AdrModeMemReg
:
/* divident==register is filtered out before, so divident size cannot be set from register */
if (!SizeCode2
(OpSize
, &DividentSizeCode
) || (OpSize
== eSymbolSize24Bit
)) WrError
(ErrNum_UndefOpSizes
);
else
{
OpSize
= OpSize2
;
DecodeAdr
(3, MModeImm
| MModeMemReg
, &DivisorAdrVals
);
switch (DivisorAdrVals.
Mode)
{
case AdrModeMemReg
:
if ((OpSize
== eSymbolSizeUnknown
) && IsReg
(&DivisorAdrVals
, &DivisorReg
))
SetOpSize
(RegSizes
[DivisorReg
]);
if (!SizeCode2
(OpSize
, &DivisorSizeCode
) || (OpSize
== eSymbolSize24Bit
)) WrError
(ErrNum_UndefOpSizes
);
else
{
PutCode
(EffCode
| DestReg
);
BAsmCode
[CodeLen
++] = LoCode
| 0x42 | (DividentSizeCode
<< 4) | (DivisorSizeCode
<< 2);
BAsmCode
[CodeLen
++] = DividentAdrVals.
Arg;
AppendAdrVals
(&DividentAdrVals
);
BAsmCode
[CodeLen
++] = DivisorAdrVals.
Arg;
AppendAdrVals
(&DivisorAdrVals
);
}
break;
case AdrModeImm
: /* was only allowed for short imm in MemReg */
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[3]);
break;
default:
break;
}
}
break;
case AdrModeImm
: /* was only allowed for short imm in MemReg */
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
break;
default:
break;
}
}
static void DecodeEXG_TFR
(Word Code
)
{
Byte SrcReg
, DestReg
;
if (ChkArgCnt
(2, 2)
&& DecodeGenRegArg
(1, &SrcReg
)
&& DecodeGenRegArg
(2, &DestReg
))
{
if ((OpSizeByteLen
(RegSizes
[SrcReg
]) >= OpSizeByteLen
(RegSizes
[DestReg
])) && Hi
(Code
))
WrError
(ErrNum_SrcLEThanDest
);
BAsmCode
[CodeLen
++] = Lo
(Code
);
BAsmCode
[CodeLen
++] = (SrcReg
<< 4) | DestReg
;
}
}
static void DecodeJMP_JSR
(Word Code
)
{
tAdrVals AdrVals
;
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(1, 1) && DecodeAdr
(1, MModeMemReg
, &AdrVals
))
{
Byte Dummy
;
if (IsReg
(&AdrVals
, &Dummy
)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else
{
if (AdrVals.
Arg == 0xfa)
PutCode
(Code
| 0x10);
else
{
PutCode
(Code
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
}
AppendAdrVals
(&AdrVals
);
}
}
}
static void DecodeLD_ST
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
if (ChkArgCnt
(2, 2) && DecodeAdr
(1, MModeReg
| MModeAReg
, &DestAdrVals
))
{
switch (DestAdrVals.
Mode)
{
case AdrModeReg
:
if (!SetOpSize
(RegSizes
[DestAdrVals.
Arg]))
return;
DecodeAdr
(2, (Code
? 0 : MModeImm
) | MModeMemReg
, &SrcAdrVals
);
switch (SrcAdrVals.
Mode)
{
case AdrModeMemReg
:
{
Byte ImmVal
;
if ((OpSize
== eSymbolSize8Bit
) && IsImmediate
(&SrcAdrVals
, OpSize
, &ImmVal
)) /* same instr length for byte, but what people expect? */
{
ChangeImmediate
(&SrcAdrVals
, OpSize
, ImmVal
);
goto immediate
;
}
if (SrcAdrVals.
Arg == 0xfa)
BAsmCode
[CodeLen
++] = (0xb0 + Code
) | DestAdrVals.
Arg;
else
{
BAsmCode
[CodeLen
++] = (0xa0 + Code
) | DestAdrVals.
Arg;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
}
AppendAdrVals
(&SrcAdrVals
);
break;
}
case AdrModeImm
:
immediate
:
BAsmCode
[CodeLen
++] = 0x90 | DestAdrVals.
Arg;
AppendAdrVals
(&SrcAdrVals
);
break;
default:
break;
}
break;
case AdrModeAReg
:
if (DestAdrVals.
Arg > 2)
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
}
if (!SetOpSize
(eSymbolSize24Bit
))
return;
DecodeAdr
(2, (Code
? 0 : MModeImm
) | MModeMemReg
, &SrcAdrVals
);
switch (SrcAdrVals.
Mode)
{
case AdrModeMemReg
:
if ((DestAdrVals.
Arg < 2) && (SrcAdrVals.
Arg == 0xfa))
BAsmCode
[CodeLen
++] = (0xb8 + Code
) | DestAdrVals.
Arg;
else if (2 == DestAdrVals.
Arg)
{
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = 0x00 + !!Code
;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
}
else
{
BAsmCode
[CodeLen
++] = (0xa8 + Code
) | DestAdrVals.
Arg;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
}
AppendAdrVals
(&SrcAdrVals
);
break;
case AdrModeImm
:
/* SrcAdrVals.Cnt must be 3 */
if ((DestAdrVals.
Arg < 2) && (SrcAdrVals.
Vals[0] < 0x04))
{
BAsmCode
[CodeLen
++] = 0xca | DestAdrVals.
Arg | (SrcAdrVals.
Vals[0] << 4);
BAsmCode
[CodeLen
++] = SrcAdrVals.
Vals[1];
BAsmCode
[CodeLen
++] = SrcAdrVals.
Vals[2];
}
else
{
PutCode
((DestAdrVals.
Arg == 2) ? 0x1b03 : (0x98 | DestAdrVals.
Arg));
AppendAdrVals
(&SrcAdrVals
);
}
break;
default:
break;
}
break;
default:
break;
}
}
}
static void DecodeLEA
(Word Code
)
{
tAdrVals DestAdrVals
, SrcAdrVals
;
Byte Reg
;
UNUSED
(Code
);
if (*AttrPart.
str.
p_str) WrError
(ErrNum_UseLessAttr
);
else if (ChkArgCnt
(2, 2) && DecodeAdr
(1, MModeReg
| MModeAReg
, &DestAdrVals
))
{
switch (DestAdrVals.
Mode)
{
case AdrModeReg
:
if (DestAdrVals.
Arg < 6) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else if (DecodeAdr
(2, MModeMemReg
, &SrcAdrVals
))
{
if (IsReg
(&SrcAdrVals
, &Reg
)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
else
{
BAsmCode
[CodeLen
++] = 0x00 | DestAdrVals.
Arg;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
AppendAdrVals
(&SrcAdrVals
);
}
}
break;
case AdrModeAReg
:
if (DestAdrVals.
Arg > 2) WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
else if (DecodeAdr
(2, MModeMemReg
, &SrcAdrVals
))
{
if (IsReg
(&SrcAdrVals
, &Reg
)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
else
{
/* XYS,(i8,XYS) */
if (((SrcAdrVals.
Arg & 0xce) == 0xc0) /* ...,(XYS,i9) */
&& ((SrcAdrVals.
Arg & 0x01) == ((SrcAdrVals.
Vals[0] >> 7) & 1)) /* i9 is i8 */
&& (DestAdrVals.
Arg == ((SrcAdrVals.
Arg >> 4) & 3))) /* destreg==srcreg */
{
BAsmCode
[CodeLen
++] = 0x18 | DestAdrVals.
Arg;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Vals[0];
}
else
{
BAsmCode
[CodeLen
++] = 0x08 | DestAdrVals.
Arg;
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
AppendAdrVals
(&SrcAdrVals
);
}
}
}
break;
default:
break;
}
}
}
static void DecodeMIN_MAX
(Word Code
)
{
tAdrVals AdrVals
;
Byte Reg
;
if (ChkArgCnt
(2, 2)
&& DecodeRegArg
(1, &Reg
, 0xff)
&& SetOpSize
(RegSizes
[Reg
])
&& DecodeAdr
(2, MModeMemReg
| MModeImm
, &AdrVals
))
{
switch (AdrVals.
Mode)
{
case AdrModeMemReg
:
PutCode
(Code
| Reg
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
break;
case AdrModeImm
: /* was only allowed for short immediate in MemReg */
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[2]);
break;
default:
break;
}
}
}
static void DecodeMOV
(Word Code
)
{
tAdrVals SrcAdrVals
, DestAdrVals
;
Byte Reg
, SizeCode
;
UNUSED
(Code
);
if (ChkArgCnt
(2, 2)
&& DecodeAdr
(2, MModeMemReg
, &DestAdrVals
))
{
/* prefer attribute to destination... */
if (IsReg
(&DestAdrVals
, &Reg
) && (OpSize
== eSymbolSizeUnknown
))
SetOpSize
(RegSizes
[Reg
]);
if (!DecodeAdr
(1, MModeMemReg
| MModeImm
, &SrcAdrVals
))
return;
/* ...to source operand size */
if (IsReg
(&SrcAdrVals
, &Reg
) && (OpSize
== eSymbolSizeUnknown
))
SetOpSize
(RegSizes
[Reg
]);
if (!SizeCode2
(OpSize
, &SizeCode
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
switch (SrcAdrVals.
Mode)
{
case AdrModeImm
:
PutCode
(0x0c + SizeCode
);
AppendAdrVals
(&SrcAdrVals
);
BAsmCode
[CodeLen
++] = DestAdrVals.
Arg;
AppendAdrVals
(&DestAdrVals
);
break;
case AdrModeMemReg
:
PutCode
(0x1c | SizeCode
);
BAsmCode
[CodeLen
++] = SrcAdrVals.
Arg;
AppendAdrVals
(&SrcAdrVals
);
BAsmCode
[CodeLen
++] = DestAdrVals.
Arg;
AppendAdrVals
(&DestAdrVals
);
break;
default:
break;
}
}
}
static void DecodePSH_PUL
(Word Code
)
{
Word RegMask
= 0, ThisRegMask
;
int z
;
Byte Reg
;
static const Word RegMasks
[8] = { 0x0002, 0x0001, 0x2000, 0x1000, 0x0008, 0x004, 0x0800, 0x0400 };
if (!ChkArgCnt
(1, ArgCntMax
))
return;
for (z
= 1; z
<= ArgCnt
; z
++)
{
if (!as_strcasecmp
(ArgStr
[z
].
str.
p_str, "ALL"))
ThisRegMask
= 0x3f3f;
else if (!as_strcasecmp
(ArgStr
[z
].
str.
p_str, "ALL16b"))
ThisRegMask
= 0x3003;
else if (DecodeRegStr
(ArgStr
[z
].
str.
p_str, &Reg
))
ThisRegMask
= RegMasks
[Reg
];
else if (!as_strcasecmp
(ArgStr
[z
].
str.
p_str, "CCH"))
ThisRegMask
= 0x0020;
else if (!as_strcasecmp
(ArgStr
[z
].
str.
p_str, "CCL"))
ThisRegMask
= 0x0010;
else if (DecodeAdrRegStr
(ArgStr
[z
].
str.
p_str, &Reg
) && (Reg
< 2))
ThisRegMask
= 0x0200 >> Reg
;
else
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[z
]);
return;
}
if (ThisRegMask
& RegMask
)
{
WrStrErrorPos
(ErrNum_DoubleReg
, &ArgStr
[z
]);
return;
}
RegMask
|= ThisRegMask
;
}
if (RegMask
== 0x3f3f)
PutCode
(Code
| 0x00);
else if (RegMask
== 0x3003)
PutCode
(Code
| 0x40);
else if (Hi
(RegMask
) && !Lo
(RegMask
))
PutCode
(Code
| 0x40 | Hi
(RegMask
));
else if (Lo
(RegMask
) && !Hi
(RegMask
))
PutCode
(Code
| 0x00 | Lo
(RegMask
));
else
WrError
(ErrNum_InvRegList
);
}
static void DecodeROL_ROR
(Word Code
)
{
tAdrVals AdrVals
;
Byte Reg
, SizeCode
;
if (ChkArgCnt
(1, 1) && DecodeAdr
(1, MModeMemReg
, &AdrVals
))
{
if (IsReg
(&AdrVals
, &Reg
) && !SetOpSize
(RegSizes
[Reg
]))
return;
if (OpSize
== eSymbolSizeUnknown
)
{
WrError
(ErrNum_UndefOpSizes
);
return;
}
if (!SizeCode2
(OpSize
, &SizeCode
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
PutCode
(Code
| SizeCode
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
}
}
static void DecodeTBcc
(Word Code
)
{
tAdrVals AdrVals
;
if (!ChkArgCnt
(2, 2) || !DecodeAdr
(1, MModeReg
| MModeAReg
| MModeMemReg
| MModeImm
, &AdrVals
))
return;
switch (AdrVals.
Mode)
{
case AdrModeReg
:
if (!SetOpSize
(RegSizes
[AdrVals.
Arg]))
return;
PutCode
(Code
| AdrVals.
Arg);
break;
case AdrModeAReg
:
if (AdrVals.
Arg >= 2)
{
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[1]);
return;
}
if (!SetOpSize
(eSymbolSize24Bit
))
return;
PutCode
(Code
| 0x0008 | AdrVals.
Arg);
break;
case AdrModeMemReg
:
{
Byte SizeCode
;
if (OpSize
== eSymbolSizeUnknown
)
{
WrError
(ErrNum_UndefOpSizes
);
return;
}
if (!SizeCode2
(OpSize
, &SizeCode
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
PutCode
(Code
| 0x000c | SizeCode
);
BAsmCode
[CodeLen
++] = AdrVals.
Arg;
AppendAdrVals
(&AdrVals
);
break;
}
case AdrModeImm
: /* was only allowed for short immediate */
WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
return;
default:
return;
}
OpSize
= OpSize2
;
if (!DecodeBranchCore
(2))
CodeLen
= 0;
}
static void DecodeTRAP
(Word Code
)
{
tAdrVals AdrVals
;
UNUSED
(Code
);
if (ChkArgCnt
(1, 1) && SetOpSize
(eSymbolSize8Bit
) && DecodeAdr
(1, MModeImm
, &AdrVals
))
{
BAsmCode
[CodeLen
++] = 0x1b;
BAsmCode
[CodeLen
++] = AdrVals.
Vals[0];
switch ((AdrVals.
Vals[0] >> 4) & 0x0f)
{
case 12: case 13: case 14: case 15:
break;
case 10: case 11:
if ((AdrVals.
Vals[0] & 0x0f) >= 8)
break;
else
goto warn
;
case 9:
if ((AdrVals.
Vals[0] & 0x0f) >= 2)
break;
/* else fall-through */
default:
warn
:
WrError
(ErrNum_TrapValidInstruction
);
}
}
}
static void DecodeDEFBIT
(Word Code
)
{
LongWord BitSpec
;
UNUSED
(Code
);
/* if in structure definition, add special element to structure */
if (ActPC
== StructSeg
)
{
Boolean OK
;
Byte BitPos
;
PStructElem pElement
;
if (!ChkArgCnt
(2, 2))
return;
BitPos
= EvalBitPosition
(&ArgStr
[2], &OK
, (OpSize
== eSymbolSizeUnknown
) ? eSymbolSize32Bit
: OpSize
);
if (!OK
)
return;
pElement
= CreateStructElem
(&LabPart
);
if (!pElement
)
return;
pElement
->pRefElemName
= as_strdup
(ArgStr
[1].
str.
p_str);
pElement
->OpSize
= OpSize
;
pElement
->BitPos
= BitPos
;
pElement
->ExpandFnc
= ExpandS12ZBit
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElement
);
}
else
{
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= eSymbolSize8Bit
;
if (OpSize
> eSymbolSize32Bit
)
{
WrError
(ErrNum_InvOpSize
);
return;
}
if (DecodeBitArg
(&BitSpec
, 1, ArgCnt
, OpSize
))
{
*ListLine
= '=';
DissectBit_S12Z
(ListLine
+ 1, STRINGSIZE
- 3, BitSpec
);
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, BitSpec
, SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
}
static void DecodeDEFBITFIELD
(Word Code
)
{
UNUSED
(Code
);
/* if in structure definition, add special element to structure */
if (ActPC
== StructSeg
)
{
Word BitField
;
PStructElem pElement
;
if (!ChkArgCnt
(2, 2))
return;
if (!DecodeImmBitField
(&ArgStr
[2], &BitField
))
return;
pElement
= CreateStructElem
(&LabPart
);
if (!pElement
)
return;
pElement
->pRefElemName
= as_strdup
(ArgStr
[1].
str.
p_str);
pElement
->OpSize
= OpSize
;
pElement
->BitPos
= BitField
& 31;
pElement
->BitWidthM1
= (BitField
>> 5) - 1;
pElement
->ExpandFnc
= ExpandS12ZBitfield
;
AddStructElem
(pInnermostNamedStruct
->StructRec
, pElement
);
}
else
{
LongWord BitfieldSpec
;
/* opposed to bit operations, bit field operations also work
24 bit operands: */
if (OpSize
== eSymbolSizeUnknown
)
OpSize
= eSymbolSize8Bit
;
if ((OpSize
> eSymbolSize32Bit
) && (OpSize
!= eSymbolSize24Bit
))
{
WrError
(ErrNum_InvOpSize
);
return;
}
if (DecodeBitfieldArg
(&BitfieldSpec
, 1, ArgCnt
, OpSize
))
{
*ListLine
= '=';
DissectBit_S12Z
(ListLine
+ 1, STRINGSIZE
- 3, BitfieldSpec
);
PushLocHandle
(-1);
EnterIntSymbol
(&LabPart
, BitfieldSpec
, SegBData
, False
);
PopLocHandle
();
/* TODO: MakeUseList? */
}
}
}
/*--------------------------------------------------------------------------*/
/* Code Table Handling */
static void AddFixed
(const char *pName
, Word Code
)
{
AddInstTable
(InstTable
, pName
, Code
, DecodeFixed
);
}
static void AddBranch
(const char *pName
, Word Code
)
{
AddInstTable
(InstTable
, pName
, Code
, DecodeBranch
);
}
static void AddReg
(const char *pName
, Word Code
)
{
AddInstTable
(InstTable
, pName
, Code
, DecodeReg
);
}
static void AddRegMemImm
(const char *pName
, Word Code
)
{
AddInstTable
(InstTable
, pName
, Code
, DecodeRegMemImm
);
}
static void AddCondition
(const char *pName
, Word Code
, InstProc Proc
)
{
char InstrName
[20];
as_snprintf
(InstrName
, sizeof(InstrName
), pName
, "NE"); AddInstTable
(InstTable
, InstrName
, Code
| (0 << 4), Proc
);
as_snprintf
(InstrName
, sizeof(InstrName
), pName
, "EQ"); AddInstTable
(InstTable
, InstrName
, Code
| (1 << 4), Proc
);
as_snprintf
(InstrName
, sizeof(InstrName
), pName
, "PL"); AddInstTable
(InstTable
, InstrName
, Code
| (2 << 4), Proc
);
as_snprintf
(InstrName
, sizeof(InstrName
), pName
, "MI"); AddInstTable
(InstTable
, InstrName
, Code
| (3 << 4), Proc
);
as_snprintf
(InstrName
, sizeof(InstrName
), pName
, "GT"); AddInstTable
(InstTable
, InstrName
, Code
| (4 << 4), Proc
);
as_snprintf
(InstrName
, sizeof(InstrName
), pName
, "LE"); AddInstTable
(InstTable
, InstrName
, Code
| (5 << 4), Proc
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(405);
SetDynamicInstTable
(InstTable
);
AddFixed
("NOP", NOPCode
);
AddFixed
("BGND", 0x0000);
AddFixed
("CLC", 0xcefe);
AddFixed
("CLI", 0xceef);
AddFixed
("CLV", 0xcefd);
AddFixed
("RTI", 0x1b90);
AddFixed
("RTS", 0x0005);
AddFixed
("SEC", 0xde01);
AddFixed
("SEI", 0xde10);
AddFixed
("SEV", 0xde02);
AddFixed
("STOP", 0x1b05);
AddFixed
("SWI", 0x00ff);
AddFixed
("SYS", 0x1b07);
AddFixed
("WAI", 0x1b06);
AddFixed
("SPARE", 0x00ef);
AddBranch
("BCC", 0x0024);
AddBranch
("BCS", 0x0025);
AddBranch
("BEQ", 0x0027);
AddBranch
("BGE", 0x002c);
AddBranch
("BGT", 0x002e);
AddBranch
("BHI", 0x0022);
AddBranch
("BHS", 0x0024);
AddBranch
("BLE", 0x002f);
AddBranch
("BLO", 0x0025);
AddBranch
("BLS", 0x0023);
AddBranch
("BLT", 0x002d);
AddBranch
("BMI", 0x002b);
AddBranch
("BNE", 0x0026);
AddBranch
("BPL", 0x002a);
AddBranch
("BRA", 0x0020);
AddBranch
("BSR", 0x0021);
AddBranch
("BVC", 0x0028);
AddBranch
("BVS", 0x0029);
AddReg
("ABS", 0x1b40);
AddReg
("SAT", 0x1ba0);
AddRegMemImm
("ADC", 0x1b50);
AddRegMemImm
("ADD", 0x0050);
AddRegMemImm
("AND", 0x0058);
AddRegMemImm
("BIT", 0x1b58);
AddRegMemImm
("EOR", 0x1b78);
AddRegMemImm
("OR", 0x0078);
AddRegMemImm
("SBC", 0x1b70);
AddInstTable
(InstTable
, "SUB", 0x0070, DecodeSUB
);
AddInstTable
(InstTable
, "CMP", 0x00e0, DecodeCMP
);
AddInstTable
(InstTable
, "ANDCC", 0x00ce, DecodeImm8
);
AddInstTable
(InstTable
, "ORCC" , 0x00de, DecodeImm8
);
AddInstTable
(InstTable
, "TRAP" , 0, DecodeTRAP
);
AddInstTable
(InstTable
, "ASL", 0xc0, DecodeShift
);
AddInstTable
(InstTable
, "ASR", 0x80, DecodeShift
);
AddInstTable
(InstTable
, "LSL", 0x40, DecodeShift
);
AddInstTable
(InstTable
, "LSR", 0x00, DecodeShift
);
AddInstTable
(InstTable
, "BCLR", 0xec, DecodeBit
);
AddInstTable
(InstTable
, "BSET", 0xed, DecodeBit
);
AddInstTable
(InstTable
, "BTGL", 0xee, DecodeBit
);
AddInstTable
(InstTable
, "BFEXT", 0x00, DecodeBitField
);
AddInstTable
(InstTable
, "BFINS", 0x80, DecodeBitField
);
AddInstTable
(InstTable
, "BRCLR", 0x02, DecodeBitRel
);
AddInstTable
(InstTable
, "BRSET", 0x03, DecodeBitRel
);
AddInstTable
(InstTable
, "CLB", 0x1b91, DecodeTwoReg
);
AddInstTable
(InstTable
, "CLR", 0x0000, DecodeCLR
);
AddInstTable
(InstTable
, "COM", 0x00cc, DecodeCOM_NEG
);
AddInstTable
(InstTable
, "NEG", 0x00dc, DecodeCOM_NEG
);
AddCondition
("DB%s", 0x0d80, DecodeDBcc
);
AddInstTable
(InstTable
, "DEC", 0x0040, DecodeINC_DEC
);
AddInstTable
(InstTable
, "INC", 0x0030, DecodeINC_DEC
);
AddInstTable
(InstTable
, "DIVS", 0x3081, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "DIVU", 0x3001, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "MODS", 0x3881, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "MODU", 0x3801, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "MACS", 0x4881, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "MACU", 0x4801, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "MULS", 0x4880, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "MULU", 0x4800, DecodeDIV_MOD
);
AddInstTable
(InstTable
,"QMULS", 0xb081, DecodeDIV_MOD
);
AddInstTable
(InstTable
,"QMULU", 0xb001, DecodeDIV_MOD
);
AddInstTable
(InstTable
, "EXG", 0x00ae, DecodeEXG_TFR
);
AddInstTable
(InstTable
, "TFR", 0x009e, DecodeEXG_TFR
);
AddInstTable
(InstTable
, "SEX", 0x01ae, DecodeEXG_TFR
);
AddInstTable
(InstTable
, "ZEX", 0x019e, DecodeEXG_TFR
);
AddInstTable
(InstTable
, "JMP", 0x00aa, DecodeJMP_JSR
);
AddInstTable
(InstTable
, "JSR", 0x00ab, DecodeJMP_JSR
);
AddInstTable
(InstTable
, "LD" , 0x0000, DecodeLD_ST
);
AddInstTable
(InstTable
, "ST" , 0x0020, DecodeLD_ST
);
AddInstTable
(InstTable
, "MOV" , 0x0000, DecodeMOV
);
AddInstTable
(InstTable
, "LEA" , 0x0000, DecodeLEA
);
AddInstTable
(InstTable
, "MAXS", 0x1b28, DecodeMIN_MAX
);
AddInstTable
(InstTable
, "MAXU", 0x1b18, DecodeMIN_MAX
);
AddInstTable
(InstTable
, "MINS", 0x1b20, DecodeMIN_MAX
);
AddInstTable
(InstTable
, "MINU", 0x1b10, DecodeMIN_MAX
);
AddInstTable
(InstTable
, "PSH", 0x0400, DecodePSH_PUL
);
AddInstTable
(InstTable
, "PUL", 0x0480, DecodePSH_PUL
);
AddInstTable
(InstTable
, "ROL", 0x1064, DecodeROL_ROR
);
AddInstTable
(InstTable
, "ROR", 0x1024, DecodeROL_ROR
);
AddCondition
("TB%s", 0x0b00, DecodeTBcc
);
AddInstTable
(InstTable
, "DEFBIT", 0, DecodeDEFBIT
);
AddInstTable
(InstTable
, "DEFBITFIELD", 0, DecodeDEFBITFIELD
);
init_moto8_pseudo
(InstTable
, e_moto_8_be
| e_moto_8_db
| e_moto_8_dw
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
}
/*--------------------------------------------------------------------------*/
/* Semiglobal Functions */
static Boolean DecodeAttrPart_S12Z
(void)
{
int z
;
if (strlen(AttrPart.
str.
p_str) > 2)
{
WrStrErrorPos
(ErrNum_UndefAttr
, &AttrPart
);
return False
;
}
for (z
= 0; z
< 2; z
++)
{
if (AttrPart.
str.
p_str[z
] == '\0')
break;
if (!DecodeMoto16AttrSize
(AttrPart.
str.
p_str[z
], &AttrPartOpSize
[z
], True
))
return False
;
}
return True
;
}
static void MakeCode_S12Z
(void)
{
CodeLen
= 0;
DontPrint
= False
;
OpSize
= (AttrPartOpSize
[0] != eSymbolSizeUnknown
) ? AttrPartOpSize
[0] : eSymbolSizeUnknown
;
OpSize2
= (AttrPartOpSize
[1] != eSymbolSizeUnknown
) ? AttrPartOpSize
[1] : eSymbolSizeUnknown
;
/* zu ignorierendes */
if (Memo
(""))
return;
/* Pseudoanweisungen */
/* TODO: handle eSymbolSize24Bit in DC/DS */
if (DecodeMoto16Pseudo
(OpSize
, True
)) return;
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_S12Z
(void)
{
return Memo
("DEFBIT") || Memo
("DEFBITFIELD");
}
static void SwitchTo_S12Z
(void)
{
const TFamilyDescr
*pDescr
= FindFamilyByName
("S12Z");
TurnWords
= False
;
SetIntConstMode
(eIntConstModeMoto
);
PCSymbol
= "*";
HeaderID
= pDescr
->Id
;
NOPCode
= 0x01;
DivideChars
= ",";
HasAttrs
= True
;
AttrChars
= ".";
ValidSegs
= (1 << SegCode
);
Grans
[SegCode
] = 1; ListGrans
[SegCode
] = 1; SegInits
[SegCode
] = 0;
SegLimits
[SegCode
] = 0xffffff;
DecodeAttrPart
= DecodeAttrPart_S12Z
;
MakeCode
= MakeCode_S12Z
;
IsDef
= IsDef_S12Z
;
SwitchFrom
= DeinitFields
;
DissectBit
= DissectBit_S12Z
;
InitFields
();
AddMoto16PseudoONOFF
(False
);
}
void codes12z_init
(void)
{
(void)AddCPU
("S912ZVC19F0MKH" , SwitchTo_S12Z
);
(void)AddCPU
("S912ZVC19F0MLF" , SwitchTo_S12Z
);
(void)AddCPU
("S912ZVCA19F0MKH", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVCA19F0MLF", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVCA19F0WKH", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVH128F2CLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVH128F2CLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVH64F2CLQ" , SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY64F1CLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY32F1CLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY64F1CLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY32F1CLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHL64F1CLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHL32F1CLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHL64F1CLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHL32F1CLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVFP64F1CLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVFP64F1CLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVH128F2VLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVH128F2VLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVH64F2VLQ" , SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY64F1VLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY32F1VLQ", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY64F1VL" , SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHY32F1VLL", SwitchTo_S12Z
);
(void)AddCPU
("S912ZVHL64F1VLQ", SwitchTo_S12Z
);
}