/* motpseudo.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS */
/* */
/* Commonly Used Motorola-Style Pseudo Instructions */
/* */
/*****************************************************************************/
/*****************************************************************************
* Includes
*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "bpemu.h"
#include "be_le.h"
#include "ieeefloat.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "chartrans.h"
#include "asmcode.h"
#include "errmsg.h"
#include "aplfloat.h"
#include "motpseudo.h"
#define LEAVE goto func_exit
/*****************************************************************************
* Local Functions
*****************************************************************************/
static Boolean CutRep(tStrComp *pDest, const tStrComp *pSrc, LongInt *pErg, tSymbolFlags *pFlags)
{
tStrComp Src;
if (pFlags)
*pFlags = eSymbolFlag_None;
StrCompRefRight(&Src, pSrc, 0);
KillPrefBlanksStrCompRef(&Src);
if (*Src.str.p_str != '[')
{
*pErg = 1;
*pDest = *pSrc;
return True;
}
else
{
tStrComp RepArg;
char *pEnd;
Boolean OK;
pEnd = QuotPos(Src.str.p_str + 1, ']');
if (!pEnd)
{
WrError(ErrNum_BrackErr);
return False;
}
else
{
StrCompSplitRef(&RepArg, pDest, &Src, pEnd);
StrCompIncRefLeft(&RepArg, 1);
*pErg = EvalStrIntExpressionWithFlags(&RepArg, Int32, &OK, pFlags);
return OK;
}
}
}
static void PutByte(Byte Value, Boolean big_endian)
{
if ((ListGran() == 1) || (!(CodeLen & 1)))
BAsmCode[CodeLen] = Value;
else if (big_endian)
WAsmCode[CodeLen >> 1] = (((Word)BAsmCode[CodeLen -1]) << 8) | Value;
else
WAsmCode[CodeLen >> 1] = (((Word)Value) << 8) | BAsmCode[CodeLen -1];
CodeLen++;
}
void DecodeMotoBYT(Word big_endian)
{
if (ChkArgCnt(1, ArgCntMax))
{
ShortInt SpaceFlag = -1;
tStrComp *pArg, Arg;
LongInt Rep;
Boolean OK = True;
forallargs (pArg, OK)
{
if (!*pArg->str.p_str)
{
OK = FALSE;
WrError(ErrNum_EmptyArgument);
break;
}
OK = CutRep(&Arg, pArg, &Rep, NULL);
if (!OK)
break;
if (!strcmp(Arg.
str.
p_str, "?"))
{
if (SpaceFlag == 0)
{
WrError(ErrNum_MixDBDS);
OK = FALSE;
}
else
{
SpaceFlag = 1;
CodeLen += Rep;
}
}
else if (SpaceFlag == 1)
{
WrError(ErrNum_MixDBDS);
OK = FALSE;
}
else
{
TempResult t;
SpaceFlag = 0;
as_tempres_ini(&t);
EvalStrExpression(&Arg, &t);
switch (t.Typ)
{
case TempInt:
ToInt:
if (!mFirstPassUnknownOrQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int8))
{
WrStrErrorPos(ErrNum_OverRange, &Arg);
OK = False;
}
else if (SetMaxCodeLen(CodeLen + Rep))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
{
LongInt z2;
for (z2 = 0; z2 < Rep; z2++)
PutByte(t.Contents.Int, big_endian);
}
break;
case TempFloat:
WrStrErrorPos(ErrNum_StringOrIntButFloat, &Arg);
OK = False;
break;
case TempString:
{
int l;
if (MultiCharToInt(&t, 1))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &t.Contents.str, &Arg))
OK = False;
else
{
l = t.Contents.str.len;
if (SetMaxCodeLen(CodeLen + (Rep * l)))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
{
LongInt z2;
int z3;
for (z2 = 0; z2 < Rep; z2++)
for (z3 = 0; z3 < l; z3++)
PutByte(t.Contents.str.p_str[z3], big_endian);
}
}
break;
}
default:
OK = False;
break;
}
as_tempres_free(&t);
}
}
if (!OK)
CodeLen = 0;
else
{
if (SpaceFlag == 1)
DontPrint = True;
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize8Bit);
}
}
}
static void PutADR(Word Value, Boolean big_endian)
{
if (ListGran() > 1)
{
WAsmCode[CodeLen >> 1] = Value;
CodeLen += 2;
}
else if (big_endian)
{
BAsmCode[CodeLen++] = Hi(Value);
BAsmCode[CodeLen++] = Lo(Value);
}
else
{
BAsmCode[CodeLen++] = Lo(Value);
BAsmCode[CodeLen++] = Hi(Value);
}
}
void DecodeMotoADR(Word big_endian)
{
if (ChkArgCnt(1, ArgCntMax))
{
tStrComp *pArg, Arg;
Boolean OK = True;
LongInt Rep;
ShortInt SpaceFlag = -1;
forallargs (pArg, OK)
{
if (!*pArg->str.p_str)
{
OK = FALSE;
WrError(ErrNum_EmptyArgument);
break;
}
OK = CutRep(&Arg, pArg, &Rep, NULL);
if (!OK)
break;
if (!strcmp(Arg.
str.
p_str, "?"))
{
if (SpaceFlag == 0)
{
WrError(ErrNum_MixDBDS);
OK = False;
}
else
{
SpaceFlag = 1;
CodeLen += 2 * Rep;
}
}
else if (SpaceFlag == 1)
{
WrError(ErrNum_MixDBDS);
OK = False;
}
else
{
TempResult Res;
LongInt z2, Cnt;
SpaceFlag = 0;
as_tempres_ini(&Res);
EvalStrExpression(&Arg, &Res);
switch (Res.Typ)
{
case TempInt:
ToInt:
if (mFirstPassUnknown(Res.Flags))
Res.Contents.Int &= 0xffff;
if (!mSymbolQuestionable(Res.Flags) && !RangeCheck(Res.Contents.Int, Int16))
{
WrError(ErrNum_OverRange);
Res.Typ = TempNone;
}
Cnt = 1;
break;
case TempString:
if (MultiCharToInt(&Res, 2))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &Res.Contents.str, &Arg))
Res.Typ = TempNone;
else
Cnt = Res.Contents.str.len;
break;
case TempFloat:
WrStrErrorPos(ErrNum_StringOrIntButFloat, &Arg);
/* fall-through */
default:
Res.Typ = TempNone;
Cnt = 0;
break;
}
if (TempNone == Res.Typ)
{
OK = False;
break;
}
if (SetMaxCodeLen(CodeLen + ((Cnt * Rep) << 1)))
{
WrError(ErrNum_CodeOverflow);
OK = False;
break;
}
for (z2 = 0; z2 < Rep; z2++)
switch (Res.Typ)
{
case TempInt:
PutADR(Res.Contents.Int, big_endian);
break;
case TempString:
{
unsigned z3;
for (z3 = 0; z3 < Res.Contents.str.len; z3++)
PutADR(Res.Contents.str.p_str[z3], big_endian);
break;
}
default:
break;
}
as_tempres_free(&Res);
}
}
if (!OK)
CodeLen = 0;
else
{
if (SpaceFlag)
DontPrint = True;
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize16Bit);
}
}
}
void DecodeMotoDCM(Word big_endian)
{
if (ChkArgCnt(1, ArgCntMax))
{
tStrComp *pArg, Arg;
Boolean OK = True;
LongInt Rep;
ShortInt SpaceFlag = -1;
forallargs (pArg, OK)
{
if (!*pArg->str.p_str)
{
OK = FALSE;
WrError(ErrNum_EmptyArgument);
break;
}
OK = CutRep(&Arg, pArg, &Rep, NULL);
if (!OK)
break;
if (!strcmp(Arg.
str.
p_str, "?"))
{
if (SpaceFlag == 0)
{
WrError(ErrNum_MixDBDS);
OK = False;
}
else
{
SpaceFlag = 1;
CodeLen += 4 * Rep;
}
}
else if (SpaceFlag == 1)
{
WrError(ErrNum_MixDBDS);
OK = False;
}
else
{
TempResult Res;
LongInt z2;
int ret;
Word buf[2];
SpaceFlag = 0;
as_tempres_ini(&Res);
EvalStrExpression(&Arg, &Res);
switch (Res.Typ)
{
case TempInt:
TempResultToFloat(&Res);
break;
case TempFloat:
break;
case TempString:
WrStrErrorPos(ErrNum_FloatButString, &Arg);
/* fall-through */
default:
Res.Typ = TempNone;
break;
}
if (TempNone == Res.Typ)
{
OK = False;
break;
}
if (SetMaxCodeLen(CodeLen + (Rep << 2)))
{
WrError(ErrNum_CodeOverflow);
OK = False;
break;
}
ret = Double_2_apl4(Res.Contents.Float, buf);
if (!check_apl_fp_dispose_result(ret, &Arg))
{
OK = False;
break;
}
for (z2 = 0; z2 < Rep; z2++)
{
PutADR(buf[0], big_endian);
PutADR(buf[1], big_endian);
}
as_tempres_free(&Res);
}
}
if (!OK)
CodeLen = 0;
else
{
if (SpaceFlag)
DontPrint = True;
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize16Bit);
}
}
}
static void DecodeFCC(Word big_endian)
{
if (ChkArgCnt(1, ArgCntMax))
{
Boolean OK = True;
tStrComp *pArg, Arg;
TempResult t;
as_tempres_ini(&t);
forallargs (pArg, OK)
{
LongInt Rep;
if (!*pArg->str.p_str)
{
OK = FALSE;
WrError(ErrNum_EmptyArgument);
break;
}
OK = CutRep(&Arg, pArg, &Rep, NULL);
if (!OK)
break;
EvalStrExpression(&Arg, &t);
switch (t.Typ)
{
case TempString:
{
int l;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &t.Contents.str, &Arg))
OK = False;
else
{
l = t.Contents.str.len;
if (SetMaxCodeLen(CodeLen + Rep * l))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
{
LongInt z2;
int z3;
for (z2 = 0; z2 < Rep; z2++)
for (z3 = 0; z3 < l; z3++)
PutByte(t.Contents.str.p_str[z3], big_endian);
}
}
break;
}
case TempNone:
OK = False;
break;
default:
WrStrErrorPos(ErrNum_ExpectString, &Arg);
OK = False;
}
}
as_tempres_free(&t);
if (!OK)
CodeLen = 0;
else if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize8Bit);
}
}
void DecodeMotoDFS(Word Index)
{
UNUSED(Index);
if (ChkArgCnt(1, 1))
{
Word HVal16;
Boolean OK;
tSymbolFlags Flags;
HVal16 = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags);
if (mFirstPassUnknown(Flags))
WrError(ErrNum_FirstPassCalc);
else if (OK)
{
DontPrint = True;
CodeLen = HVal16;
if (!HVal16)
WrError(ErrNum_NullResMem);
BookKeeping();
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize8Bit);
}
}
}
/*****************************************************************************
* Global Functions
*****************************************************************************/
static PInstTable inst_table_moto8 = NULL;
void init_moto8_pseudo(PInstTable p_inst_table, unsigned flags)
{
if (!p_inst_table)
p_inst_table = inst_table_moto8 = CreateInstTable(23);
AddInstTable(p_inst_table, "BYT", !!(flags & e_moto_8_be), DecodeMotoBYT);
AddInstTable(p_inst_table, "FCB", !!(flags & e_moto_8_be), DecodeMotoBYT);
if (flags & e_moto_8_db)
AddInstTable(p_inst_table, "DB", !!(flags & e_moto_8_be), DecodeMotoBYT);
AddInstTable(p_inst_table, "ADR", !!(flags & e_moto_8_be), DecodeMotoADR);
AddInstTable(p_inst_table, "FDB", !!(flags & e_moto_8_be), DecodeMotoADR);
if (flags & e_moto_8_dw)
AddInstTable(p_inst_table, "DW", !!(flags & e_moto_8_be), DecodeMotoADR);
if (flags & e_moto_8_ddb)
AddInstTable(p_inst_table, "DDB", True, DecodeMotoADR);
if (flags & e_moto_8_dcm)
AddInstTable(p_inst_table, "DCM", True, DecodeMotoDCM);
AddInstTable(p_inst_table, "FCC", !!(flags & e_moto_8_be), DecodeFCC);
AddInstTable(p_inst_table, "DFS", 0, DecodeMotoDFS);
AddInstTable(p_inst_table, "RMB", 0, DecodeMotoDFS);
if (flags & e_moto_8_ds)
AddInstTable(p_inst_table, "DS", 0, DecodeMotoDFS);
}
Boolean decode_moto8_pseudo(void)
{
return LookupInstTable(inst_table_moto8, OpPart.str.p_str);
}
void deinit_moto8_pseudo(void)
{
DestroyInstTable(inst_table_moto8);
inst_table_moto8 = NULL;
}
static void DigIns(char Ch, int Pos, Byte *pDest)
{
int bytepos = Pos >> 1, bitpos = (Pos & 1) << 2;
Byte dig = Ch - '0';
pDest[bytepos] |= (dig << bitpos);
}
void ConvertMotoFloatDec(Double F, Byte *pDest, Boolean NeedsBig)
{
char s[30], Man[30], Exp[30];
char *pSplit;
int z, ManLen, ExpLen;
Byte epos;
UNUSED(NeedsBig);
/* convert to ASCII, split mantissa & exponent */
as_snprintf(s, sizeof(s), "%0.16e", F);
pSplit
= strchr(s
, HexStartCharacter
+ ('e' - 'a'));
if (!pSplit)
{
}
else
{
*pSplit = '\0';
}
/* handle mantissa sign */
if (*Man == '-')
{
pDest[11] |= 0x80; strmov(Man, Man + 1);
}
else if (*Man == '+')
strmov(Man, Man + 1);
/* handle exponent sign */
if (*Exp == '-')
{
pDest[11] |= 0x40;
strmov(Exp, Exp + 1);
}
else if (*Exp == '+')
strmov(Exp, Exp + 1);
/* integral part of mantissa (one digit) */
DigIns(*Man, 16, pDest);
strmov(Man, Man + 2);
/* truncate mantissa if we have more digits than we can represent */
Man[16] = '\0';
/* insert mantissa digits */
for (z = 0; z < ManLen; z++)
DigIns(Man[z], 15 - z, pDest);
/* truncate exponent if we have more digits than we can represent - this should
never occur since an IEEE double is limited to ~1E308 and we have for digits */
strmov
(Exp
, Exp
+ strlen(Exp
) - 4);
/* insert exponent bits */
for (z = ExpLen - 1; z >= 0; z--)
{
epos = ExpLen - 1 - z;
if (epos == 3)
DigIns(Exp[z], 19, pDest);
else
DigIns(Exp[z], epos + 20, pDest);
}
if (HostBigEndian)
WSwap(pDest, 12);
}
static void EnterByte(LargeWord b, Boolean BigEndian)
{
UNUSED(BigEndian);
if (((CodeLen & 1) == 1) && (!HostBigEndian) && (ListGran() != 1))
{
BAsmCode[CodeLen ] = BAsmCode[CodeLen - 1];
BAsmCode[CodeLen - 1] = b;
}
else
{
BAsmCode[CodeLen] = b;
}
CodeLen++;
}
static void EnterWord(LargeWord w, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = Hi(w);
BAsmCode[CodeLen + 1] = Lo(w);
}
else
{
BAsmCode[CodeLen ] = Lo(w);
BAsmCode[CodeLen + 1] = Hi(w);
}
}
else
WAsmCode[CodeLen >> 1] = w;
CodeLen += 2;
}
static void EnterPointer(LargeWord w, Boolean BigEndian)
{
if (BigEndian)
{
EnterByte((w >> 16) & 0xff, BigEndian);
EnterByte((w >> 8) & 0xff, BigEndian);
EnterByte((w ) & 0xff, BigEndian);
}
else
{
EnterByte((w ) & 0xff, BigEndian);
EnterByte((w >> 8) & 0xff, BigEndian);
EnterByte((w >> 16) & 0xff, BigEndian);
}
}
static void EnterLWord(LargeWord l, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = (l >> 24) & 0xff;
BAsmCode[CodeLen + 1] = (l >> 16) & 0xff;
BAsmCode[CodeLen + 2] = (l >> 8) & 0xff;
BAsmCode[CodeLen + 3] = (l ) & 0xff;
}
else
{
BAsmCode[CodeLen ] = (l ) & 0xff;
BAsmCode[CodeLen + 1] = (l >> 8) & 0xff;
BAsmCode[CodeLen + 2] = (l >> 16) & 0xff;
BAsmCode[CodeLen + 3] = (l >> 24) & 0xff;
}
}
else
{
WAsmCode[(CodeLen >> 1) ] = (l >> 16) & 0xffff;
WAsmCode[(CodeLen >> 1) + 1] = (l ) & 0xffff;
}
CodeLen += 4;
}
static void EnterQWord(LargeWord q, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
#ifdef HAS64
BAsmCode[CodeLen ] = (q >> 56) & 0xff;
BAsmCode[CodeLen + 1] = (q >> 48) & 0xff;
BAsmCode[CodeLen + 2] = (q >> 40) & 0xff;
BAsmCode[CodeLen + 3] = (q >> 32) & 0xff;
#else
/* TempResult is LargeInt, so sign-extend */
BAsmCode[CodeLen ] =
BAsmCode[CodeLen + 1] =
BAsmCode[CodeLen + 2] =
BAsmCode[CodeLen + 3] = (q & 0x80000000ul) ? 0xff : 0x00;
#endif
BAsmCode[CodeLen + 4] = (q >> 24) & 0xff;
BAsmCode[CodeLen + 5] = (q >> 16) & 0xff;
BAsmCode[CodeLen + 6] = (q >> 8) & 0xff;
BAsmCode[CodeLen + 7] = (q ) & 0xff;
}
else
{
BAsmCode[CodeLen ] = (q ) & 0xff;
BAsmCode[CodeLen + 1] = (q >> 8) & 0xff;
BAsmCode[CodeLen + 2] = (q >> 16) & 0xff;
BAsmCode[CodeLen + 3] = (q >> 24) & 0xff;
#ifdef HAS64
BAsmCode[CodeLen + 4] = (q >> 32) & 0xff;
BAsmCode[CodeLen + 5] = (q >> 40) & 0xff;
BAsmCode[CodeLen + 6] = (q >> 48) & 0xff;
BAsmCode[CodeLen + 7] = (q >> 56) & 0xff;
#else
/* TempResult is LargeInt, so sign-extend */
BAsmCode[CodeLen + 4] =
BAsmCode[CodeLen + 5] =
BAsmCode[CodeLen + 6] =
BAsmCode[CodeLen + 7] = (q & 0x80000000ul) ? 0xff : 0x00;
#endif
}
}
else
{
#ifdef HAS64
WAsmCode[(CodeLen >> 1) ] = (q >> 48) & 0xffff;
WAsmCode[(CodeLen >> 1) + 1] = (q >> 32) & 0xffff;
#else
/* TempResult is LargeInt, so sign-extend */
WAsmCode[(CodeLen >> 1) ] =
WAsmCode[(CodeLen >> 1) + 1] = (q & 0x80000000ul) ? 0xffff : 0x00;
#endif
WAsmCode[(CodeLen >> 1) + 2] = (q >> 16) & 0xffff;
WAsmCode[(CodeLen >> 1) + 3] = (q ) & 0xffff;
}
CodeLen += 8;
}
static void EnterIEEE2(Word *pField, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = Hi(pField[0]);
BAsmCode[CodeLen + 1] = Lo(pField[0]);
}
else
{
BAsmCode[CodeLen ] = Lo(pField[0]);
BAsmCode[CodeLen + 1] = Hi(pField[0]);
}
}
else
{
WAsmCode[(CodeLen >> 1) ] = pField[0];
}
CodeLen += 2;
}
static void EnterIEEE4(Word *pField, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = Hi(pField[1]);
BAsmCode[CodeLen + 1] = Lo(pField[1]);
BAsmCode[CodeLen + 2] = Hi(pField[0]);
BAsmCode[CodeLen + 3] = Lo(pField[0]);
}
else
{
BAsmCode[CodeLen ] = Lo(pField[0]);
BAsmCode[CodeLen + 1] = Hi(pField[0]);
BAsmCode[CodeLen + 2] = Lo(pField[1]);
BAsmCode[CodeLen + 3] = Hi(pField[1]);
}
}
else
{
WAsmCode[(CodeLen >> 1) ] = pField[1];
WAsmCode[(CodeLen >> 1) + 1] = pField[0];
}
CodeLen += 4;
}
static void EnterIEEE8(Word *pField, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = Hi(pField[3]);
BAsmCode[CodeLen + 1] = Lo(pField[3]);
BAsmCode[CodeLen + 2] = Hi(pField[2]);
BAsmCode[CodeLen + 3] = Lo(pField[2]);
BAsmCode[CodeLen + 4] = Hi(pField[1]);
BAsmCode[CodeLen + 5] = Lo(pField[1]);
BAsmCode[CodeLen + 6] = Hi(pField[0]);
BAsmCode[CodeLen + 7] = Lo(pField[0]);
}
else
{
BAsmCode[CodeLen ] = Lo(pField[0]);
BAsmCode[CodeLen + 1] = Hi(pField[0]);
BAsmCode[CodeLen + 2] = Lo(pField[1]);
BAsmCode[CodeLen + 3] = Hi(pField[1]);
BAsmCode[CodeLen + 4] = Lo(pField[2]);
BAsmCode[CodeLen + 5] = Hi(pField[2]);
BAsmCode[CodeLen + 6] = Lo(pField[3]);
BAsmCode[CodeLen + 7] = Hi(pField[3]);
}
}
else
{
WAsmCode[(CodeLen >> 1) ] = pField[3];
WAsmCode[(CodeLen >> 1) + 1] = pField[2];
WAsmCode[(CodeLen >> 1) + 2] = pField[1];
WAsmCode[(CodeLen >> 1) + 3] = pField[0];
}
CodeLen += 8;
}
static void EnterIEEE10(Word *pField, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = Hi(pField[4]);
BAsmCode[CodeLen + 1] = Lo(pField[4]);
BAsmCode[CodeLen + 2] = 0;
BAsmCode[CodeLen + 3] = 0;
BAsmCode[CodeLen + 4] = Hi(pField[3]);
BAsmCode[CodeLen + 5] = Lo(pField[3]);
BAsmCode[CodeLen + 6] = Hi(pField[2]);
BAsmCode[CodeLen + 7] = Lo(pField[2]);
BAsmCode[CodeLen + 8] = Hi(pField[1]);
BAsmCode[CodeLen + 9] = Lo(pField[1]);
BAsmCode[CodeLen +10] = Hi(pField[0]);
BAsmCode[CodeLen +11] = Lo(pField[0]);
}
else
{
BAsmCode[CodeLen ] = Lo(pField[0]);
BAsmCode[CodeLen + 1] = Hi(pField[0]);
BAsmCode[CodeLen + 2] = Lo(pField[1]);
BAsmCode[CodeLen + 3] = Hi(pField[1]);
BAsmCode[CodeLen + 4] = Lo(pField[2]);
BAsmCode[CodeLen + 5] = Hi(pField[2]);
BAsmCode[CodeLen + 6] = Lo(pField[3]);
BAsmCode[CodeLen + 7] = Hi(pField[3]);
BAsmCode[CodeLen + 8] = 0;
BAsmCode[CodeLen + 9] = 0;
BAsmCode[CodeLen +10] = Lo(pField[4]);
BAsmCode[CodeLen +11] = Hi(pField[4]);
}
}
else
{
WAsmCode[(CodeLen >> 1) ] = pField[4];
WAsmCode[(CodeLen >> 1) + 1] = 0;
WAsmCode[(CodeLen >> 1) + 2] = pField[3];
WAsmCode[(CodeLen >> 1) + 3] = pField[2];
WAsmCode[(CodeLen >> 1) + 4] = pField[1];
WAsmCode[(CodeLen >> 1) + 5] = pField[0];
}
CodeLen += 12;
}
static void EnterMotoFloatDec(Word *pField, Boolean BigEndian)
{
if (ListGran() == 1)
{
if (BigEndian)
{
BAsmCode[CodeLen ] = Hi(pField[5]);
BAsmCode[CodeLen + 1] = Lo(pField[5]);
BAsmCode[CodeLen + 2] = Hi(pField[4]);
BAsmCode[CodeLen + 3] = Lo(pField[4]);
BAsmCode[CodeLen + 4] = Hi(pField[3]);
BAsmCode[CodeLen + 5] = Lo(pField[3]);
BAsmCode[CodeLen + 6] = Hi(pField[2]);
BAsmCode[CodeLen + 7] = Lo(pField[2]);
BAsmCode[CodeLen + 8] = Hi(pField[1]);
BAsmCode[CodeLen + 9] = Lo(pField[1]);
BAsmCode[CodeLen +10] = Hi(pField[0]);
BAsmCode[CodeLen +11] = Lo(pField[0]);
}
else
{
BAsmCode[CodeLen ] = Lo(pField[0]);
BAsmCode[CodeLen + 1] = Hi(pField[0]);
BAsmCode[CodeLen + 2] = Lo(pField[1]);
BAsmCode[CodeLen + 3] = Hi(pField[1]);
BAsmCode[CodeLen + 4] = Lo(pField[2]);
BAsmCode[CodeLen + 5] = Hi(pField[2]);
BAsmCode[CodeLen + 6] = Lo(pField[3]);
BAsmCode[CodeLen + 7] = Hi(pField[3]);
BAsmCode[CodeLen + 8] = Lo(pField[4]);
BAsmCode[CodeLen + 9] = Hi(pField[4]);
BAsmCode[CodeLen +10] = Lo(pField[5]);
BAsmCode[CodeLen +11] = Hi(pField[5]);
}
}
else
{
WAsmCode[(CodeLen >> 1) ] = pField[5];
WAsmCode[(CodeLen >> 1) + 1] = pField[4];
WAsmCode[(CodeLen >> 1) + 2] = pField[3];
WAsmCode[(CodeLen >> 1) + 3] = pField[2];
WAsmCode[(CodeLen >> 1) + 4] = pField[1];
WAsmCode[(CodeLen >> 1) + 5] = pField[0];
}
CodeLen += 12;
}
static void Double_2_ieee2_wrap(Double Inp, Byte *pDest, Boolean BigEndian)
{
(void)Double_2_ieee2(Inp, pDest, BigEndian);
}
void AddMoto16PseudoONOFF(Boolean default_padding_value)
{
SetFlag(&DoPadding, DoPaddingName, default_padding_value);
AddONOFF(DoPaddingName, &DoPadding, DoPaddingName, False);
}
/*!------------------------------------------------------------------------
* \fn GetWSize(tSymbolSize OpSize)
* \brief return size in bytes of data type
* \param OpSize data type
* \return size in bytes
* ------------------------------------------------------------------------ */
static Word GetWSize(tSymbolSize OpSize)
{
switch (OpSize)
{
case eSymbolSize8Bit:
return 1;
case eSymbolSize16Bit:
return 2;
case eSymbolSize24Bit:
return 3;
case eSymbolSize32Bit:
return 4;
case eSymbolSize64Bit:
return 8;
case eSymbolSizeFloat32Bit:
return 4;
case eSymbolSizeFloat64Bit:
return 8;
/* NOTE: Double_2_ieee10() creates 10 bytes, but WSize is set to 12 (two
padding bytes in binary representation). This means that WSwap() will
swap 12 instead of 10 bytes, which doesn't hurt, since TurnField is
large enough and the two (garbage) bytes at the end will not be used
by EnterIEEE10() anyway: */
case eSymbolSizeFloat96Bit:
return 12;
case eSymbolSizeFloatDec96Bit:
return 12;
case eSymbolSizeFloat16Bit:
return 2;
default:
return 0;
}
}
/*!------------------------------------------------------------------------
* \fn DecodeMotoDC(void)
* \brief decode DC.x instruction
* ------------------------------------------------------------------------ */
void DecodeMotoDC(tSymbolSize OpSize, Boolean BigEndian)
{
ShortInt SpaceFlag;
tStrComp *pArg, Arg;
LongInt z2, WSize, Rep = 0;
char *zp;
Boolean OK;
TempResult t;
tSymbolFlags Flags;
void (*EnterInt)(LargeWord, Boolean) = NULL;
void (*ConvertFloat)(Double, Byte*, Boolean) = NULL;
void (*EnterFloat)(Word*, Boolean) = NULL;
void (*Swap)(void*, int) = NULL;
IntType IntTypeEnum = UInt1;
FloatType FloatTypeEnum = Float32;
Boolean PadBeforeStart = Odd(EProgCounter()) && DoPadding && (OpSize != eSymbolSize8Bit);
as_tempres_ini(&t);
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, OpSize);
if (!ChkArgCnt(1, ArgCntMax))
LEAVE;
if (OpSize < 0)
OpSize = eSymbolSize16Bit;
WSize = GetWSize(OpSize);
switch (OpSize)
{
case eSymbolSize8Bit:
EnterInt = EnterByte;
IntTypeEnum = Int8;
break;
case eSymbolSize16Bit:
EnterInt = EnterWord;
IntTypeEnum = Int16;
break;
case eSymbolSize24Bit:
EnterInt = EnterPointer;
IntTypeEnum = Int24;
break;
case eSymbolSize32Bit:
EnterInt = EnterLWord;
IntTypeEnum = Int32;
break;
case eSymbolSize64Bit:
EnterInt = EnterQWord;
#ifdef HAS64
IntTypeEnum = Int64;
#else
IntTypeEnum = Int32;
#endif
break;
case eSymbolSizeFloat16Bit:
ConvertFloat = Double_2_ieee2_wrap;
EnterFloat = EnterIEEE2;
FloatTypeEnum = Float16;
Swap = NULL;
break;
case eSymbolSizeFloat32Bit:
ConvertFloat = Double_2_ieee4;
EnterFloat = EnterIEEE4;
FloatTypeEnum = Float32;
Swap = DWSwap;
break;
case eSymbolSizeFloat64Bit:
ConvertFloat = Double_2_ieee8;
EnterFloat = EnterIEEE8;
FloatTypeEnum = Float64;
Swap = QWSwap;
break;
/* NOTE: Double_2_ieee10() creates 10 bytes, but WSize is set to 12 (two
padding bytes in binary representation). This means that WSwap() will
swap 12 instead of 10 bytes, which doesn't hurt, since TurnField is
large enough and the two (garbage) bytes at the end will not be used
by EnterIEEE10() anyway: */
case eSymbolSizeFloat96Bit:
ConvertFloat = Double_2_ieee10;
EnterFloat = EnterIEEE10;
FloatTypeEnum = Float80;
Swap = TWSwap;
break;
case eSymbolSizeFloatDec96Bit:
ConvertFloat = ConvertMotoFloatDec;
EnterFloat = EnterMotoFloatDec;
FloatTypeEnum = FloatDec;
break;
default:
break;
}
OK = True;
SpaceFlag = -1;
forallargs (pArg, OK)
{
if (!*pArg->str.p_str)
{
OK = FALSE;
WrError(ErrNum_EmptyArgument);
break;
}
OK = CutRep(&Arg, pArg, &Rep, &Flags);
if (!OK)
break;
if (mFirstPassUnknown(Flags))
{
OK = FALSE;
WrError(ErrNum_FirstPassCalc);
break;
}
if (!strcmp(Arg.
str.
p_str, "?"))
{
if (SpaceFlag == 0)
{
WrError(ErrNum_MixDBDS);
OK = FALSE;
}
else
{
if (PadBeforeStart)
{
InsertPadding(1, True);
PadBeforeStart = False;
}
SpaceFlag = 1;
CodeLen += (Rep * WSize);
}
}
else if (SpaceFlag == 1)
{
WrError(ErrNum_MixDBDS);
OK = FALSE;
}
else
{
SpaceFlag = 0;
if (PadBeforeStart)
{
InsertPadding(1, False);
PadBeforeStart = False;
}
EvalStrExpression(&Arg, &t);
switch (t.Typ)
{
case TempInt:
ToInt:
if (!EnterInt)
{
if (ConvertFloat && EnterFloat)
{
TempResultToFloat(&t);
goto HandleFloat;
}
else
{
WrStrErrorPos(ErrNum_StringOrIntButFloat, pArg);
OK = False;
}
}
else if (!mFirstPassUnknownOrQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, IntTypeEnum))
{
WrError(ErrNum_OverRange);
OK = False;
}
else if (SetMaxCodeLen(CodeLen + (Rep * WSize)))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
for (z2 = 0; z2 < Rep; z2++)
EnterInt(t.Contents.Int, BigEndian);
break;
HandleFloat:
case TempFloat:
if (!ConvertFloat || !EnterFloat)
{
WrStrErrorPos(ErrNum_StringOrIntButFloat, pArg);
OK = False;
}
else if (!FloatRangeCheck(t.Contents.Float, FloatTypeEnum))
{
WrError(ErrNum_OverRange);
OK = False;
}
else if (SetMaxCodeLen(CodeLen + (Rep * WSize)))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
{
Word TurnField[8];
ConvertFloat(t.Contents.Float, (Byte *) TurnField, HostBigEndian);
if (HostBigEndian && Swap)
Swap((void*) TurnField, WSize);
for (z2 = 0; z2 < Rep; z2++)
EnterFloat(TurnField, BigEndian);
}
break;
case TempString:
if (MultiCharToInt(&t, (WSize < 8) ? WSize : 8))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &t.Contents.str, &Arg)) { }
else if (!EnterInt)
{
if (ConvertFloat && EnterFloat)
{
if (SetMaxCodeLen(CodeLen + (Rep * WSize * t.Contents.str.len)))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
{
for (z2 = 0; z2 < Rep; z2++)
for (zp = t.Contents.str.p_str; zp < t.Contents.str.p_str + t.Contents.str.len; zp++)
{
Word TurnField[8];
ConvertFloat((usint) (*zp & 0xff), (Byte *) TurnField, HostBigEndian);
if (HostBigEndian && Swap)
Swap((void*) TurnField, WSize);
EnterFloat(TurnField, BigEndian);
}
}
}
else
{
WrError(ErrNum_FloatButString);
OK = False;
}
}
else if (SetMaxCodeLen(CodeLen + Rep * t.Contents.str.len))
{
WrError(ErrNum_CodeOverflow);
OK = False;
}
else
for (z2 = 0; z2 < Rep; z2++)
for (zp = t.Contents.str.p_str; zp < t.Contents.str.p_str + t.Contents.str.len; EnterInt(((usint) *(zp++)) & 0xff, BigEndian));
break;
case TempNone:
OK = False;
break;
default:
}
}
}
/* purge results if an error occured */
if (!OK) CodeLen = 0;
/* just space reservation ? */
else if (SpaceFlag == 1)
DontPrint = True;
func_exit:
as_tempres_free(&t);
}
Boolean DecodeMoto16Pseudo(tSymbolSize OpSize, Boolean BigEndian)
{
LongInt HVal;
Boolean ValOK;
tSymbolFlags Flags;
Boolean PadBeforeStart;
if (OpSize < 0)
OpSize = eSymbolSize16Bit;
PadBeforeStart = Odd(EProgCounter()) && DoPadding && (OpSize != eSymbolSize8Bit);
if (*OpPart.str.p_str != 'D')
return False;
if (Memo("DC"))
{
DecodeMotoDC(OpSize, BigEndian);
return True;
}
if (Memo("DS"))
{
Word WSize = GetWSize(OpSize);
if (ChkArgCnt(1, 1))
{
HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags);
if (mFirstPassUnknown(Flags))
WrError(ErrNum_FirstPassCalc);
if (ValOK && !mFirstPassUnknown(Flags))
{
Boolean OddSize = (eSymbolSize8Bit == OpSize) || (eSymbolSize24Bit == OpSize);
if (PadBeforeStart)
{
InsertPadding(1, True);
PadBeforeStart = False;
}
DontPrint = True;
/* value of 0 means aligning the PC. Doesn't make sense for bytes and 24 bit values */
if ((HVal == 0) && !OddSize)
{
LongWord NewPC = EProgCounter() + WSize - 1;
NewPC -= NewPC % WSize;
CodeLen = NewPC - EProgCounter();
if (CodeLen == 0)
{
DontPrint = False;
if (WSize == 1)
WrError(ErrNum_NullResMem);
}
}
else
CodeLen = HVal * WSize;
if (DontPrint)
BookKeeping();
}
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, OpSize);
return True;
}
return False;
}
static Boolean DecodeMoto16AttrSizeCore(char SizeSpec, tSymbolSize *pResult, Boolean Allow24)
{
switch (as_toupper(SizeSpec))
{
case 'B': *pResult = eSymbolSize8Bit; break;
case 'W': *pResult = eSymbolSize16Bit; break;
case 'L': *pResult = eSymbolSize32Bit; break;
case 'Q': *pResult = eSymbolSize64Bit; break;
case 'S': *pResult = eSymbolSizeFloat32Bit; break;
case 'D': *pResult = eSymbolSizeFloat64Bit; break;
case 'X': *pResult = eSymbolSizeFloat96Bit; break;
case 'C': *pResult = eSymbolSizeFloat16Bit; break;
case 'P': *pResult = Allow24 ? eSymbolSize24Bit : eSymbolSizeFloatDec96Bit; break;
case '\0': break;
default:
return False;
}
return True;
}
/*!------------------------------------------------------------------------
* \fn DecodeMoto16AttrSize(char SizeSpec, tSymbolSize *pResult, Boolean Allow24)
* \brief decode Motorola-style operand size character
* \param SizeSpec size specifier character
* \param pResult returns result size
* \param Allow24 allow 'p' as specifier for 24 Bits (S12Z-specific)
* \return True if decoded
* ------------------------------------------------------------------------ */
Boolean DecodeMoto16AttrSize(char SizeSpec, tSymbolSize *pResult, Boolean Allow24)
{
if (!DecodeMoto16AttrSizeCore(SizeSpec, pResult, Allow24))
{
WrError(ErrNum_UndefAttr);
return False;
}
return True;
}
Boolean DecodeMoto16AttrSizeStr(const struct sStrComp *pSizeSpec, tSymbolSize *pResult, Boolean Allow24)
{
if ((strlen(pSizeSpec
->str.
p_str) > 1)
|| !DecodeMoto16AttrSizeCore(*pSizeSpec->str.p_str, pResult, Allow24))
{
WrStrErrorPos(ErrNum_UndefAttr, pSizeSpec);
return False;
}
return True;
}