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