Subversion Repositories pentevo

Rev

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

  1. /* code78k3.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator 78K3-Familie                                                */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "bpemu.h"
  16. #include "strutil.h"
  17. #include "asmdef.h"
  18. #include "asmsub.h"
  19. #include "asmpars.h"
  20. #include "asmitree.h"
  21. #include "codepseudo.h"
  22. #include "intpseudo.h"
  23. #include "codevars.h"
  24. #include "headids.h"
  25. #include "errmsg.h"
  26.  
  27. #include "code78k3.h"
  28.  
  29. /*-------------------------------------------------------------------------*/
  30.  
  31. enum
  32. {
  33.   ModNone = -1,
  34.   ModImm = 0,
  35.   ModReg8 = 1,
  36.   ModReg16 = 2,
  37.   ModMem = 3,
  38.   ModShort = 4,
  39.   ModSFR = 5,
  40.   ModAbs = 6,
  41.   ModShortIndir = 7,
  42.   ModSP = 8,
  43.   ModSTBC = 9,
  44.   ModWDM = 10
  45. };
  46.  
  47. #define MModImm (1 << ModImm)
  48. #define MModReg8 (1 << ModReg8)
  49. #define MModReg16 (1 << ModReg16)
  50. #define MModMem (1 << ModMem)
  51. #define MModShort (1 << ModShort)
  52. #define MModSFR (1 << ModSFR)
  53. #define MModAbs (1 << ModAbs)
  54. #define MModShortIndir (1 << ModShortIndir)
  55. #define MModSP (1 << ModSP)
  56. #define MModSTBC (1 << ModSTBC)
  57. #define MModWDM (1 << ModWDM)
  58.  
  59. #define PSWLAddr 0xfffe
  60. #define PSWHAddr 0xffff
  61.  
  62. /*-------------------------------------------------------------------------*/
  63.  
  64. static CPUVar CPU78310;
  65.  
  66. typedef struct
  67. {
  68.   ShortInt Mode, Val;
  69.   Byte Vals[3];
  70.   tSymbolFlags ValSymFlags;
  71.   Boolean ForceLong, ForceRel;
  72.   int Cnt;
  73. } tAdrResult;
  74.  
  75. static ShortInt OpSize;
  76. static Boolean AssumeByte;
  77. static LongInt Reg_RSS;
  78.  
  79. /*-------------------------------------------------------------------------*/
  80. /* address decoders */
  81.  
  82. static Byte AccReg8(void)
  83. {
  84.   return Reg_RSS ? 5 : 1;
  85. }
  86.  
  87. static Byte BReg8(void)
  88. {
  89.   return Reg_RSS ? 7 : 3;
  90. }
  91.  
  92. static Byte CReg8(void)
  93. {
  94.   return Reg_RSS ? 6 : 2;
  95. }
  96.  
  97. static Byte AccReg16(void)
  98. {
  99.   return Reg_RSS ? 2 : 0;
  100. }
  101.  
  102. static Boolean SetOpSize(ShortInt NewSize)
  103. {
  104.   if (OpSize < 0)
  105.   {
  106.     OpSize = NewSize;
  107.     return True;
  108.   }
  109.   else if (OpSize != NewSize)
  110.   {
  111.     WrError(ErrNum_ConfOpSizes);
  112.     return False;
  113.   }
  114.   else
  115.     return True;
  116. }
  117.  
  118. static ShortInt DecodeReg8(const char *pAsc)
  119. {
  120.   ShortInt Result = -1;
  121.  
  122.   switch (strlen(pAsc))
  123.   {
  124.     case 1:
  125.     {
  126.       static const char Reg8Names[9] = "XACBEDLH";
  127.       const char *pPos = strchr(Reg8Names, as_toupper(*pAsc));
  128.  
  129.       if (pPos)
  130.       {
  131.         Result = pPos - Reg8Names;
  132.         /* E/D/L/H maps to R12..R15 */
  133.         if (Result >= 4)
  134.           Result += 8;
  135.         /* X/A/C/B maps to R4..7 if RSS=1 */
  136.         else if (Reg_RSS)
  137.           Result += 4;
  138.       }
  139.  
  140.       break;
  141.     }
  142.  
  143.     case 2:
  144.     {
  145.       if ((toupper(pAsc[0]) == 'R') && isdigit(pAsc[1]))
  146.         Result = pAsc[1] - '0';
  147.  
  148.       break;
  149.     }
  150.  
  151.     case 3:
  152.     {
  153.       static const char Reg8Names[][4] = { "VPL", "VPH", "UPL", "UPH", "R10", "R11", "R12", "R13", "R14", "R15", "" };
  154.       int z;
  155.  
  156.       for (z = 0; *Reg8Names[z]; z++)
  157.         if (!as_strcasecmp(pAsc, Reg8Names[z]))
  158.         {
  159.           /* map to 8..11 resp. 10..15 */
  160.           Result = (z > 4) ? z + 6 : z + 8;
  161.           break;
  162.         }
  163.     }
  164.   }
  165.  
  166.   return Result;
  167. }
  168.  
  169. static ShortInt DecodeReg16(const char *pAsc)
  170. {
  171.   ShortInt Result = -1;
  172.  
  173.   switch (strlen(pAsc))
  174.   {
  175.     case  2:
  176.     {
  177.       static const char Reg16Names[][3] = { "AX", "BC", "VP", "UP", "DE", "HL", "" };
  178.       int z;
  179.  
  180.       for (z = 0; *Reg16Names[z]; z++)
  181.         if (!as_strcasecmp(Reg16Names[z], pAsc))
  182.         {
  183.           Result = ((z >= 2) || Reg_RSS) ? z + 2 : z;
  184.           break;
  185.         }
  186.       break;
  187.     }
  188.  
  189.     case 3:
  190.     {
  191.       if ((toupper(pAsc[0]) == 'R') && (toupper(pAsc[1]) == 'P')
  192.        && (pAsc[2] >= '0') && (pAsc[2] <= '7'))
  193.         Result = pAsc[2] - '0';
  194.  
  195.       break;
  196.     }
  197.   }
  198.  
  199.   return Result;
  200. }
  201.  
  202. static ShortInt DecodeIndReg16(const char *pAsc)
  203. {
  204.   int l = strlen(pAsc);
  205.   char Copy[10];
  206.  
  207.   if ((l < 2) || (l > 5) || (*pAsc != '[') || (pAsc[l -1] != ']'))
  208.     return -1;
  209.   memcpy(Copy, pAsc + 1, l - 2); Copy[l - 2] = '\0';
  210.   l =  DecodeReg16(Copy);
  211.   return l;
  212. }
  213.  
  214. static ShortInt DecodeRegBank(const char *pAsc)
  215. {
  216.   if ((strlen(pAsc) == 3)
  217.    && (toupper(pAsc[0]) == 'R') && (toupper(pAsc[1]) == 'B')
  218.    && (pAsc[2] >= '0') && (pAsc[2] <= '7'))
  219.     return pAsc[2] - '0';
  220.   else
  221.     return -1;
  222. }
  223.  
  224. static void ExecAssumeByte(void)
  225. {
  226.   if ((OpSize == -1) && AssumeByte)
  227.   {
  228.     SetOpSize(0);
  229.     AssumeByte = False;
  230.   }
  231. }
  232.  
  233. static ShortInt DecodeAdr(const tStrComp *pArg, Word Mask, tAdrResult *pResult)
  234. {
  235.   Boolean OK;
  236.   Word WordOp;
  237.   int ArgLen;
  238.   unsigned Offset;
  239.  
  240.   pResult->Mode = ModNone;
  241.   pResult->Cnt = 0;
  242.   pResult->ForceLong =
  243.   pResult->ForceRel = False;
  244.  
  245.   /* immediate ? */
  246.  
  247.   if (*pArg->str.p_str == '#')
  248.   {
  249.     ExecAssumeByte();
  250.     switch (OpSize)
  251.     {
  252.       case 0:
  253.         pResult->Vals[0] = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK);
  254.         if (OK)
  255.         {
  256.           pResult->Cnt = 1;
  257.           pResult->Mode = ModImm;
  258.         }
  259.         break;
  260.       case 1:
  261.         WordOp = EvalStrIntExpressionOffs(pArg, 1, Int16, &OK);
  262.         if (OK)
  263.         {
  264.           pResult->Vals[0] = Lo(WordOp);
  265.           pResult->Vals[1] = Hi(WordOp);
  266.           pResult->Cnt = 2;
  267.           pResult->Mode = ModImm;
  268.         }
  269.         break;
  270.       default:
  271.         WrError(ErrNum_UndefOpSizes);
  272.     }
  273.     goto AdrFound;
  274.   }
  275.  
  276.   /* 8 bit registers? */
  277.  
  278.   if ((pResult->Val = DecodeReg8(pArg->str.p_str)) >= 0)
  279.   {
  280.     pResult->Mode = ModReg8;
  281.     SetOpSize(0);
  282.     goto AdrFound;
  283.   }
  284.  
  285.   if (!as_strcasecmp(pArg->str.p_str, "STBC"))
  286.   {
  287.     pResult->Mode = ModSTBC;
  288.     SetOpSize(0);
  289.     goto AdrFound;
  290.   }
  291.  
  292.   if (!as_strcasecmp(pArg->str.p_str, "WDM"))
  293.   {
  294.     pResult->Mode = ModWDM;
  295.     SetOpSize(0);
  296.     goto AdrFound;
  297.   }
  298.  
  299.   /* 16 bit registers? */
  300.  
  301.   if ((pResult->Val = DecodeReg16(pArg->str.p_str)) >= 0)
  302.   {
  303.     pResult->Mode = ModReg16;
  304.     SetOpSize(1);
  305.     goto AdrFound;
  306.   }
  307.  
  308.   if (!as_strcasecmp(pArg->str.p_str, "SP"))
  309.   {
  310.     pResult->Mode = ModSP;
  311.     SetOpSize(1);
  312.     goto AdrFound;
  313.   }
  314.  
  315.   /* memory-indirect addressing? */
  316.  
  317.   ArgLen = strlen(pArg->str.p_str);
  318.   if ((ArgLen >= 2) && (pArg->str.p_str[ArgLen - 1] == ']'))
  319.   {
  320.     tStrComp Arg;
  321.     char *pStart;
  322.  
  323.     StrCompRefRight(&Arg, pArg, 0);
  324.  
  325.     /* remove ']' */
  326.  
  327.     StrCompShorten(&Arg, 1);
  328.  
  329.     pStart = RQuotPos(Arg.str.p_str, '[');
  330.     if (!pStart)
  331.     {
  332.       WrError(ErrNum_BrackErr);
  333.       goto AdrFound;
  334.     }
  335.  
  336.     /* purely indirect? */
  337.  
  338.     if (pStart == Arg.str.p_str)
  339.     {
  340.       static const char Modes[][5] = { "DE+",  "HL+",  "DE-",  "HL-",  "DE",  "HL",  "VP",  "UP",
  341.                                        "RP6+", "RP7+", "RP6-", "RP7-", "RP6", "RP7", "RP4", "RP5" };
  342.       unsigned z;
  343.       char *pSep, Save;
  344.       tStrComp Base, Remainder;
  345.  
  346.       /* skip '[' */
  347.  
  348.       StrCompIncRefLeft(&Arg, 1);
  349.  
  350.       /* simple expression without displacement? */
  351.  
  352.       for (z = 0; z < sizeof(Modes) / sizeof(*Modes); z++)
  353.         if (!as_strcasecmp(Arg.str.p_str, Modes[z]))
  354.         {
  355.           pResult->Mode = ModMem; pResult->Val = 0x16;
  356.           pResult->Vals[0] = z % (sizeof(Modes) / sizeof(*Modes) / 2);
  357.           pResult->Cnt = 1;
  358.           goto AdrFound;
  359.         }
  360.  
  361.       /* no -> extract base register. Its name ends with the first non-letter,
  362.          which either means +/- or a blank */
  363.  
  364.       for (pSep = Arg.str.p_str; *pSep; pSep++)
  365.         if (!as_isalpha(*pSep))
  366.           break;
  367.  
  368.       /* decode base register.  SP is not otherwise handled. */
  369.  
  370.       Save = StrCompSplitRef(&Base, &Remainder, &Arg, pSep);
  371.       if (!as_strcasecmp(Base.str.p_str, "SP"))
  372.         pResult->Vals[0] = 1;
  373.       else
  374.       {
  375.         int tmp;
  376.  
  377.         tmp = DecodeReg16(Base.str.p_str);
  378.         switch (tmp)
  379.         {
  380.           case -1: pResult->Vals[0] = 0xff; break; /* no register */
  381.           case 4: pResult->Vals[0] = 4; break; /* VP */
  382.           case 5: pResult->Vals[0] = 3; break; /* UP */
  383.           case 6: pResult->Vals[0] = 0; break; /* DE */
  384.           case 7: pResult->Vals[0] = 2; break; /* HL */
  385.           default:
  386.             WrStrErrorPos(ErrNum_InvReg, &Base);
  387.             goto AdrFound;
  388.         }
  389.       }
  390.       *pSep = Save;
  391.  
  392.       /* no base register detected: purely indirect */
  393.  
  394.       if (0xff == pResult->Vals[0])
  395.       {
  396.         tSymbolFlags Flags;
  397.  
  398.         WordOp = EvalStrIntExpressionWithFlags(&Arg, UInt16, &OK, &Flags);
  399.         if (OK)
  400.         {
  401.           if (mFirstPassUnknown(Flags))
  402.             WordOp = 0xfe20;
  403.           if (ChkRange(WordOp, 0xfe20, 0xff1f))
  404.           {
  405.             pResult->Mode = ModShortIndir;
  406.             pResult->Vals[0] = Lo(WordOp);
  407.           }
  408.         }
  409.         goto AdrFound;
  410.       }
  411.  
  412.       /* Now that we have the base, prepare displacement.  May
  413.          be an 8/16-bit register in certain combinations, or a number: */
  414.  
  415.       if (*pSep == '+')
  416.       {
  417.         int tmp;
  418.  
  419.         tmp = DecodeReg8(pSep + 1);
  420.         if (tmp == -1); /* no reg at all */
  421.         else if ((tmp == AccReg8())  /* A */
  422.               || (tmp == BReg8())) /* B */
  423.         {
  424.           if (pResult->Vals[0] == 0) /* DE+A/B */
  425.           {
  426.             pResult->Mode = ModMem; pResult->Val = 0x17;
  427.             pResult->Cnt = 1; pResult->Vals[0] = tmp & 2;
  428.             goto AdrFound;
  429.           }
  430.           else if (pResult->Vals[0] == 2) /* HL+A/B */
  431.           {
  432.             pResult->Mode = ModMem; pResult->Val = 0x17;
  433.             pResult->Cnt = 1; pResult->Vals[0] = tmp;
  434.             goto AdrFound;
  435.           }
  436.           else
  437.             WrError(ErrNum_InvAddrMode);
  438.           goto AdrFound;
  439.         }
  440.         else
  441.         {
  442.           WrError(ErrNum_InvAddrMode);
  443.           goto AdrFound;
  444.         }
  445.         tmp = DecodeReg16(pSep + 1);
  446.         switch (tmp)
  447.         {
  448.           case -1: /* no reg at all */
  449.             break;
  450.           case 6: /* DE */
  451.           case 7: /* HL */
  452.             if (pResult->Vals[0] == 4) /* VP+DE/HL */
  453.             {
  454.               pResult->Mode = ModMem; pResult->Val = 0x17;
  455.               pResult->Cnt = 1; pResult->Vals[0] = tmp - 2;
  456.               goto AdrFound;
  457.             }
  458.             /* fall-through */
  459.           default:
  460.             WrError(ErrNum_InvAddrMode);
  461.             goto AdrFound;
  462.         }
  463.       }
  464.  
  465.       /* it's a number: put a fake 0 in front so displacement expression evaluates correctly! */
  466.  
  467.       if (pSep > Arg.str.p_str)
  468.         pSep--;
  469.       *pSep = '0';
  470.       pResult->Vals[1] = EvalStrIntExpressionOffs(&Arg, pSep - Arg.str.p_str, Int8, &OK);
  471.       if (OK)
  472.       {
  473.         pResult->Mode = ModMem; pResult->Val = 0x06;
  474.         pResult->Cnt = 2;
  475.         goto AdrFound;
  476.       }
  477.     }
  478.  
  479.     /* no -> with outer displacement */
  480.  
  481.     else
  482.     {
  483.       int tmp;
  484.       tStrComp Disp, Reg;
  485.  
  486.       /* split displacement + register */
  487.  
  488.       StrCompSplitRef(&Disp, &Reg, &Arg, pStart);
  489.  
  490.        /* handle base register */
  491.  
  492.       tmp = DecodeReg8(Reg.str.p_str);
  493.       if ((tmp == AccReg8()) /* A */
  494.        || (tmp == BReg8())) /* B */
  495.       {
  496.         pResult->Vals[0] = tmp & 3;
  497.       }
  498.       else if (tmp == -1)
  499.       {
  500.         tmp = DecodeReg16(Reg.str.p_str);
  501.         if (tmp >= 6) /* DE/HL */
  502.         {
  503.           pResult->Vals[0] = (tmp - 6) << 1;
  504.         }
  505.         else
  506.         {
  507.           WrStrErrorPos(ErrNum_InvReg, &Reg);
  508.           goto AdrFound;
  509.         }
  510.       }
  511.       else
  512.       {
  513.         WrStrErrorPos(ErrNum_InvReg, &Reg);
  514.         goto AdrFound;
  515.       }
  516.  
  517.       /* compute displacement */
  518.  
  519.       WordOp = EvalStrIntExpression(&Disp, Int16, &OK);
  520.       if (OK)
  521.       {
  522.         pResult->Mode = ModMem; pResult->Val = 0x0a;
  523.         pResult->Vals[1] = Lo(WordOp); pResult->Vals[2] = Hi(WordOp);
  524.         pResult->Cnt = 3;
  525.         goto AdrFound;
  526.       }
  527.     }
  528.   }
  529.  
  530.   /* OK, nothing but absolute left...exclamation mark enforces 16-bit addressing,
  531.      dollar sign relative addressing.  Relative flag is only a hint to the individual
  532.      instruction decoders and not used in this context. */
  533.  
  534.   Offset = 0;
  535.   if (pArg->str.p_str[Offset] == '!')
  536.   {
  537.     pResult->ForceLong = True;
  538.     Offset++;
  539.   }
  540.   else if (pArg->str.p_str[Offset] == '$')
  541.   {
  542.     pResult->ForceRel = True;
  543.     Offset++;
  544.   }
  545.  
  546.   WordOp = EvalStrIntExpressionOffsWithFlags(pArg, Offset, UInt16, &OK, &pResult->ValSymFlags);
  547.   if (OK)
  548.   {
  549.     if ((Mask & MModShort) && (!pResult->ForceLong) && ((WordOp >= 0xfe20) && (WordOp <= 0xff1f)))
  550.     {
  551.       pResult->Mode = ModShort; pResult->Cnt = 1;
  552.       pResult->Vals[0] = Lo(WordOp);
  553.     }
  554.     else if ((Mask & MModSFR) && (!pResult->ForceLong) && (Hi(WordOp) == 0xff))
  555.     {
  556.       pResult->Mode = ModSFR; pResult->Cnt = 1;
  557.       pResult->Vals[0] = Lo(WordOp);
  558.     }
  559.     else
  560.     {
  561.       pResult->Mode = ModAbs; pResult->Cnt = 2;
  562.       pResult->Vals[0] = Lo(WordOp);
  563.       pResult->Vals[1] = Hi(WordOp);
  564.     }
  565.   }
  566.  
  567. AdrFound:
  568.  
  569.   if ((pResult->Mode != ModNone) && (!(Mask & (1 << pResult->Mode))))
  570.   {
  571.     WrError(ErrNum_InvAddrMode);
  572.     pResult->Mode = ModNone; pResult->Cnt = 0;
  573.   }
  574.   return pResult->Mode;
  575. }
  576.  
  577. static void AppendDisp(const tStrComp *pArg)
  578. {
  579.   Boolean OK;
  580.   LongInt Dist;
  581.   tSymbolFlags Flags;
  582.  
  583.   Dist = EvalStrIntExpressionOffsWithFlags(pArg, !!(*pArg->str.p_str == '$'), UInt16, &OK, &Flags) - (EProgCounter() + CodeLen + 1);
  584.   if (!mSymbolQuestionable(Flags) && ((Dist < -128) || (Dist > 127)))
  585.   {
  586.     WrError(ErrNum_JmpDistTooBig);
  587.     CodeLen = 0;
  588.   }
  589.   else
  590.     BAsmCode[CodeLen++] = Dist & 0xff;
  591. }
  592.  
  593. static Boolean ChkAcc(tStrComp *pArg)
  594. {
  595.   tAdrResult AdrResult;
  596.  
  597.   if (DecodeAdr(pArg, OpSize ? MModReg16 : MModReg8, &AdrResult) == ModNone)
  598.     return False;
  599.  
  600.   if (((OpSize) && (AdrResult.Val != AccReg16()))
  601.    || ((!OpSize) && (AdrResult.Val != AccReg8())))
  602.   {
  603.     WrError(ErrNum_InvAddrMode);
  604.     return False;
  605.   }
  606.  
  607.   return True;
  608. }
  609.  
  610. static Boolean DecodeBitAdr(const tStrComp *pArg, LongWord *pResult)
  611. {
  612.   char *pSplit;
  613.   Boolean OK;
  614.  
  615.   pSplit = RQuotPos(pArg->str.p_str, '.');
  616.  
  617.   if (pSplit)
  618.   {
  619.     tStrComp RegArg, BitArg;
  620.  
  621.     StrCompSplitRef(&RegArg, &BitArg, pArg, pSplit);
  622.  
  623.     *pResult = EvalStrIntExpression(&BitArg, UInt3, &OK) << 8;
  624.     if (OK)
  625.     {
  626.       tAdrResult AdrResult;
  627.  
  628.       switch (DecodeAdr(&RegArg, MModReg8 | MModSFR | MModShort, &AdrResult))
  629.       {
  630.         case ModReg8:
  631.           if ((AdrResult.Val != AccReg8()) && (AdrResult.Val != AccReg8() - 1))
  632.           {
  633.             WrStrErrorPos(ErrNum_InvReg, &RegArg);
  634.             OK = FALSE;
  635.           }
  636.           else
  637.             *pResult |= (((LongWord)(AdrResult.Val & 1)) << 11) | 0x00030000;
  638.           break;
  639.         case ModSFR:
  640.           switch (AdrResult.Vals[0])
  641.           {
  642.             case PSWLAddr & 0xff:
  643.               *pResult |= 0x00020000;
  644.               break;
  645.             case PSWHAddr & 0xff:
  646.               *pResult |= 0x00020800;
  647.               break;
  648.             default:
  649.               *pResult |= 0x01080800 | *AdrResult.Vals;
  650.               break;
  651.           }
  652.           break;
  653.         case ModShort:
  654.           *pResult |= 0x01080000 | *AdrResult.Vals;
  655.           break;
  656.         default:
  657.           OK = FALSE;
  658.       }
  659.     }
  660.   }
  661.   else
  662.     *pResult = EvalStrIntExpression(pArg, UInt32, &OK);
  663.  
  664.   return OK;
  665. }
  666.  
  667. /*-------------------------------------------------------------------------*/
  668. /* Instruction Decoders */
  669.  
  670. static void DecodeFixed(Word Index)
  671. {
  672.   if (ChkArgCnt(0, 0))
  673.     BAsmCode[CodeLen++] = Lo(Index);
  674. }
  675.  
  676. static void DecodeMOV(Word Is16)
  677. {
  678.   if (Is16)
  679.     SetOpSize(1);
  680.  
  681.   if (ChkArgCnt(2, 2))
  682.   {
  683.     tAdrResult DestAdrResult;
  684.  
  685.     switch (DecodeAdr(&ArgStr[1], MModReg16 | MModSP | MModShort | MModSFR
  686.                     | (Is16 ? 0 : (MModReg8 | MModSTBC | MModWDM | MModAbs | MModShortIndir | MModMem)), &DestAdrResult))
  687.     {
  688.       case ModReg8:
  689.       {
  690.         tAdrResult SrcAdrResult;
  691.  
  692.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8 | ((DestAdrResult.Val == AccReg8()) ? (MModMem | MModAbs | MModShort | MModSFR | MModShortIndir) : 0), &SrcAdrResult))
  693.         {
  694.           case ModImm:
  695.             if (DestAdrResult.Val >= 8) WrError(ErrNum_InvAddrMode);
  696.             else
  697.             {
  698.               BAsmCode[CodeLen++] = 0xb8 | DestAdrResult.Val;
  699.               BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  700.             }
  701.             break;
  702.           case ModReg8:
  703.             if (SrcAdrResult.Val >= 8) WrError(ErrNum_InvAddrMode);
  704.             else if (DestAdrResult.Val == AccReg8())
  705.               BAsmCode[CodeLen++] = 0xd0 | SrcAdrResult.Val;
  706.             else
  707.             {
  708.               BAsmCode[CodeLen++] = 0x24;
  709.               BAsmCode[CodeLen++] = (DestAdrResult.Val << 4) | SrcAdrResult.Val;
  710.             }
  711.             break;
  712.           case ModMem:
  713.             if ((SrcAdrResult.Val == 0x16) && (SrcAdrResult.Vals[0] <= 5))
  714.               BAsmCode[CodeLen++] = 0x58 | SrcAdrResult.Vals[0];
  715.             else
  716.             {
  717.               BAsmCode[CodeLen++] = 0x00 | SrcAdrResult.Val;
  718.               BAsmCode[CodeLen++] = 0x00 | (SrcAdrResult.Vals[0] << 4);
  719.               memcpy(BAsmCode + CodeLen, SrcAdrResult.Vals + 1, SrcAdrResult.Cnt - 1);
  720.               CodeLen += SrcAdrResult.Cnt - 1;
  721.             }
  722.             break;
  723.           case ModAbs:
  724.             BAsmCode[CodeLen++] = 0x09;
  725.             BAsmCode[CodeLen++] = 0xf0;
  726.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  727.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  728.             break;
  729.           case ModShort:
  730.             BAsmCode[CodeLen++] = 0x20;
  731.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  732.             break;
  733.           case ModSFR:
  734.             BAsmCode[CodeLen++] = 0x10;
  735.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  736.             break;
  737.           case ModShortIndir:
  738.             BAsmCode[CodeLen++] = 0x18;
  739.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  740.             break;
  741.         }
  742.         break;
  743.       }
  744.       case ModSTBC:
  745.       {
  746.         tAdrResult SrcAdrResult;
  747.  
  748.         switch (DecodeAdr(&ArgStr[2], MModImm, &SrcAdrResult))
  749.         {
  750.           case ModImm:
  751.             BAsmCode[CodeLen++] = 0x09;
  752.             BAsmCode[CodeLen++] = 0x44;
  753.             BAsmCode[CodeLen++] = 0xff - SrcAdrResult.Vals[0];
  754.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  755.             break;
  756.         }
  757.         break;
  758.       }
  759.       case ModWDM:
  760.       {
  761.         tAdrResult SrcAdrResult;
  762.  
  763.         switch (DecodeAdr(&ArgStr[2], MModImm, &SrcAdrResult))
  764.         {
  765.           case ModImm:
  766.             BAsmCode[CodeLen++] = 0x09;
  767.             BAsmCode[CodeLen++] = 0x42;
  768.             BAsmCode[CodeLen++] = 0xff - SrcAdrResult.Vals[0];
  769.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  770.             break;
  771.         }
  772.         break;
  773.       }
  774.       case ModReg16:
  775.       {
  776.         tAdrResult SrcAdrResult;
  777.  
  778.         switch (DecodeAdr(&ArgStr[2], MModReg16 | MModImm | ((DestAdrResult.Val == AccReg16()) ? (MModShort | MModSFR | MModSP) : 0), &SrcAdrResult))
  779.         {
  780.           case ModReg16:
  781.             BAsmCode[CodeLen++] = 0x24;
  782.             BAsmCode[CodeLen++] = 0x08 | (DestAdrResult.Val << 5) | SrcAdrResult.Val;
  783.             break;
  784.           case ModImm:
  785.             BAsmCode[CodeLen++] = 0x60 | DestAdrResult.Val;
  786.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  787.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  788.             break;
  789.           case ModShort:
  790.             BAsmCode[CodeLen++] = 0x1c;
  791.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  792.             break;
  793.           case ModSFR:
  794.             BAsmCode[CodeLen++] = 0x11;
  795.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  796.             break;
  797.           case ModSP:
  798.             BAsmCode[CodeLen++] = 0x11;
  799.             BAsmCode[CodeLen++] = 0xfc;
  800.             break;
  801.         }
  802.         break;
  803.       }
  804.       case ModSP:
  805.       {
  806.         tAdrResult SrcAdrResult;
  807.  
  808.         switch (DecodeAdr(&ArgStr[2], MModReg16 | MModImm, &SrcAdrResult))
  809.         {
  810.           case ModReg16:
  811.             if (SrcAdrResult.Val != AccReg16()) WrError(ErrNum_InvAddrMode);
  812.             else
  813.             {
  814.               BAsmCode[CodeLen++] = 0x13;
  815.               BAsmCode[CodeLen++] = 0xfc;
  816.             }
  817.             break;
  818.           case ModImm:
  819.             BAsmCode[CodeLen++] = 0x0b;
  820.             BAsmCode[CodeLen++] = 0xfc;
  821.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  822.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  823.             break;
  824.         }
  825.         break;
  826.       }
  827.       case ModShort:
  828.       {
  829.         tAdrResult SrcAdrResult;
  830.  
  831.         AssumeByte = (OpSize == -1);
  832.         switch (DecodeAdr(&ArgStr[2], MModImm | MModShort | MModReg8 | MModReg16, &SrcAdrResult))
  833.         {
  834.           case ModImm:
  835.             BAsmCode[CodeLen++] = OpSize ? 0x0c : 0x3a;
  836.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  837.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  838.             if (OpSize)
  839.               BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  840.             break;
  841.           case ModShort:
  842.             ExecAssumeByte();
  843.             BAsmCode[CodeLen++] = (OpSize == 1) ? 0x3c : 0x38;
  844.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  845.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  846.             break;
  847.           case ModReg8:
  848.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  849.             else
  850.             {
  851.               BAsmCode[CodeLen++] = 0x22;
  852.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  853.             }
  854.             break;
  855.           case ModReg16:
  856.             if (SrcAdrResult.Val != AccReg16()) WrError(ErrNum_InvAddrMode);
  857.             else
  858.             {
  859.               BAsmCode[CodeLen++] = 0x1a;
  860.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  861.             }
  862.             break;
  863.         }
  864.         break;
  865.       }
  866.       case ModSFR:
  867.       {
  868.         tAdrResult SrcAdrResult;
  869.  
  870.         AssumeByte = (OpSize == -1);
  871.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8 | MModReg16, &SrcAdrResult))
  872.         {
  873.           case ModImm:
  874.             BAsmCode[CodeLen++] = OpSize ? 0x0b : 0x2b;
  875.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  876.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  877.             if (OpSize)
  878.               BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  879.             break;
  880.           case ModReg8:
  881.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  882.             else
  883.             {
  884.               BAsmCode[CodeLen++] = 0x12;
  885.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  886.             }
  887.             break;
  888.           case ModReg16:
  889.             if (SrcAdrResult.Val != AccReg16()) WrError(ErrNum_InvAddrMode);
  890.             else
  891.             {
  892.               BAsmCode[CodeLen++] = 0x13;
  893.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  894.             }
  895.             break;
  896.         }
  897.         break;
  898.       }
  899.       case ModMem:
  900.       {
  901.         tAdrResult SrcAdrResult;
  902.  
  903.         SetOpSize(0);
  904.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8, &SrcAdrResult))
  905.         {
  906.           case ModReg8:
  907.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  908.             else if ((DestAdrResult.Val == 0x16) && (DestAdrResult.Vals[0] <= 5))
  909.               BAsmCode[CodeLen++] = 0x50 | DestAdrResult.Vals[0];
  910.             else
  911.             {
  912.               BAsmCode[CodeLen++] = 0x00 | DestAdrResult.Val;
  913.               BAsmCode[CodeLen++] = 0x80 | (DestAdrResult.Vals[0] << 4);
  914.               memcpy(BAsmCode + CodeLen, DestAdrResult.Vals + 1, DestAdrResult.Cnt - 1);
  915.               CodeLen += DestAdrResult.Cnt - 1;
  916.             }
  917.             break;
  918.           /* ModImm? */
  919.         }
  920.         break;
  921.       }
  922.       case ModAbs:
  923.       {
  924.         tAdrResult SrcAdrResult;
  925.  
  926.         switch (DecodeAdr(&ArgStr[2], MModReg8, &SrcAdrResult))
  927.         {
  928.           case ModReg8:
  929.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  930.             else
  931.             {
  932.               BAsmCode[CodeLen++] = 0x09;
  933.               BAsmCode[CodeLen++] = 0xf1;
  934.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  935.               BAsmCode[CodeLen++] = DestAdrResult.Vals[1];
  936.             }
  937.             break;
  938.         }
  939.         break;
  940.       }
  941.       case ModShortIndir:
  942.       {
  943.         tAdrResult SrcAdrResult;
  944.  
  945.         switch (DecodeAdr(&ArgStr[2], MModReg8, &SrcAdrResult))
  946.         {
  947.           case ModReg8:
  948.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  949.             else
  950.             {
  951.               BAsmCode[CodeLen++] = 0x19;
  952.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  953.             }
  954.             break;
  955.         }
  956.         break;
  957.       }
  958.     }
  959.   }
  960. }
  961.  
  962. static void DecodeXCH(Word Is16)
  963. {
  964.   if (Is16)
  965.     SetOpSize(1);
  966.  
  967.   if (ChkArgCnt(2, 2))
  968.   {
  969.     tAdrResult DestAdrResult;
  970.  
  971.     switch (DecodeAdr(&ArgStr[1], MModReg16 | MModShort | MModSFR
  972.                     | (Is16 ? 0 : (MModReg8 | MModShortIndir | MModMem)), &DestAdrResult))
  973.     {
  974.       case ModReg8:
  975.       {
  976.         tAdrResult SrcAdrResult;
  977.  
  978.         switch (DecodeAdr(&ArgStr[2], MModReg8 | ((DestAdrResult.Val == AccReg8()) ? (MModMem | MModShort | MModShortIndir | MModSFR) : 0), &SrcAdrResult))
  979.         {
  980.           case ModReg8:
  981.             if ((DestAdrResult.Val == AccReg8()) && (SrcAdrResult.Val < 8))
  982.               BAsmCode[CodeLen++] = 0xd8 | SrcAdrResult.Val;
  983.             else if ((SrcAdrResult.Val == AccReg8()) && (DestAdrResult.Val < 8))
  984.               BAsmCode[CodeLen++] = 0xd8 | DestAdrResult.Val;
  985.             else if (DestAdrResult.Val < 8)
  986.             {
  987.               BAsmCode[CodeLen++] = 0x25;
  988.               BAsmCode[CodeLen++] = 0x00 | (SrcAdrResult.Val << 4) | DestAdrResult.Val;
  989.             }
  990.             else if (SrcAdrResult.Val < 8)
  991.             {
  992.               BAsmCode[CodeLen++] = 0x25;
  993.               BAsmCode[CodeLen++] = 0x00 | (DestAdrResult.Val << 4) | SrcAdrResult.Val;
  994.             }
  995.             else
  996.               WrError(ErrNum_InvRegPair);
  997.             break;
  998.           case ModMem:
  999.             BAsmCode[CodeLen++] = 0x00 | SrcAdrResult.Val;
  1000.             BAsmCode[CodeLen++] = 0x04 | (SrcAdrResult.Vals[0] << 4);
  1001.             memcpy(BAsmCode + CodeLen, SrcAdrResult.Vals + 1, SrcAdrResult.Cnt - 1);
  1002.             CodeLen += SrcAdrResult.Cnt - 1;
  1003.             break;
  1004.           case ModShort:
  1005.             BAsmCode[CodeLen++] = 0x21;
  1006.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1007.             break;
  1008.           case ModSFR:
  1009.             BAsmCode[CodeLen++] = 0x01;
  1010.             BAsmCode[CodeLen++] = 0x21;
  1011.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1012.             break;
  1013.           case ModShortIndir:
  1014.             BAsmCode[CodeLen++] = 0x23;
  1015.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1016.             break;
  1017.         }
  1018.         break;
  1019.       }
  1020.       case ModReg16:
  1021.       {
  1022.         tAdrResult SrcAdrResult;
  1023.  
  1024.         switch (DecodeAdr(&ArgStr[2], MModReg16 | ((DestAdrResult.Val == AccReg16()) ? (MModShort | MModSFR) : 0), &SrcAdrResult))
  1025.         {
  1026.           case ModReg16:
  1027.             BAsmCode[CodeLen++] = 0x25;
  1028.             BAsmCode[CodeLen++] = 0x08 | (DestAdrResult.Val << 5) | SrcAdrResult.Val;
  1029.             break;
  1030.           case ModShort:
  1031.             BAsmCode[CodeLen++] = 0x1b;
  1032.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1033.             break;
  1034.           case ModSFR:
  1035.             BAsmCode[CodeLen++] = 0x01;
  1036.             BAsmCode[CodeLen++] = 0x1b;
  1037.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1038.             break;
  1039.         }
  1040.         break;
  1041.       }
  1042.       case ModShort:
  1043.       {
  1044.         tAdrResult SrcAdrResult;
  1045.  
  1046.         switch (DecodeAdr(&ArgStr[2], MModReg8 | MModReg16 | MModShort, &SrcAdrResult))
  1047.         {
  1048.           case ModReg8:
  1049.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  1050.             else
  1051.             {
  1052.               BAsmCode[CodeLen++] = 0x21;
  1053.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1054.             }
  1055.             break;
  1056.           case ModReg16:
  1057.             if (SrcAdrResult.Val != AccReg16()) WrError(ErrNum_InvAddrMode);
  1058.             else
  1059.             {
  1060.               BAsmCode[CodeLen++] = 0x1b;
  1061.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1062.             }
  1063.             break;
  1064.           case ModShort:
  1065.             BAsmCode[CodeLen++] = (OpSize == 1) ? 0x2a : 0x39;
  1066.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1067.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1068.             break;
  1069.         }
  1070.         break;
  1071.       }
  1072.       case ModSFR:
  1073.       {
  1074.         tAdrResult SrcAdrResult;
  1075.  
  1076.         switch (DecodeAdr(&ArgStr[2], MModReg8 | MModReg16, &SrcAdrResult))
  1077.         {
  1078.           case ModReg8:
  1079.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  1080.             else
  1081.             {
  1082.               BAsmCode[CodeLen++] = 0x01;
  1083.               BAsmCode[CodeLen++] = 0x21;
  1084.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1085.             }
  1086.             break;
  1087.           case ModReg16:
  1088.             if (SrcAdrResult.Val != AccReg16()) WrError(ErrNum_InvAddrMode);
  1089.             else
  1090.             {
  1091.               BAsmCode[CodeLen++] = 0x01;
  1092.               BAsmCode[CodeLen++] = 0x1b;
  1093.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1094.             }
  1095.             break;
  1096.         }
  1097.         break;
  1098.       }
  1099.       case ModMem:
  1100.       {
  1101.         tAdrResult SrcAdrResult;
  1102.  
  1103.         switch (DecodeAdr(&ArgStr[2], MModReg8, &SrcAdrResult))
  1104.         {
  1105.           case ModReg8:
  1106.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  1107.             else
  1108.             {
  1109.               BAsmCode[CodeLen++] = 0x00 | DestAdrResult.Val;
  1110.               BAsmCode[CodeLen++] = 0x04 | (DestAdrResult.Vals[0] << 4);
  1111.               memcpy(BAsmCode + CodeLen, DestAdrResult.Vals + 1, DestAdrResult.Cnt - 1);
  1112.               CodeLen += DestAdrResult.Cnt - 1;
  1113.             }
  1114.             break;
  1115.         }
  1116.         break;
  1117.       }
  1118.       case ModShortIndir:
  1119.       {
  1120.         tAdrResult SrcAdrResult;
  1121.  
  1122.         switch (DecodeAdr(&ArgStr[2], MModReg8, &SrcAdrResult))
  1123.         {
  1124.           case ModReg8:
  1125.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  1126.             else
  1127.             {
  1128.               BAsmCode[CodeLen++] = 0x23;
  1129.               BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1130.             }
  1131.             break;
  1132.         }
  1133.         break;
  1134.       }
  1135.     }
  1136.   }
  1137. }
  1138.  
  1139. static void DecodeALU(Word Props)
  1140. {
  1141.   const Byte Code8 = (Props >> 0) & 15,
  1142.              Code16 = (Props >> 4) & 15,
  1143.              Code16Reg = (Props >> 8) & 15;
  1144.   const Boolean Is16 = (Props & 0x8000) || False,
  1145.                 May16 = (Props & 0x4000) || False;
  1146.  
  1147.   if (Is16)
  1148.     SetOpSize(1);
  1149.  
  1150.   if (ChkArgCnt(2, 2))
  1151.   {
  1152.     tAdrResult DestAdrResult;
  1153.  
  1154.     switch (DecodeAdr(&ArgStr[1],
  1155.                       MModShort | MModSFR
  1156.                     | (May16 ? MModReg16 : 0)
  1157.                     | (Is16 ? 0 : (MModReg8 | MModMem)), &DestAdrResult))
  1158.     {
  1159.       case ModReg8:
  1160.       {
  1161.         tAdrResult SrcAdrResult;
  1162.  
  1163.         switch (DecodeAdr(&ArgStr[2], MModReg8 | ((DestAdrResult.Val == AccReg8()) ? (MModShort | MModSFR | MModMem | MModImm) : 0), &SrcAdrResult))
  1164.         {
  1165.           case ModReg8:
  1166.             if (SrcAdrResult.Val >= 8) WrError(ErrNum_InvAddrMode);
  1167.             else
  1168.             {
  1169.               BAsmCode[CodeLen++] = 0x88 | Code8;
  1170.               BAsmCode[CodeLen++] = (DestAdrResult.Val << 4) | SrcAdrResult.Val;
  1171.             }
  1172.             break;
  1173.           case ModShort:
  1174.             BAsmCode[CodeLen++] = 0x98 | Code8;
  1175.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1176.             break;
  1177.           case ModSFR:
  1178.             BAsmCode[CodeLen++] = 0x01;
  1179.             BAsmCode[CodeLen++] = 0x98 | Code8;
  1180.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1181.             break;
  1182.           case ModMem:
  1183.             BAsmCode[CodeLen++] = 0x00 | SrcAdrResult.Val;
  1184.             BAsmCode[CodeLen++] = 0x08 | Code8 | (SrcAdrResult.Vals[0] << 4);
  1185.             memcpy(BAsmCode + CodeLen, SrcAdrResult.Vals + 1, SrcAdrResult.Cnt - 1);
  1186.             CodeLen += SrcAdrResult.Cnt - 1;
  1187.             break;
  1188.           case ModImm:
  1189.             BAsmCode[CodeLen++] = 0xa8 | Code8;
  1190.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1191.             break;
  1192.         }
  1193.         break;
  1194.       }
  1195.       case ModReg16:
  1196.       {
  1197.         tAdrResult SrcAdrResult;
  1198.  
  1199.         switch (DecodeAdr(&ArgStr[2], MModReg16 | ((DestAdrResult.Val  == AccReg16()) ? (MModShort | MModImm | MModSFR) : 0), &SrcAdrResult))
  1200.         {
  1201.           case ModReg16:
  1202.             BAsmCode[CodeLen++] = 0x88 | Code16Reg;
  1203.             BAsmCode[CodeLen++] = 0x08 | (DestAdrResult.Val  << 5) | SrcAdrResult.Val;
  1204.             break;
  1205.           case ModShort:
  1206.             BAsmCode[CodeLen++] = 0x10 | Code16;
  1207.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1208.             break;
  1209.           case ModSFR:
  1210.             BAsmCode[CodeLen++] = 0x01;
  1211.             BAsmCode[CodeLen++] = 0x1d | Code16;
  1212.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1213.             break;
  1214.           case ModImm:
  1215.             BAsmCode[CodeLen++] = 0x20 | Code16;
  1216.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1217.             break;
  1218.         }
  1219.         break;
  1220.       }
  1221.       case ModShort:
  1222.       {
  1223.         tAdrResult SrcAdrResult;
  1224.  
  1225.         AssumeByte = (OpSize == -1);
  1226.         switch (DecodeAdr(&ArgStr[2], MModShort | MModImm, &SrcAdrResult))
  1227.         {
  1228.           case ModShort:
  1229.             BAsmCode[CodeLen++] = OpSize ? (0x30 | Code16) : (0x78 | Code8);
  1230.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1231.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1232.             break;
  1233.           case ModImm:
  1234.             BAsmCode[CodeLen++] = OpSize ? (0x00 | Code16) : (0x68 | Code8);
  1235.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1236.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1237.             if (OpSize)
  1238.               BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  1239.             break;
  1240.         }
  1241.         break;
  1242.       }
  1243.       case ModSFR:
  1244.       {
  1245.         tAdrResult SrcAdrResult;
  1246.  
  1247.         AssumeByte = (OpSize == -1);
  1248.         switch (DecodeAdr(&ArgStr[2], MModImm, &SrcAdrResult))
  1249.         {
  1250.           case ModImm:
  1251.             BAsmCode[CodeLen++] = 0x01;
  1252.             BAsmCode[CodeLen++] = OpSize ? (0x00 | Code16) : (0x68 | Code8);
  1253.             BAsmCode[CodeLen++] = DestAdrResult.Vals[0];
  1254.             BAsmCode[CodeLen++] = SrcAdrResult.Vals[0];
  1255.             if (OpSize)
  1256.               BAsmCode[CodeLen++] = SrcAdrResult.Vals[1];
  1257.             break;
  1258.         }
  1259.         break;
  1260.       }
  1261.       case ModMem:
  1262.       {
  1263.         tAdrResult SrcAdrResult;
  1264.  
  1265.         switch (DecodeAdr(&ArgStr[2], MModReg8, &SrcAdrResult))
  1266.         {
  1267.           case ModReg8:
  1268.             if (SrcAdrResult.Val != AccReg8()) WrError(ErrNum_InvAddrMode);
  1269.             else
  1270.             {
  1271.               BAsmCode[CodeLen++] = 0x00 | DestAdrResult.Val;
  1272.               BAsmCode[CodeLen++] = 0x88 | Code8 | (DestAdrResult.Vals[0] << 4);
  1273.               memcpy(BAsmCode + CodeLen, DestAdrResult.Vals + 1, DestAdrResult.Cnt - 1);
  1274.               CodeLen += DestAdrResult.Cnt - 1;
  1275.             }
  1276.             break;
  1277.         }
  1278.         break;
  1279.       }
  1280.     }
  1281.   }
  1282. }
  1283.  
  1284. static void DecodeMULDIV(Word Props)
  1285. {
  1286.   if (ChkArgCnt(1, 1))
  1287.   {
  1288.     tAdrResult AdrResult;
  1289.  
  1290.     if (Props & 0x8000)
  1291.       SetOpSize(1);
  1292.     switch (DecodeAdr(&ArgStr[1], MModReg16 | ((OpSize == 1) ? 0 : MModReg8), &AdrResult))
  1293.     {
  1294.       case ModReg8:
  1295.         if (AdrResult.Val > 7) WrError(ErrNum_InvAddrMode);
  1296.         else
  1297.         {
  1298.           BAsmCode[CodeLen++] = 0x05;
  1299.           BAsmCode[CodeLen++] = 0x08 | ((Props << 4) & 0xf0) | AdrResult.Val;
  1300.         }
  1301.         break;
  1302.       case ModReg16:
  1303.         BAsmCode[CodeLen++] = 0x05;
  1304.         BAsmCode[CodeLen++] = 0x08 | (Props & 0xf0) | AdrResult.Val;
  1305.         break;
  1306.     }
  1307.   }
  1308. }
  1309.  
  1310. static void DecodeINCDEC(Word Props)
  1311. {
  1312.   const Byte Code = Props & 1;
  1313.  
  1314.   if (ChkArgCnt(1, 1))
  1315.   {
  1316.     tAdrResult AdrResult;
  1317.  
  1318.     if (Props & 2)
  1319.       SetOpSize(1);
  1320.     switch (DecodeAdr(&ArgStr[1], MModShort | MModReg16 | MModSP | ((OpSize == 1) ? 0 : MModReg8), &AdrResult))
  1321.     {
  1322.       case ModReg8:
  1323.         if (AdrResult.Val > 7) WrError(ErrNum_InvAddrMode);
  1324.         else
  1325.           BAsmCode[CodeLen++] = 0xc0 | AdrResult.Val | (Code << 3);
  1326.         break;
  1327.       case ModReg16:
  1328.         if (AdrResult.Val < 4) WrError(ErrNum_InvAddrMode);
  1329.         else
  1330.           BAsmCode[CodeLen++] = 0x40 | AdrResult.Val | (Code << 3);
  1331.         break;
  1332.       case ModSP:
  1333.         BAsmCode[CodeLen++] = 0x05;
  1334.         BAsmCode[CodeLen++] = 0xc8 | Code;
  1335.         break;
  1336.       case ModShort:
  1337.         if (OpSize == 1)
  1338.         {
  1339.           BAsmCode[CodeLen++] = 0x07;
  1340.           BAsmCode[CodeLen++] = 0xe8 | Code;
  1341.         }
  1342.         else
  1343.           BAsmCode[CodeLen++] = 0x26 | Code;
  1344.         BAsmCode[CodeLen++] = AdrResult.Vals[0];
  1345.         break;
  1346.     }
  1347.   }
  1348. }
  1349.  
  1350. static void DecodeShift(Word Props)
  1351. {
  1352.   Boolean OK;
  1353.   Byte Shift;
  1354.   tAdrResult AdrResult;
  1355.  
  1356.   if (!ChkArgCnt(2, 2))
  1357.     return;
  1358.  
  1359.   Shift = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
  1360.   if (!OK)
  1361.     return;
  1362.  
  1363.   if (Props & 0x8000)
  1364.     SetOpSize(1);
  1365.   switch (DecodeAdr(&ArgStr[1], ((OpSize != 1) ? MModReg8 : 0) | ((Props & 0x4000) ? MModReg16 : 0), &AdrResult))
  1366.   {
  1367.     case ModReg8:
  1368.       if (AdrResult.Val > 7) WrError(ErrNum_InvAddrMode);
  1369.       else
  1370.       {
  1371.         BAsmCode[CodeLen++] = 0x30 | (Props & 1);
  1372.         BAsmCode[CodeLen++] = (Props & 0xf0) | AdrResult.Val | (Shift << 3);
  1373.       }
  1374.       break;
  1375.     case ModReg16:
  1376.       BAsmCode[CodeLen++] = 0x30 | (Props & 1);
  1377.       BAsmCode[CodeLen++] = ((Props & 0xf00) >> 4) | AdrResult.Val | (Shift << 3);
  1378.       break;
  1379.   }
  1380. }
  1381.  
  1382. static void DecodeROLROR4(Word Code)
  1383. {
  1384.   ShortInt Reg;
  1385.  
  1386.   if (!ChkArgCnt(1, 1));
  1387.   else if ((Reg = DecodeIndReg16(ArgStr[1].str.p_str)) < 0) WrError(ErrNum_InvAddrMode);
  1388.   else
  1389.   {
  1390.     BAsmCode[CodeLen++] = 0x05;
  1391.     BAsmCode[CodeLen++] = Code | Reg;
  1392.   }
  1393. }
  1394.  
  1395. static void DecodeBIT(Word Index)
  1396. {
  1397.   LongWord Result;
  1398.  
  1399.   UNUSED(Index);
  1400.  
  1401.   if (ChkArgCnt(1, 1)
  1402.    && DecodeBitAdr(&ArgStr[1], &Result))
  1403.     EnterIntSymbol(&LabPart, Result, SegNone, False);
  1404. }
  1405.  
  1406. static void DecodeMOV1(Word Index)
  1407. {
  1408.   LongWord Bit;
  1409.   int ArgPos;
  1410.  
  1411.   UNUSED(Index);
  1412.  
  1413.   if (ChkArgCnt(2, 2))
  1414.   {
  1415.     if (!as_strcasecmp(ArgStr[1].str.p_str, "CY"))
  1416.       ArgPos = 2;
  1417.     else if (!as_strcasecmp(ArgStr[2].str.p_str, "CY"))
  1418.       ArgPos = 1;
  1419.     else
  1420.     {
  1421.       WrError(ErrNum_InvAddrMode);
  1422.       return;
  1423.     }
  1424.     if (DecodeBitAdr(&ArgStr[ArgPos], &Bit))
  1425.     {
  1426.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1427.       BAsmCode[CodeLen++] = ((2 - ArgPos) << 4) | ((Bit >> 8) & 0xff);
  1428.       if (Bit & 0x1000000)
  1429.         BAsmCode[CodeLen++] = Bit & 0xff;
  1430.     }
  1431.   }
  1432. }
  1433.  
  1434. static void DecodeANDOR1(Word Index)
  1435. {
  1436.   LongWord Bit;
  1437.  
  1438.   if (!ChkArgCnt(2, 2));
  1439.   else if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrError(ErrNum_InvAddrMode);
  1440.   else
  1441.   {
  1442.     tStrComp *pArg, BitArg;
  1443.  
  1444.     pArg = &ArgStr[2];
  1445.     if (*pArg->str.p_str == '/')
  1446.     {
  1447.       StrCompRefRight(&BitArg, pArg, 1);
  1448.       pArg = &BitArg;
  1449.       Index |= 0x10;
  1450.     }
  1451.     if (DecodeBitAdr(pArg, &Bit))
  1452.     {
  1453.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1454.       BAsmCode[CodeLen++] = Index  | ((Bit >> 8) & 0xff);
  1455.       if (Bit & 0x1000000)
  1456.         BAsmCode[CodeLen++] = Bit & 0xff;
  1457.     }
  1458.   }
  1459. }
  1460.  
  1461. static void DecodeXOR1(Word Index)
  1462. {
  1463.   LongWord Bit;
  1464.  
  1465.   UNUSED(Index);
  1466.  
  1467.   if (!ChkArgCnt(2, 2));
  1468.   else if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrError(ErrNum_InvAddrMode);
  1469.   else
  1470.   {
  1471.     if (DecodeBitAdr(&ArgStr[2], &Bit))
  1472.     {
  1473.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1474.       BAsmCode[CodeLen++] = 0x60 | ((Bit >> 8) & 0xff);
  1475.       if (Bit & 0x1000000)
  1476.         BAsmCode[CodeLen++] = Bit & 0xff;
  1477.     }
  1478.   }
  1479. }
  1480.  
  1481. static void DecodeBit1(Word Index)
  1482. {
  1483.   LongWord Bit;
  1484.  
  1485.   UNUSED(Index);
  1486.  
  1487.   if (!ChkArgCnt(1, 1));
  1488.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "CY"))
  1489.   {
  1490.     BAsmCode[CodeLen++] = 0x40 | (9 - (Index >> 4));
  1491.   }
  1492.   else if (DecodeBitAdr(&ArgStr[1], &Bit))
  1493.   {
  1494.     if ((Index >= 0x80) && ((Bit & 0xfffff800) == 0x01080000))
  1495.     {
  1496.       BAsmCode[CodeLen++] = (0x130 - Index) | ((Bit >> 8) & 7);
  1497.       BAsmCode[CodeLen++] = Bit & 0xff;
  1498.     }
  1499.     else
  1500.     {
  1501.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1502.       BAsmCode[CodeLen++] = Index | ((Bit >> 8) & 0xff);
  1503.       if (Bit & 0x1000000)
  1504.         BAsmCode[CodeLen++] = Bit & 0xff;
  1505.     }
  1506.   }
  1507. }
  1508.  
  1509. static void DecodeCALL(Word Code)
  1510. {
  1511.   ShortInt Reg;
  1512.  
  1513.   UNUSED(Code);
  1514.  
  1515.   if (!ChkArgCnt(1, 1));
  1516.   else if ((Reg = DecodeIndReg16(ArgStr[1].str.p_str)) >= 0)
  1517.   {
  1518.     BAsmCode[CodeLen++] = 0x05;
  1519.     BAsmCode[CodeLen++] = 0x78 | Reg;
  1520.   }
  1521.   else
  1522.   {
  1523.     tAdrResult AdrResult;
  1524.  
  1525.     switch (DecodeAdr(&ArgStr[1], MModAbs | MModReg16, &AdrResult))
  1526.     {
  1527.       case ModAbs:
  1528.         BAsmCode[CodeLen++] = 0x28;
  1529.         BAsmCode[CodeLen++] = AdrResult.Vals[0];
  1530.         BAsmCode[CodeLen++] = AdrResult.Vals[1];
  1531.         break;
  1532.       case ModReg16:
  1533.         BAsmCode[CodeLen++] = 0x05;
  1534.         BAsmCode[CodeLen++] = 0x58 | AdrResult.Val;
  1535.         break;
  1536.     }
  1537.   }
  1538. }
  1539.  
  1540. static void DecodeCALLF(Word Index)
  1541. {
  1542.   Word AdrWord;
  1543.   Boolean OK;
  1544.  
  1545.   UNUSED(Index);
  1546.  
  1547.   if (ChkArgCnt(1, 1))
  1548.   {
  1549.     tSymbolFlags Flags;
  1550.  
  1551.     AdrWord = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '!'), UInt12, &OK, &Flags);
  1552.     if (OK)
  1553.     {
  1554.       if (mFirstPassUnknown(Flags))
  1555.         AdrWord |= 0x800;
  1556.       if (AdrWord < 0x800) WrError(ErrNum_UnderRange);
  1557.       else
  1558.       {
  1559.         BAsmCode[CodeLen++] = 0x90 | (Hi(AdrWord) & 7);
  1560.         BAsmCode[CodeLen++] = Lo(AdrWord);
  1561.       }
  1562.     }
  1563.   }
  1564. }
  1565.  
  1566. static void DecodeCALLT(Word Index)
  1567. {
  1568.   Word AdrWord;
  1569.   Boolean OK;
  1570.   int l;
  1571.  
  1572.   UNUSED(Index);
  1573.  
  1574.   if (ChkArgCnt(1, 1))
  1575.   {
  1576.     l = strlen(ArgStr[1].str.p_str);
  1577.     if ((*ArgStr[1].str.p_str != '[') || (ArgStr[1].str.p_str[l - 1] != ']')) WrError(ErrNum_InvAddrMode);
  1578.     else
  1579.     {
  1580.       tStrComp Arg;
  1581.       tSymbolFlags Flags;
  1582.  
  1583.       StrCompRefRight(&Arg, &ArgStr[1], 1);
  1584.       StrCompShorten(&Arg, 1);
  1585.       AdrWord = EvalStrIntExpressionWithFlags(&Arg, UInt7, &OK, &Flags);
  1586.       if (OK)
  1587.       {
  1588.         if (mFirstPassUnknown(Flags))
  1589.         AdrWord = 0x40;
  1590.         if (ChkRange(AdrWord, 0x40, 0x7e))
  1591.         {
  1592.           if (AdrWord & 1) WrError(ErrNum_AddrMustBeEven);
  1593.           else
  1594.           {
  1595.             BAsmCode[CodeLen++] = 0xe0 | ((AdrWord - 0x40) >> 1);
  1596.           }
  1597.         }
  1598.       }
  1599.     }
  1600.   }
  1601. }
  1602.  
  1603. static void DecodePUSHPOP(Word Code)
  1604. {
  1605.   Boolean IsU = (Code & 2) || False;
  1606.   ShortInt Reg;
  1607.  
  1608.   if (ChkArgCnt(1, ArgCntMax))
  1609.   {
  1610.     Word Mask = 0, ThisMask;
  1611.     int z;
  1612.  
  1613.     for (z = 1; z <= ArgCnt; z++)
  1614.     {
  1615.       /* special case, either bit 5 or separate instruction */
  1616.  
  1617.       if (!as_strcasecmp(ArgStr[z].str.p_str, "PSW"))
  1618.         ThisMask = IsU ? 0x20 : 0x100;
  1619.  
  1620.       /* user stack ptr itself cannot be pushed onto user stack */
  1621.  
  1622.       else if (((Reg = DecodeReg16(ArgStr[z].str.p_str)) < 0)
  1623.             || (IsU && (Reg == 5)))
  1624.       {
  1625.         WrStrErrorPos(ErrNum_InvReg, &ArgStr[z]);
  1626.         return;
  1627.       }
  1628.       else
  1629.         ThisMask = 1 << Reg;
  1630.  
  1631.       /* register already named? */
  1632.  
  1633.       if (Mask & ThisMask)
  1634.       {
  1635.         WrStrErrorPos(ErrNum_InvRegList, &ArgStr[z]);
  1636.         return;
  1637.       }
  1638.       else
  1639.         Mask |= ThisMask;
  1640.     }
  1641.  
  1642.     /* cannot mix separate PSW and other registers in one instruction */
  1643.  
  1644.     if (Lo(Mask) && Hi(Mask)) WrError(ErrNum_InvRegList);
  1645.     else if (Hi(Mask))
  1646.       BAsmCode[CodeLen++] = Hi(Code);
  1647.     else
  1648.     {
  1649.       BAsmCode[CodeLen++] = Lo(Code);
  1650.       BAsmCode[CodeLen++] = Lo(Mask);
  1651.     }
  1652.   }
  1653. }
  1654.  
  1655. static void DecodeBR(Word Code)
  1656. {
  1657.   ShortInt Reg;
  1658.  
  1659.   UNUSED(Code);
  1660.  
  1661.   if (!ChkArgCnt(1, 1));
  1662.   else if ((Reg = DecodeIndReg16(ArgStr[1].str.p_str)) >= 0)
  1663.   {
  1664.     BAsmCode[CodeLen++] = 0x05;
  1665.     BAsmCode[CodeLen++] = 0x68 | Reg;
  1666.   }
  1667.   else
  1668.   {
  1669.     tAdrResult AdrResult;
  1670.  
  1671.     switch (DecodeAdr(&ArgStr[1], MModAbs | MModReg16, &AdrResult))
  1672.     {
  1673.       case ModReg16:
  1674.         BAsmCode[CodeLen++] = 0x05;
  1675.         BAsmCode[CodeLen++] = 0x48 | AdrResult.Val;
  1676.         break;
  1677.       case ModAbs:
  1678.       {
  1679.         Word AbsAddr = (((Word)AdrResult.Vals[1]) << 8) | AdrResult.Vals[0];
  1680.         Integer Dist = AbsAddr - (EProgCounter() + 2);
  1681.         Boolean DistOK = (Dist >= -128) && (Dist < 127);
  1682.  
  1683.         if (AdrResult.ForceRel && !DistOK) WrError(ErrNum_JmpDistTooBig);
  1684.         else if (AdrResult.ForceLong || !DistOK)
  1685.         {
  1686.           BAsmCode[CodeLen++] = 0x14;
  1687.           BAsmCode[CodeLen++] = AdrResult.Vals[0];
  1688.           BAsmCode[CodeLen++] = AdrResult.Vals[1];
  1689.         }
  1690.         else
  1691.         {
  1692.           BAsmCode[CodeLen++] = 0x14;
  1693.           BAsmCode[CodeLen++] = Dist & 0xff;
  1694.         }
  1695.         break;
  1696.       }
  1697.     }
  1698.   }
  1699. }
  1700.  
  1701. static void DecodeBranch(Word Code)
  1702. {
  1703.   if (ChkArgCnt(1, 1))
  1704.   {
  1705.     if (Hi(Code))
  1706.       BAsmCode[CodeLen++] = Hi(Code);
  1707.     BAsmCode[CodeLen++] = Lo(Code);
  1708.  
  1709.     AppendDisp(&ArgStr[1]);
  1710.   }
  1711. }
  1712.  
  1713. static void DecodeBrBit(Word Index)
  1714. {
  1715.   LongWord Bit;
  1716.  
  1717.   UNUSED(Index);
  1718.  
  1719.   if (!ChkArgCnt(2, 2));
  1720.   else if (DecodeBitAdr(&ArgStr[1], &Bit))
  1721.   {
  1722.     if ((Bit & 0xfffff800) == 0x01080000)
  1723.     {
  1724.       if (Index == 0x80)
  1725.       {
  1726.         BAsmCode[CodeLen++] = 0x70 | ((Bit >> 8) & 7);
  1727.         BAsmCode[CodeLen++] = Bit & 0xff;
  1728.       }
  1729.       else
  1730.       {
  1731.         BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1732.         BAsmCode[CodeLen++] = (0x130 - Index) | ((Bit >> 8) & 0xff);
  1733.         if (Bit & 0x1000000)
  1734.           BAsmCode[CodeLen++] = Bit & 0xff;
  1735.       }
  1736.     }
  1737.     else
  1738.     {
  1739.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1740.       BAsmCode[CodeLen++] = (0x130 - Index) | ((Bit >> 8) & 0xff);
  1741.       if (Bit & 0x1000000)
  1742.         BAsmCode[CodeLen++] = Bit & 0xff;
  1743.     }
  1744.  
  1745.     AppendDisp(&ArgStr[2]);
  1746.   }
  1747. }
  1748.  
  1749. static void DecodeDBNZ(Word Code)
  1750. {
  1751.   UNUSED(Code);
  1752.  
  1753.   if (ChkArgCnt(2, 2))
  1754.   {
  1755.     tAdrResult AdrResult;
  1756.  
  1757.     switch (DecodeAdr(&ArgStr[1], MModReg8 | MModShort, &AdrResult))
  1758.     {
  1759.       case ModReg8:
  1760.         if ((AdrResult.Val != CReg8()) && (AdrResult.Val != BReg8())) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  1761.         else
  1762.           BAsmCode[CodeLen++] = 0x30 | (AdrResult.Val & 3);
  1763.         break;
  1764.       case ModShort:
  1765.         BAsmCode[CodeLen++] = 0x3b;
  1766.         BAsmCode[CodeLen++] = AdrResult.Vals[0];
  1767.         break;
  1768.       default:
  1769.         return;
  1770.     }
  1771.  
  1772.     AppendDisp(&ArgStr[2]);
  1773.   }
  1774. }
  1775.  
  1776. static void DecodeBRKCS(Word Code)
  1777. {
  1778.   ShortInt Bank;
  1779.  
  1780.   UNUSED(Code);
  1781.  
  1782.   if (!ChkArgCnt(1, 1));
  1783.   else if ((Bank = DecodeRegBank(ArgStr[1].str.p_str)) < 0) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  1784.   else
  1785.   {
  1786.     BAsmCode[CodeLen++] = 0x05;
  1787.     BAsmCode[CodeLen++] = 0xd8 | Bank;
  1788.   }
  1789. }
  1790.  
  1791. static void DecodeRETCS(Word Code)
  1792. {
  1793.   UNUSED(Code);
  1794.  
  1795.   if (ChkArgCnt(1, 1))
  1796.   {
  1797.     tAdrResult AdrResult;
  1798.  
  1799.     switch (DecodeAdr(&ArgStr[1], MModAbs, &AdrResult))
  1800.     {
  1801.       case ModAbs:
  1802.         BAsmCode[CodeLen++] = 0x29;
  1803.         BAsmCode[CodeLen++] = AdrResult.Vals[0];
  1804.         BAsmCode[CodeLen++] = AdrResult.Vals[1];
  1805.         break;
  1806.     }
  1807.   }
  1808. }
  1809.  
  1810. static void DecodeString1(Word Code)
  1811. {
  1812.   UNUSED(Code);
  1813.  
  1814.   SetOpSize(0);
  1815.   if (!ChkArgCnt(2, 2));
  1816.   else if (ChkAcc(&ArgStr[2]))
  1817.   {
  1818.     tAdrResult AdrResult;
  1819.  
  1820.     switch (DecodeAdr(&ArgStr[1], MModMem, &AdrResult))
  1821.     {
  1822.       case ModMem:
  1823.         if ((AdrResult.Val != 0x16) || (AdrResult.Vals[0] & 13)) WrError(ErrNum_InvAddrMode);
  1824.         else
  1825.         {
  1826.           BAsmCode[CodeLen++] = 0x15;
  1827.           BAsmCode[CodeLen++] = Code | ((AdrResult.Vals[0] & 2) << 3);
  1828.         }
  1829.         break;
  1830.     }
  1831.   }
  1832. }
  1833.  
  1834. static void DecodeString2(Word Code)
  1835. {
  1836.   tAdrResult SrcAdrResult, DestAdrResult;
  1837.  
  1838.   UNUSED(Code);
  1839.  
  1840.   if (!ChkArgCnt(2, 2))
  1841.     return;
  1842.  
  1843.   if (DecodeAdr(&ArgStr[1], MModMem, &DestAdrResult) != ModMem)
  1844.     return;
  1845.   if ((DestAdrResult.Val != 0x16) || (DestAdrResult.Vals[0] & 5)) /* [DE-] or [DE+] */
  1846.   {
  1847.     WrError(ErrNum_InvAddrMode);
  1848.     return;
  1849.   }
  1850.  
  1851.   if (DecodeAdr(&ArgStr[2], MModMem, &SrcAdrResult) != ModMem)
  1852.     return;
  1853.   if ((SrcAdrResult.Val != 0x16)
  1854.    || ((SrcAdrResult.Vals[0] & 5) != 1) /* [HL-] or [HL+] */
  1855.    || ((DestAdrResult.Vals[0] ^ SrcAdrResult.Vals[0]) & 2)) /* match [DE+] with [HL+] and [DE-] with [HL-] */
  1856.   {
  1857.     WrError(ErrNum_InvAddrMode);
  1858.     return;
  1859.   }
  1860.  
  1861.   BAsmCode[CodeLen++] = 0x15;
  1862.   BAsmCode[CodeLen++] = Code | ((SrcAdrResult.Vals[0] & 2) << 3);
  1863. }
  1864.  
  1865. static void DecodeSEL(Word Code)
  1866. {
  1867.   ShortInt Bank = 0;
  1868.  
  1869.   UNUSED(Code);
  1870.  
  1871.   if (!ChkArgCnt(1, 2));
  1872.   else if ((Bank = DecodeRegBank(ArgStr[1].str.p_str)) < 0) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  1873.   else if ((ArgCnt == 2) && (as_strcasecmp(ArgStr[2].str.p_str, "ALT"))) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
  1874.   {
  1875.     BAsmCode[CodeLen++] = 0x05;
  1876.     BAsmCode[CodeLen++] = 0xa8 | Bank | ((ArgCnt - 1) << 4);
  1877.   }
  1878. }
  1879.  
  1880. /*-------------------------------------------------------------------------*/
  1881. /* dynamic code table handling */
  1882.  
  1883. static void AddFixed(const char *NName, Word NCode)
  1884. {
  1885.   AddInstTable(InstTable, NName, NCode, DecodeFixed);
  1886. }
  1887.  
  1888. static void InitFields(void)
  1889. {
  1890.   InstTable = CreateInstTable(201);
  1891.  
  1892.   AddInstTable(InstTable, "MOV",  0, DecodeMOV);
  1893.   AddInstTable(InstTable, "MOVW", 1, DecodeMOV);
  1894.   AddInstTable(InstTable, "XCH",  0, DecodeXCH);
  1895.   AddInstTable(InstTable, "XCHW", 1, DecodeXCH);
  1896.  
  1897.   AddInstTable(InstTable, "ADD",  0x40d0, DecodeALU);
  1898.   AddInstTable(InstTable, "ADDW", 0xc0d0, DecodeALU);
  1899.   AddInstTable(InstTable, "ADDC", 0x0001, DecodeALU);
  1900.   AddInstTable(InstTable, "SUB",  0x42e2, DecodeALU);
  1901.   AddInstTable(InstTable, "SUBW", 0xc2e2, DecodeALU);
  1902.   AddInstTable(InstTable, "SUBC", 0x0003, DecodeALU);
  1903.   AddInstTable(InstTable, "AND",  0x0004, DecodeALU);
  1904.   AddInstTable(InstTable, "OR",   0x0006, DecodeALU);
  1905.   AddInstTable(InstTable, "XOR",  0x0005, DecodeALU);
  1906.   AddInstTable(InstTable, "CMP",  0x47f7, DecodeALU);
  1907.   AddInstTable(InstTable, "CMPW", 0xc7f7, DecodeALU);
  1908.  
  1909.   AddInstTable(InstTable, "MULU",  0x0020, DecodeMULDIV);
  1910.   AddInstTable(InstTable, "DIVU",  0x00e1, DecodeMULDIV);
  1911.   AddInstTable(InstTable, "MULUW", 0x8020, DecodeMULDIV);
  1912.   AddInstTable(InstTable, "DIVUX", 0x80e1, DecodeMULDIV);
  1913.  
  1914.   AddInstTable(InstTable, "INC",   0, DecodeINCDEC);
  1915.   AddInstTable(InstTable, "INCW",  2, DecodeINCDEC);
  1916.   AddInstTable(InstTable, "DEC",   1, DecodeINCDEC);
  1917.   AddInstTable(InstTable, "DECW",  3, DecodeINCDEC);
  1918.  
  1919.   AddInstTable(InstTable, "ROR",   0x0040, DecodeShift);
  1920.   AddInstTable(InstTable, "ROL",   0x0041, DecodeShift);
  1921.   AddInstTable(InstTable, "RORC",  0x0000, DecodeShift);
  1922.   AddInstTable(InstTable, "ROLC",  0x0001, DecodeShift);
  1923.   AddInstTable(InstTable, "SHR",   0x4c80, DecodeShift);
  1924.   AddInstTable(InstTable, "SHL",   0x4c81, DecodeShift);
  1925.   AddInstTable(InstTable, "SHRW",  0xcc80, DecodeShift);
  1926.   AddInstTable(InstTable, "SHLW",  0xcc81, DecodeShift);
  1927.  
  1928.   AddInstTable(InstTable, "ROL4",  0x88, DecodeROLROR4);
  1929.   AddInstTable(InstTable, "ROR4",  0x98, DecodeROLROR4);
  1930.   AddFixed("ADJ4", 0x0004);
  1931.  
  1932.   AddInstTable(InstTable, "MOV1", 0, DecodeMOV1);
  1933.   AddInstTable(InstTable, "AND1", 0x20, DecodeANDOR1);
  1934.   AddInstTable(InstTable, "OR1" , 0x40, DecodeANDOR1);
  1935.   AddInstTable(InstTable, "XOR1" , 0, DecodeXOR1);
  1936.  
  1937.   AddInstTable(InstTable, "SET1", 0x80, DecodeBit1);
  1938.   AddInstTable(InstTable, "CLR1", 0x90, DecodeBit1);
  1939.   AddInstTable(InstTable, "NOT1", 0x70, DecodeBit1);
  1940.  
  1941.   AddInstTable(InstTable, "CALL", 0, DecodeCALL);
  1942.   AddInstTable(InstTable, "CALLF", 0, DecodeCALLF);
  1943.   AddInstTable(InstTable, "CALLT", 0, DecodeCALLT);
  1944.   AddFixed("BRK", 0x005e);
  1945.   AddFixed("RET", 0x0056);
  1946.   AddFixed("RETI", 0x0057);
  1947.  
  1948.   AddInstTable(InstTable, "PUSH",  0x4935, DecodePUSHPOP);
  1949.   AddInstTable(InstTable, "PUSHU", 0x0037, DecodePUSHPOP);
  1950.   AddInstTable(InstTable, "POP",   0x4834, DecodePUSHPOP);
  1951.   AddInstTable(InstTable, "POPU",  0x0036, DecodePUSHPOP);
  1952.  
  1953.   AddInstTable(InstTable, "BR", 0, DecodeBR);
  1954.  
  1955.   AddInstTable(InstTable, "BC",   0x83, DecodeBranch);
  1956.   AddInstTable(InstTable, "BL",   0x83, DecodeBranch);
  1957.   AddInstTable(InstTable, "BNC",  0x82, DecodeBranch);
  1958.   AddInstTable(InstTable, "BNL",  0x82, DecodeBranch);
  1959.   AddInstTable(InstTable, "BZ",   0x81, DecodeBranch);
  1960.   AddInstTable(InstTable, "BE",   0x81, DecodeBranch);
  1961.   AddInstTable(InstTable, "BNZ",  0x80, DecodeBranch);
  1962.   AddInstTable(InstTable, "BNE",  0x80, DecodeBranch);
  1963.   AddInstTable(InstTable, "BV",   0x85, DecodeBranch);
  1964.   AddInstTable(InstTable, "BPE",  0x85, DecodeBranch);
  1965.   AddInstTable(InstTable, "BNV",  0x84, DecodeBranch);
  1966.   AddInstTable(InstTable, "BPO",  0x84, DecodeBranch);
  1967.   AddInstTable(InstTable, "BN",   0x87, DecodeBranch);
  1968.   AddInstTable(InstTable, "BP",   0x86, DecodeBranch);
  1969.   AddInstTable(InstTable, "BGT",0x07fb, DecodeBranch);
  1970.   AddInstTable(InstTable, "BGE",0x07f9, DecodeBranch);
  1971.   AddInstTable(InstTable, "BLT",0x07f8, DecodeBranch);
  1972.   AddInstTable(InstTable, "BLE",0x07fa, DecodeBranch);
  1973.   AddInstTable(InstTable, "BH", 0x07fd, DecodeBranch);
  1974.   AddInstTable(InstTable, "BNH",0x07fc, DecodeBranch);
  1975.  
  1976.   AddInstTable(InstTable, "BT"    , 0x80, DecodeBrBit);
  1977.   AddInstTable(InstTable, "BF"    , 0x90, DecodeBrBit);
  1978.   AddInstTable(InstTable, "BTCLR" , 0x60, DecodeBrBit);
  1979.   AddInstTable(InstTable, "BFSET" , 0x70, DecodeBrBit);
  1980.  
  1981.   AddInstTable(InstTable, "DBNZ", 0, DecodeDBNZ);
  1982.  
  1983.   AddInstTable(InstTable, "BRKCS", 0, DecodeBRKCS);
  1984.   AddInstTable(InstTable, "RETCS", 0, DecodeRETCS);
  1985.  
  1986.   AddInstTable(InstTable, "MOVM",   0x00, DecodeString1);
  1987.   AddInstTable(InstTable, "XCHM",   0x01, DecodeString1);
  1988.   AddInstTable(InstTable, "CMPME",  0x04, DecodeString1);
  1989.   AddInstTable(InstTable, "CMPMNE", 0x05, DecodeString1);
  1990.   AddInstTable(InstTable, "CMPMC",  0x07, DecodeString1);
  1991.   AddInstTable(InstTable, "CMPMNC", 0x06, DecodeString1);
  1992.  
  1993.   AddInstTable(InstTable, "MOVBK",   0x20, DecodeString2);
  1994.   AddInstTable(InstTable, "XCHBK",   0x21, DecodeString2);
  1995.   AddInstTable(InstTable, "CMPBKE",  0x24, DecodeString2);
  1996.   AddInstTable(InstTable, "CMPBKNE", 0x25, DecodeString2);
  1997.   AddInstTable(InstTable, "CMPBKC",  0x27, DecodeString2);
  1998.   AddInstTable(InstTable, "CMPBKNC", 0x26, DecodeString2);
  1999.  
  2000.   AddFixed("SWRS", 0x43);
  2001.   AddInstTable(InstTable, "SEL", 0, DecodeSEL);
  2002.   AddFixed("NOP", 0x00);
  2003.   AddFixed("EI", 0x4b);
  2004.   AddFixed("DI", 0x4a);
  2005.  
  2006.   AddInstTable(InstTable, "BIT", 0, DecodeBIT);
  2007. }
  2008.  
  2009. static void DeinitFields(void)
  2010. {
  2011.   DestroyInstTable(InstTable);
  2012. }
  2013.  
  2014. /*-------------------------------------------------------------------------*/
  2015. /* interface to common layer */
  2016.  
  2017. static void MakeCode_78K3(void)
  2018. {
  2019.   CodeLen = 0; DontPrint = False; OpSize = -1;
  2020.   AssumeByte = False;
  2021.  
  2022.   /* zu ignorierendes */
  2023.  
  2024.   if (Memo(""))
  2025.     return;
  2026.  
  2027.   /* Pseudoanweisungen */
  2028.  
  2029.   if (DecodeIntelPseudo(False))
  2030.     return;
  2031.  
  2032.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  2033.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  2034. }
  2035.  
  2036. static Boolean IsDef_78K3(void)
  2037. {
  2038.   return Memo("BIT");
  2039. }
  2040.  
  2041. static void InternSymbol_78K3(char *pAsc, TempResult *pErg)
  2042. {
  2043.   if (!as_strcasecmp(pAsc, "PSWL"))
  2044.     as_tempres_set_int(pErg, PSWLAddr);
  2045.   else if (!as_strcasecmp(pAsc, "PSWH"))
  2046.     as_tempres_set_int(pErg, PSWHAddr);
  2047. }
  2048.  
  2049. static void SwitchFrom_78K3(void)
  2050. {
  2051.   DeinitFields();
  2052. }
  2053.  
  2054. static void SwitchTo_78K3(void)
  2055. {
  2056.   static const ASSUMERec ASSUME78K3s[] =
  2057.   {
  2058.     {"RSS" , &Reg_RSS , 0,  0x1,  0x0, NULL},
  2059.   };
  2060.  
  2061.   const TFamilyDescr *pDescr;
  2062.  
  2063.   pDescr = FindFamilyByName("78K3");
  2064.  
  2065.   TurnWords = False;
  2066.   SetIntConstMode(eIntConstModeIntel);
  2067.  
  2068.   PCSymbol = "PC";
  2069.   HeaderID = pDescr->Id;
  2070.   NOPCode = 0x00;
  2071.   DivideChars = ",";
  2072.   HasAttrs = False;
  2073.  
  2074.   ValidSegs = 1 << SegCode;
  2075.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  2076.   SegLimits[SegCode] = 0xffff;
  2077.  
  2078.   pASSUMERecs = ASSUME78K3s;
  2079.   ASSUMERecCnt = sizeof(ASSUME78K3s) / sizeof(ASSUME78K3s[0]);
  2080.  
  2081.   MakeCode = MakeCode_78K3;
  2082.   IsDef = IsDef_78K3;
  2083.   InternSymbol = InternSymbol_78K3;
  2084.   SwitchFrom = SwitchFrom_78K3; InitFields();
  2085. }
  2086.  
  2087. void code78k3_init(void)
  2088. {
  2089.   CPU78310 = AddCPU("78310", SwitchTo_78K3);
  2090. }
  2091.