Top secrets sources NedoPC pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

/* 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->FullWordCnt += div;
    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:
      assert(0);
  }
  (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:
      assert(0);
  }
  (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:
      assert(0);
  }
  (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:
      assert(0);
  }
  (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);
}