/* codemn2610.c */
/****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS, C-Version */
/* */
/* Code Generator for MN161x Processor - alternate version */
/* */
/****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "bpemu.h"
#include "be_le.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmpars.h"
#include "asmsub.h"
#include "motpseudo.h"
#include "asmitree.h"
#include "codevars.h"
#include "headids.h"
#include "errmsg.h"
#include "codepseudo.h"
#include "ibmfloat.h"
#include "onoff_common.h"
#include "chartrans.h"
#include "codemn2610.h"
/*--------------------------------------------------------------------------*/
/* Definitions */
typedef struct
{
const char *pName
;
Word Code
;
} tCodeTable
;
typedef struct
{
Word Code
;
CPUVar MinCPU
;
} tFixedOrder
;
enum
{
eAddrRegX0
,
eAddrRegX1
,
eAddrRegIC
,
eAddrRegCnt
};
static CPUVar CPUMN1610
, CPUMN1613
;
static tSymbolSize OpSize
;
static LongInt BaseRegVals
[4];
#define ASSUMEMN1613Count 4
static ASSUMERec ASSUMEMN1613
[ASSUMEMN1613Count
] =
{
{ "CSBR", BaseRegVals
+ 0, 0, 15, 16, NULL
},
{ "SSBR", BaseRegVals
+ 1, 0, 15, 16, NULL
},
{ "TSR0", BaseRegVals
+ 2, 0, 15, 16, NULL
},
{ "TSR1", BaseRegVals
+ 3, 0, 15, 16, NULL
}
};
static tFixedOrder
*FixedOrders
;
/*--------------------------------------------------------------------------*/
/* Adress Decoders */
static Boolean DecodeTable
(const char *pArg
, Word
*pResult
, const tCodeTable
*pTable
)
{
for (; pTable
->pName
; pTable
++)
if (!as_strcasecmp
(pArg
, pTable
->pName
))
{
*pResult
= pTable
->Code
;
return True
;
}
return False
;
}
static const tCodeTable RegCodes
[] =
{
{ "R0", 0 },
{ "R1", 1 },
{ "R2", 2 },
{ "R3", 3 },
{ "R4", 4 },
{ "SP", 5 },
{ "STR", 6 },
{ "IC", 7 },
{ "X0", 3 },
{ "X1", 4 },
{ NULL
, 0 }
};
#define DecodeRegCore(pArg, pResult) (DecodeTable((pArg), (pResult), RegCodes))
static Boolean DecodeReg
(const tStrComp
*pArg
, Word
*pResult
, Byte Mask
)
{
Boolean Result
= DecodeRegCore
(pArg
->str.
p_str, pResult
) && (Mask
& (1 << *pResult
));
if (!Result
)
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
return Result
;
}
static const tCodeTable DRegCodes
[] =
{
{ "DR0", 0 },
{ NULL
, 0 }
};
#define DecodeDRegCore(pArg, pResult) (DecodeTable((pArg), (pResult), DRegCodes))
static Boolean DecodeDReg
(const tStrComp
*pArg
)
{
Word DummyReg
;
Boolean Result
= DecodeDRegCore
(pArg
->str.
p_str, &DummyReg
) && !DummyReg
;
if (!Result
)
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
return Result
;
}
static const tCodeTable SkipCodes
[] =
{
{ "" , 0 },
{ "SKP", 1 },
{ "M" , 2 },
{ "PZ" , 3 },
{ "E" , 4 },
{ "Z" , 4 },
{ "NE" , 5 },
{ "NZ" , 5 },
{ "MZ" , 6 },
{ "P" , 7 },
{ "EZ" , 8 },
{ "ENZ", 9 },
{ "OZ" , 10 },
{ "ONZ", 11 },
{ "LMZ", 12 },
{ "LP" , 13 },
{ "LPZ", 14 },
{ "LM" , 15 },
{ NULL
, 0 }
};
#define DecodeSkipCore(pArg, pResult) (DecodeTable((pArg), (pResult), SkipCodes))
static Boolean DecodeSkip
(const tStrComp
*pArg
, Word
*pResult
)
{
Boolean Result
= DecodeSkipCore
(pArg
->str.
p_str, pResult
);
if (!Result
)
WrStrErrorPos
(ErrNum_UndefCond
, pArg
);
return Result
;
}
static const tCodeTable AddrRegCodes
[] =
{
{ "(X0)", eAddrRegX0
},
{ "(X1)", eAddrRegX1
},
{ "(IC)", eAddrRegIC
},
{ NULL
, 0 }
};
#define DecodeAddrReg(pArg, pResult) (DecodeTable((pArg), (pResult), AddrRegCodes))
static const tCodeTable EECodes
[] =
{
{ "" , 0 },
{ "RE", 1 },
{ "SE", 2 },
{ "CE", 3 },
{ NULL
, 0 }
};
#define DecodeEECore(pArg, pResult) (DecodeTable((pArg), (pResult), EECodes))
static Boolean DecodeEE
(const tStrComp
*pArg
, Word
*pResult
)
{
Boolean Result
= DecodeEECore
(pArg
->str.
p_str, pResult
);
if (!Result
)
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
return Result
;
}
static const tCodeTable AllBRCodes
[] =
{
{ "CSBR", 0 },
{ "SSBR", 1 },
{ "TSR0", 2 },
{ "TSR1", 3 },
{ "OSR0", 4 },
{ "OSR1", 5 },
{ "OSR2", 6 },
{ "OSR3", 7 },
{ NULL
, 0 }
};
#define DecodeAllBRCore(pArg, pResult, IsWrite) (DecodeTable((pArg), (pResult), AllBRCodes + IsWrite))
static const tCodeTable BRCodes
[] =
{
{ "CSBR", 0 },
{ "SSBR", 1 },
{ "TSR0", 2 },
{ "TSR1", 3 },
{ NULL
, 0 }
};
#define DecodeBRCore(pArg, pResult) (DecodeTable((pArg), (pResult), BRCodes))
static Boolean DecodeBR
(const tStrComp
*pArg
, Word
*pResult
)
{
Boolean Result
= DecodeBRCore
(pArg
->str.
p_str, pResult
);
if (!Result
)
WrStrErrorPos
(ErrNum_UnknownSegReg
, pArg
);
return Result
;
}
static const tCodeTable SRegCodes
[] =
{
{ "SBRB", 0 },
{ "ICB" , 1 },
{ "NPP" , 2 },
{ NULL
, 0 }
};
#define DecodeSRegCore(pArg, pResult) (DecodeTable((pArg), (pResult), SRegCodes))
static Boolean DecodeSOrAllBReg
(const tStrComp
*pArg
, Word
*pResult
, unsigned IsS
, Boolean IsWrite
)
{
Boolean Result
= IsS
? DecodeSRegCore
(pArg
->str.
p_str, pResult
) : DecodeAllBRCore
(pArg
->str.
p_str, pResult
, IsWrite
);
if (!Result
)
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
return Result
;
}
static tCodeTable HRegCodes
[] =
{
{ "TCR" , 0 },
{ "TIR" , 1 },
{ "TSR" , 2 },
{ "SCR" , 3 },
{ "SSR" , 4 },
{ NULL
, 5 }, /* filled @ runtime with SOR/SIR */
{ "IISR", 6 },
{ NULL
, 0 }
};
#define DecodeHRegCore(pArg, pResult) (DecodeTable((pArg), (pResult), HRegCodes))
static Boolean DecodeHReg
(const tStrComp
*pArg
, Word
*pResult
, Boolean IsWrite
)
{
Boolean Result
;
HRegCodes
[5].
pName = IsWrite
? "SOR" : "SIR";
Result
= DecodeHRegCore
(pArg
->str.
p_str, pResult
);
if (!Result
)
WrStrErrorPos
(ErrNum_InvReg
, pArg
);
return Result
;
}
/*!------------------------------------------------------------------------
* \fn Word ChkPage(LongWord Addr, Word Base, const tStrComp *pArg, bool Warn)
* \brief check whether a linear address is reachable via the given segment register, and compute offset
* \param Addr linear address in 64/256K space
* \param Base index of segment register to be used
* \param pArg textual argument for warnings (may be NULL)
* \return resulting offset
* ------------------------------------------------------------------------ */
static Word ChkPage
(LongWord Addr
, Word Base
, const tStrComp
*pArg
)
{
Addr
-= BaseRegVals
[Base
] << 14;
Addr
&= SegLimits
[SegCode
];
if ((Addr
>= 0x10000ul
) && pArg
)
WrStrErrorPos
(ErrNum_InAccPage
, pArg
);
return Addr
& 0xffff;
}
/*!------------------------------------------------------------------------
* \fn DecodeMem(tStrComp *pArg, Word *pResult)
* \brief parse memory address expression
* \param pArg memory argument in source
* \param pResult resulting code for instruction word (xxMMMxxxDDDDDDDD)
* \return True if successfully parsed
* ------------------------------------------------------------------------ */
static Boolean DecodeMem
(tStrComp
*pArg
, Word
*pResult
)
{
tStrComp Arg
;
Boolean TotIndirect
= IsIndirect
(pArg
->str.
p_str), OK
;
Word R
;
Integer Disp
;
int l
;
tSymbolFlags Flags
;
if (TotIndirect
)
{
StrCompRefRight
(&Arg
, pArg
, 1);
KillPrefBlanksStrCompRef
(&Arg
);
StrCompShorten
(&Arg
, 1);
KillPostBlanksStrComp
(&Arg
);
}
else
StrCompRefRight
(&Arg
, pArg
, 0);
l
= strlen(Arg.
str.
p_str);
if ((l
>= 4) && DecodeAddrReg
(Arg.
str.
p_str + l
- 4, &R
))
{
Boolean DispIndirect
;
StrCompShorten
(&Arg
, 4);
KillPostBlanksStrComp
(&Arg
);
DispIndirect
= IsIndirect
(Arg.
str.
p_str);
Disp
= EvalStrIntExpression
(&Arg
, (R
== 2) ? SInt8
: UInt8
, &OK
);
if (!OK
)
return False
;
if (R
== 2)
{
if (DispIndirect
) /* ((disp)(IC)), (disp)(IC) not possible */
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
return False
;
}
else /* (disp(IC)) */
{
*pResult
= ((TotIndirect
? 3 : 1) << 11) | (Disp
& 0xff);
return True
;
}
}
else if (TotIndirect
) /* (disp(Xn)), ((disp)(Xn)) not possible */
{
WrStrErrorPos
(ErrNum_InvAddrMode
, pArg
);
return False
;
}
else /* disp(Xn), (disp)(Xn) */
{
*pResult
= (((DispIndirect
? 6 : 4) + R
) << 11) | (Disp
& 0xff);
return True
;
}
}
else if (TotIndirect
&& DecodeRegCore
(Arg.
str.
p_str, &R
)) /* plain (ic) (x0) (x1) without displacement */
{
switch (R
)
{
case 3:
*pResult
= (4 << 11);
return True
;
case 4:
*pResult
= (5 << 11);
return True
;
case 7:
*pResult
= (1 << 11);
return True
;
default:
goto plaindisp
;
}
}
else
{
int ArgOffset
, ForceMode
;
LongWord Addr
;
plaindisp
:
/* For (Addr), there is only the 'zero-page' variant: */
if (TotIndirect
)
{
ArgOffset
= 0;
ForceMode
= 1;
}
/* For direct addressing, either zero-page or IC-relative may be used.
Check for explicit request: */
else switch (*Arg.
str.
p_str)
{
case '>':
ArgOffset
= 1;
ForceMode
= 2;
break;
case '<':
ArgOffset
= 1;
ForceMode
= 1;
break;
default:
ArgOffset
= ForceMode
= 0;
}
/* evaluate expression */
Addr
= EvalStrIntExpressionOffsWithFlags
(&Arg
, ArgOffset
, (MomCPU
== CPUMN1613
) ? UInt18
: UInt16
, &OK
, &Flags
);
if (!OK
)
return False
;
/* now generate mode */
switch (ForceMode
)
{
case 0:
{
if (ChkPage
(Addr
, 0, NULL
) < 256)
goto case1
;
else
goto case2
;
}
case 1:
case1
:
{
Word Offset
= ChkPage
(Addr
, 0, NULL
);
if (!mFirstPassUnknownOrQuestionable
(Flags
) && (Offset
> 255))
{
WrStrErrorPos
(ErrNum_OverRange
, pArg
);
return False
;
}
else
{
*pResult
= ((TotIndirect
? 2 : 0) << 11) | (Offset
& 0xff);
return True
;
}
}
case 2:
case2
:
{
LongInt Disp
= Addr
- EProgCounter
();
if (!mFirstPassUnknownOrQuestionable
(Flags
) && ((Disp
> 127) || (Disp
< -128)))
{
WrStrErrorPos
(ErrNum_DistTooBig
, pArg
);
return False
;
}
else
{
*pResult
= (1 << 11) | (Disp
& 0xff);
return True
;
}
}
default:
return False
;
}
}
}
static Boolean DecodeIReg
(tStrComp
*pStrArg
, Word
*pResult
, Word Mask
, Word Allowed
)
{
char *pArg
= pStrArg
->str.
p_str;
int l
= strlen(pArg
);
char *pEnd
= pArg
+ l
, Save
;
Word Reg
;
Boolean OK
;
if ((l
> 2) && (*pArg
== '(') && (*(pEnd
- 1) == ')'))
{
pArg
++; pEnd
--;
*pResult
= 1 << 6;
}
else if ((l
> 3) && (*pArg
== '(') && (*(pEnd
- 2) == ')') && (*(pEnd
- 1) == '+'))
{
pArg
++; pEnd
-= 2;
*pResult
= 3 << 6;
}
else if ((l
> 3) && (*pArg
== '-') && (pArg
[1] == '(') && (*(pEnd
- 1) == ')'))
{
pArg
+= 2; pEnd
--;
*pResult
= 2 << 6;
}
else
goto error
;
while ((pArg
< pEnd
) && isspace(*pArg
))
pArg
++;
while ((pEnd
> pArg
) && isspace(*(pEnd
- 1)))
pEnd
--;
Save
= *pEnd
; *pEnd
= '\0';
OK
= DecodeRegCore
(pArg
, &Reg
);
*pEnd
= Save
;
if (!OK
|| (Reg
< 1) || (Reg
> 4))
goto error
;
*pResult
|= (Reg
- 1);
if ((*pResult
& Mask
) != Allowed
)
goto error
;
return True
;
error
:
WrStrErrorPos
(ErrNum_InvAddrMode
, pStrArg
);
return False
;
}
/*--------------------------------------------------------------------------*/
/* Instruction Decoders */
static void DecodeFixed
(Word Index
)
{
const tFixedOrder
*pOrder
= FixedOrders
+ Index
;
if (ChkArgCnt
(0, 0) && ChkMinCPU
(pOrder
->MinCPU
))
{
WAsmCode
[0] = pOrder
->Code
;
CodeLen
= 1;
}
}
static void DecodeOneReg
(Word Code
)
{
Word Reg
;
if (ChkArgCnt
(1, 1)
&& DecodeReg
(&ArgStr
[1], &Reg
, 0x7f)) /* do not allow IC as register */
{
WAsmCode
[0] = Code
| (Reg
<< 8);
CodeLen
= 1;
}
}
static void DecodeRegImm
(Word Code
)
{
Word Reg
;
if (ChkArgCnt
(2, 2)
&& DecodeReg
(&ArgStr
[1], &Reg
, 0x7f)) /* do not allow IC as register */
{
tEvalResult EvalResult
;
WAsmCode
[0] = EvalStrIntExpressionWithResult
(&ArgStr
[2], Int8
, &EvalResult
) & 0xff;
if (EvalResult.
OK)
{
if (Code
& 0x1000)
ChkSpace
(SegIO
, EvalResult.
AddrSpaceMask);
WAsmCode
[0] |= Code
| (Reg
<< 8);
CodeLen
= 1;
}
}
}
static void DecodeTwoReg
(Word Code
)
{
Word Rd
, Rs
, Skip
= 0;
if (ChkArgCnt
(2, 3)
&& DecodeReg
(&ArgStr
[1], &Rd
, 0x7f) /* do not allow IC as register */
&& DecodeReg
(&ArgStr
[2], &Rs
, 0x7f) /* do not allow IC as register */
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
WAsmCode
[0] = Code
| (Rd
<< 8) | (Skip
<< 4) | Rs
;
CodeLen
= 1;
}
}
static void DecodeEAReg
(Word Code
)
{
Word R
, EA
;
if (ChkArgCnt
(2, 2)
&& DecodeReg
(&ArgStr
[1], &R
, 0x3f)
&& DecodeMem
(&ArgStr
[2], &EA
))
{
WAsmCode
[0] = Code
| EA
| (R
<< 8);
CodeLen
= 1;
}
}
static void DecodeEA
(Word Code
)
{
Word EA
;
if (ChkArgCnt
(1, 1)
&& DecodeMem
(&ArgStr
[1], &EA
))
{
WAsmCode
[0] = Code
| EA
;
CodeLen
= 1;
}
}
static void DecodeShift
(Word Code
)
{
Word R
, Skip
= 0, EE
= 0;
if (ChkArgCnt
(1, 3)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f)) /* do not allow IC as register */
{
Boolean OK
;
if (ArgCnt
== 3)
OK
= DecodeEE
(&ArgStr
[2], &EE
) && DecodeSkip
(&ArgStr
[3], &Skip
);
else if (ArgCnt
== 1)
OK
= True
;
else
OK
= DecodeEECore
(ArgStr
[2].
str.
p_str, &EE
) || DecodeSkip
(&ArgStr
[2], &Skip
);
if (OK
)
{
WAsmCode
[0] = Code
| (R
<< 8) | (Skip
<< 4) | EE
;
CodeLen
= 1;
}
}
}
static void DecodeImm4
(Word Code
)
{
Word R
, Skip
= 0;
if (ChkArgCnt
(2, 3)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f)
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
Word Num
;
Boolean OK
;
Num
= EvalStrIntExpression
(&ArgStr
[2], UInt4
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
| (R
<< 8) | (Skip
<< 4) | (Num
& 15);
CodeLen
= 1;
}
}
}
static void DecodeImm2
(Word Code
)
{
if (ChkArgCnt
(1, 1))
{
Boolean OK
;
WAsmCode
[0] = Code
| EvalStrIntExpression
(&ArgStr
[1], UInt2
, &OK
);
if (OK
)
CodeLen
= 1;
}
}
static void DecodeLD_STD
(Word Code
)
{
Word R
, Base
= 0;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x3f) /* do not allow IC/STR as register */
&& ((ArgCnt
<= 2) || DecodeBR
(&ArgStr
[2], &Base
)))
{
Boolean OK
;
LongWord Addr
;
Addr
= EvalStrIntExpression
(&ArgStr
[ArgCnt
], UInt18
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
| R
| (Base
<< 4);
WAsmCode
[1] = ChkPage
(Addr
, Base
, &ArgStr
[ArgCnt
]);
CodeLen
= 2;
}
}
}
static void DecodeLR_STR
(Word Code
)
{
Word R
, IR
, Base
= 0;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x3f) /* do not allow STR/IC as register */
&& ((ArgCnt
<= 2) || DecodeBR
(&ArgStr
[2], &Base
))
&& DecodeIReg
(&ArgStr
[ArgCnt
], &IR
, 0x00, 0x00))
{
WAsmCode
[0] = Code
| (R
<< 8) | IR
| (Base
<< 4);
CodeLen
= 1;
}
}
static void DecodeR0RISkip
(Word Code
)
{
Word R
, RI
, Skip
= 0;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x01)
&& DecodeIReg
(&ArgStr
[2], &RI
, 0xc0, 0x40)
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
WAsmCode
[0] = Code
| (Skip
<< 4) | (RI
& 3);
CodeLen
= 1;
}
}
static void DecodeRImmSkip
(Word Code
)
{
Word R
, Skip
= 0;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f) /* do not allow IC as register */
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
Boolean OK
;
WAsmCode
[1] = EvalStrIntExpression
(&ArgStr
[2], Int16
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
| (R
<< 8) | (Skip
<< 4);
CodeLen
= 2;
}
}
}
static Boolean ChkCarry
(int StartIndex
, Boolean
*pHasCarryArg
, Word
*pCarryVal
)
{
if (ArgCnt
< StartIndex
)
{
*pHasCarryArg
= False
;
*pCarryVal
= 0;
return True
;
}
else
{
Boolean Result
;
*pHasCarryArg
= !as_strcasecmp
(ArgStr
[StartIndex
].
str.
p_str, "C")
|| !as_strcasecmp
(ArgStr
[StartIndex
].
str.
p_str, "0")
|| !as_strcasecmp
(ArgStr
[StartIndex
].
str.
p_str, "1");
*pCarryVal
= *pHasCarryArg
&& (ArgStr
[StartIndex
].
str.
p_str[0] != '0');
Result
= (ArgCnt
== StartIndex
) || *pHasCarryArg
;
if (!Result
)
WrStrErrorPos
(ErrNum_InvReg
, &ArgStr
[StartIndex
]);
return Result
;
}
}
static void DecodeDR0RISkip
(Word Code
)
{
Word Skip
= 0, Ri
, CarryVal
= 0;
Boolean OptCarry
= !!(Code
& 0x10), HasCarryArg
= False
;
Code
&= ~
0x10;
if (ChkArgCnt
(2, 3 + OptCarry
)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeDReg
(&ArgStr
[1])
&& DecodeIReg
(&ArgStr
[2], &Ri
, 0xc0, 0x40)
&& (!OptCarry
|| ChkCarry
(3, &HasCarryArg
, &CarryVal
))
&& ((ArgCnt
< 3 + HasCarryArg
) || DecodeSkip
(&ArgStr
[3 + HasCarryArg
], &Skip
)))
{
WAsmCode
[0] = Code
| (Skip
<< 4) | (Ri
& 3) | (CarryVal
<< 3);
CodeLen
= 1;
}
}
static void DecodeDAA_DAS
(Word Code
)
{
Word R
, Ri
, Skip
= 0, CarryVal
= 0;
Boolean HasCarryArg
= False
;
if (ChkArgCnt
(2, 4)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x01)
&& DecodeIReg
(&ArgStr
[2], &Ri
, 0xc0, 0x40)
&& ChkCarry
(3, &HasCarryArg
, &CarryVal
)
&& ((ArgCnt
< 3 + HasCarryArg
) || DecodeSkip
(&ArgStr
[3 + HasCarryArg
], &Skip
)))
{
WAsmCode
[0] = Code
| (Skip
<< 4) | (Ri
& 3) | (CarryVal
<< 3);
CodeLen
= 1;
}
}
static void DecodeNEG
(Word Code
)
{
Word R
, Skip
= 0, CarryVal
= 0;
Boolean HasCarryArg
= False
;
if (ChkArgCnt
(1, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f) /* do not allow IC as register */
&& ChkCarry
(2, &HasCarryArg
, &CarryVal
)
&& ((ArgCnt
< 2 + HasCarryArg
) || DecodeSkip
(&ArgStr
[2 + HasCarryArg
], &Skip
)))
{
WAsmCode
[0] = Code
| (Skip
<< 4) | R
| (CarryVal
<< 3);
CodeLen
= 1;
}
}
static void DecodeRDR_WTR
(Word Code
)
{
Word R
, Ri
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x3f) /* do not allow IC/STR */
&& DecodeIReg
(&ArgStr
[2], &Ri
, 0xc0, 0x40))
{
WAsmCode
[0] = Code
| (R
<< 8) | (Ri
& 3);
CodeLen
= 1;
}
}
static void DecodeBD_BALD
(Word Code
)
{
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(CPUMN1613
))
{
Boolean OK
;
LongWord Addr
= EvalStrIntExpression
(&ArgStr
[1], UInt18
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
;
WAsmCode
[1] = ChkPage
(Addr
, 0, &ArgStr
[1]);
CodeLen
= 2;
}
}
}
static void DecodeBL_BALL
(Word Code
)
{
if (!ChkArgCnt
(1, 1));
else if (!ChkMinCPU
(CPUMN1613
));
else if (!IsIndirect
(ArgStr
[1].
str.
p_str)) WrStrErrorPos
(ErrNum_InvAddrMode
, &ArgStr
[1]);
else
{
Boolean OK
;
LongWord Addr
= EvalStrIntExpression
(&ArgStr
[1], UInt18
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
;
WAsmCode
[1] = ChkPage
(Addr
, 0, &ArgStr
[1]);
CodeLen
= 2;
}
}
}
static void DecodeBR_BALR
(Word Code
)
{
Word Ri
;
if (ChkArgCnt
(1, 1)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeIReg
(&ArgStr
[1], &Ri
, 0xc0, 0x40))
{
WAsmCode
[0] = Code
| (Ri
& 3);
CodeLen
= 1;
}
}
static void DecodeTSET_TRST
(Word Code
)
{
Word R
, Skip
= 0;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f) /* do not allow IC as register */
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
Boolean OK
;
LongWord Addr
= EvalStrIntExpression
(&ArgStr
[2], UInt18
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
| R
| (Skip
<< 4);
WAsmCode
[1] = ChkPage
(Addr
, 0, &ArgStr
[2]);
CodeLen
= 2;
}
}
}
static void DecodeFIX
(Word Code
)
{
Word Skip
= 0, R
;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x01)
&& DecodeDReg
(&ArgStr
[2])
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
WAsmCode
[0] = Code
| (Skip
<< 4);
CodeLen
= 1;
}
}
static void DecodeFLT
(Word Code
)
{
Word Skip
= 0, R
;
if (ChkArgCnt
(2, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeDReg
(&ArgStr
[1])
&& DecodeReg
(&ArgStr
[2], &R
, 0x01)
&& ((ArgCnt
< 3) || DecodeSkip
(&ArgStr
[3], &Skip
)))
{
WAsmCode
[0] = Code
| (Skip
<< 4);
CodeLen
= 1;
}
}
static void DecodeSRBT
(Word Code
)
{
Word R
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x01)
&& DecodeReg
(&ArgStr
[2], &R
, 0x7f))
{
WAsmCode
[0] = Code
| R
;
CodeLen
= 1;
}
}
static void DecodeDEBP
(Word Code
)
{
Word R
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[2], &R
, 0x01)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f))
{
WAsmCode
[0] = Code
| R
;
CodeLen
= 1;
}
}
static void DecodeBLK
(Word Code
)
{
Word Ri
;
if (ChkArgCnt
(3, 3)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeIReg
(&ArgStr
[1], &Ri
, 0xff, 0x41)
&& DecodeIReg
(&ArgStr
[2], &Ri
, 0xff, 0x40)
&& DecodeReg
(&ArgStr
[3], &Ri
, 0x01))
{
WAsmCode
[0] = Code
;
CodeLen
= 1;
}
}
static void DecodeLBS_STBS
(Word Code
)
{
Word R
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeSOrAllBReg
(&ArgStr
[1], &R
, Code
& 8, !(Code
& 0x80)))
{
Boolean OK
;
LongWord Addr
= EvalStrIntExpression
(&ArgStr
[2], UInt18
, &OK
);
if (OK
)
{
WAsmCode
[0] = Code
| (R
<< 4);
WAsmCode
[1] = ChkPage
(Addr
, 0, &ArgStr
[2]);
CodeLen
= 2;
}
}
}
static void DecodeCPYBS_SETBS
(Word Code
)
{
Word R
, BSR
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f) /* do not allow IC */
&& DecodeSOrAllBReg
(&ArgStr
[2], &BSR
, Code
& 8, !(Code
& 0x80)))
{
WAsmCode
[0] = Code
| R
| (BSR
<< 4);
CodeLen
= 1;
}
}
static void DecodeCPYH_SETH
(Word Code
)
{
Word R
, BSR
;
if (ChkArgCnt
(2, 2)
&& ChkMinCPU
(CPUMN1613
)
&& DecodeReg
(&ArgStr
[1], &R
, 0xff)
&& DecodeHReg
(&ArgStr
[2], &BSR
, !(Code
& 0x80)))
{
WAsmCode
[0] = Code
| R
| (BSR
<< 4);
CodeLen
= 1;
}
}
static void DecodeCLR
(Word Code
)
{
Word R
;
if (ChkArgCnt
(1, 1)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f)) /* do not allow IC */
{
/* == EOR R,R */
WAsmCode
[0] = Code
| (R
<< 8) | R
;
CodeLen
= 1;
}
}
static void DecodeSKIP
(Word Code
)
{
Word R
, Skip
;
if (ChkArgCnt
(2, 2)
&& DecodeReg
(&ArgStr
[1], &R
, 0x7f) /* do not allow IC */
&& DecodeSkip
(&ArgStr
[2], &Skip
))
{
/* == MV R,R,SKIP */
WAsmCode
[0] = Code
| (R
<< 8) | (Skip
<< 4) | R
;
}
}
void IncMaxCodeLen
(unsigned NumWords
)
{
SetMaxCodeLen
((CodeLen
+ NumWords
) * 2);
}
static void AppendWord
(Word data
, Boolean
*p_half_filled_word
)
{
IncMaxCodeLen
(1);
WAsmCode
[CodeLen
++] = data
;
*p_half_filled_word
= False
;
}
static void AppendByte
(Byte data
, Boolean
*p_half_filled_word
)
{
if (*p_half_filled_word
)
{
WAsmCode
[CodeLen
- 1] |= data
& 0xff;
*p_half_filled_word
= False
;
}
else
{
AppendWord
(data
<< 8, p_half_filled_word
);
*p_half_filled_word
= True
;
}
}
static void DecodeDC
(Word Code
)
{
Boolean HalfFilledWord
= False
;
TempResult t
;
UNUSED
(Code
);
as_tempres_ini
(&t
);
if (ChkArgCnt
(1, ArgCntMax
))
{
Boolean OK
= True
;
tStrComp
*pArg
;
forallargs
(pArg
, OK
)
{
EvalStrExpression
(pArg
, &t
);
if (mFirstPassUnknown
(t.
Flags) && (t.
Typ == TempInt
)) t.
Contents.
Int &= 0x7fff;
switch (t.
Typ)
{
case TempInt
:
if (Packing
)
{
if (mFirstPassUnknown
(t.
Flags))
t.
Contents.
Int &= 127;
if (ChkRange
(t.
Contents.
Int, -128, 255))
AppendByte
(t.
Contents.
Int, &HalfFilledWord
);
else
OK
= False
;
}
else
{
ToInt
:
if (mFirstPassUnknown
(t.
Flags))
t.
Contents.
Int &= 32767;
if (ChkRange
(t.
Contents.
Int, -32768, 65535))
AppendWord
(t.
Contents.
Int, &HalfFilledWord
);
else
OK
= False
;
}
break;
case TempString
:
{
Word Trans
;
int z2
;
if (MultiCharToInt
(&t
, 2))
goto ToInt
;
if (as_chartrans_xlate_nonz_dynstr
(CurrTransTable
->p_table
, &t.
Contents.
str, pArg
))
OK
= False
;
else
for (z2
= 0; z2
< (int)t.
Contents.
str.
len; z2
++)
{
Trans
= ((usint
) t.
Contents.
str.
p_str[z2
]) & 0xff;
AppendByte
(Trans
, &HalfFilledWord
);
}
break;
}
case TempFloat
:
{
IncMaxCodeLen
(2);
if (Double2IBMFloat
(&WAsmCode
[CodeLen
], t.
Contents.
Float, False
))
CodeLen
+= 2;
else
OK
= False
;
HalfFilledWord
= False
;
break;
}
default:
OK
= False
;
}
}
if (!OK
)
CodeLen
= 0;
}
as_tempres_free
(&t
);
}
static void DecodeDS
(Word Index
)
{
Boolean OK
;
Word Size
;
tSymbolFlags Flags
;
UNUSED
(Index
);
Size
= EvalStrIntExpressionWithFlags
(&ArgStr
[1], UInt16
, &OK
, &Flags
);
if (mFirstPassUnknown
(Flags
)) WrError
(ErrNum_FirstPassCalc
);
if (OK
&& !mFirstPassUnknown
(Flags
))
{
DontPrint
= True
;
if (!Size
) WrError
(ErrNum_NullResMem
);
CodeLen
= Size
;
BookKeeping
();
}
}
/*--------------------------------------------------------------------------*/
/* Codetabellen */
static void AddFixed
(const char *pName
, Word Code
, CPUVar MinCPU
)
{
order_array_rsv_end
(FixedOrders
, tFixedOrder
);
FixedOrders
[InstrZ
].
Code = Code
;
FixedOrders
[InstrZ
].
MinCPU = MinCPU
;
AddInstTable
(InstTable
, pName
, InstrZ
++, DecodeFixed
);
}
static void InitFields
(void)
{
InstTable
= CreateInstTable
(201);
InstrZ
= 0;
AddFixed
("H" , 0x2000 , CPUMN1610
);
AddFixed
("RET" , 0x2003 , CPUMN1610
);
AddFixed
("NOP" , NOPCode
, CPUMN1610
);
AddFixed
("PSHM", 0x170f , CPUMN1613
);
AddFixed
("POPM", 0x1707 , CPUMN1613
);
AddFixed
("RETL", 0x3f07 , CPUMN1613
);
AddInstTable
(InstTable
, "PUSH", 0x2001, DecodeOneReg
);
AddInstTable
(InstTable
, "POP" , 0x2002, DecodeOneReg
);
/* allow WR as alias to WT */
AddInstTable
(InstTable
, "RD" , 0x1800, DecodeRegImm
);
AddInstTable
(InstTable
, "WT" , 0x1000, DecodeRegImm
);
AddInstTable
(InstTable
, "WR" , 0x1000, DecodeRegImm
);
AddInstTable
(InstTable
, "MVI" , 0x0800, DecodeRegImm
);
AddInstTable
(InstTable
, "A" , 0x5808, DecodeTwoReg
);
AddInstTable
(InstTable
, "S" , 0x5800, DecodeTwoReg
);
AddInstTable
(InstTable
, "C" , 0x5008, DecodeTwoReg
);
AddInstTable
(InstTable
, "CB" , 0x5000, DecodeTwoReg
);
AddInstTable
(InstTable
, "MV" , 0x7808, DecodeTwoReg
);
AddInstTable
(InstTable
, "MVB" , 0x7800, DecodeTwoReg
);
AddInstTable
(InstTable
, "BSWP", 0x7008, DecodeTwoReg
);
AddInstTable
(InstTable
, "DSWP", 0x7000, DecodeTwoReg
);
AddInstTable
(InstTable
, "LAD" , 0x6800, DecodeTwoReg
);
AddInstTable
(InstTable
, "AND" , 0x6808, DecodeTwoReg
);
AddInstTable
(InstTable
, "OR" , 0x6008, DecodeTwoReg
);
AddInstTable
(InstTable
, "EOR" , 0x6000, DecodeTwoReg
);
AddInstTable
(InstTable
, "L" , 0xc000, DecodeEAReg
);
AddInstTable
(InstTable
, "ST" , 0x8000, DecodeEAReg
);
AddInstTable
(InstTable
, "B" , 0xc700, DecodeEA
);
AddInstTable
(InstTable
, "BAL" , 0x8700, DecodeEA
);
AddInstTable
(InstTable
, "IMS" , 0xc600, DecodeEA
);
AddInstTable
(InstTable
, "DMS" , 0x8600, DecodeEA
);
AddInstTable
(InstTable
, "SL" , 0x200c, DecodeShift
);
AddInstTable
(InstTable
, "SR" , 0x2008, DecodeShift
);
AddInstTable
(InstTable
, "SBIT", 0x3800, DecodeImm4
);
AddInstTable
(InstTable
, "RBIT", 0x3000, DecodeImm4
);
AddInstTable
(InstTable
, "TBIT", 0x2800, DecodeImm4
);
AddInstTable
(InstTable
, "AI" , 0x4800, DecodeImm4
);
AddInstTable
(InstTable
, "SI" , 0x4000, DecodeImm4
);
AddInstTable
(InstTable
, "LPSW", 0x2004, DecodeImm2
);
/* new to MN1613 */
AddInstTable
(InstTable
, "LD" , 0x2708, DecodeLD_STD
);
AddInstTable
(InstTable
, "STD" , 0x2748, DecodeLD_STD
);
AddInstTable
(InstTable
, "LR" , 0x2000, DecodeLR_STR
);
AddInstTable
(InstTable
, "STR" , 0x2004, DecodeLR_STR
);
AddInstTable
(InstTable
, "MVWR", 0x7f08, DecodeR0RISkip
);
AddInstTable
(InstTable
, "MVBR", 0x7f00, DecodeR0RISkip
);
AddInstTable
(InstTable
, "BSWR", 0x7708, DecodeR0RISkip
);
AddInstTable
(InstTable
, "DSWR", 0x7700, DecodeR0RISkip
);
AddInstTable
(InstTable
, "AWR" , 0x5f08, DecodeR0RISkip
);
AddInstTable
(InstTable
, "SWR" , 0x5f00, DecodeR0RISkip
);
AddInstTable
(InstTable
, "CWR" , 0x5708, DecodeR0RISkip
);
AddInstTable
(InstTable
, "CBR" , 0x5700, DecodeR0RISkip
);
AddInstTable
(InstTable
, "LADR", 0x6f00, DecodeR0RISkip
);
AddInstTable
(InstTable
, "ANDR", 0x6f08, DecodeR0RISkip
);
AddInstTable
(InstTable
, "ORR" , 0x6708, DecodeR0RISkip
);
AddInstTable
(InstTable
, "EORR", 0x6700, DecodeR0RISkip
);
AddInstTable
(InstTable
, "MVWI", 0x780f, DecodeRImmSkip
);
AddInstTable
(InstTable
, "AWI" , 0x580f, DecodeRImmSkip
);
AddInstTable
(InstTable
, "SWI" , 0x5807, DecodeRImmSkip
);
AddInstTable
(InstTable
, "CWI" , 0x500f, DecodeRImmSkip
);
AddInstTable
(InstTable
, "CBI" , 0x5007, DecodeRImmSkip
);
AddInstTable
(InstTable
, "LADI", 0x6807, DecodeRImmSkip
);
AddInstTable
(InstTable
, "ANDI", 0x680f, DecodeRImmSkip
);
AddInstTable
(InstTable
, "ORI" , 0x600f, DecodeRImmSkip
);
AddInstTable
(InstTable
, "EORI", 0x6007, DecodeRImmSkip
);
AddInstTable
(InstTable
, "AD" , 0x4f14, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "SD" , 0x4714, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "M" , 0x7f0c, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "D" , 0x770c, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "FA" , 0x6f0c, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "FS" , 0x6f04, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "FM" , 0x670c, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "FD" , 0x6704, DecodeDR0RISkip
);
AddInstTable
(InstTable
, "DAA" , 0x5f04, DecodeDAA_DAS
);
AddInstTable
(InstTable
, "DAS" , 0x5704, DecodeDAA_DAS
);
AddInstTable
(InstTable
, "RDR" , 0x2014, DecodeRDR_WTR
);
AddInstTable
(InstTable
, "WTR" , 0x2010, DecodeRDR_WTR
);
AddInstTable
(InstTable
, "BD" , 0x2607, DecodeBD_BALD
);
AddInstTable
(InstTable
, "BALD", 0x2617, DecodeBD_BALD
);
AddInstTable
(InstTable
, "BL" , 0x270f, DecodeBL_BALL
);
AddInstTable
(InstTable
, "BALL", 0x271f, DecodeBL_BALL
);
AddInstTable
(InstTable
, "BR" , 0x2704, DecodeBR_BALR
);
AddInstTable
(InstTable
, "BALR", 0x2714, DecodeBR_BALR
);
AddInstTable
(InstTable
, "TSET", 0x1708, DecodeTSET_TRST
);
AddInstTable
(InstTable
, "TRST", 0x1700, DecodeTSET_TRST
);
AddInstTable
(InstTable
, "NEG" , 0x1f00, DecodeNEG
);
AddInstTable
(InstTable
, "FIX" , 0x1f0f, DecodeFIX
);
AddInstTable
(InstTable
, "FLT" , 0x1f07, DecodeFLT
);
AddInstTable
(InstTable
, "SRBT", 0x3f70, DecodeSRBT
);
AddInstTable
(InstTable
, "DEBP", 0x3ff0, DecodeDEBP
);
AddInstTable
(InstTable
, "BLK" , 0x3f17, DecodeBLK
);
AddInstTable
(InstTable
, "LB" , 0x0f07, DecodeLBS_STBS
);
AddInstTable
(InstTable
, "LS" , 0x0f0f, DecodeLBS_STBS
);
AddInstTable
(InstTable
, "STB" , 0x0f87, DecodeLBS_STBS
);
AddInstTable
(InstTable
, "STS" , 0x0f8f, DecodeLBS_STBS
);
AddInstTable
(InstTable
, "CPYB", 0x0f80, DecodeCPYBS_SETBS
);
AddInstTable
(InstTable
, "CPYS", 0x0f88, DecodeCPYBS_SETBS
);
AddInstTable
(InstTable
, "SETB", 0x0f00, DecodeCPYBS_SETBS
);
AddInstTable
(InstTable
, "SETS", 0x0f08, DecodeCPYBS_SETBS
);
AddInstTable
(InstTable
, "CPYH", 0x3f80, DecodeCPYH_SETH
);
AddInstTable
(InstTable
, "SETH", 0x3f00, DecodeCPYH_SETH
);
/* aliases */
AddInstTable
(InstTable
, "CLR", 0x6000, DecodeCLR
);
AddInstTable
(InstTable
, "CLEAR", 0x6000, DecodeCLR
);
AddInstTable
(InstTable
, "SKIP", 0x7808, DecodeSKIP
);
/* pseudo instructions */
AddInstTable
(InstTable
, "DC" , 0, DecodeDC
);
AddInstTable
(InstTable
, "DS" , 0, DecodeDS
);
}
static void DeinitFields
(void)
{
DestroyInstTable
(InstTable
);
order_array_free
(FixedOrders
);
}
/*--------------------------------------------------------------------------*/
/* Interface to AS */
static Boolean DecodeAttrPart_MN1610_Alt
(void)
{
if (strlen(AttrPart.
str.
p_str) > 1)
{
WrStrErrorPos
(ErrNum_UndefAttr
, &AttrPart
);
return False
;
}
return DecodeMoto16AttrSize
(*AttrPart.
str.
p_str, &AttrPartOpSize
[0], False
);
}
static void MakeCode_MN1610_Alt
(void)
{
OpSize
= (AttrPartOpSize
[0] != eSymbolSizeUnknown
) ? AttrPartOpSize
[0] : eSymbolSize16Bit
;
/* Ignore empty instruction */
if (Memo
("")) return;
/* Pseudo Instructions */
if (!LookupInstTable
(InstTable
, OpPart.
str.
p_str))
WrStrErrorPos
(ErrNum_UnknownInstruction
, &OpPart
);
}
static Boolean IsDef_MN1610_Alt
(void)
{
return FALSE
;
}
static void SwitchFrom_MN1610_Alt
(void)
{
DeinitFields
();
}
static void SwitchTo_MN1610_Alt
(void)
{
const TFamilyDescr
*FoundDescr
;
FoundDescr
= FindFamilyByName
("MN161x");
TurnWords
= True
;
SetIntConstMode
(eIntConstModeIBM
);
PCSymbol
= "*";
HeaderID
= FoundDescr
->Id
;
NOPCode
= 0x7808; /* MV R0,R0 */
DivideChars
= ",";
HasAttrs
= False
;
AttrChars
= ".";
ValidSegs
= (1 << SegCode
) | (1 << SegIO
);
Grans
[SegCode
] = Grans
[SegIO
] = 2;
ListGrans
[SegCode
] = ListGrans
[SegIO
] = 2;
SegInits
[SegCode
] = SegInits
[SegIO
] = 0;
if (MomCPU
== CPUMN1613
)
{
SegLimits
[SegCode
] = 0x3ffff;
SegLimits
[SegIO
] = 0xffff;
pASSUMERecs
= ASSUMEMN1613
;
ASSUMERecCnt
= ASSUMEMN1613Count
;
}
else
{
SegLimits
[SegCode
] = 0xffff;
SegLimits
[SegIO
] = 0xff; /* no RDR/WTR insn */
}
onoff_packing_add
(False
);
DecodeAttrPart
= DecodeAttrPart_MN1610_Alt
;
MakeCode
= MakeCode_MN1610_Alt
;
IsDef
= IsDef_MN1610_Alt
;
SwitchFrom
= SwitchFrom_MN1610_Alt
;
InitFields
();
}
/*--------------------------------------------------------------------------*/
/* Initialisierung */
void codemn2610_init
(void)
{
CPUMN1610
= AddCPU
("MN1610ALT", SwitchTo_MN1610_Alt
);
CPUMN1613
= AddCPU
("MN1613ALT", SwitchTo_MN1610_Alt
);
}