/* intpseudo.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS */
/* */
/* Commonly Used Intel-Style Pseudo Instructions */
/* */
/*****************************************************************************/
/*****************************************************************************
* Includes
*****************************************************************************/
#include "stdinc.h"
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include "bpemu.h"
#include "be_le.h"
#include "strutil.h"
#include "nls.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "onoff_common.h"
#include "chartrans.h"
#include "errmsg.h"
#include "ieeefloat.h"
#include "decfloat.h"
#include "intpseudo.h"
#define LEAVE goto func_exit
/*****************************************************************************
* Local Types
*****************************************************************************/
struct sLayoutCtx;
typedef Boolean (*TLayoutFunc)(
#ifdef __PROTOS__
const tStrComp *pArg, struct sLayoutCtx *pCtx
#endif
);
typedef enum
{
DSNone, DSConstant, DSSpace
} tDSFlag;
struct sCurrCodeFill
{
LongInt FullWordCnt;
int LastWordFill;
};
typedef struct sCurrCodeFill tCurrCodeFill;
struct sLayoutCtx
{
tDSFlag DSFlag;
Word flags;
TLayoutFunc LayoutFunc;
int BaseElemLenBits, FullWordSize, ElemsPerFullWord, ListGran;
Boolean (*Put4I)(Byte b, struct sLayoutCtx *pCtx);
Boolean (*Put8I)(Byte b, struct sLayoutCtx *pCtx);
Boolean (*Put16I)(Word w, struct sLayoutCtx *pCtx);
Boolean (*Put16F)(Double f, struct sLayoutCtx *pCtx);
Boolean (*Put32I)(LongWord l, struct sLayoutCtx *pCtx);
Boolean (*Put32F)(Double f, struct sLayoutCtx *pCtx);
Boolean (*Put48I)(LargeWord q, struct sLayoutCtx *pCtx);
Boolean (*Put48F)(Double f, struct sLayoutCtx *pCtx);
Boolean (*Put64I)(LargeWord q, struct sLayoutCtx *pCtx);
Boolean (*Put64F)(Double f, struct sLayoutCtx *pCtx);
Boolean (*Put80F)(Double t, struct sLayoutCtx *pCtx);
Boolean (*Replicate)(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx);
tCurrCodeFill CurrCodeFill, FillIncPerElem;
const tStrComp *pCurrComp;
int LoHiMap;
};
typedef struct sLayoutCtx tLayoutCtx;
/*****************************************************************************
* Global Variables
*****************************************************************************/
static char Z80SyntaxName[] = "Z80SYNTAX";
tZ80Syntax CurrZ80Syntax;
/*****************************************************************************
* Local Functions
*****************************************************************************/
void _DumpCodeFill(const char *pTitle, const tCurrCodeFill *pFill)
{
fprintf(stderr
, "%s %u %d\n", pTitle
, (unsigned)pFill
->FullWordCnt
, pFill
->LastWordFill
);
}
/*!------------------------------------------------------------------------
* \fn Boolean SetDSFlag(struct sLayoutCtx *pCtx, tDSFlag Flag)
* \brief check set data disposition/reservation flag in context
* \param pCtx context
* \param Flag operation to be set
* \return True if operation could be set or was alreday set
* ------------------------------------------------------------------------ */
static Boolean SetDSFlag(struct sLayoutCtx *pCtx, tDSFlag Flag)
{
if ((pCtx->DSFlag != DSNone) && (pCtx->DSFlag != Flag))
{
WrStrErrorPos(ErrNum_MixDBDS, pCtx->pCurrComp);
return False;
}
pCtx->DSFlag = Flag;
return True;
}
/*!------------------------------------------------------------------------
* \fn IncMaxCodeLen(struct sLayoutCtx *pCtx, LongWord NumFullWords)
* \brief assure xAsmCode has space for at moleast n more full words
* \param pCtxcontext
* \param NumFullWords # of additional words intended to write
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean IncMaxCodeLen(struct sLayoutCtx *pCtx, LongWord NumFullWords)
{
if (SetMaxCodeLen((pCtx->CurrCodeFill.FullWordCnt + NumFullWords) * pCtx->FullWordSize))
{
WrStrErrorPos(ErrNum_CodeOverflow, pCtx->pCurrComp);
return False;
}
else
return True;
}
static LargeWord ByteInWord(Byte b, int Pos)
{
return ((LargeWord)b) << (Pos << 3);
}
static Byte NibbleInByte(Byte n, int Pos)
{
return (n & 15) << (Pos << 2);
}
static Word NibbleInWord(Byte n, int Pos)
{
return ((Word)(n & 15)) << (Pos << 2);
}
static Byte ByteFromWord(LargeWord w, int Pos)
{
return (w >> (Pos << 3)) & 0xff;
}
static Byte NibbleFromByte(Byte b, int Pos)
{
return (b >> (Pos << 2)) & 0x0f;
}
static Byte NibbleFromWord(Word w, int Pos)
{
return (w >> (Pos << 2)) & 0x0f;
}
/*!------------------------------------------------------------------------
* \fn SubCodeFill
* \brief perform 'c = a - b' on tCurrCodeFill structures
* \param c result
* \param b, c arguments
* ------------------------------------------------------------------------ */
static void SubCodeFill(tCurrCodeFill *c, const tCurrCodeFill *a, const tCurrCodeFill *b, struct sLayoutCtx *pCtx)
{
c->FullWordCnt = a->FullWordCnt - b->FullWordCnt;
if ((c->LastWordFill = a->LastWordFill - b->LastWordFill) < 0)
{
c->LastWordFill += pCtx->ElemsPerFullWord;
c->FullWordCnt--;
}
}
/*!------------------------------------------------------------------------
* \fn MultCodeFill(tCurrCodeFill *b, LongWord a, struct sLayoutCtx *pCtx)
* \brief perform 'b *= a' on tCurrCodeFill structures
* \param b what to multiply
* \param a scaling factor
* ------------------------------------------------------------------------ */
static void MultCodeFill(tCurrCodeFill *b, LongWord a, struct sLayoutCtx *pCtx)
{
b->FullWordCnt *= a;
b->LastWordFill *= a;
if (pCtx->ElemsPerFullWord > 1)
{
LongWord
div = b
->LastWordFill
/ pCtx
->ElemsPerFullWord
,
mod = b->LastWordFill % pCtx->ElemsPerFullWord;
b->LastWordFill = mod;
}
}
/*!------------------------------------------------------------------------
* \fn IncCodeFill(tCurrCodeFill *a, struct sLayoutCtx *pCtx)
* \brief advance tCurrCodeFill pointer by one base element
* \param a pointer to increment
* \param pCtx context
* ------------------------------------------------------------------------ */
static void IncCodeFill(tCurrCodeFill *a, struct sLayoutCtx *pCtx)
{
if (++a->LastWordFill >= pCtx->ElemsPerFullWord)
{
a->LastWordFill -= pCtx->ElemsPerFullWord;
a->FullWordCnt++;
}
}
/*!------------------------------------------------------------------------
* \fn IncCurrCodeFill(struct sLayoutCtx *pCtx)
* \brief advance CodeFill pointer in context and reserve memory
* \param pCtx context
* \return True if success
* ------------------------------------------------------------------------ */
static Boolean IncCurrCodeFill(struct sLayoutCtx *pCtx)
{
LongInt OldFullWordCnt = pCtx->CurrCodeFill.FullWordCnt;
IncCodeFill(&pCtx->CurrCodeFill, pCtx);
if (OldFullWordCnt == pCtx->CurrCodeFill.FullWordCnt)
return True;
else if (!IncMaxCodeLen(pCtx, 1))
return False;
else
{
WAsmCode[pCtx->CurrCodeFill.FullWordCnt] = 0;
return True;
}
}
/*!------------------------------------------------------------------------
* \fn IncCodeFillBy(tCurrCodeFill *a, const tCurrCodeFill *inc, struct sLayoutCtx *pCtx)
* \brief perform 'a += inc' on tCurrCodeFill structures
* \param a what to advance
* \param inc by what to advance
* \param pCtx context
* ------------------------------------------------------------------------ */
static void IncCodeFillBy(tCurrCodeFill *a, const tCurrCodeFill *inc, struct sLayoutCtx *pCtx)
{
a->LastWordFill += inc->LastWordFill;
if ((pCtx->ElemsPerFullWord > 1) && (a->LastWordFill >= pCtx->ElemsPerFullWord))
{
a->LastWordFill -= pCtx->ElemsPerFullWord;
a->FullWordCnt++;
}
a->FullWordCnt += inc->FullWordCnt;
}
/*****************************************************************************
* Function: LayoutNibble
* Purpose: parse argument, interprete as nibble,
* and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put4I_To_8(Byte b, struct sLayoutCtx *pCtx)
{
tCurrCodeFill Pos = pCtx->CurrCodeFill;
if (!IncCurrCodeFill(pCtx))
return False;
if (!Pos.LastWordFill)
BAsmCode[Pos.FullWordCnt] = NibbleInByte(b, Pos.LastWordFill ^ pCtx->LoHiMap);
else
BAsmCode[Pos.FullWordCnt] |= NibbleInByte(b, Pos.LastWordFill ^ pCtx->LoHiMap);
return True;
}
static Boolean Replicate4_To_8(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
{
Byte b;
tCurrCodeFill CurrPos;
CurrPos = *pStartPos;
while ((CurrPos.FullWordCnt != pEndPos->FullWordCnt) || (CurrPos.LastWordFill != pEndPos->LastWordFill))
{
b = NibbleFromByte(BAsmCode[CurrPos.FullWordCnt], CurrPos.LastWordFill ^ pCtx->LoHiMap);
if (!Put4I_To_8(b, pCtx))
return False;
IncCodeFill(&CurrPos, pCtx);
}
return True;
}
static Boolean Put4I_To_16(Byte b, struct sLayoutCtx *pCtx)
{
tCurrCodeFill Pos = pCtx->CurrCodeFill;
if (!IncCurrCodeFill(pCtx))
return False;
if (!Pos.LastWordFill)
WAsmCode[Pos.FullWordCnt] = NibbleInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
else
WAsmCode[Pos.FullWordCnt] |= NibbleInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
return True;
}
static Boolean Replicate4_To_16(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
{
Byte b;
tCurrCodeFill CurrPos;
CurrPos = *pStartPos;
while ((CurrPos.FullWordCnt != pEndPos->FullWordCnt) || (CurrPos.LastWordFill != pEndPos->LastWordFill))
{
b = NibbleFromWord(WAsmCode[CurrPos.FullWordCnt], CurrPos.LastWordFill ^ pCtx->LoHiMap);
if (!Put4I_To_16(b, pCtx))
return False;
IncCodeFill(&CurrPos, pCtx);
}
return True;
}
static Boolean LayoutNibble(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
Boolean Result = False;
TempResult t;
as_tempres_ini(&t);
EvalStrExpression(pExpr, &t);
switch (t.Typ)
{
case TempInt:
if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xf;
if (!mSymbolQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int4)) WrStrErrorPos(ErrNum_OverRange, pExpr);
else
{
if (!pCtx->Put4I(t.Contents.Int, pCtx))
LEAVE;
Result = True;
}
break;
case TempFloat:
WrStrErrorPos(ErrNum_IntButFloat, pExpr);
break;
case TempString:
WrStrErrorPos(ErrNum_IntButString, pExpr);
break;
default:
break;
}
func_exit:
as_tempres_free(&t);
return Result;
}
/*****************************************************************************
* Function: LayoutByte
* Purpose: parse argument, interprete as byte,
* and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put8I_To_8(Byte b, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 1))
return False;
if ((pCtx->ListGran == 1) || !(pCtx->CurrCodeFill.FullWordCnt & 1))
BAsmCode[pCtx->CurrCodeFill.FullWordCnt] = b;
else if (pCtx->flags & eIntPseudoFlag_Turn)
WAsmCode[pCtx->CurrCodeFill.FullWordCnt >> 1] = (((Word)BAsmCode[pCtx->CurrCodeFill.FullWordCnt - 1]) << 8) | b;
else
WAsmCode[pCtx->CurrCodeFill.FullWordCnt >> 1] = (((Word)b) << 8) | BAsmCode[pCtx->CurrCodeFill.FullWordCnt - 1];
pCtx->CurrCodeFill.FullWordCnt++;
return True;
}
static Boolean Put8I_To_16(Byte b, struct sLayoutCtx *pCtx)
{
tCurrCodeFill Pos = pCtx->CurrCodeFill;
if (!IncCurrCodeFill(pCtx))
return False;
if (!Pos.LastWordFill)
WAsmCode[Pos.FullWordCnt] = ByteInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
else
WAsmCode[Pos.FullWordCnt] |= ByteInWord(b, Pos.LastWordFill ^ pCtx->LoHiMap);
return True;
}
static Boolean Replicate8ToN_To_8(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
{
tCurrCodeFill Pos;
if (!IncMaxCodeLen(pCtx, pEndPos->FullWordCnt - pStartPos->FullWordCnt))
return False;
for (Pos = *pStartPos; Pos.FullWordCnt < pEndPos->FullWordCnt; Pos.FullWordCnt += pCtx->BaseElemLenBits / 8)
{
memcpy(&BAsmCode
[pCtx
->CurrCodeFill.
FullWordCnt], &BAsmCode
[Pos.
FullWordCnt], pCtx
->BaseElemLenBits
/ 8);
pCtx->CurrCodeFill.FullWordCnt += pCtx->BaseElemLenBits / 8;
}
if (Pos.FullWordCnt != pEndPos->FullWordCnt)
{
WrXError(ErrNum_InternalError, "DUP replication inconsistency");
return False;
}
return True;
}
static Boolean Replicate8_To_16(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
{
Byte b;
tCurrCodeFill CurrPos;
CurrPos = *pStartPos;
while ((CurrPos.FullWordCnt != pEndPos->FullWordCnt) || (CurrPos.LastWordFill != pEndPos->LastWordFill))
{
b = ByteFromWord(WAsmCode[CurrPos.FullWordCnt], CurrPos.LastWordFill ^ pCtx->LoHiMap);
if (!Put8I_To_16(b, pCtx))
return False;
IncCodeFill(&CurrPos, pCtx);
}
return True;
}
static Boolean LayoutByte(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
Boolean Result = False;
TempResult t;
as_tempres_ini(&t);
EvalStrExpression(pExpr, &t);
switch (t.Typ)
{
case TempInt:
ToInt:
if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xff;
if (!mSymbolQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int8)) WrStrErrorPos(ErrNum_OverRange, pExpr);
else
{
if (!pCtx->Put8I(t.Contents.Int, pCtx))
LEAVE;
Result = True;
}
break;
case TempFloat:
WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
break;
case TempString:
{
unsigned ch;
const char *p_run;
size_t run_len;
int ret;
if (MultiCharToInt(&t, 1))
goto ToInt;
p_run = t.Contents.str.p_str;
run_len = t.Contents.str.len;
while (!(ret = as_chartrans_xlate_next(CurrTransTable->p_table, &ch, &p_run, &run_len)))
{
if (!pCtx->Put8I(ch, pCtx))
LEAVE;
}
if (ENOENT == ret)
{
WrStrErrorPos(ErrNum_UnmappedChar, pExpr);
LEAVE;
}
Result = True;
break;
}
default:
break;
}
func_exit:
as_tempres_free(&t);
return Result;
}
/*****************************************************************************
* Function: LayoutWord
* Purpose: parse argument, interprete as 16-bit word,
* and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put16I_To_8(Word w, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 2))
return False;
if (pCtx->ListGran == 2)
WAsmCode[pCtx->CurrCodeFill.FullWordCnt >> 1] = w;
else
{
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = Lo(w);
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = Hi(w);
}
pCtx->CurrCodeFill.FullWordCnt += 2;
return True;
}
static Boolean Put16F_To_8(Double t, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 2))
return False;
if (!Double_2_ieee2(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap))
{
WrError(ErrNum_OverRange);
return False;
}
pCtx->CurrCodeFill.FullWordCnt += 2;
return True;
}
static Boolean Put16I_To_16(Word w, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 1))
return False;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt++] = w;
return True;
}
static Boolean Put16F_To_16(Double t, struct sLayoutCtx *pCtx)
{
Byte Tmp[2];
if (!IncMaxCodeLen(pCtx, 1))
return False;
Double_2_ieee2(t, Tmp, !!pCtx->LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ pCtx->LoHiMap) | ByteInWord(Tmp[1], 1 ^ pCtx->LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 1;
return True;
}
static Boolean Replicate16ToN_To_16(const tCurrCodeFill *pStartPos, const tCurrCodeFill *pEndPos, struct sLayoutCtx *pCtx)
{
tCurrCodeFill Pos;
if (!IncMaxCodeLen(pCtx, pEndPos->FullWordCnt - pStartPos->FullWordCnt))
return False;
for (Pos = *pStartPos; Pos.FullWordCnt < pEndPos->FullWordCnt; Pos.FullWordCnt += pCtx->BaseElemLenBits / 16)
{
memcpy(&WAsmCode
[pCtx
->CurrCodeFill.
FullWordCnt], &WAsmCode
[Pos.
FullWordCnt], pCtx
->BaseElemLenBits
/ 8);
pCtx->CurrCodeFill.FullWordCnt += pCtx->BaseElemLenBits / 16;
}
if (Pos.FullWordCnt != pEndPos->FullWordCnt)
{
WrXError(ErrNum_InternalError, "DUP replication inconsistency");
return False;
}
return True;
}
static Boolean LayoutWord(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
Boolean Result = False;
const Boolean allow_string = !!(pCtx->flags & eIntPseudoFlag_AllowString),
allow_float = !!pCtx->Put16F;
TempResult t;
as_tempres_ini(&t);
EvalStrExpression(pExpr, &t);
Result = True;
switch (t.Typ)
{
case TempInt:
ToInt:
if (pCtx->Put16I)
{
if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xffff;
if (!mSymbolQuestionable(t.Flags) && !RangeCheck(t.Contents.Int, Int16)) WrStrErrorPos(ErrNum_OverRange, pExpr);
else
{
if (!pCtx->Put16I(t.Contents.Int, pCtx))
LEAVE;
Result = True;
}
break;
}
else
TempResultToFloat(&t);
/* fall-through */
case TempFloat:
if (!allow_float) WrStrErrorPos(allow_string ? ErrNum_StringOrIntButFloat : ErrNum_IntButFloat, pExpr);
else if (!FloatRangeCheck(t.Contents.Float, Float16)) WrStrErrorPos(ErrNum_OverRange, pExpr);
else
{
if (!pCtx->Put16F(t.Contents.Float, pCtx))
LEAVE;
Result = True;
}
break;
case TempString:
if (!allow_string) WrStrErrorPos(allow_float ? ErrNum_IntOrFloatButString : ErrNum_IntButString, pExpr);
else
{
unsigned z;
if (MultiCharToInt(&t, 2))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &t.Contents.str, pExpr))
LEAVE;
for (z = 0; z < t.Contents.str.len; z++)
if (!pCtx->Put16I(t.Contents.str.p_str[z], pCtx))
LEAVE;
Result = True;
}
break;
case TempReg:
if (allow_float && allow_string)
WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
else if (allow_float)
WrStrErrorPos(ErrNum_IntOrFloatButReg, pExpr);
else if (allow_string)
WrStrErrorPos(ErrNum_IntOrStringButReg, pExpr);
else
WrStrErrorPos(ErrNum_IntButReg, pExpr);
break;
default:
break;
}
func_exit:
as_tempres_free(&t);
return Result;
}
/*****************************************************************************
* Function: LayoutDoubleWord
* Purpose: parse argument, interprete as 32-bit word or
single precision float, and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put32I_To_8(LongWord l, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 4))
return False;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = (l ) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = (l >> 8) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] = (l >> 16) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l >> 24) & 0xff;
pCtx->CurrCodeFill.FullWordCnt += 4;
return True;
}
static Boolean Put32F_To_8(Double t, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 4))
return False;
if (pCtx->flags & eIntPseudoFlag_DECFormat)
{
int ret = Double_2_dec4(t, WAsmCode + (pCtx->CurrCodeFill.FullWordCnt / 2));
if (ret)
{
check_dec_fp_dispose_result(ret, pCtx->pCurrComp);
return False;
}
}
else
Double_2_ieee4(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 4;
return True;
}
static Boolean Put32I_To_16(LongWord l, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 2))
return False;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = LoWord(l);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = HiWord(l);
pCtx->CurrCodeFill.FullWordCnt += 2;
return True;
}
static Boolean Put32F_To_16(Double t, struct sLayoutCtx *pCtx)
{
Byte Tmp[4];
if (!IncMaxCodeLen(pCtx, 2))
return False;
Double_2_ieee4(t, Tmp, !!pCtx->LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ pCtx->LoHiMap) | ByteInWord(Tmp[1], 1 ^ pCtx->LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 1] = ByteInWord(Tmp[2], 0 ^ pCtx->LoHiMap) | ByteInWord(Tmp[3], 1 ^ pCtx->LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 2;
return True;
}
static Boolean LayoutDoubleWord(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
TempResult erg;
Boolean Result = False;
const Boolean allow_string = !!(pCtx->flags & eIntPseudoFlag_AllowString),
allow_float = !!pCtx->Put32F;
Word Cnt = 0;
as_tempres_ini(&erg);
EvalStrExpression(pExpr, &erg);
Result = False;
switch (erg.Typ)
{
case TempNone:
break;
case TempInt:
ToInt:
if (pCtx->Put32I)
{
if (mFirstPassUnknown(erg.Flags)) erg.Contents.Int &= 0xfffffffful;
if (!mSymbolQuestionable(erg.Flags) && !RangeCheck(erg.Contents.Int, Int32)) WrStrErrorPos(ErrNum_OverRange, pExpr);
else
{
if (!pCtx->Put32I(erg.Contents.Int, pCtx))
LEAVE;
Cnt = 4;
Result = True;
}
break;
}
else
TempResultToFloat(&erg);
/* fall-through */
case TempFloat:
if (!allow_float) WrStrErrorPos(allow_string ? ErrNum_StringOrIntButFloat : ErrNum_IntButFloat, pExpr);
else if (!FloatRangeCheck(erg.Contents.Float, Float32)) WrStrErrorPos(ErrNum_OverRange, pExpr);
else
{
if (!pCtx->Put32F(erg.Contents.Float, pCtx))
LEAVE;
Cnt = 4;
Result = True;
}
break;
case TempString:
if (!allow_string) WrStrErrorPos(allow_float ? ErrNum_IntOrFloatButString : ErrNum_IntButString, pExpr);
else
{
unsigned z;
if (MultiCharToInt(&erg, 4))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &erg.Contents.str, pExpr))
WrStrErrorPos(ErrNum_UnmappedChar, pExpr);
for (z = 0; z < erg.Contents.str.len; z++)
if (!pCtx->Put32I(erg.Contents.str.p_str[z], pCtx))
LEAVE;
Cnt = erg.Contents.str.len * 4;
Result = True;
}
break;
case TempReg:
if (allow_float && allow_string)
WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
else if (allow_float)
WrStrErrorPos(ErrNum_IntOrFloatButReg, pExpr);
else if (allow_string)
WrStrErrorPos(ErrNum_IntOrStringButReg, pExpr);
else
WrStrErrorPos(ErrNum_IntButReg, pExpr);
break;
case TempAll:
}
(void)Cnt;
func_exit:
as_tempres_free(&erg);
return Result;
}
/*****************************************************************************
* Function: LayoutMacAddr
* Purpose: parse argument, interprete as 48-bit word or
float, and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put48I_To_8(LargeWord l, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 8))
return False;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap) ] = (l ) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap) ] = (l >> 8) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ (pCtx->LoHiMap & 1))] = (l >> 16) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ (pCtx->LoHiMap & 1))] = (l >> 24) & 0xff;
#ifdef HAS64
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (4 ^ pCtx->LoHiMap) ] = (l >> 32) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (5 ^ pCtx->LoHiMap) ] = (l >> 40) & 0xff;
#else
/* TempResult is TempInt, so sign-extend */
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (4 ^ pCtx->LoHiMap) ] =
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (5 ^ pCtx->LoHiMap) ] = (l & 0x80000000ul) ? 0xff : 0x00;
#endif
pCtx->CurrCodeFill.FullWordCnt += 6;
return True;
}
static Boolean Put48F_To_8(Double t, struct sLayoutCtx *pCtx)
{
/* make space for 8 bytes - last word of D format float is truncated */
if (!IncMaxCodeLen(pCtx, 8))
return False;
if (pCtx->flags & eIntPseudoFlag_DECFormat)
{
/* LoHiMap (endianess) is ignored */
int ret = Double_2_dec8(t, WAsmCode + (pCtx->CurrCodeFill.FullWordCnt / 2));
if (ret)
{
check_dec_fp_dispose_result(ret, pCtx->pCurrComp);
return False;
}
}
else
assert(0); /* no 6 byte IEEE float format */
pCtx->CurrCodeFill.FullWordCnt += 6;
return True;
}
static Boolean Put48I_To_16(LargeWord l, struct sLayoutCtx *pCtx)
{
int LoHiMap = pCtx->LoHiMap ? 2 : 0; /* 5 or 0 -> 2 or 0 */
if (!IncMaxCodeLen(pCtx, 3))
return False;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ LoHiMap) ] = (l ) & 0xffff;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ (LoHiMap & 1))] = (l >> 16) & 0xffff;
#ifdef HAS64
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ LoHiMap) ] = (l >> 32) & 0xffff;
#else
/* TempResult is TempInt, so sign-extend */
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ LoHiMap) ] = (l & 0x80000000ul) ? 0xffff : 0x0000;
#endif
pCtx->CurrCodeFill.FullWordCnt += 3;
return True;
}
static Boolean Put48F_To_16(Double t, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 3))
return False;
if (pCtx->flags & eIntPseudoFlag_DECFormat)
{
Word Tmp[4];
int ret = Double_2_dec8(t, Tmp);
if (ret)
{
check_dec_fp_dispose_result(ret, pCtx->pCurrComp);
return False;
}
/* LoHiMap (endianess) is ignored */
memcpy(&WAsmCode
[pCtx
->CurrCodeFill.
FullWordCnt], Tmp
, 6);
}
else
assert(0); /* no 6 byte IEEE float format */
pCtx->CurrCodeFill.FullWordCnt += 3;
return True;
}
static Boolean LayoutMacAddr(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
Boolean Result = False;
TempResult erg;
Word Cnt = 0;
as_tempres_ini(&erg);
EvalStrExpression(pExpr, &erg);
Result = False;
switch(erg.Typ)
{
case TempNone:
break;
case TempInt:
ToInt:
if (pCtx->Put48I)
{
if (!pCtx->Put64I(erg.Contents.Int, pCtx))
LEAVE;
Cnt = 6;
Result = True;
break;
}
else
TempResultToFloat(&erg);
/* fall-through */
case TempFloat:
if (!pCtx->Put48F) WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
else if (!pCtx->Put48F(erg.Contents.Float, pCtx))
LEAVE;
Cnt = 6;
Result = True;
break;
case TempString:
{
unsigned z;
if (MultiCharToInt(&erg, 6))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &erg.Contents.str, pExpr))
LEAVE;
for (z = 0; z < erg.Contents.str.len; z++)
if (!pCtx->Put48I(erg.Contents.str.p_str[z], pCtx))
LEAVE;
Cnt = erg.Contents.str.len * 6;
Result = True;
break;
}
case TempReg:
WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
break;
case TempAll:
}
(void)Cnt;
func_exit:
as_tempres_free(&erg);
return Result;
}
/*****************************************************************************
* Function: LayoutQuadWord
* Purpose: parse argument, interprete as 64-bit word or
double precision float, and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put64I_To_8(LargeWord l, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 8))
return False;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = (l ) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = (l >> 8) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] = (l >> 16) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l >> 24) & 0xff;
#ifdef HAS64
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (4 ^ pCtx->LoHiMap)] = (l >> 32) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (5 ^ pCtx->LoHiMap)] = (l >> 40) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (6 ^ pCtx->LoHiMap)] = (l >> 48) & 0xff;
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (7 ^ pCtx->LoHiMap)] = (l >> 56) & 0xff;
#else
/* TempResult is TempInt, so sign-extend */
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (4 ^ pCtx->LoHiMap)] =
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (5 ^ pCtx->LoHiMap)] =
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (6 ^ pCtx->LoHiMap)] =
BAsmCode[pCtx->CurrCodeFill.FullWordCnt + (7 ^ pCtx->LoHiMap)] = (l & 0x80000000ul) ? 0xff : 0x00;
#endif
pCtx->CurrCodeFill.FullWordCnt += 8;
return True;
}
static Boolean Put64F_To_8(Double t, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 8))
return False;
if (pCtx->flags & eIntPseudoFlag_DECFormat)
{
int ret = Double_2_dec8(t, WAsmCode + (pCtx->CurrCodeFill.FullWordCnt / 2));
if (ret)
{
check_dec_fp_dispose_result(ret, pCtx->pCurrComp);
return False;
}
}
else
Double_2_ieee8(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 8;
return True;
}
static Boolean Put64I_To_16(LargeWord l, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 4))
return False;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (0 ^ pCtx->LoHiMap)] = (l ) & 0xffff;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (1 ^ pCtx->LoHiMap)] = (l >> 16) & 0xffff;
#ifdef HAS64
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] = (l >> 32) & 0xffff;
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l >> 48) & 0xffff;
#else
/* TempResult is TempInt, so sign-extend */
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (2 ^ pCtx->LoHiMap)] =
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + (3 ^ pCtx->LoHiMap)] = (l & 0x80000000ul) ? 0xffff : 0x0000;
#endif
pCtx->CurrCodeFill.FullWordCnt += 4;
return True;
}
static Boolean Put64F_To_16(Double t, struct sLayoutCtx *pCtx)
{
Byte Tmp[8];
int LoHiMap = pCtx->LoHiMap & 1;
if (!IncMaxCodeLen(pCtx, 4))
return False;
Double_2_ieee8(t, Tmp, !!pCtx->LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ LoHiMap) | ByteInWord(Tmp[1], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 1] = ByteInWord(Tmp[2], 0 ^ LoHiMap) | ByteInWord(Tmp[3], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 2] = ByteInWord(Tmp[4], 0 ^ LoHiMap) | ByteInWord(Tmp[5], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 3] = ByteInWord(Tmp[6], 0 ^ LoHiMap) | ByteInWord(Tmp[7], 1 ^ LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 4;
return True;
}
static Boolean LayoutQuadWord(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
Boolean Result = False;
const Boolean allow_string = !!(pCtx->flags & eIntPseudoFlag_AllowString),
allow_float = !!pCtx->Put64F;
TempResult erg;
Word Cnt = 0;
as_tempres_ini(&erg);
EvalStrExpression(pExpr, &erg);
Result = False;
switch (erg.Typ)
{
case TempNone:
break;
case TempInt:
ToInt:
if (pCtx->Put64I)
{
if (!pCtx->Put64I(erg.Contents.Int, pCtx))
LEAVE;
Cnt = 8;
Result = True;
break;
}
else
TempResultToFloat(&erg);
/* fall-through */
case TempFloat:
if (!allow_float) WrStrErrorPos(ErrNum_StringOrIntButFloat, pExpr);
else if (!pCtx->Put64F(erg.Contents.Float, pCtx))
LEAVE;
Cnt = 8;
Result = True;
break;
case TempString:
if (!allow_string) WrStrErrorPos(allow_float ? ErrNum_IntOrFloatButString : ErrNum_IntButString, pExpr);
else
{
unsigned z;
if (MultiCharToInt(&erg, 8))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &erg.Contents.str, pExpr))
LEAVE;
for (z = 0; z < erg.Contents.str.len; z++)
if (!pCtx->Put64I(erg.Contents.str.p_str[z], pCtx))
LEAVE;
Cnt = erg.Contents.str.len * 8;
Result = True;
}
break;
case TempReg:
WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
break;
case TempAll:
}
(void)Cnt;
func_exit:
as_tempres_free(&erg);
return Result;
}
/*****************************************************************************
* Function: LayoutTenBytes
* Purpose: parse argument, interprete extended precision float,
* and put into result buffer
* Result: TRUE if no errors occured
*****************************************************************************/
static Boolean Put80F_To_8(Double t, struct sLayoutCtx *pCtx)
{
if (!IncMaxCodeLen(pCtx, 10))
return False;
Double_2_ieee10(t, BAsmCode + pCtx->CurrCodeFill.FullWordCnt, !!pCtx->LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 10;
return True;
}
static Boolean Put80F_To_16(Double t, struct sLayoutCtx *pCtx)
{
Byte Tmp[10];
int LoHiMap = pCtx->LoHiMap & 1;
if (!IncMaxCodeLen(pCtx, 5))
return False;
Double_2_ieee10(t, Tmp, !!pCtx->LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 0] = ByteInWord(Tmp[0], 0 ^ LoHiMap) | ByteInWord(Tmp[1], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 1] = ByteInWord(Tmp[2], 0 ^ LoHiMap) | ByteInWord(Tmp[3], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 2] = ByteInWord(Tmp[4], 0 ^ LoHiMap) | ByteInWord(Tmp[5], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 3] = ByteInWord(Tmp[6], 0 ^ LoHiMap) | ByteInWord(Tmp[7], 1 ^ LoHiMap);
WAsmCode[pCtx->CurrCodeFill.FullWordCnt + 4] = ByteInWord(Tmp[8], 0 ^ LoHiMap) | ByteInWord(Tmp[9], 1 ^ LoHiMap);
pCtx->CurrCodeFill.FullWordCnt += 5;
return True;
}
static Boolean LayoutTenBytes(const tStrComp *pExpr, struct sLayoutCtx *pCtx)
{
Boolean Result = False;
TempResult erg;
Word Cnt;
as_tempres_ini(&erg);
EvalStrExpression(pExpr, &erg);
Result = False;
switch(erg.Typ)
{
case TempNone:
break;
case TempInt:
ToInt:
TempResultToFloat(&erg);
/* fall-through */
case TempFloat:
if (!pCtx->Put80F(erg.Contents.Float, pCtx))
LEAVE;
Cnt = 10;
Result = True;
break;
case TempString:
{
unsigned z;
if (MultiCharToInt(&erg, 4))
goto ToInt;
if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &erg.Contents.str, pExpr))
LEAVE;
for (z = 0; z < erg.Contents.str.len; z++)
if (!pCtx->Put80F(erg.Contents.str.p_str[z], pCtx))
LEAVE;
Cnt = erg.Contents.str.len * 10;
Result = True;
break;
}
case TempReg:
WrStrErrorPos(ErrNum_StringOrIntOrFloatButReg, pExpr);
break;
case TempAll:
}
(void)Cnt;
func_exit:
as_tempres_free(&erg);
return Result;
}
/*****************************************************************************
* Global Functions
*****************************************************************************/
/*****************************************************************************
* Function: DecodeIntelPseudo
* Purpose: handle Intel-style pseudo instructions
* Result: TRUE if mnemonic was handled
*****************************************************************************/
static Boolean DecodeIntelPseudo_ValidSymChar(char ch)
{
ch = as_toupper(ch);
return (((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= '0') && (ch <= '9'))
|| (ch == '_')
|| (ch == '.'));
}
static void DecodeIntelPseudo_HandleQuote(int *pDepth, Byte *pQuote, char Ch)
{
switch (Ch)
{
case '(':
if (!(*pQuote))
(*pDepth)++;
break;
case ')':
if (!(*pQuote))
(*pDepth)--;
break;
case '\'':
if (!((*pQuote) & 2))
(*pQuote) ^= 1;
break;
case '"':
if (!((*pQuote) & 1))
(*pQuote) ^= 2;
break;
}
}
static Boolean DecodeIntelPseudo_LayoutMult(const tStrComp *pArg, struct sLayoutCtx *pCtx)
{
int z, Depth, Len, LastNonBlank;
Boolean OK, LastValid, Result;
Byte Quote;
const char *pDupFnd, *pRun;
const tStrComp *pSaveComp;
pSaveComp = pCtx->pCurrComp;
pCtx->pCurrComp = pArg;
/* search for DUP:
- Exclude parts in parentheses, and parts in quotation marks.
- Assure there is some (non-blank) token before DUP, so if there
is e.g. a plain DUP as argument, it will not be interpreted as
DUP operator. */
Depth = Quote = 0;
LastValid = FALSE;
LastNonBlank = -1;
pDupFnd
= NULL
; Len
= strlen(pArg
->str.
p_str);
for (pRun = pArg->str.p_str; pRun < pArg->str.p_str + Len - 2; pRun++)
{
DecodeIntelPseudo_HandleQuote(&Depth, &Quote, *pRun);
if (!Depth && !Quote)
{
if (!LastValid
&& (LastNonBlank >= 0)
&& !DecodeIntelPseudo_ValidSymChar(pRun[3])
&& !as_strncasecmp(pRun, "DUP", 3))
{
pDupFnd = pRun;
break;
}
if (!as_isspace(*pRun))
LastNonBlank = pRun - pArg->str.p_str;
}
LastValid = DecodeIntelPseudo_ValidSymChar(*pRun);
}
/* found DUP: */
if (pDupFnd)
{
LongInt DupCnt;
char *pSep, *pRun;
String CopyStr;
tStrComp Copy, DupArg, RemArg, ThisRemArg;
tCurrCodeFill DUPStartFill, DUPEndFill;
tSymbolFlags Flags;
/* operate on copy */
StrCompMkTemp(&Copy, CopyStr, sizeof(CopyStr));
StrCompCopy(&Copy, pArg);
pSep = Copy.str.p_str + (pDupFnd - pArg->str.p_str);
/* evaluate count */
StrCompSplitRef(&DupArg, &RemArg, &Copy, pSep);
DupCnt = EvalStrIntExpressionWithFlags(&DupArg, Int32, &OK, &Flags);
if (mFirstPassUnknown(Flags))
{
WrStrErrorPos(ErrNum_FirstPassCalc, &DupArg); return False;
}
if (!OK)
{
Result = False;
goto func_exit;
}
/* catch invalid counts */
if (DupCnt <= 0)
{
if (DupCnt < 0)
WrStrErrorPos(ErrNum_NegDUP, &DupArg);
Result = True;
goto func_exit;
}
/* split into parts and evaluate */
StrCompIncRefLeft(&RemArg, 2);
KillPrefBlanksStrCompRef(&RemArg);
Len
= strlen(RemArg.
str.
p_str);
if ((Len >= 2) && (*RemArg.str.p_str == '(') && (RemArg.str.p_str[Len - 1] == ')'))
{
StrCompIncRefLeft(&RemArg, 1);
StrCompShorten(&RemArg, 1);
Len -= 2;
}
DUPStartFill = pCtx->CurrCodeFill;
do
{
pSep = NULL; Quote = Depth = 0;
for (pRun = RemArg.str.p_str; *pRun; pRun++)
{
DecodeIntelPseudo_HandleQuote(&Depth, &Quote, *pRun);
if ((!Depth) && (!Quote) && (*pRun == ','))
{
pSep = pRun;
break;
}
}
if (pSep)
StrCompSplitRef(&RemArg, &ThisRemArg, &RemArg, pSep);
KillPrefBlanksStrCompRef(&RemArg);
KillPostBlanksStrComp(&RemArg);
if (!DecodeIntelPseudo_LayoutMult(&RemArg, pCtx))
{
Result = False;
goto func_exit;
}
if (pSep)
RemArg = ThisRemArg;
}
while (pSep);
DUPEndFill = pCtx->CurrCodeFill;
/* replicate result (data or reserve) */
switch (pCtx->DSFlag)
{
case DSConstant:
for (z = 1; z <= DupCnt - 1; z++)
if (!pCtx->Replicate(&DUPStartFill, &DUPEndFill, pCtx))
{
Result = False;
goto func_exit;
}
break;
case DSSpace:
{
tCurrCodeFill Diff;
SubCodeFill(&Diff, &DUPEndFill, &DUPStartFill, pCtx);
MultCodeFill(&Diff, DupCnt - 1, pCtx);
IncCodeFillBy(&pCtx->CurrCodeFill, &Diff, pCtx);
break;
}
default:
Result = False;
goto func_exit;
}
Result = True;
}
/* no DUP: simple expression. Differentiate space reservation & data disposition */
else if (!strcmp(pArg
->str.
p_str, "?"))
{
Result = SetDSFlag(pCtx, DSSpace);
if (Result)
IncCodeFillBy(&pCtx->CurrCodeFill, &pCtx->FillIncPerElem, pCtx);
}
else
Result = SetDSFlag(pCtx, DSConstant) && pCtx->LayoutFunc(pArg, pCtx);
func_exit:
pCtx->pCurrComp = pSaveComp;
return Result;
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDx(tLayoutCtx *pLayoutCtx)
* \brief Intel-style constant disposition
* \param pLayoutCtx layout infos & context
* ------------------------------------------------------------------------ */
static void DecodeIntelDx(tLayoutCtx *pLayoutCtx)
{
tStrComp *pArg;
Boolean OK;
pLayoutCtx->DSFlag = DSNone;
pLayoutCtx->FullWordSize = Grans[ActPC];
if ((pLayoutCtx->FullWordSize == 1) && !(pLayoutCtx->flags & eIntPseudoFlag_DECFormat))
pLayoutCtx->ListGran = 1;
else
pLayoutCtx->ListGran = ActListGran;
pLayoutCtx->ElemsPerFullWord = (8 * pLayoutCtx->FullWordSize) / pLayoutCtx->BaseElemLenBits;
if (pLayoutCtx->ElemsPerFullWord > 1)
{
pLayoutCtx->FillIncPerElem.FullWordCnt = 0;
pLayoutCtx->FillIncPerElem.LastWordFill = 1;
}
else
{
pLayoutCtx->FillIncPerElem.FullWordCnt = pLayoutCtx->BaseElemLenBits / (8 * pLayoutCtx->FullWordSize);
pLayoutCtx->FillIncPerElem.LastWordFill = 0;
}
OK = True;
forallargs(pArg, OK)
{
if (!*pArg->str.p_str)
{
OK = FALSE;
WrStrErrorPos(ErrNum_EmptyArgument, pArg);
}
else
OK = DecodeIntelPseudo_LayoutMult(pArg, pLayoutCtx);
}
/* Finalize: add optional padding if fractions of full words
remain unused & set code length */
if (OK)
{
if (pLayoutCtx->CurrCodeFill.LastWordFill)
{
WrError(ErrNum_PaddingAdded);
pLayoutCtx->CurrCodeFill.LastWordFill = 0;
pLayoutCtx->CurrCodeFill.FullWordCnt++;
}
CodeLen = pLayoutCtx->CurrCodeFill.FullWordCnt;
}
DontPrint = (pLayoutCtx->DSFlag == DSSpace);
if (DontPrint)
{
BookKeeping();
if (!CodeLen && OK) WrError(ErrNum_NullResMem);
}
if (OK)
ActListGran = pLayoutCtx->ListGran;
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDN(Word Flags)
* \brief Intel-style constant disposition - nibbles
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDN(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutNibble;
LayoutCtx.BaseElemLenBits = 4;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put4I = Put4I_To_8;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
LayoutCtx.Replicate = Replicate4_To_8;
break;
case 2:
LayoutCtx.Put4I = Put4I_To_16;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 3 : 0;
LayoutCtx.Replicate = Replicate4_To_16;
break;
}
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDB(Word BigEndian)
* \brief Intel-style constant disposition - bytes
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDB(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutByte;
LayoutCtx.BaseElemLenBits = 8;
LayoutCtx.flags = Flags;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put8I = Put8I_To_8;
LayoutCtx.Replicate = Replicate8ToN_To_8;
break;
case 2:
LayoutCtx.Put8I = Put8I_To_16;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
LayoutCtx.Replicate = Replicate8_To_16;
break;
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize8Bit);
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDW(Word Flags)
* \brief Intel-style constant disposition - words
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDW(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutWord;
LayoutCtx.BaseElemLenBits = 16;
LayoutCtx.flags = Flags;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put16I = (Flags & eIntPseudoFlag_AllowInt) ? Put16I_To_8 : NULL;
LayoutCtx.Put16F = (Flags & eIntPseudoFlag_AllowFloat) ? Put16F_To_8 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
LayoutCtx.Replicate = Replicate8ToN_To_8;
break;
case 2:
LayoutCtx.Put16I = (Flags & eIntPseudoFlag_AllowInt) ? Put16I_To_16 : NULL;
LayoutCtx.Put16F = (Flags & eIntPseudoFlag_AllowFloat) ? Put16F_To_16 : NULL;
LayoutCtx.Replicate = Replicate16ToN_To_16;
break;
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize16Bit);
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDD(Word Flags)
* \brief Intel-style constant disposition - 32-bit words
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDD(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutDoubleWord;
LayoutCtx.BaseElemLenBits = 32;
LayoutCtx.flags = Flags;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put32I = (Flags & eIntPseudoFlag_AllowInt) ? Put32I_To_8 : NULL;
LayoutCtx.Put32F = (Flags & eIntPseudoFlag_AllowFloat) ? Put32F_To_8 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 3 : 0;
LayoutCtx.Replicate = Replicate8ToN_To_8;
break;
case 2:
LayoutCtx.Put32I = (Flags & eIntPseudoFlag_AllowInt) ? Put32I_To_16 : NULL;
LayoutCtx.Put32F = (Flags & eIntPseudoFlag_AllowFloat) ? Put32F_To_16 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
LayoutCtx.Replicate = Replicate16ToN_To_16;
break;
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize32Bit);
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDM(Word Flags)
* \brief Intel-style constant disposition - 48-bit words
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDM(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutMacAddr;
LayoutCtx.BaseElemLenBits = 48;
LayoutCtx.flags = Flags;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put48I = (Flags & eIntPseudoFlag_AllowInt) ? Put48I_To_8 : NULL;
LayoutCtx.Put48F = (Flags & eIntPseudoFlag_AllowFloat) ? Put48F_To_8 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 5 : 0;
LayoutCtx.Replicate = Replicate8ToN_To_8;
break;
case 2:
LayoutCtx.Put48I = (Flags & eIntPseudoFlag_AllowInt) ? Put48I_To_16 : NULL;
LayoutCtx.Put48F = (Flags & eIntPseudoFlag_AllowFloat) ? Put48F_To_16 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 2 : 0;
LayoutCtx.Replicate = Replicate16ToN_To_16;
break;
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize48Bit);
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDQ(Word Flags)
* \brief Intel-style constant disposition - 64-bit words
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDQ(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutQuadWord;
LayoutCtx.BaseElemLenBits = 64;
LayoutCtx.flags = Flags;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put64I = (Flags & eIntPseudoFlag_AllowInt) ? Put64I_To_8 : NULL;
LayoutCtx.Put64F = (Flags & eIntPseudoFlag_AllowFloat) ? Put64F_To_8 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 7 : 0;
LayoutCtx.Replicate = Replicate8ToN_To_8;
break;
case 2:
LayoutCtx.Put64I = (Flags & eIntPseudoFlag_AllowInt) ? Put64I_To_16 : NULL;
LayoutCtx.Put64F = (Flags & eIntPseudoFlag_AllowFloat) ? Put64F_To_16 : NULL;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 3 : 0;
LayoutCtx.Replicate = Replicate16ToN_To_16;
break;
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize64Bit);
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDT(Word Flags)
* \brief Intel-style constant disposition - 80-bit words
* \param Flags Data Type & Endianess Flags
* ------------------------------------------------------------------------ */
void DecodeIntelDT(Word Flags)
{
tLayoutCtx LayoutCtx;
memset(&LayoutCtx
, 0, sizeof(LayoutCtx
));
LayoutCtx.LayoutFunc = LayoutTenBytes;
LayoutCtx.BaseElemLenBits = 80;
LayoutCtx.flags = Flags;
switch (Grans[ActPC])
{
case 1:
LayoutCtx.Put80F = Put80F_To_8;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
LayoutCtx.Replicate = Replicate8ToN_To_8;
break;
case 2:
LayoutCtx.Put80F = Put80F_To_16;
LayoutCtx.LoHiMap = (Flags & eIntPseudoFlag_BigEndian) ? 1 : 0;
LayoutCtx.Replicate = Replicate16ToN_To_16;
break;
}
if (*LabPart.str.p_str)
SetSymbolOrStructElemSize(&LabPart, eSymbolSize80Bit);
DecodeIntelDx(&LayoutCtx);
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelDS(Word item_size)
* \brief Intel-style memory reservation
* \param item_size # of bytes per reserved item
* ------------------------------------------------------------------------ */
void DecodeIntelDS(Word item_size)
{
if (ChkArgCnt(1, 1))
{
tSymbolFlags Flags;
Boolean OK;
LongInt HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
else if (OK)
{
DontPrint = True;
CodeLen = HVal * (LongInt)item_size;
if (!HVal)
WrError(ErrNum_NullResMem);
BookKeeping();
}
}
}
/*!------------------------------------------------------------------------
* \fn DecodeIntelPseudo(Boolean BigEndian)
* \brief decode Intel-style pseudo instructions
* \param BigEndian target endianess
* \return True if instruction found
* ------------------------------------------------------------------------ */
Boolean DecodeIntelPseudo(Boolean BigEndian)
{
static PInstTable InstTables[2] = { NULL, NULL };
int Idx = !!BigEndian;
if (!InstTables[Idx])
{
PInstTable InstTable = CreateInstTable(17);
Word Flag = BigEndian ? eIntPseudoFlag_BigEndian : eIntPseudoFlag_None;
AddInstTable(InstTable, "DN", Flag | eIntPseudoFlag_AllowInt, DecodeIntelDN);
AddInstTable(InstTable, "DB", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString, DecodeIntelDB);
AddInstTable(InstTable, "DW", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString | eIntPseudoFlag_AllowFloat, DecodeIntelDW);
AddInstTable(InstTable, "DD", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString | eIntPseudoFlag_AllowFloat, DecodeIntelDD);
AddInstTable(InstTable, "DQ", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString | eIntPseudoFlag_AllowFloat, DecodeIntelDQ);
AddInstTable(InstTable, "DT", Flag | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString | eIntPseudoFlag_AllowFloat, DecodeIntelDT);
AddInstTable(InstTable, "DS", 1, DecodeIntelDS);
InstTables[Idx] = InstTable;
}
return LookupInstTable(InstTables[Idx], OpPart.str.p_str);
}
/*!------------------------------------------------------------------------
* \fn DecodeZ80SYNTAX(Word Code)
* \brief change Z80 syntax support for target
* ------------------------------------------------------------------------ */
static void DecodeZ80SYNTAX(Word Code)
{
UNUSED(Code);
if (ChkArgCnt(1, 1))
{
tStrComp TmpComp;
StrCompMkTemp(&TmpComp, Z80SyntaxName, 0);
NLS_UpString(ArgStr[1].str.p_str);
if (!as_strcasecmp(ArgStr[1].str.p_str, "OFF"))
{
CurrZ80Syntax = eSyntax808x;
EnterIntSymbol(&TmpComp, 0, SegNone, True);
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "ON"))
{
CurrZ80Syntax = eSyntaxBoth;
EnterIntSymbol(&TmpComp, 1, SegNone, True);
}
else if (!as_strcasecmp(ArgStr[1].str.p_str, "EXCLUSIVE"))
{
CurrZ80Syntax = eSyntaxZ80;
EnterIntSymbol(&TmpComp, 2, SegNone, True);
}
else
WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
}
}
/*!------------------------------------------------------------------------
* \fn ChkZ80Syntax(tZ80Syntax InstrSyntax)
* \brief check whether instruction's syntax (808x/Z80) fits to selected one
* \param InstrSyntax instruction syntax
* \return True if all fine
* ------------------------------------------------------------------------ */
Boolean ChkZ80Syntax(tZ80Syntax InstrSyntax)
{
if ((InstrSyntax == eSyntax808x) && (!(CurrZ80Syntax & eSyntax808x)))
{
WrStrErrorPos(ErrNum_Z80SyntaxExclusive, &OpPart);
return False;
}
else if ((InstrSyntax == eSyntaxZ80) && (!(CurrZ80Syntax & eSyntaxZ80)))
{
WrStrErrorPos(ErrNum_Z80SyntaxNotEnabled, &OpPart);
return False;
}
else
return True;
}
/*!------------------------------------------------------------------------
* \fn AddZ80Syntax(struct sInstTable *InstTable)
* \brief add Z80SYNTAX instruction to list & possibly set default
* \param InstTable table to add to
* ------------------------------------------------------------------------ */
void AddZ80Syntax(struct sInstTable *InstTable)
{
if (!onoff_test_and_set(e_onoff_reg_z80syntax))
{
tStrComp TmpComp;
CurrZ80Syntax = eSyntax808x;
StrCompMkTemp(&TmpComp, Z80SyntaxName, 0);
EnterIntSymbol(&TmpComp, 0, SegNone, True);
}
AddInstTable(InstTable, "Z80SYNTAX", 0, DecodeZ80SYNTAX);
}