/* code6816.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
/*                                                                           */
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegeneratormodul CPU16                                                  */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"

#include <string.h>
#include <ctype.h>

#include "nls.h"
#include "nlmessages.h"
#include "as.rsc"
#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "errmsg.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "motpseudo.h"
#include "intpseudo.h"
#include "codevars.h"
#include "assume.h"
#include "headids.h"

#include "code6816.h"

/*---------------------------------------------------------------------------*/

typedef struct
{
  tSymbolSize Size;
  Word Code, ExtCode;
  Byte AdrMask, ExtShift;
} GenOrder;

typedef struct
{
  Word Code1, Code2;
} EmuOrder;

enum
{
  ModNone = -1,
  ModDisp8 = 0,
  ModDisp16 = 1,
  ModDispE = 2,
  ModAbs = 3,
  ModImm = 4,
  ModImmExt = 5,
  ModDisp20 = ModDisp16,
  ModAbs20 = ModAbs
};

#define MModDisp8 (1 << ModDisp8)
#define MModDisp16 (1 << ModDisp16)
#define MModDispE (1 << ModDispE)
#define MModAbs (1 << ModAbs)
#define MModImm (1 << ModImm)
#define MModImmExt (1 << ModImmExt)
#define MModDisp20 MModDisp16
#define MModAbs20 MModAbs

static ShortInt AdrMode;
static Byte AdrPart;
static Byte AdrVals[4];

static LongInt Reg_EK;

static GenOrder *GenOrders;
static EmuOrder *EmuOrders;

static CPUVar CPU6816;

static const char Regs[][4] =
{
  "D",
  "E",
  "X",
  "Y",
  "Z",
  "K",
  "CCR"
};

/*-------------------------------------------------------------------------*/

typedef enum
{
  ShortDisp,
  LongDisp,
  NoDisp
} DispType;

static unsigned SplitSize(char *Asc, DispType *pErg)
{
  if (strlen(Asc) < 1)
  {
    *pErg = NoDisp;
    return 0;
  }
  else if (*Asc == '>')
  {
    *pErg = LongDisp;
    return 1;
  }
  else if (*Asc == '<')
  {
    *pErg = ShortDisp;
    return 1;
  }
  else
  {
    *pErg = NoDisp;
    return 0;
  }
}

static void DecodeAdr(int Start, int Stop, tSymbolSize op_size, Boolean LongAdr, Byte Mask)
{
  Integer V16;
  LongInt V32;
  Boolean OK;
  unsigned Offset;
  DispType Size;

  AdrMode = ModNone;
  AdrCnt = 0;

  Stop -= Start - 1;
  if (Stop < 1)
  {
    char Str[100];

    as_snprintf(Str, sizeof(Str), getmessage(Num_ErrMsgAddrArgCnt), 1, 2, Stop - Start + 1);
    WrXError(ErrNum_WrongArgCnt, Str);
    return;
  }

  /* immediate ? */

  if (*ArgStr[Start].str.p_str == '#')
  {
    Offset = SplitSize(ArgStr[Start].str.p_str + 1, &Size);
    switch (op_size)
    {
      case eSymbolSizeUnknown:
        WrError(ErrNum_UndefOpSizes);
        break;
      case eSymbolSize8Bit:
        AdrVals[0] = EvalStrIntExpressionOffs(&ArgStr[Start], 1 + Offset, Int8, &OK);
        if (OK)
        {
          AdrCnt = 1;
          AdrMode = ModImm;
        }
        break;
      case eSymbolSize16Bit:
        V16 = EvalStrIntExpressionOffs(&ArgStr[Start], 1 + Offset, (Size == ShortDisp) ? SInt8 : Int16, &OK);
        if ((Size == NoDisp) && (V16 >= -128) && (V16 <= 127) && ((Mask & MModImmExt) != 0))
          Size = ShortDisp;
        if (OK)
        {
          if (Size == ShortDisp)
          {
            AdrVals[0] = Lo(V16);
            AdrCnt = 1;
            AdrMode = ModImmExt;
          }
          else
          {
            AdrVals[0] = Hi(V16);
            AdrVals[1] = Lo(V16);
            AdrCnt = 2;
            AdrMode = ModImm;
          }
        }
        break;
      case eSymbolSize32Bit:
        V32 = EvalStrIntExpressionOffs(&ArgStr[Start], 1 + Offset, Int32, &OK);
        if (OK)
        {
          AdrVals[0] = (V32 >> 24) & 0xff;
          AdrVals[1] = (V32 >> 16) & 0xff;
          AdrVals[2] = (V32 >>  8) & 0xff;
          AdrVals[3] = V32 & 0xff;
          AdrCnt = 4;
          AdrMode = ModImm;
        }
        break;
      default:
        break;
    }
    goto chk;
  }

  /* zusammengesetzt ? */

  if (Stop == 2)
  {
    AdrPart = 0xff;
    if (!as_strcasecmp(ArgStr[Start + 1].str.p_str, "X"))
      AdrPart = 0x00;
    else if (!as_strcasecmp(ArgStr[Start + 1].str.p_str, "Y"))
      AdrPart = 0x10;
    else if (!as_strcasecmp(ArgStr[Start + 1].str.p_str, "Z"))
      AdrPart = 0x20;
    else
      WrStrErrorPos(ErrNum_InvReg, &ArgStr[Start + 1]);
    if (AdrPart != 0xff)
    {
      if (!as_strcasecmp(ArgStr[Start].str.p_str, "E"))
        AdrMode = ModDispE;
      else
      {
        Offset = SplitSize(ArgStr[Start].str.p_str, &Size);
        if (Size == ShortDisp)
          V32 = EvalStrIntExpressionOffs(&ArgStr[Start], Offset, UInt8, &OK);
        else if (LongAdr)
          V32 = EvalStrIntExpressionOffs(&ArgStr[Start], Offset, SInt20, &OK);
        else
          V32 = EvalStrIntExpressionOffs(&ArgStr[Start], Offset, SInt16, &OK);
        if (OK)
        {
          if (Size == NoDisp)
          {
            if ((V32 >= 0) && (V32 <= 255) && ((Mask & MModDisp8) != 0))
              Size = ShortDisp;
          }
          if (Size == ShortDisp)
          {
            AdrVals[0] = V32 & 0xff;
            AdrCnt = 1;
            AdrMode = ModDisp8;
          }
          else if (LongAdr)
          {
            AdrVals[0] = (V32 >> 16) & 0x0f;
            AdrVals[1] = (V32 >> 8) & 0xff;
            AdrVals[2] = V32 & 0xff;
            AdrCnt = 3;
            AdrMode = ModDisp16;
          }
          else
          {
            AdrVals[0] = (V32 >> 8) & 0xff;
            AdrVals[1] = V32 & 0xff;
            AdrCnt = 2;
            AdrMode = ModDisp16;
          }
        }
      }
    }
    goto chk;
  }

   /* absolut ? */

  else
  {
    Offset = SplitSize(ArgStr[Start].str.p_str, &Size);
    V32 = EvalStrIntExpressionOffs(&ArgStr[Start], Offset, UInt20, &OK);
    if (OK)
    {
      if (LongAdr)
      {
        AdrVals[0] = (V32 >> 16) & 0xff;
        AdrVals[1] = (V32 >> 8) & 0xff;
        AdrVals[2] = V32 & 0xff;
        AdrMode = ModAbs;
        AdrCnt = 3;
      }
      else
      {
        if ((V32 >> 16) != Reg_EK) WrError(ErrNum_InAccPage);
        AdrVals[0] = (V32 >> 8) & 0xff;
        AdrVals[1] = V32 & 0xff;
        AdrMode = ModAbs;
        AdrCnt = 2;
      }
    }
    goto chk;
  }

chk:
  if ((AdrMode != ModNone) && (!(Mask & (1 << AdrMode))))
  {
    WrError(ErrNum_InvAddrMode);
    AdrMode = ModNone;
     AdrCnt = 0;
  }
}

/*-------------------------------------------------------------------------*/

static void DecodeFixed(Word Code)
{
  if (moto8_chk_no_args())
  {
    BAsmCode[0] = Hi(Code);
    BAsmCode[1] = Lo(Code);
    CodeLen = 2;
  }
}

static void DecodeEmu(Word Index)
{
  EmuOrder *pOrder = EmuOrders + Index;

  if (moto8_chk_no_args())
  {
    BAsmCode[0] = Hi(pOrder->Code1);
    BAsmCode[1] = Lo(pOrder->Code1);
    BAsmCode[2] = Hi(pOrder->Code2);
    BAsmCode[3] = Lo(pOrder->Code2);
    CodeLen = 4;
  }
}

static void DecodeRel(Word Code)
{
  Boolean OK;
  tSymbolFlags Flags;
  LongInt AdrLong;

  if (ChkArgCnt(1, 1))
  {
    AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt24, &OK, &Flags) - EProgCounter() - 6;
    if (AdrLong & 1) WrError(ErrNum_NotAligned);
    else if (Code & 0x8000)
    {
      if (!mSymbolQuestionable(Flags) && ((AdrLong > 0x7fffl) || (AdrLong < -0x8000l))) WrError(ErrNum_JmpDistTooBig);
      else
      {
        BAsmCode[0] = 0x37;
        BAsmCode[1] = Lo(Code) + 0x80;
        BAsmCode[2] = (AdrLong >> 8) & 0xff;
        BAsmCode[3] = AdrLong & 0xff;
        CodeLen = 4;
      }
    }
    else
    {
      if (!mSymbolQuestionable(Flags) && ((AdrLong > 0x7fl) || (AdrLong < -0x80l))) WrError(ErrNum_JmpDistTooBig);
      else
      {
        BAsmCode[0] = 0xb0 + Lo(Code);
        BAsmCode[1] = AdrLong & 0xff;
        CodeLen = 2;
      }
    }
  }
}

static void DecodeLRel(Word Code)
{
  Boolean OK;
  tSymbolFlags Flags;
  LongInt AdrLong;

  if (ChkArgCnt(1, 1))
  {
    AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt24, &OK, &Flags) - EProgCounter() - 6;
    if (AdrLong & 1) WrError(ErrNum_NotAligned);
    else if (!mSymbolQuestionable(Flags) && ((AdrLong > 0x7fffl) || (AdrLong < -0x8000l))) WrError(ErrNum_JmpDistTooBig);
    else
    {
      BAsmCode[0] = Hi(Code);
      BAsmCode[1] = Lo(Code);
      BAsmCode[2] = (AdrLong >> 8) & 0xff;
      BAsmCode[3] = AdrLong & 0xff;
      CodeLen = 4;
    }
  }
}

static void DecodeGen(Word Index)
{
  GenOrder *pOrder = GenOrders + Index;

  if (ChkArgCnt(1, 2))
  {
    DecodeAdr(1, ArgCnt, pOrder->Size, False, pOrder->AdrMask);
    switch (AdrMode)
    {
      case ModDisp8:
        BAsmCode[0] = pOrder->Code + AdrPart;
        BAsmCode[1] = AdrVals[0];
        CodeLen = 2;
        break;
      case ModDisp16:
        BAsmCode[0] = 0x17 + pOrder->ExtShift;
        BAsmCode[1] = pOrder->Code + (pOrder->Size << 6) + AdrPart;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
        break;
      case ModDispE:
        BAsmCode[0] = 0x27;
        BAsmCode[1] = pOrder->Code + AdrPart;
        CodeLen = 2;
        break;
      case ModAbs:
        BAsmCode[0] = 0x17 + pOrder->ExtShift;
        BAsmCode[1] = pOrder->Code + (pOrder->Size << 6) + 0x30;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
        break;
      case ModImm:
        if (pOrder->Size == eSymbolSize8Bit)
        {
          BAsmCode[0] = pOrder->Code + 0x30;
          BAsmCode[1] = AdrVals[0];
          CodeLen = 2;
        }
        else
        {
          BAsmCode[0] = 0x37;
          BAsmCode[1] = pOrder->Code + 0x30;
          memcpy(BAsmCode + 2, AdrVals, AdrCnt);
          CodeLen = 2 + AdrCnt;
        }
        break;
      case ModImmExt:
        BAsmCode[0] = pOrder->ExtCode;
        BAsmCode[1] = AdrVals[0];
        CodeLen = 2;
        break;
    }
  }
}

static void DecodeAux(Word Code)
{
  if (ChkArgCnt(1, 2))
  {
    DecodeAdr(1, ArgCnt, eSymbolSize16Bit, False, (*OpPart.str.p_str == 'S' ? 0 : MModImm) | MModDisp8 | MModDisp16 | MModAbs);
    switch (AdrMode)
    {
      case ModDisp8:
        BAsmCode[0] = Code + AdrPart;
        BAsmCode[1] = AdrVals[0];
        CodeLen = 2;
        break;
      case ModDisp16:
        BAsmCode[0] = 0x17;
        BAsmCode[1] = Code + AdrPart;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
        break;
      case ModAbs:
        BAsmCode[0] = 0x17;
        BAsmCode[1] = Code + 0x30;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
        break;
      case ModImm:
        BAsmCode[0] = 0x37;
        BAsmCode[1] = Code + 0x30;
        if (*OpPart.str.p_str == 'L') BAsmCode[1] -= 0x40;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
       break;
    }
  }
}

static void DecodeImm(Word Code)
{
  if (ChkArgCnt(1, 1))
  {
    DecodeAdr(1, 1, eSymbolSize16Bit, False, MModImm | MModImmExt);
    switch (AdrMode)
    {
      case ModImm:
        BAsmCode[0] = 0x37;
        BAsmCode[1] = Code;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
        break;
      case ModImmExt:
        BAsmCode[0] = Code;
        BAsmCode[1] = AdrVals[0];
        CodeLen = 2;
        break;
    }
  }
}

static void DecodeExt(Word Code)
{
  if (ChkArgCnt(1, 1))
  {
    DecodeAdr(1, 1, eSymbolSize16Bit, False, MModAbs);
    switch (AdrMode)
    {
      case ModAbs:
       BAsmCode[0] = Hi(Code);
       BAsmCode[1] = Lo(Code);
       memcpy(BAsmCode + 2, AdrVals, AdrCnt);
       CodeLen = 2 + AdrCnt;
       break;
    }
  }
}

static void DecodeStkMult(Word Index)
{
  int z;
  Boolean OK;

  if (ChkArgCnt(1, ArgCntMax))
  {
    OK = True;
    BAsmCode[1] = 0;
    for (z = 1; z <= ArgCnt; z++)
      if (OK)
      {
        const size_t RegCnt = as_array_size(Regs);
        size_t z2 = 0;
        NLS_UpString(ArgStr[z].str.p_str);
        while ((z2 < RegCnt) && strcmp(ArgStr[z].str.p_str, Regs[z2]))
          z2++;
        if (z2 >= RegCnt)
        {
          WrStrErrorPos(ErrNum_InvReg, &ArgStr[z]);
          OK = False;
        }
        else
          BAsmCode[1] |= Index ? (1 << z2) : (1 << (RegCnt - 1 - z2));
      }
    if (OK)
    {
      BAsmCode[0] = 0x34 | (Index ^ 1);
      CodeLen = 2;
    }
  }
}

static void DecodeMov(Word Index)
{
  Boolean OK;

  if (ArgCnt == 2)
  {
    DecodeAdr(1, 1, eSymbolSizeUnknown, False, MModAbs);
    if (AdrMode == ModAbs)
    {
      memcpy(BAsmCode + 2, AdrVals, 2);
      DecodeAdr(2, 2, eSymbolSizeUnknown, False, MModAbs);
      if (AdrMode == ModAbs)
      {
        memcpy(BAsmCode + 4, AdrVals, 2);
        BAsmCode[0] = 0x37;
        BAsmCode[1] = 0xfe | Index;
        CodeLen = 6;
      }
    }
  }
  else if (!ChkArgCnt(3, 3));
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "X"))
  {
    BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], SInt8, &OK);
    if (OK)
    {
      DecodeAdr(3, 3, eSymbolSizeUnknown, False, MModAbs);
      if (AdrMode == ModAbs)
      {
        memcpy(BAsmCode + 2, AdrVals, 2);
        BAsmCode[0] = 0x30 | Index;
        CodeLen = 4;
      }
    }
  }
  else if (!as_strcasecmp(ArgStr[3].str.p_str, "X"))
  {
    BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], SInt8, &OK);
    if (OK)
    {
      DecodeAdr(1, 1, eSymbolSizeUnknown, False, MModAbs);
      if (AdrMode == ModAbs)
      {
        memcpy(BAsmCode + 2, AdrVals, 2);
        BAsmCode[0] = 0x32 | Index;
        CodeLen = 4;
      }
    }
  }
  else WrError(ErrNum_InvAddrMode);
}

static void DecodeLogp(Word Index)
{
  if (ChkArgCnt(1, 1))
  {
    DecodeAdr(1, 1, eSymbolSize16Bit, False, MModImm);
    switch (AdrMode)
    {
      case ModImm:
        BAsmCode[0] = 0x37;
        BAsmCode[1] = 0x3a | Index;
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        CodeLen = 2 + AdrCnt;
        break;
    }
  }
}

static void DecodeMac(Word Index)
{
  Byte Val;
  Boolean OK;

  if (ChkArgCnt(2, 2))
  {
    Val = EvalStrIntExpression(&ArgStr[1], SInt4, &OK) & 0x0f;
    if (OK)
    {
      BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], SInt4, &OK) & 0x0f;
      if (OK)
      {
        BAsmCode[1] |= (Val << 4);
        BAsmCode[0] = 0x7b | Index;
        CodeLen = 2;
      }
    }
  }
}

static void DecodeBit8(Word Index)
{
  Byte Mask;

  if (ChkArgCnt(2, 3))
  {
    DecodeAdr(ArgCnt, ArgCnt, eSymbolSize8Bit, False, MModImm);
    switch (AdrMode)
    {
      case ModImm:
        Mask = AdrVals[0];
        DecodeAdr(1, ArgCnt - 1, eSymbolSizeUnknown, False, MModDisp8 | MModDisp16 | MModAbs);
        switch (AdrMode)
        {
          case ModDisp8:
            BAsmCode[0] = 0x17;
            BAsmCode[1] = 0x08 | Index | AdrPart;
            BAsmCode[2] = Mask;
            BAsmCode[3] = AdrVals[0];
            CodeLen = 4;
            break;
          case ModDisp16:
            BAsmCode[0] = 0x08 | Index | AdrPart;
            BAsmCode[1] = Mask;
            memcpy(BAsmCode + 2, AdrVals, AdrCnt);
            CodeLen = 2 + AdrCnt;
            break;
          case ModAbs:
            BAsmCode[0] = 0x38 + Index;
            BAsmCode[1] = Mask;
            memcpy(BAsmCode + 2, AdrVals, AdrCnt);
            CodeLen = 2 + AdrCnt;
            break;
        }
        break;
    }
  }
}

static void DecodeBit16(Word Index)
{
  if (ChkArgCnt(2, 3))
  {
    DecodeAdr(ArgCnt, ArgCnt, eSymbolSize16Bit, False, MModImm);
    switch (AdrMode)
    {
      case ModImm:
        memcpy(BAsmCode + 4, AdrVals, AdrCnt);
        DecodeAdr(1, ArgCnt - 1, eSymbolSizeUnknown, False, MModDisp16 | MModAbs);
        switch (AdrMode)
        {
          case ModDisp16:
            BAsmCode[0] = 0x27;
            BAsmCode[1] = 0x08 | Index | AdrPart;
            memcpy(BAsmCode + 2, AdrVals, AdrCnt);
            CodeLen = 4 + AdrCnt;
            break;
          case ModAbs:
            BAsmCode[0] = 0x27;
            BAsmCode[1] = 0x38 | Index;
            memcpy(BAsmCode + 2, AdrVals, AdrCnt);
            CodeLen = 4 + AdrCnt;
            break;
        }
    }
  }
}

static void DecodeBrBit(Word Index)
{
  Boolean OK;
  tSymbolFlags Flags;
  LongInt AdrLong;

  if (ChkArgCnt(3, 4))
  {
    DecodeAdr(ArgCnt - 1, ArgCnt - 1, eSymbolSize8Bit, False, MModImm);
    if (AdrMode == ModImm)
    {
      BAsmCode[1] = AdrVals[0];
      AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], UInt20, &OK, &Flags) - EProgCounter() - 6;
      if (OK)
      {
        DecodeAdr(1, ArgCnt - 2, eSymbolSizeUnknown, False, MModDisp8 | MModDisp16 | MModAbs);
        switch (AdrMode)
        {
          case ModDisp8:
            if ((AdrLong >= -128) && (AdrLong < 127))
            {
              BAsmCode[0] = 0xcb - (Index << 6) + AdrPart;
              BAsmCode[2] = AdrVals[0];
              BAsmCode[3] = AdrLong & 0xff;
              CodeLen = 4;
            }
            else if (!mSymbolQuestionable(Flags) && ((AdrLong <- 0x8000l) || (AdrLong > 0x7fffl))) WrError(ErrNum_JmpDistTooBig);
            else
            {
              BAsmCode[0] = 0x0a + AdrPart + Index;
              BAsmCode[2] = 0;
              BAsmCode[3] = AdrVals[0];
              BAsmCode[4] = (AdrLong >> 8) & 0xff;
              BAsmCode[5] = AdrLong & 0xff;
              CodeLen = 6;
            }
            break;
          case ModDisp16:
            if (!mSymbolQuestionable(Flags) && ((AdrLong < -0x8000l) || (AdrLong > 0x7fffl))) WrError(ErrNum_JmpDistTooBig);
            else
            {
              BAsmCode[0] = 0x0a + AdrPart + Index;
              memcpy(BAsmCode + 2,AdrVals, 2);
              BAsmCode[4] = (AdrLong >> 8) & 0xff;
              BAsmCode[5] = AdrLong & 0xff;
              CodeLen = 6;
            }
            break;
          case ModAbs:
            if (!mSymbolQuestionable(Flags) && ((AdrLong < -0x8000l) || (AdrLong > 0x7fffl))) WrError(ErrNum_JmpDistTooBig);
            else
            {
              BAsmCode[0] = 0x3a | Index;
              memcpy(BAsmCode + 2, AdrVals, 2);
              BAsmCode[4] = (AdrLong >> 8) & 0xff;
              BAsmCode[5] = AdrLong & 0xff;
              CodeLen = 6;
            }
            break;
        }
      }
    }
  }
}

static void DecodeJmpJsr(Word Index)
{
  if (ChkArgCnt(1, 2))
  {
    DecodeAdr(1, ArgCnt, eSymbolSize16Bit, True, MModAbs20 | MModDisp20);
    switch (AdrMode)
    {
      case ModAbs20:
        BAsmCode[0] = 0x7a + (Index << 7);
        memcpy(BAsmCode + 1, AdrVals, AdrCnt);
        CodeLen = 1 + AdrCnt;
        break;
      case ModDisp20:
        BAsmCode[0] = Index ? 0x89 : 0x4b;
        BAsmCode[0] += AdrPart;
        memcpy(BAsmCode + 1, AdrVals, AdrCnt);
        CodeLen = 1 + AdrCnt;
        break;
    }
  }
}

static void DecodeBsr(Word Index)
{
  Boolean OK;
  tSymbolFlags Flags;
  LongInt AdrLong;

  UNUSED(Index);

  if (ChkArgCnt(1, 1))
  {
    AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt24, &OK, &Flags) - EProgCounter() - 6;
    if (AdrLong & 1) WrError(ErrNum_NotAligned);
    else if (!mSymbolQuestionable(Flags) & ((AdrLong > 0x7fl) || (AdrLong < -0x80l))) WrError(ErrNum_JmpDistTooBig);
    else
    {
      BAsmCode[0] = 0x36;
      BAsmCode[1] = AdrLong & 0xff;
      CodeLen = 2;
    }
  }
}

/*-------------------------------------------------------------------------*/

static void AddFixed(const char *NName, Word NCode)
{
  AddInstTable(InstTable, NName, NCode, DecodeFixed);
}

static void AddRel(const char *NName, Word NCode)
{
  AddInstTable(InstTable, NName, NCode, DecodeRel);
}

static void AddLRel(const char *NName, Word NCode)
{
  AddInstTable(InstTable, NName, NCode, DecodeLRel);
}

static void AddGen(const char *NName, tSymbolSize NSize, Word NCode, Word NExtCode, Byte NShift, Byte NMask)
{
  order_array_rsv_end(GenOrders, GenOrder);
  GenOrders[InstrZ].Code = NCode;
  GenOrders[InstrZ].ExtCode = NExtCode;
  GenOrders[InstrZ].Size = NSize;
  GenOrders[InstrZ].AdrMask = NMask;
  GenOrders[InstrZ].ExtShift = NShift;
  AddInstTable(InstTable, NName, InstrZ++, DecodeGen);
}

static void AddAux(const char *NName, Word NCode)
{
  AddInstTable(InstTable, NName, NCode, DecodeAux);
}

static void AddImm(const char *NName, Word NCode)
{
  AddInstTable(InstTable, NName, NCode, DecodeImm);
}

static void AddExt(const char *NName, Word NCode)
{
  AddInstTable(InstTable, NName, NCode, DecodeExt);
}

static void AddEmu(const char *NName, Word NCode1, Word NCode2)
{
  order_array_rsv_end(EmuOrders, EmuOrder);
  EmuOrders[InstrZ].Code1 = NCode1;
  EmuOrders[InstrZ].Code2 = NCode2;
  AddInstTable(InstTable, NName, InstrZ++, DecodeEmu);
}

static void InitFields(void)
{
  InstTable = CreateInstTable(405);

  add_null_pseudo(InstTable);

  AddFixed("ABA"   , 0x370b); AddFixed("ABX"   , 0x374f);
  AddFixed("ABY"   , 0x375f); AddFixed("ABZ"   , 0x376f);
  AddFixed("ACE"   , 0x3722); AddFixed("ACED"  , 0x3723);
  AddFixed("ADE"   , 0x2778); AddFixed("ADX"   , 0x37cd);
  AddFixed("ADY"   , 0x37dd); AddFixed("ADZ"   , 0x37ed);
  AddFixed("AEX"   , 0x374d); AddFixed("AEY"   , 0x375d);
  AddFixed("AEZ"   , 0x376d); AddFixed("ASLA"  , 0x3704);
  AddFixed("ASLB"  , 0x3714); AddFixed("ASLD"  , 0x27f4);
  AddFixed("ASLE"  , 0x2774); AddFixed("ASLM"  , 0x27b6);
  AddFixed("LSLB"  , 0x3714); AddFixed("LSLD"  , 0x27f4);
  AddFixed("LSLE"  , 0x2774); AddFixed("LSLA"  , 0x3704);
  AddFixed("ASRA"  , 0x370d); AddFixed("ASRB"  , 0x371d);
  AddFixed("ASRD"  , 0x27fd); AddFixed("ASRE"  , 0x277d);
  AddFixed("ASRM"  , 0x27ba); AddFixed("BGND"  , 0x37a6);
  AddFixed("CBA"   , 0x371b); AddFixed("CLRA"  , 0x3705);
  AddFixed("CLRB"  , 0x3715); AddFixed("CLRD"  , 0x27f5);
  AddFixed("CLRE"  , 0x2775); AddFixed("CLRM"  , 0x27b7);
  AddFixed("COMA"  , 0x3700); AddFixed("COMB"  , 0x3710);
  AddFixed("COMD"  , 0x27f0); AddFixed("COME"  , 0x2770);
  AddFixed("DAA"   , 0x3721); AddFixed("DECA"  , 0x3701);
  AddFixed("DECB"  , 0x3711); AddFixed("EDIV"  , 0x3728);
  AddFixed("EDIVS" , 0x3729); AddFixed("EMUL"  , 0x3725);
  AddFixed("EMULS" , 0x3726); AddFixed("FDIV"  , 0x372b);
  AddFixed("FMULS" , 0x3727); AddFixed("IDIV"  , 0x372a);
  AddFixed("INCA"  , 0x3703); AddFixed("INCB"  , 0x3713);
  AddFixed("LPSTOP", 0x27f1); AddFixed("LSRA"  , 0x370f);
  AddFixed("LSRB"  , 0x371f); AddFixed("LSRD"  , 0x27ff);
  AddFixed("LSRE"  , 0x277f); AddFixed("MUL"   , 0x3724);
  AddFixed("NEGA"  , 0x3702); AddFixed("NEGB"  , 0x3712);
  AddFixed("NEGD"  , 0x27f2); AddFixed("NEGE"  , 0x2772);
  AddFixed("NOP"   , 0x274c); AddFixed("PSHA"  , 0x3708);
  AddFixed("PSHB"  , 0x3718); AddFixed("PSHMAC", 0x27b8);
  AddFixed("PULA"  , 0x3709); AddFixed("PULB"  , 0x3719);
  AddFixed("PULMAC", 0x27b9); AddFixed("ROLA"  , 0x370c);
  AddFixed("ROLB"  , 0x371c); AddFixed("ROLD"  , 0x27fc);
  AddFixed("ROLE"  , 0x277c); AddFixed("RORA"  , 0x370e);
  AddFixed("RORB"  , 0x371e); AddFixed("RORD"  , 0x27fe);
  AddFixed("RORE"  , 0x277e); AddFixed("RTI"   , 0x2777);
  AddFixed("RTS"   , 0x27f7); AddFixed("SBA"   , 0x370a);
  AddFixed("SDE"   , 0x2779); AddFixed("SWI"   , 0x3720);
  AddFixed("SXT"   , 0x27f8); AddFixed("TAB"   , 0x3717);
  AddFixed("TAP"   , 0x37fd); AddFixed("TBA"   , 0x3707);
  AddFixed("TBEK"  , 0x27fa); AddFixed("TBSK"  , 0x379f);
  AddFixed("TBXK"  , 0x379c); AddFixed("TBYK"  , 0x379d);
  AddFixed("TBZK"  , 0x379e); AddFixed("TDE"   , 0x277b);
  AddFixed("TDMSK" , 0x372f); AddFixed("TDP"   , 0x372d);
  AddFixed("TED"   , 0x27fb); AddFixed("TEDM"  , 0x27b1);
  AddFixed("TEKB"  , 0x27bb); AddFixed("TEM"   , 0x27b2);
  AddFixed("TMER"  , 0x27b4); AddFixed("TMET"  , 0x27b5);
  AddFixed("TMXED" , 0x27b3); AddFixed("TPA"   , 0x37fc);
  AddFixed("TPD"   , 0x372c); AddFixed("TSKB"  , 0x37af);
  AddFixed("TSTA"  , 0x3706); AddFixed("TSTB"  , 0x3716);
  AddFixed("TSTD"  , 0x27f6); AddFixed("TSTE"  , 0x2776);
  AddFixed("TSX"   , 0x274f); AddFixed("TSY"   , 0x275f);
  AddFixed("TSZ"   , 0x276f); AddFixed("TXKB"  , 0x37ac);
  AddFixed("TXS"   , 0x374e); AddFixed("TXY"   , 0x275c);
  AddFixed("TXZ"   , 0x276c); AddFixed("TYKB"  , 0x37ad);
  AddFixed("TYS"   , 0x375e); AddFixed("TYX"   , 0x274d);
  AddFixed("TYZ"   , 0x276d); AddFixed("TZKB"  , 0x37ae);
  AddFixed("TZS"   , 0x376e); AddFixed("TZX"   , 0x274e);
  AddFixed("TZY"   , 0x275e); AddFixed("WAI"   , 0x27f3);
  AddFixed("XGAB"  , 0x371a); AddFixed("XGDE"  , 0x277a);
  AddFixed("XGDX"  , 0x37cc); AddFixed("XGDY"  , 0x37dc);
  AddFixed("XGDZ"  , 0x37ec); AddFixed("XGEX"  , 0x374c);
  AddFixed("XGEY"  , 0x375c); AddFixed("XGEZ"  , 0x376c);
  AddFixed("DES"   , 0x3fff); AddFixed("INS"   , 0x3f01);
  AddFixed("DEX"   , 0x3cff); AddFixed("INX"   , 0x3c01);
  AddFixed("DEY"   , 0x3dff); AddFixed("INY"   , 0x3d01);
  AddFixed("PSHX"  , 0x3404); AddFixed("PULX"  , 0x3510);
  AddFixed("PSHY"  , 0x3408); AddFixed("PULY"  , 0x3508);

  AddRel("BCC" ,           4); AddRel("BCS",            5); AddRel("BEQ",            7);
  AddRel("BGE" ,          12); AddRel("BGT",           14); AddRel("BHI",            2);
  AddRel("BLE" ,          15); AddRel("BLS",            3); AddRel("BLT",           13);
  AddRel("BMI" ,          11); AddRel("BNE",            6); AddRel("BPL",           10);
  AddRel("BRA" ,           0); AddRel("BRN",            1); AddRel("BVC",            8);
  AddRel("BVS" ,           9); AddRel("BHS",            4); AddRel("BLO",            5);
  AddRel("LBCC", 0x8000 |  4); AddRel("LBCS", 0x8000 |  5); AddRel("LBEQ", 0x8000 |  7);
  AddRel("LBGE", 0x8000 | 12); AddRel("LBGT", 0x8000 | 14); AddRel("LBHI", 0x8000 |  2);
  AddRel("LBLE", 0x8000 | 15); AddRel("LBLS", 0x8000 |  3); AddRel("LBLT", 0x8000 | 13);
  AddRel("LBMI", 0x8000 | 11); AddRel("LBNE", 0x8000 |  6); AddRel("LBPL", 0x8000 | 10);
  AddRel("LBRA", 0x8000 |  0); AddRel("LBRN", 0x8000 |  1); AddRel("LBVC", 0x8000 |  8);
  AddRel("LBVS", 0x8000 |  9); AddRel("LBHS", 0x8000 |  4); AddRel("LBLO", 0x8000 |  5);

  AddLRel("LBEV", 0x3791); AddLRel("LBMV", 0x3790); AddLRel("LBSR", 0x27f9);

  InstrZ = 0;
  AddGen("ADCA", eSymbolSize8Bit , 0x43, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ADCB", eSymbolSize8Bit , 0xc3, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ADCD", eSymbolSize16Bit, 0x83, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ADCE", eSymbolSize16Bit, 0x03, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("ADDA", eSymbolSize8Bit , 0x41, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ADDB", eSymbolSize8Bit , 0xc1, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ADDD", eSymbolSize16Bit, 0x81,   0xfc, 0x20, MModDisp8 | MModImm | MModImmExt | MModDisp16 | MModAbs | MModDispE);
  AddGen("ADDE", eSymbolSize16Bit, 0x01,   0x7c, 0x20,             MModImm | MModImmExt | MModDisp16 | MModAbs            );
  AddGen("ANDA", eSymbolSize8Bit , 0x46, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ANDB", eSymbolSize8Bit , 0xc6, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ANDD", eSymbolSize16Bit, 0x86, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ANDE", eSymbolSize16Bit, 0x06, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("ASL" , eSymbolSize8Bit , 0x04, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("ASLW", eSymbolSize8Bit , 0x04, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("LSL" , eSymbolSize8Bit , 0x04, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("LSLW", eSymbolSize8Bit , 0x04, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("ASR" , eSymbolSize8Bit , 0x0d, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("ASRW", eSymbolSize8Bit , 0x0d, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("BITA", eSymbolSize8Bit , 0x49, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("BITB", eSymbolSize8Bit , 0xc9, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("CLR" , eSymbolSize8Bit , 0x05, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("CLRW", eSymbolSize8Bit , 0x05, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("CMPA", eSymbolSize8Bit , 0x48, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("CMPB", eSymbolSize8Bit , 0xc8, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("COM" , eSymbolSize8Bit , 0x00, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("COMW", eSymbolSize8Bit , 0x00, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("CPD" , eSymbolSize16Bit, 0x88, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("CPE" , eSymbolSize16Bit, 0x08, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("DEC" , eSymbolSize8Bit , 0x01, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("DECW", eSymbolSize8Bit , 0x01, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("EORA", eSymbolSize8Bit , 0x44, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("EORB", eSymbolSize8Bit , 0xc4, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("EORD", eSymbolSize16Bit, 0x84, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("EORE", eSymbolSize16Bit, 0x04, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("INC" , eSymbolSize8Bit , 0x03, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("INCW", eSymbolSize8Bit , 0x03, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("LDAA", eSymbolSize8Bit , 0x45, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("LDAB", eSymbolSize8Bit , 0xc5, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("LDD" , eSymbolSize16Bit, 0x85, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("LDE" , eSymbolSize16Bit, 0x05, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("LSR" , eSymbolSize8Bit , 0x0f, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("LSRW", eSymbolSize8Bit , 0x0f, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("NEG" , eSymbolSize8Bit , 0x02, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("NEGW", eSymbolSize8Bit , 0x02, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("ORAA", eSymbolSize8Bit , 0x47, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ORAB", eSymbolSize8Bit , 0xc7, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ORD" , eSymbolSize16Bit, 0x87, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("ORE" , eSymbolSize16Bit, 0x07, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("ROL" , eSymbolSize8Bit , 0x0c, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("ROLW", eSymbolSize8Bit , 0x0c, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("ROR" , eSymbolSize8Bit , 0x0e, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("RORW", eSymbolSize8Bit , 0x0e, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );
  AddGen("SBCA", eSymbolSize8Bit , 0x42, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("SBCB", eSymbolSize8Bit , 0xc2, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("SBCD", eSymbolSize16Bit, 0x82, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("SBCE", eSymbolSize16Bit, 0x02, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("STAA", eSymbolSize8Bit , 0x4a, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs | MModDispE);
  AddGen("STAB", eSymbolSize8Bit , 0xca, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs | MModDispE);
  AddGen("STD" , eSymbolSize16Bit, 0x8a, 0xffff, 0x20, MModDisp8 |                        MModDisp16 | MModAbs | MModDispE);
  AddGen("STE" , eSymbolSize16Bit, 0x0a, 0xffff, 0x20,                                    MModDisp16 | MModAbs            );
  AddGen("SUBA", eSymbolSize8Bit , 0x40, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("SUBB", eSymbolSize8Bit , 0xc0, 0xffff, 0x00, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("SUBD", eSymbolSize16Bit, 0x80, 0xffff, 0x20, MModDisp8 | MModImm |              MModDisp16 | MModAbs | MModDispE);
  AddGen("SUBE", eSymbolSize16Bit, 0x00, 0xffff, 0x20,             MModImm |              MModDisp16 | MModAbs            );
  AddGen("TST" , eSymbolSize8Bit , 0x06, 0xffff, 0x00, MModDisp8 |                        MModDisp16 | MModAbs            );
  AddGen("TSTW", eSymbolSize8Bit , 0x06, 0xffff, 0x10,                                    MModDisp16 | MModAbs            );

  AddAux("CPS", 0x4f); AddAux("CPX", 0x4c); AddAux("CPY", 0x4d); AddAux("CPZ", 0x4e);
  AddAux("LDS", 0xcf); AddAux("LDX", 0xcc); AddAux("LDY", 0xcd); AddAux("LDZ", 0xce);
  AddAux("STS", 0x8f); AddAux("STX", 0x8c); AddAux("STY", 0x8d); AddAux("STZ", 0x8e);

  AddImm("AIS", 0x3f); AddImm("AIX", 0x3c); AddImm("AIY", 0x3d); AddImm("AIZ", 0x3e);

  AddExt("LDED", 0x2771); AddExt("LDHI", 0x27b0); AddExt("STED", 0x2773);

  InstrZ = 0;
  AddEmu("CLC", 0x373a, 0xfeff); AddEmu("CLI", 0x373a, 0xff1f); AddEmu("CLV", 0x373a, 0xfdff);
  AddEmu("SEC", 0x373b, 0x0100); AddEmu("SEI", 0x373b, 0x00e0); AddEmu("SEV", 0x373b, 0x0200);

  AddInstTable(InstTable, "PSHM", 1, DecodeStkMult);
  AddInstTable(InstTable, "PULM", 0, DecodeStkMult);

  AddInstTable(InstTable, "MOVB", 0, DecodeMov);
  AddInstTable(InstTable, "MOVW", 1, DecodeMov);

  AddInstTable(InstTable, "ANDP", 0, DecodeLogp);
  AddInstTable(InstTable, "ORP" , 1, DecodeLogp);

  AddInstTable(InstTable, "MAC" , 0 << 7, DecodeMac);
  AddInstTable(InstTable, "RMAC", 1 << 7, DecodeMac);

  AddInstTable(InstTable, "BCLR", 0, DecodeBit8);
  AddInstTable(InstTable, "BSET", 1, DecodeBit8);

  AddInstTable(InstTable, "BCLRW", 0, DecodeBit16);
  AddInstTable(InstTable, "BSETW", 1, DecodeBit16);

  AddInstTable(InstTable, "BRCLR", 0, DecodeBrBit);
  AddInstTable(InstTable, "BRSET", 1, DecodeBrBit);

  AddInstTable(InstTable, "JMP", 0, DecodeJmpJsr);
  AddInstTable(InstTable, "JSR", 1, DecodeJmpJsr);
  AddInstTable(InstTable, "BSR", 0, DecodeBsr);

  add_moto8_pseudo(InstTable, e_moto_pseudo_flags_be);
  add_moto8_comment_onoff();
  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)
{
  order_array_free(GenOrders);
  order_array_free(EmuOrders);
  DestroyInstTable(InstTable); InstTable = NULL;
}

/*-------------------------------------------------------------------------*/

static Boolean DecodeAttrPart_6816(void)
{
  if (strlen(AttrPart.str.p_str) > 1)
  {
    WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
    return False;
  }
  return DecodeMoto16AttrSize(*AttrPart.str.p_str, &AttrPartOpSize[0], False);
}

static void MakeCode_6816(void)
{
  AdrCnt = 0;

  /* Operandengroesse festlegen. ACHTUNG! Das gilt nur fuer die folgenden
     Pseudobefehle! Die Maschinenbefehle ueberschreiben diesen Wert! */

  if (AttrPartOpSize[0] == eSymbolSizeUnknown)
    AttrPartOpSize[0] = eSymbolSize8Bit;

  if (!LookupInstTable(InstTable, OpPart.str.p_str))
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
}

static void InitCode_6816(void)
{
  Reg_EK = 0;
}

static Boolean IsDef_6816(void)
{
  return False;
}

static void SwitchFrom_6816(void)
{
  DeinitFields();
}

static void SwitchTo_6816(void)
{
  static as_assume_rec_t ASSUME6816s[11] =
  {
    { "EK" , &Reg_EK , 0 , 0xff , 0x100, NULL }
  };
  const TFamilyDescr *p_descr = FindFamilyByName("68HC16");

  TurnWords = False;
  SetIntConstMode(eIntConstModeMoto);

  PCSymbol = "*";
  HeaderID = p_descr->Id;
  NOPCode = 0x274c;
  DivideChars = ",";
  HasAttrs = True;
  AttrChars = ".";

  ValidSegs = (1 << SegCode);
  Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  SegLimits[SegCode] = 0xfffffl;

  DecodeAttrPart = DecodeAttrPart_6816;
  MakeCode = MakeCode_6816;
  IsDef = IsDef_6816;
  SwitchFrom = SwitchFrom_6816;
  AddMoto16PseudoONOFF(False);

  assume_set(ASSUME6816s, as_array_size(ASSUME6816s));

  InitFields();
}

void code6816_init(void)
{
  CPU6816 = AddCPU("68HC16", SwitchTo_6816);

  AddInitPassProc(InitCode_6816);
}
