Top secrets sources NedoPC pentevo

Rev

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

/* code370.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
/*                                                                           */
/* AS-Portierung                                                             */
/*                                                                           */
/* Codegenerator 370-Familie                                                 */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"

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

#include "bpemu.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "intformat.h"
#include "intpseudo.h"
#include "codevars.h"
#include "errmsg.h"

#include "code370.h"

typedef struct
{
  char *Name;
  Word Code;
} FixedOrder;

enum
{
  ModNone = -1,
  ModAccA = 0,       /* A */
  ModAccB = 1,       /* B */
  ModReg = 2,        /* Rn */
  ModPort = 3,       /* Pn */
  ModAbs = 4,        /* nnnn */
  ModBRel = 5,       /* nnnn(B) */
  ModSPRel = 6,      /* nn(SP) */
  ModIReg = 7,       /* @Rn */
  ModRegRel = 8,     /* nn(Rn) */
  ModImm = 9,        /* #nn */
  ModImmBRel = 10,   /* #nnnn(B) */
  ModImmRegRel = 11  /* #nn(Rm) */
};

#define MModAccA (1 << ModAccA)
#define MModAccB (1 << ModAccB)
#define MModReg (1 << ModReg)
#define MModPort (1 << ModPort)
#define MModAbs (1 << ModAbs)
#define MModBRel (1 << ModBRel)
#define MModSPRel (1 << ModSPRel)
#define MModIReg (1 << ModIReg)
#define MModRegRel (1 << ModRegRel)
#define MModImm (1 << ModImm)
#define MModImmBRel (1 << ModImmBRel)
#define MModImmRegRel (1 << ModImmRegRel)

static CPUVar CPU37010, CPU37020, CPU37030, CPU37040, CPU37050;

static Byte OpSize;
static ShortInt AdrType;
static Byte AdrVals[2];

/****************************************************************************/

static char *HasDisp(char *Asc)
{
  char *p;
  int Lev;

  if ((*Asc) && (Asc[strlen(Asc) - 1] == ')'))
  {
    p = Asc + strlen(Asc) - 2;
    Lev = 0;
    while ((p >= Asc) && (Lev != -1))
    {
      switch (*p)
      {
        case '(': Lev--; break;
        case ')': Lev++; break;
      }
      if (Lev != -1)
        p--;
    }
    if (p < Asc)
    {
      WrXError(ErrNum_BrackErr, Asc);
      return NULL;
    }
  }
  else
    p = NULL;

  return p;
}

static void DecodeAdrRel(const tStrComp *pArg, Word Mask, Boolean AddrRel)
{
  Integer HVal;
  char *p;
  Boolean OK;

  AdrType = ModNone;
  AdrCnt = 0;

  if (!as_strcasecmp(pArg->str.p_str, "A"))
  {
    if (Mask & MModAccA)
      AdrType = ModAccA;
    else if (Mask & MModReg)
    {
      AdrCnt = 1;
      AdrVals[0] = 0;
      AdrType = ModReg;
    }
    else
    {
      AdrCnt = 2;
      AdrVals[0] = 0;
      AdrVals[1] = 0;
      AdrType = ModAbs;
    }
    goto chk;
  }

  if (!as_strcasecmp(pArg->str.p_str, "B"))
  {
    if (Mask & MModAccB)
      AdrType = ModAccB;
    else if (Mask & MModReg)
    {
      AdrCnt = 1;
      AdrVals[0] = 1;
      AdrType = ModReg;
    }
    else
    {
      AdrCnt = 2;
      AdrVals[0] = 0;
      AdrVals[1] = 1;
      AdrType = ModAbs;
    }
    goto chk;
  }

  if (*pArg->str.p_str == '#')
  {
    tStrComp Arg;

    StrCompRefRight(&Arg, pArg, 1);
    p = HasDisp(Arg.str.p_str);
    if (!p)
    {
      switch (OpSize)
      {
        case 0:
          AdrVals[0] = EvalStrIntExpression(&Arg, Int8, &OK);
          break;
        case 1:
          HVal = EvalStrIntExpression(&Arg, Int16, &OK);
          AdrVals[0] = Hi(HVal); AdrVals[1] = Lo(HVal);
          break;
      }
      if (OK)
      {
        AdrCnt = 1 + OpSize;
        AdrType = ModImm;
      }
    }
    else
    {
      tStrComp Left, Right;
      tSymbolFlags Flags;

      StrCompSplitRef(&Left, &Right, &Arg, p);
      HVal = EvalStrIntExpressionWithFlags(&Left, Int16, &OK, &Flags);
      if (OK)
      {
        *p = '(';
        if (!as_strcasecmp(p, "(B)"))
        {
          AdrVals[0] = Hi(HVal);
          AdrVals[1] = Lo(HVal);
          AdrCnt = 2;
          AdrType = ModImmBRel;
        }
        else
        {
          if (mFirstPassUnknown(Flags))
            HVal &= 127;
          if (ChkRange(HVal, -128, 127))
          {
            AdrVals[0] = HVal & 0xff;
            AdrCnt = 1;
            AdrVals[1] = EvalStrIntExpression(&Arg, UInt8, &OK);
            if (OK)
            {
              AdrCnt = 2;
              AdrType = ModImmRegRel;
            }
          }
        }
      }
    }
    goto chk;
  }

  if (*pArg->str.p_str == '@')
  {
    AdrVals[0] = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK);
    if (OK)
    {
      AdrCnt = 1;
      AdrType = ModIReg;
    }
    goto chk;
  }

  p = HasDisp(pArg->str.p_str);

  if (!p)
  {
    HVal = EvalStrIntExpression(pArg, Int16, &OK);
    if (OK)
    {
      if (((Mask & MModReg) != 0) && (Hi(HVal) == 0))
      {
        AdrVals[0] = Lo(HVal);
        AdrCnt = 1;
        AdrType = ModReg;
      }
      else if (((Mask & MModPort) != 0) && (Hi(HVal) == 0x10))
      {
        AdrVals[0] = Lo(HVal);
        AdrCnt = 1;
        AdrType = ModPort;
      }
      else
      {
        if (AddrRel)
          HVal -= EProgCounter() + 3;
        AdrVals[0] = Hi(HVal);
        AdrVals[1] = Lo(HVal);
        AdrCnt = 2;
        AdrType = ModAbs;
      }
    }
    goto chk;
  }
  else
  {
    tStrComp Left, Right;
    tSymbolFlags Flags;

    StrCompSplitRef(&Left, &Right, pArg, p);
    HVal = EvalStrIntExpressionWithFlags(&Left, Int16, &OK, &Flags);
    if (mFirstPassUnknown(Flags))
      HVal &= 0x7f;
    if (OK)
    {
      StrCompShorten (&Right, 1);
      if (!as_strcasecmp(Right.str.p_str, "B"))
      {
        if (AddrRel)
          HVal -= EProgCounter() + 3;
        AdrVals[0] = Hi(HVal);
        AdrVals[1] = Lo(HVal);
        AdrCnt = 2;
        AdrType = ModBRel;
      }
      else if (!as_strcasecmp(Right.str.p_str, "SP"))
      {
        if (AddrRel)
          HVal -= EProgCounter() + 3;
        if (HVal > 127) WrError(ErrNum_OverRange);
        else if (HVal < -128) WrError(ErrNum_UnderRange);
        else
        {
          AdrVals[0] = HVal & 0xff;
          AdrCnt = 1;
          AdrType = ModSPRel;
        }
      }
      else
      {
        if (HVal > 127) WrError(ErrNum_OverRange);
        else if (HVal < -128) WrError(ErrNum_UnderRange);
        else
        {
          AdrVals[0] = HVal & 0xff;
          AdrVals[1] = EvalStrIntExpression(&Right, Int8, &OK);
          if (OK)
          {
            AdrCnt = 2;
            AdrType = ModRegRel;
          }
        }
      }
    }
    goto chk;
  }

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

static void DecodeAdr(const tStrComp *pArg, Word Mask)
{
  DecodeAdrRel(pArg, Mask, FALSE);
}

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

static void DissectBitValue(LargeWord Symbol, Word *pAddr, Byte *pBit)
{
  *pAddr = Symbol & 0xffff;
  *pBit = (Symbol >> 16) & 7;
}

static void DissectBit_370(char *pDest, size_t DestSize, LargeWord Symbol)
{
  Word Addr;
  Byte Bit;

  DissectBitValue(Symbol, &Addr, &Bit);

  if (Addr < 2)
    as_snprintf(pDest, DestSize, "%c", HexStartCharacter + Addr);
  else
    as_snprintf(pDest, DestSize, "%~0.*u%s",
                ListRadixBase, (unsigned)Addr, GetIntConstIntelSuffix(ListRadixBase));
  as_snprcatf(pDest, DestSize, ".%c", Bit + '0');
}

static Boolean DecodeBitExpr(int Start, int Stop, LongWord *pResult)
{
  Boolean OK;

  if (Start == Stop)
  {
    *pResult = EvalStrIntExpression(&ArgStr[Start], UInt19, &OK);
    return OK;
  }
  else
  {
    Byte Bit;
    Word Addr;

    Bit = EvalStrIntExpression(&ArgStr[Start], UInt3, &OK);
    if (!OK)
      return OK;

    if ((!as_strcasecmp(ArgStr[Stop].str.p_str, "A")) || (!as_strcasecmp(ArgStr[Stop].str.p_str, "B")))
    {
      Addr = toupper(*ArgStr[Stop].str.p_str) - 'A';
      OK = True;
    }
    else
    {
      tSymbolFlags Flags;

      Addr = EvalStrIntExpressionWithFlags(&ArgStr[Stop], UInt16, &OK, &Flags);
      if (!OK)
        return OK;
      if (mFirstPassUnknown(Flags))
        Addr &= 0xff;
      if (Addr & 0xef00) /* 00h...0ffh, 1000h...10ffh allowed */
      {
        WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[Stop]);
        return False;
      }
    }

    *pResult = (((LongWord)Bit) << 16) + Addr;
    return True;
  }
}

/****************************************************************************/

static void DecodeFixed(Word Code)
{
  if (ChkArgCnt(0, 0))
    PutCode(Code);
}

static void DecodeDBIT(Word Code)
{
  LongWord Value;

  UNUSED(Code);

  if (ChkArgCnt(1, 2) && DecodeBitExpr(1, ArgCnt, &Value))
  {
    PushLocHandle(-1);
    EnterIntSymbol(&LabPart, Value, SegBData, False);
    *ListLine = '=';
    DissectBit_370(ListLine + 1, STRINGSIZE - 1, Value);
    PopLocHandle();
  }
}

static void DecodeMOV(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(2, 2))
  {
    DecodeAdr(&ArgStr[2], MModAccB + MModReg + MModPort + MModAbs + MModIReg + MModBRel
                       + MModSPRel + MModRegRel + MModAccA);
    switch (AdrType)
    {
      case ModAccA:
        DecodeAdr(&ArgStr[1], MModReg + MModAbs + MModIReg + MModBRel + MModRegRel
                           + MModSPRel + MModAccB + MModPort + MModImm);
        switch (AdrType)
        {
          case ModReg:
            BAsmCode[0] = 0x12;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModAbs:
            BAsmCode[0] = 0x8a;
            memcpy(BAsmCode + 1, AdrVals, 2);
            CodeLen = 3;
            break;
          case ModIReg:
            BAsmCode[0] = 0x9a;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModBRel:
            BAsmCode[0] = 0xaa;
            memcpy(BAsmCode + 1, AdrVals, 2);
            CodeLen = 3;
            break;
          case ModRegRel:
            BAsmCode[0] = 0xf4;
            BAsmCode[1] = 0xea;
            memcpy(BAsmCode + 2, AdrVals, 2);
            CodeLen = 4;
            break;
          case ModSPRel:
            BAsmCode[0] = 0xf1;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModAccB:
            BAsmCode[0] = 0x62;
            CodeLen = 1;
            break;
          case ModPort:
            BAsmCode[0] = 0x80;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0x22;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
        }
        break;
      case ModAccB:
        DecodeAdr(&ArgStr[1], MModAccA + MModReg + MModPort + MModImm);
        switch (AdrType)
        {
          case ModAccA:
            BAsmCode[0] = 0xc0;
            CodeLen = 1;
            break;
          case ModReg:
            BAsmCode[0] = 0x32;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModPort:
            BAsmCode[0] = 0x91;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0x52;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
        }
        break;
      case ModReg:
        BAsmCode[1] = BAsmCode[2] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModAccA + MModAccB + MModReg + MModPort + MModImm);
        switch (AdrType)
        {
          case ModAccA:
            BAsmCode[0] = 0xd0;
            CodeLen = 2;
            break;
          case ModAccB:
            BAsmCode[0] = 0xd1;
            CodeLen = 2;
            break;
          case ModReg:
            BAsmCode[0] = 0x42;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
          case ModPort:
            BAsmCode[0] = 0xa2;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
          case ModImm:
            BAsmCode[0] = 0x72;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
        }
        break;
      case ModPort:
        BAsmCode[1] = BAsmCode[2] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModAccA + MModAccB + MModReg + MModImm);
        switch (AdrType)
        {
          case ModAccA:
            BAsmCode[0] = 0x21;
            CodeLen = 2;
            break;
          case ModAccB:
            BAsmCode[0] = 0x51;
            CodeLen = 2;
            break;
          case ModReg:
            BAsmCode[0] = 0x71;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
          case ModImm:
            BAsmCode[0] = 0xf7;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
        }
        break;
      case ModAbs:
        memcpy(BAsmCode + 1, AdrVals, AdrCnt);
        DecodeAdr(&ArgStr[1], MModAccA);
        if (AdrType != ModNone)
        {
          BAsmCode[0] = 0x8b;
          CodeLen = 3;
        }
        break;
      case ModIReg:
        BAsmCode[1] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModAccA);
        if (AdrType != ModNone)
        {
          BAsmCode[0] = 0x9b;
          CodeLen = 2;
        }
        break;
      case ModBRel:
        memcpy(BAsmCode + 1, AdrVals, AdrCnt);
        DecodeAdr(&ArgStr[1], MModAccA);
        if (AdrType != ModNone)
        {
          BAsmCode[0] = 0xab;
          CodeLen = 3;
        }
        break;
      case ModSPRel:
        BAsmCode[1] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModAccA);
        if (AdrType != ModNone)
        {
          BAsmCode[0] = 0xf2;
          CodeLen = 2;
        }
        break;
      case ModRegRel:
        memcpy(BAsmCode + 2, AdrVals, AdrCnt);
        DecodeAdr(&ArgStr[1], MModAccA);
        if (AdrType != ModNone)
        {
          BAsmCode[0] = 0xf4;
          BAsmCode[1] = 0xeb;
          CodeLen = 4;
        }
        break;
    }
  }
}

static void DecodeMOVW(Word Code)
{
  UNUSED(Code);

  OpSize = 1;
  if (ChkArgCnt(2, 2))
  {
    DecodeAdr(&ArgStr[2], MModReg);
    if (AdrType != ModNone)
    {
      Byte AdrVal = AdrVals[0];

      DecodeAdr(&ArgStr[1], MModReg + MModImm + MModImmBRel + MModImmRegRel);
      switch (AdrType)
      {
        case ModReg:
          BAsmCode[0] = 0x98;
          BAsmCode[1] = AdrVals[0];
          BAsmCode[2] = AdrVal;
          CodeLen = 3;
          break;
        case ModImm:
          BAsmCode[0] = 0x88;
          memcpy(BAsmCode + 1, AdrVals, 2);
          BAsmCode[3] = AdrVal;
          CodeLen = 4;
          break;
        case ModImmBRel:
          BAsmCode[0] = 0xa8;
          memcpy(BAsmCode + 1, AdrVals, 2);
          BAsmCode[3] = AdrVal;
          CodeLen = 4;
          break;
        case ModImmRegRel:
          BAsmCode[0] = 0xf4;
          BAsmCode[1] = 0xe8;
          memcpy(BAsmCode + 2, AdrVals, 2);
          BAsmCode[4] = AdrVal;
          CodeLen = 5;
          break;
      }
    }
  }
}

static void DecodeRel8(Word Code)
{
  if (ChkArgCnt(1, 1))
  {
    Boolean OK;
    tSymbolFlags Flags;
    Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags) - (EProgCounter() + 2);

    if (OK)
    {
      if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128))) WrError(ErrNum_JmpDistTooBig);
      else
      {
        CodeLen = 2;
        BAsmCode[0] = Code;
        BAsmCode[1] = AdrInt & 0xff;
      }
    }
  }
}

static void DecodeCMP(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(2, 2))
  {
    DecodeAdr(&ArgStr[2], MModAccA + MModAccB + MModReg);
    switch (AdrType)
    {
      case ModAccA:
        DecodeAdr(&ArgStr[1], MModAbs + MModIReg + MModBRel + MModRegRel + MModSPRel + MModAccB + MModReg + MModImm);
        switch (AdrType)
        {
          case ModAbs:
            BAsmCode[0] = 0x8d;
            memcpy(BAsmCode + 1, AdrVals, 2);
            CodeLen = 3;
            break;
          case ModIReg:
            BAsmCode[0] = 0x9d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModBRel:
            BAsmCode[0] = 0xad;
            memcpy(BAsmCode + 1, AdrVals, 2);
            CodeLen = 3;
            break;
          case ModRegRel:
            BAsmCode[0] = 0xf4;
            BAsmCode[1] = 0xed;
            memcpy(BAsmCode + 2, AdrVals, 2);
            CodeLen = 4;
            break;
          case ModSPRel:
            BAsmCode[0] = 0xf3;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModAccB:
            BAsmCode[0] = 0x6d;
            CodeLen = 1;
            break;
          case ModReg:
            BAsmCode[0] = 0x1d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0x2d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
        }
        break;
      case ModAccB:
        DecodeAdr(&ArgStr[1], MModReg + MModImm);
        switch (AdrType)
        {
          case ModReg:
            BAsmCode[0] = 0x3d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0x5d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
        }
        break;
      case ModReg:
        BAsmCode[2] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModReg + MModImm);
        switch (AdrType)
        {
          case ModReg:
            BAsmCode[0] = 0x4d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
          case ModImm:
            BAsmCode[0] = 0x7d;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
        }
        break;
    }
  }
}

static void DecodeALU1(Word Code)
{
  if (ChkArgCnt(2, 2))
  {
    DecodeAdr(&ArgStr[2], MModAccA + MModAccB + MModReg);
    switch (AdrType)
    {
      case ModAccA:
        DecodeAdr(&ArgStr[1], MModAccB + MModReg + MModImm);
        switch (AdrType)
        {
          case ModAccB:
            CodeLen = 1;
            BAsmCode[0] = 0x60 + Code;
            break;
          case ModReg:
            CodeLen = 2;
            BAsmCode[0] = 0x10 + Code;
            BAsmCode[1] = AdrVals[0];
            break;
          case ModImm:
            CodeLen = 2;
            BAsmCode[0] = 0x20 + Code;
            BAsmCode[1] = AdrVals[0];
            break;
        }
        break;
      case ModAccB:
        DecodeAdr(&ArgStr[1], MModReg + MModImm);
        switch (AdrType)
        {
          case ModReg:
            CodeLen = 2;
            BAsmCode[0] = 0x30 + Code;
            BAsmCode[1] = AdrVals[0];
            break;
          case ModImm:
            CodeLen = 2;
            BAsmCode[0] = 0x50 + Code;
            BAsmCode[1] = AdrVals[0];
            break;
        }
        break;
      case ModReg:
        BAsmCode[2] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModReg + MModImm);
        switch (AdrType)
        {
          case ModReg:
            CodeLen = 3;
            BAsmCode[0] = 0x40 + Code;
            BAsmCode[1] = AdrVals[0];
            break;
          case ModImm:
            CodeLen = 3;
            BAsmCode[0] = 0x70 + Code;
            BAsmCode[1] = AdrVals[0];
            break;
        }
        break;
    }
  }
}

static void DecodeALU2(Word Code)
{
  Boolean Rela = Hi(Code) != 0;
  Code &= 0xff;

  if (ChkArgCnt(Rela ? 3 : 2, Rela ? 3 : 2))
  {
    DecodeAdr(&ArgStr[2], MModAccA + MModAccB + MModReg + MModPort);
    switch (AdrType)
    {
      case ModAccA:
        DecodeAdr(&ArgStr[1], MModAccB + MModReg + MModImm);
        switch (AdrType)
        {
          case ModAccB:
            BAsmCode[0] = 0x60 + Code;
            CodeLen = 1;
            break;
          case ModReg:
            BAsmCode[0] = 0x10 + Code;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0x20 + Code;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
        }
        break;
      case ModAccB:
        DecodeAdr(&ArgStr[1], MModReg + MModImm);
        switch (AdrType)
        {
          case ModReg:
            BAsmCode[0] = 0x30 + Code;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0x50 + Code;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 2;
            break;
        }
        break;
      case ModReg:
        BAsmCode[2] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModReg + MModImm);
        switch (AdrType)
        {
          case ModReg:
            BAsmCode[0] = 0x40 + Code;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
          case ModImm:
            BAsmCode[0] = 0x70 + Code;
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
        }
        break;
      case ModPort:
        BAsmCode[1] = AdrVals[0];
        DecodeAdr(&ArgStr[1], MModAccA + MModAccB + MModImm);
        switch (AdrType)
        {
          case ModAccA:
            BAsmCode[0] = 0x80 + Code;
            CodeLen = 2;
            break;
          case ModAccB:
            BAsmCode[0] = 0x90 + Code;
            CodeLen = 2;
            break;
          case ModImm:
            BAsmCode[0] = 0xa0 + Code;
            BAsmCode[2] = BAsmCode[1];
            BAsmCode[1] = AdrVals[0];
            CodeLen = 3;
            break;
        }
        break;
    }
    if ((CodeLen != 0) && (Rela))
    {
      Boolean OK;
      tSymbolFlags Flags;
      Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[3], UInt16, &OK, &Flags) - (EProgCounter() + CodeLen + 1);

      if (!OK)
        CodeLen = 0;
      else if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128)))
      {
        WrError(ErrNum_JmpDistTooBig);
        CodeLen = 0;
      }
      else
        BAsmCode[CodeLen++] = AdrInt & 0xff;
    }
  }
}

static void DecodeJmp(Word Code)
{
  Boolean AddrRel = Hi(Code) != 0;
  Code &= 0xff;

  if (ChkArgCnt(1, 1))
  {
    DecodeAdrRel(&ArgStr[1], MModAbs + MModIReg + MModBRel + MModRegRel, AddrRel);
    switch (AdrType)
    {
      case ModAbs:
        CodeLen = 3;
        BAsmCode[0] = 0x80 + Code;
        memcpy(BAsmCode + 1, AdrVals, 2);
        break;
      case ModIReg:
        CodeLen = 2;
        BAsmCode[0] = 0x90 + Code;
        BAsmCode[1] = AdrVals[0];
        break;
      case ModBRel:
        CodeLen = 3;
        BAsmCode[0] = 0xa0 + Code;
        memcpy(BAsmCode + 1, AdrVals, 2);
        break;
      case ModRegRel:
        CodeLen = 4;
        BAsmCode[0] = 0xf4;
        BAsmCode[1] = 0xe0 + Code;
        memcpy(BAsmCode + 2, AdrVals, 2);
        break;
    }
  }
}

static void DecodeABReg(Word Code)
{
  int IsDJNZ = Hi(Code) & 1;
  Boolean IsStack = (Code & 0x200) || False;

  Code &= 0xff;

  if (!ChkArgCnt(1 + IsDJNZ, 1 + IsDJNZ));
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "ST"))
  {
    if (IsStack)
    {
      BAsmCode[0] = 0xf3 + Code;
      CodeLen = 1;
    }
    else
      WrError(ErrNum_InvAddrMode);
  }
  else
  {
    DecodeAdr(&ArgStr[1], MModAccA + MModAccB + MModReg);
    switch (AdrType)
    {
      case ModAccA:
        BAsmCode[0] = 0xb0 + Code;
        CodeLen = 1;
        break;
      case ModAccB:
        BAsmCode[0] = 0xc0 + Code;
        CodeLen = 1;
        break;
      case ModReg:
        BAsmCode[0] = 0xd0 + Code;
        BAsmCode[CodeLen + 1] = AdrVals[0];
        CodeLen = 2;
        break;
    }
    if ((IsDJNZ) && (CodeLen != 0))
    {
      Boolean OK;
      tSymbolFlags Flags;
      Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[2], Int16, &OK, &Flags) - (EProgCounter() + CodeLen + 1);

      if (!OK)
        CodeLen = 0;
      else if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128)))
      {
        WrError(ErrNum_JmpDistTooBig);
        CodeLen = 0;
      }
      else
        BAsmCode[CodeLen++] = AdrInt & 0xff;
    }
  }
}

static void DecodeBit(Word Code)
{
  int Rela = Hi(Code);
  LongWord BitExpr;

  Code &= 0xff;

  if (ChkArgCnt(1 + Rela, 2 + Rela)
   && DecodeBitExpr(1, ArgCnt - Rela, &BitExpr))
  {
    Boolean OK;
    Word Addr;
    Byte Bit;

    DissectBitValue(BitExpr, &Addr, &Bit);

    BAsmCode[1] = 1 << Bit;
    BAsmCode[2] = Lo(Addr);
    switch (Hi(Addr))
    {
      case 0x00:
        BAsmCode[0] = 0x70 + Code;
        CodeLen = 3;
        break;
      case 0x10:
        BAsmCode[0] = 0xa0 + Code;
        CodeLen = 3;
        break;
      default:
        WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[ArgCnt - 1]);
    }
    if ((CodeLen != 0) && Rela)
    {
      tSymbolFlags Flags;
      Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int16, &OK, &Flags) - (EProgCounter() + CodeLen + 1);

      if (!OK)
        CodeLen = 0;
      else if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128)))
      {
        WrError(ErrNum_JmpDistTooBig);
        CodeLen = 0;
      }
      else
        BAsmCode[CodeLen++] = AdrInt & 0xff;
    }
  }
}

static void DecodeDIV(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(2, 2))
  {
    DecodeAdr(&ArgStr[2], MModAccA);
    if (AdrType != ModNone)
    {
      DecodeAdr(&ArgStr[1], MModReg);
      if (AdrType != ModNone)
      {
        BAsmCode[0] = 0xf4;
        BAsmCode[1] = 0xf8;
        BAsmCode[2] = AdrVals[0];
        CodeLen = 3;
      }
    }
  }
}

static void DecodeINCW(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(2, 2))
  {
    DecodeAdr(&ArgStr[2], MModReg);
    if (AdrType != ModNone)
    {
      BAsmCode[2] = AdrVals[0];
      DecodeAdr(&ArgStr[1], MModImm);
      if (AdrType != ModNone)
      {
        BAsmCode[0] = 0x70;
        BAsmCode[1] = AdrVals[0];
        CodeLen = 3;
      }
    }
  }
}

static void DecodeLDST(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(1, 1))
  {
    DecodeAdr(&ArgStr[1], MModImm);
    if (AdrType != ModNone)
    {
      BAsmCode[0] = 0xf0;
      BAsmCode[1] = AdrVals[0];
      CodeLen = 2;
    }
  }
}

static void DecodeTRAP(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(1, 1))
  {
    Boolean OK;

    BAsmCode[0] = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
    if (OK)
    {
      BAsmCode[0] = 0xef - BAsmCode[0];
      CodeLen = 1;
    }
  }
}

static void DecodeTST(Word Code)
{
  UNUSED(Code);

  if (ChkArgCnt(1, 1))
  {
    DecodeAdr(&ArgStr[1], MModAccA + MModAccB);
    switch (AdrType)
    {
      case ModAccA:
        BAsmCode[0] = 0xb0;
        CodeLen = 1;
        break;
      case ModAccB:
        BAsmCode[0] = 0xc6;
        CodeLen = 1;
        break;
    }
  }
}

/****************************************************************************/

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

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

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

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

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

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

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

static void InitFields(void)
{
  InstTable = CreateInstTable(203);
  AddInstTable(InstTable, "MOV", 0, DecodeMOV);
  AddInstTable(InstTable, "MOVW", 0, DecodeMOVW);
  AddInstTable(InstTable, "CMP", 0, DecodeCMP);
  AddInstTable(InstTable, "DIV", 0, DecodeDIV);
  AddInstTable(InstTable, "INCW", 0, DecodeINCW);
  AddInstTable(InstTable, "LDST", 0, DecodeLDST);
  AddInstTable(InstTable, "TRAP", 0, DecodeTRAP);
  AddInstTable(InstTable, "TST", 0, DecodeTST);
  AddInstTable(InstTable, "DBIT", 0, DecodeDBIT);

  InitFixed("CLRC" , 0x00b0); InitFixed("DINT" , 0xf000);
  InitFixed("EINT" , 0xf00c); InitFixed("EINTH", 0xf004);
  InitFixed("EINTL", 0xf008); InitFixed("IDLE" , 0x00f6);
  InitFixed("LDSP" , 0x00fd); InitFixed("NOP"  , 0x00ff);
  InitFixed("RTI"  , 0x00fa); InitFixed("RTS"  , 0x00f9);
  InitFixed("SETC" , 0x00f8); InitFixed("STSP" , 0x00fe);

  InitRel8("JMP", 0x00); InitRel8("JC" , 0x03); InitRel8("JEQ", 0x02);
  InitRel8("JG" , 0x0e); InitRel8("JGE", 0x0d); InitRel8("JHS", 0x0b);
  InitRel8("JL" , 0x09); InitRel8("JLE", 0x0a); InitRel8("JLO", 0x0f);
  InitRel8("JN" , 0x01); InitRel8("JNC", 0x07); InitRel8("JNE", 0x06);
  InitRel8("JNV", 0x0c); InitRel8("JNZ", 0x06); InitRel8("JP" , 0x04);
  InitRel8("JPZ", 0x05); InitRel8("JV" , 0x08); InitRel8("JZ" , 0x02);

  InitALU1("ADC",  9); InitALU1("ADD",  8);
  InitALU1("DAC", 14); InitALU1("DSB", 15);
  InitALU1("SBB", 11); InitALU1("SUB", 10); InitALU1("MPY", 12);

  InitALU2("AND" ,  3); InitALU2("BTJO",  0x0106);
  InitALU2("BTJZ",  0x0107); InitALU2("OR"  ,  4); InitALU2("XOR",  5);

  InitJmp("BR"  , 12); InitJmp("CALL" , 14);
  InitJmp("JMPL", 0x0109); InitJmp("CALLR", 0x010f);

  InitABReg("CLR"  ,  5); InitABReg("COMPL", 11); InitABReg("DEC"  ,  2);
  InitABReg("INC"  ,  3); InitABReg("INV"  ,  4); InitABReg("POP"  , 0x0209);
  InitABReg("PUSH" , 0x0208); InitABReg("RL"   , 14); InitABReg("RLC"  , 15);
  InitABReg("RR"   , 12); InitABReg("RRC"  , 13); InitABReg("SWAP" ,  7);
  InitABReg("XCHB" ,  6); InitABReg("DJNZ" , 0x010a);

  InitBit("CMPBIT",  5); InitBit("JBIT0" ,  0x0107); InitBit("JBIT1" ,  0x0106);
  InitBit("SBIT0" ,  3); InitBit("SBIT1" ,  4);
}

static void DeinitFields(void)
{
  DestroyInstTable(InstTable);
}

/****************************************************************************/

static void MakeCode_370(void)
{
  CodeLen = 0;
  DontPrint = False;
  OpSize = 0;

  /* zu ignorierendes */

  if (Memo(""))
    return;

  /* Pseudoanweisungen */

  if (DecodeIntelPseudo(True))
    return;

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

static Boolean IsDef_370(void)
{
  return (Memo("DBIT"));
}

static void InternSymbol_370(char *Asc,  TempResult *Erg)
{
  Boolean OK;
  String h;
  LargeInt Num;

  as_tempres_set_none(Erg);
  if ((strlen(Asc) < 2) || ((as_toupper(*Asc) != 'R') && (as_toupper(*Asc) != 'P')))
    return;

  strcpy(h, Asc + 1);
  if ((*h == '0') && (strlen(h) > 1))
    *h = '$';
  Num = ConstLongInt(h, &OK, 10);
  if (!OK || (Num < 0) || (Num > 255))
    return;

  if (as_toupper(*Asc) == 'P')
    Num += 0x1000;
  as_tempres_set_int(Erg, Num);
}

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

static void SwitchTo_370(void)
{
  TurnWords = False;
  SetIntConstMode(eIntConstModeIntel);

  PCSymbol = "$";
  HeaderID = 0x49;
  NOPCode = 0xff;
  DivideChars = ",";
  HasAttrs = False;

  ValidSegs = 1 << SegCode;
  Grans[SegCode ] = 1;
  ListGrans[SegCode ] = 1;
  SegInits[SegCode ] = 0;
  SegLimits[SegCode] = 0xffff;

  MakeCode = MakeCode_370;
  IsDef = IsDef_370;
  SwitchFrom = SwitchFrom_370;
  InternSymbol = InternSymbol_370;
  DissectBit = DissectBit_370;

  InitFields();
}

void code370_init(void)
{
  CPU37010 = AddCPU("370C010" , SwitchTo_370);
  CPU37020 = AddCPU("370C020" , SwitchTo_370);
  CPU37030 = AddCPU("370C030" , SwitchTo_370);
  CPU37040 = AddCPU("370C040" , SwitchTo_370);
  CPU37050 = AddCPU("370C050" , SwitchTo_370);
}