Subversion Repositories pentevo

Rev

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

  1. /* code78k2.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator 78K2-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 "code78k2.h"
  28.  
  29. /*-------------------------------------------------------------------------*/
  30.  
  31. enum
  32. {
  33.   ModNone = -1,
  34.   ModImm = 0,
  35.   ModReg8 = 1,
  36.   ModReg16 = 2,
  37.   ModMem = 3,
  38.   ModAbs = 4,
  39.   ModShort = 5,
  40.   ModSFR = 6,
  41.   ModPSW = 7,
  42.   ModSP = 8,
  43.   ModSTBC = 9
  44. };
  45.  
  46. #define MModImm (1 << ModImm)
  47. #define MModReg8 (1 << ModReg8)
  48. #define MModReg16 (1 << ModReg16)
  49. #define MModMem (1 << ModMem)
  50. #define MModAbs (1 << ModAbs)
  51. #define MModShort (1 << ModShort)
  52. #define MModSFR (1 << ModSFR)
  53. #define MModPSW (1 << ModPSW)
  54. #define MModSP (1 << ModSP)
  55. #define MModSTBC (1 << ModSTBC)
  56.  
  57. #define AccReg8 1
  58. #define AccReg16 0
  59.  
  60. #define SFR_SP 0xfc
  61. #define SFR_PSW 0xfe
  62.  
  63. /*-------------------------------------------------------------------------*/
  64.  
  65. static CPUVar CPU78214;
  66.  
  67. typedef struct
  68. {
  69.   ShortInt Mode, Val;
  70.   Byte Vals[3];
  71.   tSymbolFlags ValSymFlags;
  72.   Boolean AltBank;
  73.   int Cnt;
  74. } tAdrResult;
  75.  
  76. static ShortInt OpSize;
  77. static LongInt Reg_P6, Reg_PM6;
  78.  
  79. /*-------------------------------------------------------------------------*/
  80. /* address decoders */
  81.  
  82. static Boolean SetOpSize(ShortInt NewSize)
  83. {
  84.   if (OpSize < 0)
  85.   {
  86.     OpSize = NewSize;
  87.     return True;
  88.   }
  89.   else if (OpSize != NewSize)
  90.   {
  91.     WrError(ErrNum_ConfOpSizes);
  92.     return False;
  93.   }
  94.   else
  95.     return True;
  96. }
  97.  
  98. static ShortInt DecodeReg8(char *pAsc)
  99. {
  100.   ShortInt Result = -1;
  101.   int l = strlen(pAsc);
  102.  
  103.   if (l == 1)
  104.   {
  105.     static const char Reg8Names[9] = "XACBEDLH";
  106.     const char *pPos = strchr(Reg8Names, as_toupper(*pAsc));
  107.  
  108.     if (pPos)
  109.       Result = pPos - Reg8Names;
  110.   }
  111.  
  112.   else if ((l == 2) && (toupper(pAsc[0]) == 'R'))
  113.   {
  114.     if ((pAsc[1] >= '0') && (pAsc[1] <= '7'))
  115.       Result = pAsc[1] - '0';
  116.   }
  117.  
  118.   return Result;
  119. }
  120.  
  121. static ShortInt DecodeReg16(char *pAsc)
  122. {
  123.   ShortInt Result = -1;
  124.   int l = strlen(pAsc);
  125.  
  126.   if (l == 2)
  127.   {
  128.     static const char Reg16Names[4][3] = {"AX", "BC", "DE", "HL"};
  129.     int z;
  130.  
  131.     for (z = 0; z < 4; z++)
  132.       if (!as_strcasecmp(Reg16Names[z], pAsc))
  133.       {
  134.         Result = z;
  135.         break;
  136.       }
  137.   }
  138.  
  139.   else if ((l == 3) && (toupper(pAsc[0]) == 'R') && (toupper(pAsc[1]) == 'P'))
  140.   {
  141.     if ((pAsc[2] >= '0') && (pAsc[2] <= '3'))
  142.       Result = pAsc[2] - '0';
  143.   }
  144.  
  145.   return Result;
  146. }
  147.  
  148. static ShortInt DecodeAdr(const tStrComp *pArg, Word Mask, tAdrResult *pResult)
  149. {
  150.   Word WordOp;
  151.   LongWord LongOp;
  152.   Boolean OK;
  153.   tStrComp Arg;
  154.   unsigned ForceLong;
  155.   int ArgLen;
  156.  
  157.   pResult->Mode = ModNone;
  158.   pResult->AltBank = False;
  159.   pResult->Cnt = 0;
  160.  
  161.   /* immediate ? */
  162.  
  163.   if (*pArg->str.p_str == '#')
  164.   {
  165.     switch (OpSize)
  166.     {
  167.       case 0:
  168.         pResult->Vals[0] = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK);
  169.         if (OK)
  170.         {
  171.           pResult->Cnt = 1;
  172.           pResult->Mode = ModImm;
  173.         }
  174.         break;
  175.       case 1:
  176.         WordOp = EvalStrIntExpressionOffs(pArg, 1, Int16, &OK);
  177.         if (OK)
  178.         {
  179.           pResult->Vals[0] = Lo(WordOp);
  180.           pResult->Vals[1] = Hi(WordOp);
  181.           pResult->Cnt = 2;
  182.           pResult->Mode = ModImm;
  183.         }
  184.         break;
  185.       default:
  186.         WrError(ErrNum_UndefOpSizes);
  187.     }
  188.     goto AdrFound;
  189.   }
  190.  
  191.   /* 8 bit registers? */
  192.  
  193.   if ((pResult->Val = DecodeReg8(pArg->str.p_str)) >= 0)
  194.   {
  195.     pResult->Mode = ModReg8;
  196.     SetOpSize(0);
  197.     goto AdrFound;
  198.   }
  199.  
  200.   if (!as_strcasecmp(pArg->str.p_str, "PSW"))
  201.   {
  202.     pResult->Mode = ModPSW;
  203.     SetOpSize(0);
  204.     goto AdrFound;
  205.   }
  206.  
  207.   if (!as_strcasecmp(pArg->str.p_str, "STBC"))
  208.   {
  209.     pResult->Mode = ModSTBC;
  210.     SetOpSize(0);
  211.     goto AdrFound;
  212.   }
  213.  
  214.   /* 16 bit registers? */
  215.  
  216.   if ((pResult->Val = DecodeReg16(pArg->str.p_str)) >= 0)
  217.   {
  218.     pResult->Mode = ModReg16;
  219.     SetOpSize(1);
  220.     goto AdrFound;
  221.   }
  222.  
  223.   if (!as_strcasecmp(pArg->str.p_str, "SP"))
  224.   {
  225.     pResult->Mode = ModSP;
  226.     SetOpSize(1);
  227.     goto AdrFound;
  228.   }
  229.  
  230.   /* OK, everything that follows is memory: alternate bank ? */
  231.  
  232.   StrCompRefRight(&Arg, pArg, 0);
  233.   if (*Arg.str.p_str == '&')
  234.   {
  235.     pResult->AltBank = True;
  236.     StrCompIncRefLeft(&Arg, 1);
  237.   }
  238.  
  239.   /* memory-indirect addressing? */
  240.  
  241.   ArgLen = strlen(Arg.str.p_str);
  242.   if ((ArgLen >= 2) && (Arg.str.p_str[ArgLen - 1] == ']'))
  243.   {
  244.     tStrComp Base, Remainder;
  245.     char *pStart;
  246.  
  247.     /* remove ']' */
  248.  
  249.     StrCompShorten(&Arg, 1);
  250.  
  251.     pStart = RQuotPos(Arg.str.p_str, '[');
  252.     if (!pStart)
  253.     {
  254.       WrError(ErrNum_BrackErr);
  255.       goto AdrFound;
  256.     }
  257.  
  258.     /* purely indirect? */
  259.  
  260.     if (pStart == Arg.str.p_str)
  261.     {
  262.       static const char Modes[][5] = { "DE+",  "HL+",  "DE-",  "HL-",  "DE",  "HL",
  263.                                        "RP2+", "RP3+", "RP2-", "RP3-", "RP2", "RP3" };
  264.       unsigned z;
  265.       char *pSep, Save;
  266.  
  267.       /* skip '[' */
  268.  
  269.       StrCompIncRefLeft(&Arg, 1);
  270.  
  271.       /* simple expression without displacement? */
  272.  
  273.       for (z = 0; z < sizeof(Modes) / sizeof(*Modes); z++)
  274.         if (!as_strcasecmp(Arg.str.p_str, Modes[z]))
  275.         {
  276.           pResult->Mode = ModMem; pResult->Val = 0x16;
  277.           pResult->Vals[0] = z % (sizeof(Modes) / sizeof(*Modes) / 2);
  278.           pResult->Cnt = 1;
  279.           goto AdrFound;
  280.         }
  281.  
  282.       /* no -> extract base register. Its name ends with the first non-letter,
  283.          which either means +/- or a blank */
  284.  
  285.       for (pSep = Arg.str.p_str; *pSep; pSep++)
  286.         if (!as_isalpha(*pSep))
  287.           break;
  288.  
  289.       /* decode base register.  SP is not otherwise handled. */
  290.  
  291.       Save = StrCompSplitRef(&Base, &Remainder, &Arg, pSep);
  292.       if (!as_strcasecmp(Base.str.p_str, "SP"))
  293.         pResult->Vals[0] = 1;
  294.       else
  295.       {
  296.         int tmp;
  297.  
  298.         tmp = DecodeReg16(Base.str.p_str);
  299.         if (tmp == 2) /* DE */
  300.           pResult->Vals[0] = 0;
  301.         else if (tmp == 3) /* HL */
  302.           pResult->Vals[0] = 2;
  303.         else
  304.         {
  305.           WrStrErrorPos(ErrNum_InvReg, &Base);
  306.           goto AdrFound;
  307.         }
  308.       }
  309.  
  310.       /* now that we have the base, prepare displacement. */
  311.  
  312.       *pSep = Save;
  313.       if (pSep > Arg.str.p_str)
  314.         pSep--;
  315.       *pSep = '0';
  316.       pResult->Vals[1] = EvalStrIntExpressionOffs(&Arg, pSep - Arg.str.p_str, Int8, &OK);
  317.       if (OK)
  318.       {
  319.         pResult->Mode = ModMem; pResult->Val = 0x06;
  320.         pResult->Cnt = 2;
  321.         goto AdrFound;
  322.       }
  323.     }
  324.  
  325.     /* no -> with outer displacement */
  326.  
  327.     else
  328.     {
  329.       tStrComp Disp, Reg;
  330.       int tmp;
  331.  
  332.       /* split displacement + register */
  333.  
  334.       StrCompSplitRef(&Disp, &Reg, &Arg, pStart);
  335.  
  336.        /* handle base register */
  337.  
  338.       tmp = DecodeReg8(Reg.str.p_str);
  339.       switch (tmp)
  340.       {
  341.         case 1: /* A/B */
  342.         case 3:
  343.           pResult->Vals[0] = tmp;
  344.           break;
  345.         case -1:
  346.           tmp = DecodeReg16(Reg.str.p_str);
  347.           if (tmp >= 2) /* DE/HL */
  348.           {
  349.             pResult->Vals[0] = (tmp - 2) << 1;
  350.             break;
  351.           }
  352.           /* else fall-through */
  353.         default:
  354.           WrStrErrorPos(ErrNum_InvReg, &Reg);
  355.           goto AdrFound;
  356.       }
  357.  
  358.       /* compute displacement */
  359.  
  360.       WordOp = EvalStrIntExpression(&Disp, Int16, &OK);
  361.       if (OK)
  362.       {
  363.         pResult->Mode = ModMem; pResult->Val = 0x0a;
  364.         pResult->Vals[1] = Lo(WordOp); pResult->Vals[2] = Hi(WordOp);
  365.         pResult->Cnt = 3;
  366.         goto AdrFound;
  367.       }
  368.     }
  369.  
  370.   }
  371.  
  372.   /* OK, nothing but absolute left...exclamation mark enforces 16-bit addressing */
  373.  
  374.   ForceLong = !!(*Arg.str.p_str == '!');
  375.  
  376.   LongOp = EvalStrIntExpressionOffsWithFlags(&Arg, ForceLong, UInt20, &OK, &pResult->ValSymFlags);
  377.   if (OK)
  378.   {
  379.     if (!mFirstPassUnknown(pResult->ValSymFlags))
  380.     {
  381.       LongWord CompBank = pResult->AltBank ? Reg_P6 : Reg_PM6;
  382.       if (CompBank != (LongOp >> 16)) WrError(ErrNum_InAccPage);
  383.     }
  384.  
  385.     WordOp = LongOp & 0xffff;
  386.  
  387.     if ((Mask & MModShort) && (!ForceLong) && ((WordOp >= 0xfe20) && (WordOp <= 0xff1f)))
  388.     {
  389.       pResult->Mode = ModShort; pResult->Cnt = 1;
  390.       pResult->Vals[0] = Lo(WordOp);
  391.     }
  392.     else if ((Mask & MModSFR) && (!ForceLong) && (Hi(WordOp) == 0xff))
  393.     {
  394.       pResult->Mode = ModSFR; pResult->Cnt = 1;
  395.       pResult->Vals[0] = Lo(WordOp);
  396.     }
  397.     else
  398.     {
  399.       pResult->Mode = ModAbs; pResult->Cnt = 2;
  400.       pResult->Vals[0] = Lo(WordOp); pResult->Vals[1] = Hi(WordOp);
  401.     }
  402.   }
  403.  
  404. AdrFound:
  405.  
  406.   if ((pResult->Mode != ModNone) && (!(Mask & (1 << pResult->Mode))))
  407.   {
  408.     WrError(ErrNum_InvAddrMode);
  409.     pResult->Mode = ModNone; pResult->Cnt = 0; pResult->AltBank = False;
  410.   }
  411.   return pResult->Mode;
  412. }
  413.  
  414. static Boolean ChkAcc(const tStrComp *pArg)
  415. {
  416.   tAdrResult Result;
  417.  
  418.   if (DecodeAdr(pArg, OpSize ? MModReg16 : MModReg8, &Result) == ModNone)
  419.     return False;
  420.  
  421.   if (((OpSize) && (Result.Val != AccReg16))
  422.    || ((!OpSize) && (Result.Val != AccReg8)))
  423.   {
  424.     WrError(ErrNum_InvAddrMode);
  425.     return False;
  426.   }
  427.  
  428.   return True;
  429. }
  430.  
  431. static Boolean ChkMem1(const tAdrResult *pResult)
  432. {
  433.   return (pResult->Val == 0x16) && (*pResult->Vals >= 4);
  434. }
  435.  
  436. static Boolean DecodeBitAdr(const tStrComp *pArg, LongWord *pResult)
  437. {
  438.   char *pSplit;
  439.   Boolean OK;
  440.  
  441.   pSplit = RQuotPos(pArg->str.p_str, '.');
  442.  
  443.   if (pSplit)
  444.   {
  445.     tStrComp Reg, Bit;
  446.  
  447.     StrCompSplitRef(&Reg, &Bit, pArg, pSplit);
  448.  
  449.     *pResult = EvalStrIntExpression(&Bit, UInt3, &OK) << 8;
  450.     if (OK)
  451.     {
  452.       tAdrResult Result;
  453.  
  454.       switch (DecodeAdr(&Reg, MModReg8 | MModPSW | MModSFR | MModShort, &Result))
  455.       {
  456.         case ModReg8:
  457.           if (Result.Val >= 2)
  458.           {
  459.             WrStrErrorPos(ErrNum_InvReg, &Reg);
  460.             OK = FALSE;
  461.           }
  462.           else
  463.             *pResult |= (((LongWord)Result.Val) << 11) | 0x00030000;
  464.           break;
  465.         case ModPSW:
  466.           *pResult |= 0x00020000;
  467.           break;
  468.         case ModSFR:
  469.           *pResult |= 0x01080800 | *Result.Vals;
  470.           break;
  471.         case ModShort:
  472.           *pResult |= 0x01080000 | *Result.Vals;
  473.           break;
  474.         default:
  475.           OK = FALSE;
  476.       }
  477.     }
  478.   }
  479.   else
  480.     *pResult = EvalStrIntExpression(pArg, UInt32, &OK);
  481.  
  482.   return OK;
  483. }
  484.  
  485. /*-------------------------------------------------------------------------*/
  486. /* instruction decoders */
  487.  
  488. static void DecodeFixed(Word Index)
  489. {
  490.   if (ChkArgCnt(0, 0))
  491.     BAsmCode[CodeLen++] = Index;
  492. }
  493.  
  494. static void DecodeMOV(Word Index)
  495. {
  496.   UNUSED(Index);
  497.  
  498.   SetOpSize(0);
  499.   if (ChkArgCnt(2, 2))
  500.   {
  501.     tAdrResult DestResult;
  502.  
  503.     switch (DecodeAdr(&ArgStr[1], MModReg8 | MModShort | MModSFR | MModMem | MModAbs | MModPSW | MModSTBC, &DestResult))
  504.     {
  505.       case ModReg8:
  506.       {
  507.         tAdrResult SrcResult;
  508.  
  509.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8 | (DestResult.Val == AccReg8 ? (MModShort | MModSFR | MModAbs | MModMem | MModPSW) : 0), &SrcResult))
  510.         {
  511.           case ModImm:
  512.             BAsmCode[CodeLen++] = 0xb8 | DestResult.Val;
  513.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  514.             break;
  515.           case ModReg8:
  516.             if (DestResult.Val == AccReg8)
  517.               BAsmCode[CodeLen++] = 0xd0 | SrcResult.Val;
  518.             else
  519.             {
  520.               BAsmCode[CodeLen++] = 0x24;
  521.               BAsmCode[CodeLen++] = (DestResult.Val << 4) | SrcResult.Val;
  522.             }
  523.             break;
  524.           case ModSFR:
  525.             BAsmCode[CodeLen++] = 0x10;
  526.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  527.             break;
  528.           case ModShort:
  529.             BAsmCode[CodeLen++] = 0x20;
  530.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  531.             break;
  532.           case ModAbs:
  533.             if (SrcResult.AltBank)
  534.               BAsmCode[CodeLen++] = 0x01;
  535.             BAsmCode[CodeLen++] = 0x09;
  536.             BAsmCode[CodeLen++] = 0xf0;
  537.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  538.             BAsmCode[CodeLen++] = 1[SrcResult.Vals];
  539.             break;
  540.           case ModMem:
  541.             if (SrcResult.AltBank)
  542.               BAsmCode[CodeLen++] = 0x01;
  543.             if (SrcResult.Val == 0x16)
  544.               BAsmCode[CodeLen++] = 0x58 | *SrcResult.Vals;
  545.             else
  546.             {
  547.               BAsmCode[CodeLen++] = 0x00 | SrcResult.Val;
  548.               BAsmCode[CodeLen++] = *SrcResult.Vals << 4;
  549.               memcpy(&BAsmCode[CodeLen], SrcResult.Vals + 1, SrcResult.Cnt - 1);
  550.               CodeLen += SrcResult.Cnt - 1;
  551.             }
  552.             break;
  553.           case ModPSW:
  554.             BAsmCode[CodeLen++] = 0x10;
  555.             BAsmCode[CodeLen++] = SFR_PSW;
  556.             break;
  557.         }
  558.         break;
  559.       }
  560.  
  561.       case ModShort:
  562.       {
  563.         tAdrResult SrcResult;
  564.  
  565.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8 | MModShort, &SrcResult))
  566.         {
  567.           case ModImm:
  568.             BAsmCode[CodeLen++] = 0x3a;
  569.             BAsmCode[CodeLen++] = *DestResult.Vals;
  570.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  571.             break;
  572.           case ModReg8:
  573.             if (SrcResult.Val != AccReg8) WrError(ErrNum_InvAddrMode);
  574.             else
  575.             {
  576.               BAsmCode[CodeLen++] = 0x22;
  577.               BAsmCode[CodeLen++] = *DestResult.Vals;
  578.             }
  579.             break;
  580.           case ModShort:
  581.             BAsmCode[CodeLen++] = 0x38;
  582.             BAsmCode[CodeLen++] = *DestResult.Vals;
  583.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  584.             break;
  585.         }
  586.         break;
  587.       }
  588.  
  589.       case ModSFR:
  590.       {
  591.         tAdrResult SrcResult;
  592.  
  593.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8, &SrcResult))
  594.         {
  595.           case ModImm:
  596.             BAsmCode[CodeLen++] = 0x2b;
  597.             BAsmCode[CodeLen++] = *DestResult.Vals;
  598.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  599.             break;
  600.           case ModReg8:
  601.             if (SrcResult.Val != AccReg8) WrError(ErrNum_InvAddrMode);
  602.             else
  603.             {
  604.               BAsmCode[CodeLen++] = 0x12;
  605.               BAsmCode[CodeLen++] = *DestResult.Vals;
  606.             }
  607.             break;
  608.         }
  609.         break;
  610.       }
  611.  
  612.       case ModPSW:
  613.       {
  614.         tAdrResult SrcResult;
  615.  
  616.         switch (DecodeAdr(&ArgStr[2], MModImm | MModReg8, &SrcResult))
  617.         {
  618.           case ModImm:
  619.             BAsmCode[CodeLen++] = 0x2b;
  620.             BAsmCode[CodeLen++] = SFR_PSW;
  621.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  622.             break;
  623.           case ModReg8:
  624.             if (SrcResult.Val != AccReg8) WrError(ErrNum_InvAddrMode);
  625.             else
  626.             {
  627.               BAsmCode[CodeLen++] = 0x12;
  628.               BAsmCode[CodeLen++] = SFR_PSW;
  629.             }
  630.             break;
  631.         }
  632.         break;
  633.       }
  634.  
  635.       case ModSTBC:
  636.       {
  637.         tAdrResult SrcResult;
  638.  
  639.         switch (DecodeAdr(&ArgStr[2], MModImm, &SrcResult))
  640.         {
  641.           case ModImm:
  642.             BAsmCode[CodeLen++] = 0x09;
  643.             BAsmCode[CodeLen++] = 0xc0;
  644.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  645.             BAsmCode[CodeLen++] = ~(*SrcResult.Vals);
  646.             break;
  647.         }
  648.         break;
  649.       }
  650.  
  651.       /* only works against ACC - dump result first, since DecodeAdr
  652.          destroys values */
  653.  
  654.       case ModMem:
  655.         if (DestResult.AltBank)
  656.           BAsmCode[CodeLen++] = 0x01;
  657.         if (DestResult.Val == 0x16)
  658.           BAsmCode[CodeLen++] = 0x50 | *DestResult.Vals;
  659.         else
  660.         {
  661.           BAsmCode[CodeLen++] = 0x00 | DestResult.Val;
  662.           BAsmCode[CodeLen++] = 0x80 | (*DestResult.Vals << 4);
  663.           memcpy(&BAsmCode[CodeLen], DestResult.Vals + 1, DestResult.Cnt - 1);
  664.           CodeLen += DestResult.Cnt - 1;
  665.         }
  666.         if (!ChkAcc(&ArgStr[2]))
  667.           CodeLen = 0;
  668.         break;
  669.  
  670.       case ModAbs:
  671.         if (DestResult.AltBank)
  672.           BAsmCode[CodeLen++] = 0x01;
  673.         BAsmCode[CodeLen++] = 0x09;
  674.         BAsmCode[CodeLen++] = 0xf1;
  675.         BAsmCode[CodeLen++] = *DestResult.Vals;
  676.         BAsmCode[CodeLen++] = 1[DestResult.Vals];
  677.         if (!ChkAcc(&ArgStr[2]))
  678.           CodeLen = 0;
  679.         break;
  680.     }
  681.   }
  682. }
  683.  
  684. static void DecodeXCH(Word Index)
  685. {
  686.   UNUSED(Index);
  687.  
  688.   SetOpSize(0);
  689.   if (ChkArgCnt(2, 2))
  690.   {
  691.     tAdrResult DestResult;
  692.  
  693.     switch (DecodeAdr(&ArgStr[1], MModReg8 | MModShort | MModSFR | MModMem, &DestResult))
  694.     {
  695.       case ModReg8:
  696.       {
  697.         tAdrResult SrcResult;
  698.  
  699.         switch (DecodeAdr(&ArgStr[2], MModReg8 | ((DestResult.Val == AccReg8) ? (MModShort | MModSFR | MModMem) : 0), &SrcResult))
  700.         {
  701.           case ModReg8:
  702.             if (DestResult.Val == AccReg8)
  703.               BAsmCode[CodeLen++] = 0xd8 | SrcResult.Val;
  704.             else if (SrcResult.Val == AccReg8)
  705.               BAsmCode[CodeLen++] = 0xd8 | DestResult.Val;
  706.             else
  707.             {
  708.               BAsmCode[CodeLen++] = 0x25;
  709.               BAsmCode[CodeLen++] = (DestResult.Val << 4) | SrcResult.Val;
  710.             }
  711.             break;
  712.           case ModShort:
  713.             BAsmCode[CodeLen++] = 0x21;
  714.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  715.             break;
  716.           case ModSFR:
  717.             BAsmCode[CodeLen++] = 0x01;
  718.             BAsmCode[CodeLen++] = 0x21;
  719.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  720.             break;
  721.           case ModMem:
  722.             if (SrcResult.AltBank)
  723.               BAsmCode[CodeLen++] = 0x01;
  724.             BAsmCode[CodeLen++] = SrcResult.Val;
  725.             BAsmCode[CodeLen++] = (*SrcResult.Vals << 4) | 0x04;
  726.             memcpy(&BAsmCode[CodeLen], SrcResult.Vals + 1, SrcResult.Cnt - 1);
  727.             CodeLen += SrcResult.Cnt - 1;
  728.             break;
  729.         }
  730.         break;
  731.       }
  732.  
  733.       case ModShort:
  734.       {
  735.         tAdrResult SrcResult;
  736.  
  737.         switch (DecodeAdr(&ArgStr[2], MModReg8 | MModShort, &SrcResult))
  738.         {
  739.           case ModReg8:
  740.             if (SrcResult.Val != AccReg8) WrError(ErrNum_InvAddrMode);
  741.             else
  742.             {
  743.               BAsmCode[CodeLen++] = 0x21;
  744.               BAsmCode[CodeLen++] = *DestResult.Vals;
  745.             }
  746.             break;
  747.           case ModShort:
  748.             BAsmCode[CodeLen++] = 0x39;
  749.             BAsmCode[CodeLen++] = *DestResult.Vals;
  750.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  751.             break;
  752.         }
  753.         break;
  754.       }
  755.  
  756.       case ModSFR:
  757.         if (ChkAcc(&ArgStr[2]))
  758.         {
  759.           BAsmCode[CodeLen++] = 0x01;
  760.           BAsmCode[CodeLen++] = 0x21;
  761.           BAsmCode[CodeLen++] = *DestResult.Vals;
  762.         }
  763.         break;
  764.  
  765.       case ModMem:
  766.         if (DestResult.AltBank)
  767.           BAsmCode[CodeLen++] = 0x01;
  768.         BAsmCode[CodeLen++] = DestResult.Val;
  769.         BAsmCode[CodeLen++] = (*DestResult.Vals << 4) | 0x04;
  770.         memcpy(&BAsmCode[CodeLen], DestResult.Vals + 1, DestResult.Cnt - 1);
  771.         CodeLen += DestResult.Cnt - 1;
  772.         if (!ChkAcc(&ArgStr[2]))
  773.           CodeLen = 0;
  774.         break;
  775.     }
  776.   }
  777. }
  778.  
  779. static void DecodeMOVW(Word Index)
  780. {
  781.   UNUSED(Index);
  782.  
  783.   SetOpSize(1);
  784.   if (ChkArgCnt(2, 2))
  785.   {
  786.     tAdrResult DestResult;
  787.  
  788.     switch (DecodeAdr(&ArgStr[1], MModReg16 | MModSP | MModShort | MModSFR | MModMem, &DestResult))
  789.     {
  790.       case ModReg16:
  791.       {
  792.         tAdrResult SrcResult;
  793.  
  794.         switch (DecodeAdr(&ArgStr[2], MModReg16 | MModImm | ((DestResult.Val == AccReg16) ? (MModSP | MModShort | MModSFR | MModMem) : 0), &SrcResult))
  795.         {
  796.           case ModReg16:
  797.             BAsmCode[CodeLen++] = 0x24;
  798.             BAsmCode[CodeLen++] = 0x08 | (DestResult.Val << 5) | (SrcResult.Val << 1);
  799.             break;
  800.           case ModImm:
  801.             BAsmCode[CodeLen++] = 0x60 | (DestResult.Val << 1);
  802.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  803.             BAsmCode[CodeLen++] = 1[SrcResult.Vals];
  804.             break;
  805.           case ModShort:
  806.             BAsmCode[CodeLen++] = 0x1c;
  807.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  808.             break;
  809.           case ModSFR:
  810.             BAsmCode[CodeLen++] = 0x11;
  811.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  812.             break;
  813.           case ModSP:
  814.             BAsmCode[CodeLen++] = 0x11;
  815.             BAsmCode[CodeLen++] = SFR_SP;
  816.             break;
  817.           case ModMem:
  818.             if (ChkMem1(&SrcResult))
  819.             {
  820.               if (SrcResult.AltBank)
  821.                 BAsmCode[CodeLen++] = 0x01;
  822.               BAsmCode[CodeLen++] = 0x05;
  823.               BAsmCode[CodeLen++] = 0xe2 | (*SrcResult.Vals & 0x01);
  824.             }
  825.             break;
  826.         }
  827.         break;
  828.       }
  829.  
  830.       case ModSP:
  831.       {
  832.         tAdrResult SrcResult;
  833.  
  834.         switch (DecodeAdr(&ArgStr[2], MModReg16 | MModImm, &SrcResult))
  835.         {
  836.           case ModReg16:
  837.             if (SrcResult.Val != AccReg16) WrError(ErrNum_InvAddrMode);
  838.             else
  839.             {
  840.               BAsmCode[CodeLen++] = 0x13;
  841.               BAsmCode[CodeLen++] = SFR_SP;
  842.             }
  843.             break;
  844.           case ModImm:
  845.             BAsmCode[CodeLen++] = 0x0b;
  846.             BAsmCode[CodeLen++] = SFR_SP;
  847.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  848.             BAsmCode[CodeLen++] = 1[SrcResult.Vals];
  849.             break;
  850.         }
  851.         break;
  852.       }
  853.  
  854.       case ModShort:
  855.       {
  856.         tAdrResult SrcResult;
  857.  
  858.         switch (DecodeAdr(&ArgStr[2], MModReg16 | MModImm, &SrcResult))
  859.         {
  860.           case ModReg16:
  861.             if (SrcResult.Val != AccReg16) WrError(ErrNum_InvAddrMode);
  862.             else
  863.             {
  864.               BAsmCode[CodeLen++] = 0x1a;
  865.               BAsmCode[CodeLen++] = *DestResult.Vals;
  866.             }
  867.             break;
  868.           case ModImm:
  869.             BAsmCode[CodeLen++] = 0x0c;
  870.             BAsmCode[CodeLen++] = *DestResult.Vals;
  871.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  872.             BAsmCode[CodeLen++] = 1[SrcResult.Vals];
  873.             break;
  874.         }
  875.         break;
  876.       }
  877.  
  878.       case ModSFR:
  879.       {
  880.         tAdrResult SrcResult;
  881.  
  882.         switch (DecodeAdr(&ArgStr[2], MModReg16 | MModImm, &SrcResult))
  883.         {
  884.           case ModReg16:
  885.             if (SrcResult.Val != AccReg16) WrError(ErrNum_InvAddrMode);
  886.             else
  887.             {
  888.               BAsmCode[CodeLen++] = 0x13;
  889.               BAsmCode[CodeLen++] = *DestResult.Vals;
  890.             }
  891.             break;
  892.           case ModImm:
  893.             BAsmCode[CodeLen++] = 0x0b;
  894.             BAsmCode[CodeLen++] = *DestResult.Vals;
  895.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  896.             BAsmCode[CodeLen++] = 1[SrcResult.Vals];
  897.             break;
  898.         }
  899.         break;
  900.       }
  901.  
  902.       case ModMem:
  903.         if (ChkMem1(&DestResult))
  904.         {
  905.           if (DestResult.AltBank)
  906.             BAsmCode[CodeLen++] = 0x01;
  907.           BAsmCode[CodeLen++] = 0x05;
  908.           BAsmCode[CodeLen++] = 0xe6 | (*DestResult.Vals & 0x01);
  909.           if (!ChkAcc(&ArgStr[2]))
  910.             CodeLen = 0;
  911.         }
  912.         break;
  913.     }
  914.   }
  915. }
  916.  
  917. static void DecodeALU(Word Index)
  918. {
  919.   SetOpSize(0);
  920.   if (ChkArgCnt(2, 2))
  921.   {
  922.     tAdrResult DestResult;
  923.  
  924.     switch (DecodeAdr(&ArgStr[1], MModReg8 | MModShort | MModSFR, &DestResult))
  925.     {
  926.       case ModReg8:
  927.       {
  928.         tAdrResult SrcResult;
  929.  
  930.         switch (DecodeAdr(&ArgStr[2], MModReg8 | ((DestResult.Val == AccReg8) ? (MModImm | MModShort | MModSFR | MModMem): 0), &SrcResult))
  931.         {
  932.           case ModReg8:
  933.             BAsmCode[CodeLen++] = 0x88 | Index;
  934.             BAsmCode[CodeLen++] = (DestResult.Val << 4) | SrcResult.Val;
  935.             break;
  936.           case ModImm:
  937.             BAsmCode[CodeLen++] = 0xa8 | Index;
  938.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  939.             break;
  940.           case ModShort:
  941.             BAsmCode[CodeLen++] = 0x98 | Index;
  942.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  943.             break;
  944.           case ModSFR:
  945.             BAsmCode[CodeLen++] = 0x01;
  946.             BAsmCode[CodeLen++] = 0x98 | Index;
  947.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  948.             break;
  949.           case ModMem:
  950.             if (SrcResult.AltBank)
  951.               BAsmCode[CodeLen++] = 0x01;
  952.             BAsmCode[CodeLen++] = 0x00 | SrcResult.Val;
  953.             BAsmCode[CodeLen++] = 0x08 | (*SrcResult.Vals << 4) | Index;
  954.             memcpy(&BAsmCode[CodeLen], SrcResult.Vals + 1, SrcResult.Cnt - 1);
  955.             CodeLen += SrcResult.Cnt - 1;
  956.             break;
  957.         }
  958.         break;
  959.       }
  960.  
  961.       case ModShort:
  962.       {
  963.         tAdrResult SrcResult;
  964.  
  965.         switch (DecodeAdr(&ArgStr[2], MModImm | MModShort, &SrcResult))
  966.         {
  967.           case ModImm:
  968.             BAsmCode[CodeLen++] = 0x68 | Index;
  969.             BAsmCode[CodeLen++] = *DestResult.Vals;
  970.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  971.             break;
  972.           case ModShort:
  973.             BAsmCode[CodeLen++] = 0x78 | Index;
  974.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  975.             BAsmCode[CodeLen++] = *DestResult.Vals;
  976.             break;
  977.         }
  978.         break;
  979.       }
  980.  
  981.       case ModSFR:
  982.       {
  983.         tAdrResult SrcResult;
  984.  
  985.         switch (DecodeAdr(&ArgStr[2], MModImm, &SrcResult))
  986.         {
  987.           case ModImm:
  988.             BAsmCode[CodeLen++] = 0x01;
  989.             BAsmCode[CodeLen++] = 0x68 | Index;
  990.             BAsmCode[CodeLen++] = *DestResult.Vals;
  991.             BAsmCode[CodeLen++] = *SrcResult.Vals;
  992.             break;
  993.         }
  994.         break;
  995.       }
  996.     }
  997.   }
  998. }
  999.  
  1000. static void DecodeALU16(Word Index)
  1001. {
  1002.   static Byte Vals[3] = { 0, 2, 7 };
  1003.  
  1004.   if (ChkArgCnt(2, 2))
  1005.   {
  1006.     SetOpSize(1);
  1007.     if (ChkAcc(&ArgStr[1]))
  1008.     {
  1009.       tAdrResult Result;
  1010.  
  1011.       switch (DecodeAdr(&ArgStr[2], MModImm | MModReg16 | MModShort | MModSFR, &Result))
  1012.       {
  1013.         case ModImm:
  1014.           BAsmCode[CodeLen++] = 0x2c | Index;
  1015.           BAsmCode[CodeLen++] = *Result.Vals;
  1016.           BAsmCode[CodeLen++] = 1[Result.Vals];
  1017.           break;
  1018.         case ModReg16:
  1019.           BAsmCode[CodeLen++] = 0x88 | Vals[Index - 1];
  1020.           BAsmCode[CodeLen++] = 0x08 | (Result.Val << 1);
  1021.           break;
  1022.         case ModShort:
  1023.           BAsmCode[CodeLen++] = 0x1c | Index;
  1024.           BAsmCode[CodeLen++] = *Result.Vals;
  1025.           break;
  1026.         case ModSFR:
  1027.           BAsmCode[CodeLen++] = 0x01;
  1028.           BAsmCode[CodeLen++] = 0x1c | Index;
  1029.           BAsmCode[CodeLen++] = *Result.Vals;
  1030.           break;
  1031.       }
  1032.     }
  1033.   }
  1034. }
  1035.  
  1036. static void DecodeMULDIV(Word Index)
  1037. {
  1038.   if (ChkArgCnt(1, 1))
  1039.   {
  1040.     tAdrResult Result;
  1041.  
  1042.     switch (DecodeAdr(&ArgStr[1], MModReg8, &Result))
  1043.     {
  1044.       case ModReg8:
  1045.         BAsmCode[CodeLen++] = 0x05;
  1046.         BAsmCode[CodeLen++] = Index | Result.Val;
  1047.         break;
  1048.     }
  1049.   }
  1050. }
  1051.  
  1052. static void DecodeINCDEC(Word Index)
  1053. {
  1054.   if (ChkArgCnt(1, 1))
  1055.   {
  1056.     tAdrResult Result;
  1057.  
  1058.     switch (DecodeAdr(&ArgStr[1], MModReg8 | MModShort, &Result))
  1059.     {
  1060.       case ModReg8:
  1061.         BAsmCode[CodeLen++] = 0xc0 | (Index << 3) | Result.Val;
  1062.         break;
  1063.       case ModShort:
  1064.         BAsmCode[CodeLen++] = 0x26 | Index;
  1065.         BAsmCode[CodeLen++] = *Result.Vals;
  1066.         break;
  1067.     }
  1068.   }
  1069. }
  1070.  
  1071. static void DecodeINCDECW(Word Index)
  1072. {
  1073.   if (ChkArgCnt(1, 1))
  1074.   {
  1075.     tAdrResult Result;
  1076.  
  1077.     switch (DecodeAdr(&ArgStr[1], MModReg16 | MModSP, &Result))
  1078.     {
  1079.       case ModReg16:
  1080.         BAsmCode[CodeLen++] = 0x44 | (Index << 3) | Result.Val;
  1081.         break;
  1082.       case ModSP:
  1083.         BAsmCode[CodeLen++] = 0x05;
  1084.         BAsmCode[CodeLen++] = 0xc0 | Index;
  1085.         break;
  1086.     }
  1087.   }
  1088. }
  1089.  
  1090. static void DecodeShift8(Word Index)
  1091. {
  1092.   Boolean OK;
  1093.   Byte Shift;
  1094.  
  1095.   if (ChkArgCnt(2, 2))
  1096.   {
  1097.     tAdrResult Result;
  1098.  
  1099.     switch (DecodeAdr(&ArgStr[1], MModReg8, &Result))
  1100.     {
  1101.       case ModReg8:
  1102.         Shift = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
  1103.         if (OK)
  1104.         {
  1105.           BAsmCode[CodeLen++] = 0x30 | Hi(Index);
  1106.           BAsmCode[CodeLen++] = Lo(Index) | (Shift << 3) | Result.Val;
  1107.         }
  1108.         break;
  1109.     }
  1110.   }
  1111. }
  1112.  
  1113. static void DecodeShift16(Word Index)
  1114. {
  1115.   Boolean OK;
  1116.   Byte Shift;
  1117.  
  1118.   if (ChkArgCnt(2, 2))
  1119.   {
  1120.     tAdrResult Result;
  1121.  
  1122.     switch (DecodeAdr(&ArgStr[1], MModReg16, &Result))
  1123.     {
  1124.       case ModReg16:
  1125.         Shift = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
  1126.         if (OK)
  1127.         {
  1128.           BAsmCode[CodeLen++] = 0x30 | Hi(Index);
  1129.           BAsmCode[CodeLen++] = Lo(Index) | (Shift << 3) | (Result.Val << 1);
  1130.         }
  1131.         break;
  1132.     }
  1133.   }
  1134. }
  1135.  
  1136. static void DecodeShift4(Word Index)
  1137. {
  1138.   if (ChkArgCnt(1, 1))
  1139.   {
  1140.     tAdrResult Result;
  1141.  
  1142.     switch (DecodeAdr(&ArgStr[1], MModMem, &Result))
  1143.     {
  1144.       case ModMem:
  1145.         if (ChkMem1(&Result))
  1146.         {
  1147.           if (Index)
  1148.             BAsmCode[CodeLen++] = 0x01;
  1149.           BAsmCode[CodeLen++] = 0x05;
  1150.           BAsmCode[CodeLen++] = 0x8c | ((*Result.Vals & 1) << 1);
  1151.         }
  1152.         break;
  1153.     }
  1154.   }
  1155. }
  1156.  
  1157. static void DecodePUSHPOP(Word Index)
  1158. {
  1159.   if (ChkArgCnt(1, 1))
  1160.   {
  1161.     tAdrResult Result;
  1162.  
  1163.     switch (DecodeAdr(&ArgStr[1], MModReg16 | MModPSW | MModSFR, &Result))
  1164.     {
  1165.       case ModReg16:
  1166.         BAsmCode[CodeLen++] = 0x34 | (Index << 3) | Result.Val;
  1167.         break;
  1168.       case ModPSW:
  1169.         BAsmCode[CodeLen++] = 0x48 | Index;
  1170.         break;
  1171.       case ModSFR:
  1172.         BAsmCode[CodeLen++] = Index ? 0x29 : 0x43;
  1173.         BAsmCode[CodeLen++] = *Result.Vals;
  1174.         break;
  1175.     }
  1176.   }
  1177. }
  1178.  
  1179. static void DecodeCALL(Word Index)
  1180. {
  1181.   UNUSED(Index);
  1182.  
  1183.   if (ChkArgCnt(1, 1))
  1184.   {
  1185.     tAdrResult Result;
  1186.  
  1187.     switch (DecodeAdr(&ArgStr[1], MModAbs | MModReg16, &Result))
  1188.     {
  1189.       case ModAbs:
  1190.         BAsmCode[CodeLen++] = 0x28;
  1191.         BAsmCode[CodeLen++] = *Result.Vals;
  1192.         BAsmCode[CodeLen++] = 1[Result.Vals];
  1193.         break;
  1194.       case ModReg16:
  1195.         BAsmCode[CodeLen++] = 0x05;
  1196.         BAsmCode[CodeLen++] = 0x58 | (Result.Val << 1);
  1197.         break;
  1198.     }
  1199.   }
  1200. }
  1201.  
  1202. static void DecodeCALLF(Word Index)
  1203. {
  1204.   Word AdrWord;
  1205.   Boolean OK;
  1206.  
  1207.   UNUSED(Index);
  1208.  
  1209.   if (ChkArgCnt(1, 1))
  1210.   {
  1211.     tSymbolFlags Flags;
  1212.  
  1213.     AdrWord = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '!'), UInt12, &OK, &Flags);
  1214.     if (OK)
  1215.     {
  1216.       if (mFirstPassUnknown(Flags))
  1217.         AdrWord |= 0x800;
  1218.       if (AdrWord < 0x800) WrError(ErrNum_UnderRange);
  1219.       else
  1220.       {
  1221.         BAsmCode[CodeLen++] = 0x90 | (Hi(AdrWord) & 7);
  1222.         BAsmCode[CodeLen++] = Lo(AdrWord);
  1223.       }
  1224.     }
  1225.   }
  1226. }
  1227.  
  1228. static void DecodeCALLT(Word Index)
  1229. {
  1230.   Word AdrWord;
  1231.   Boolean OK;
  1232.   int ArgLen;
  1233.   tStrComp Arg;
  1234.  
  1235.   UNUSED(Index);
  1236.  
  1237.   if (ChkArgCnt(1, 1))
  1238.   {
  1239.     StrCompRefRight(&Arg, &ArgStr[1], 0); ArgLen = strlen(Arg.str.p_str);
  1240.     if ((*Arg.str.p_str != '[') || (Arg.str.p_str[ArgLen - 1] != ']')) WrError(ErrNum_InvAddrMode);
  1241.     else
  1242.     {
  1243.       tSymbolFlags Flags;
  1244.  
  1245.       StrCompIncRefLeft(&Arg, 1);
  1246.       StrCompShorten(&Arg, 1);
  1247.       AdrWord = EvalStrIntExpressionWithFlags(&Arg, UInt7, &OK, &Flags);
  1248.       if (OK)
  1249.       {
  1250.         if (mFirstPassUnknown(Flags))
  1251.         AdrWord = 0x40;
  1252.         if (ChkRange(AdrWord, 0x40, 0x7e))
  1253.         {
  1254.           if (AdrWord & 1) WrError(ErrNum_AddrMustBeEven);
  1255.           else
  1256.           {
  1257.             BAsmCode[CodeLen++] = 0xe0 | ((AdrWord - 0x40) >> 1);
  1258.           }
  1259.         }
  1260.       }
  1261.     }
  1262.   }
  1263. }
  1264.  
  1265. static void DecodeBR(Word Index)
  1266. {
  1267.   Boolean Rel;
  1268.  
  1269.   UNUSED(Index);
  1270.  
  1271.   if (ChkArgCnt(1, 1))
  1272.   {
  1273.     tAdrResult Result;
  1274.     tStrComp Arg;
  1275.  
  1276.     StrCompRefRight(&Arg, &ArgStr[1], 0);
  1277.     Rel = (*Arg.str.p_str == '$');
  1278.     if (Rel)
  1279.       StrCompIncRefLeft(&Arg, 1);
  1280.     switch (DecodeAdr(&Arg, MModAbs | MModReg16, &Result))
  1281.     {
  1282.       case ModAbs:
  1283.         if (Rel)
  1284.         {
  1285.           LongInt Addr = (((Word)1[Result.Vals]) << 8) | (*Result.Vals);
  1286.  
  1287.           Addr -= EProgCounter() + 2;
  1288.           if (!mSymbolQuestionable(Result.ValSymFlags) && ((Addr < -128) || (Addr > 127))) WrError(ErrNum_JmpDistTooBig);
  1289.           else
  1290.           {
  1291.             BAsmCode[CodeLen++] = 0x14;
  1292.             BAsmCode[CodeLen++] = Addr & 0xff;
  1293.           }
  1294.         }
  1295.         else
  1296.         {
  1297.           BAsmCode[CodeLen++] = 0x2c;
  1298.           BAsmCode[CodeLen++] = *Result.Vals;
  1299.           BAsmCode[CodeLen++] = 1[Result.Vals];
  1300.         }
  1301.         break;
  1302.       case ModReg16:
  1303.         BAsmCode[CodeLen++] = 0x05;
  1304.         BAsmCode[CodeLen++] = 0x48 | (Result.Val << 1);
  1305.         break;
  1306.     }
  1307.   }
  1308. }
  1309.  
  1310. static void DecodeBranch(Word Index)
  1311. {
  1312.   LongInt Addr;
  1313.   Boolean OK;
  1314.  
  1315.   if (ChkArgCnt(1, 1))
  1316.   {
  1317.     tSymbolFlags Flags;
  1318.  
  1319.     Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '$'), UInt16, &OK, &Flags) - (EProgCounter() + 2);
  1320.     if (OK)
  1321.     {
  1322.       if (!mSymbolQuestionable(Flags) && ((Addr < -128) || (Addr > 127))) WrError(ErrNum_JmpDistTooBig);
  1323.       else
  1324.       {
  1325.         BAsmCode[CodeLen++] = Index;
  1326.         BAsmCode[CodeLen++] = Addr & 0xff;
  1327.       }
  1328.     }
  1329.   }
  1330. }
  1331.  
  1332. static void DecodeDBNZ(Word Index)
  1333. {
  1334.   LongInt Addr;
  1335.   Boolean OK;
  1336.  
  1337.   UNUSED(Index);
  1338.  
  1339.   if (ChkArgCnt(2, 2))
  1340.   {
  1341.     tAdrResult Result;
  1342.  
  1343.     switch (DecodeAdr(&ArgStr[1], MModShort | MModReg8, &Result))
  1344.     {
  1345.       case ModShort:
  1346.         BAsmCode[CodeLen++] = 0x3b;
  1347.         BAsmCode[CodeLen++] = *Result.Vals;
  1348.         break;
  1349.       case ModReg8:
  1350.         if ((Result.Val < 2) || (Result.Val > 3))
  1351.         {
  1352.           WrError(ErrNum_InvAddrMode);
  1353.           Result.Mode = ModNone;
  1354.         }
  1355.         else
  1356.           BAsmCode[CodeLen++] = 0x30 | Result.Val;
  1357.         break;
  1358.     }
  1359.     if (Result.Mode != ModNone)
  1360.     {
  1361.       tSymbolFlags Flags;
  1362.  
  1363.       Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], !!(*ArgStr[2].str.p_str == '$'), UInt16, &OK, &Flags) - (EProgCounter() + CodeLen + 1);
  1364.       if (!mSymbolQuestionable(Flags) && ((Addr < -128) || (Addr > 127)))
  1365.       {
  1366.         WrError(ErrNum_JmpDistTooBig);
  1367.         CodeLen = 0;
  1368.       }
  1369.       else
  1370.         BAsmCode[CodeLen++] = Addr & 0xff;
  1371.     }
  1372.   }
  1373. }
  1374.  
  1375. static void DecodeSEL(Word Index)
  1376. {
  1377.   Boolean OK;
  1378.   Byte Bank;
  1379.  
  1380.   UNUSED(Index);
  1381.  
  1382.   if (!ChkArgCnt(1, 1));
  1383.   else if (as_strncasecmp(ArgStr[1].str.p_str, "RB", 2)) WrError(ErrNum_InvAddrMode);
  1384.   else
  1385.   {
  1386.     Bank = EvalStrIntExpressionOffs(&ArgStr[1], 2, UInt2, &OK);
  1387.     if (OK)
  1388.     {
  1389.       BAsmCode[CodeLen++] = 0x05;
  1390.       BAsmCode[CodeLen++] = 0xa8 | Bank;
  1391.     }
  1392.   }
  1393. }
  1394.  
  1395. static void DecodeBIT(Word Index)
  1396. {
  1397.   LongWord Result;
  1398.  
  1399.   UNUSED(Index);
  1400.  
  1401.   if (!ChkArgCnt(1, 1));
  1402.   else if (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 = &ArgStr[2], BitArg;
  1443.  
  1444.     if (*pArg->str.p_str == '/')
  1445.     {
  1446.       StrCompRefRight(&BitArg, &ArgStr[2], 1);
  1447.       pArg = &BitArg;
  1448.       Index |= 0x10;
  1449.     }
  1450.     if (DecodeBitAdr(pArg, &Bit))
  1451.     {
  1452.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1453.       BAsmCode[CodeLen++] = Index  | ((Bit >> 8) & 0xff);
  1454.       if (Bit & 0x1000000)
  1455.         BAsmCode[CodeLen++] = Bit & 0xff;
  1456.     }
  1457.   }
  1458. }
  1459.  
  1460. static void DecodeXOR1(Word Index)
  1461. {
  1462.   LongWord Bit;
  1463.  
  1464.   UNUSED(Index);
  1465.  
  1466.   if (!ChkArgCnt(2, 2));
  1467.   else if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrError(ErrNum_InvAddrMode);
  1468.   else
  1469.   {
  1470.     if (DecodeBitAdr(&ArgStr[2], &Bit))
  1471.     {
  1472.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1473.       BAsmCode[CodeLen++] = 0x60 | ((Bit >> 8) & 0xff);
  1474.       if (Bit & 0x1000000)
  1475.         BAsmCode[CodeLen++] = Bit & 0xff;
  1476.     }
  1477.   }
  1478. }
  1479.  
  1480. static void DecodeBit1(Word Index)
  1481. {
  1482.   LongWord Bit;
  1483.  
  1484.   UNUSED(Index);
  1485.  
  1486.   if (!ChkArgCnt(1, 1));
  1487.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "CY"))
  1488.   {
  1489.     BAsmCode[CodeLen++] = 0x40 | (9 - (Index >> 4));
  1490.   }
  1491.   else if (DecodeBitAdr(&ArgStr[1], &Bit))
  1492.   {
  1493.     if ((Index >= 0x80) && ((Bit & 0xfffff800) == 0x01080000))
  1494.     {
  1495.       BAsmCode[CodeLen++] = (0x130 - Index) | ((Bit >> 8) & 7);
  1496.       BAsmCode[CodeLen++] = Bit & 0xff;
  1497.     }
  1498.     else
  1499.     {
  1500.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1501.       BAsmCode[CodeLen++] = Index | ((Bit >> 8) & 0xff);
  1502.       if (Bit & 0x1000000)
  1503.         BAsmCode[CodeLen++] = Bit & 0xff;
  1504.     }
  1505.   }
  1506. }
  1507.  
  1508. static void DecodeBrBit(Word Index)
  1509. {
  1510.   LongWord Bit;
  1511.  
  1512.   LongInt Addr;
  1513.   Boolean OK;
  1514.  
  1515.   UNUSED(Index);
  1516.  
  1517.   if (ChkArgCnt(2, 2)
  1518.    && DecodeBitAdr(&ArgStr[1], &Bit))
  1519.   {
  1520.     tSymbolFlags Flags;
  1521.  
  1522.     if ((Bit & 0xfffff800) == 0x01080000)
  1523.     {
  1524.       if (Index == 0x80)
  1525.       {
  1526.         BAsmCode[CodeLen++] = 0x70 | ((Bit >> 8) & 7);
  1527.         BAsmCode[CodeLen++] = Bit & 0xff;
  1528.       }
  1529.       else
  1530.       {
  1531.         BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1532.         BAsmCode[CodeLen++] = (0x130 - Index) | ((Bit >> 8) & 0xff);
  1533.         if (Bit & 0x1000000)
  1534.           BAsmCode[CodeLen++] = Bit & 0xff;
  1535.       }
  1536.     }
  1537.     else
  1538.     {
  1539.       BAsmCode[CodeLen++] = 0x00 | ((Bit >> 16) & 0xff);
  1540.       BAsmCode[CodeLen++] = (0x130 - Index) | ((Bit >> 8) & 0xff);
  1541.       if (Bit & 0x1000000)
  1542.         BAsmCode[CodeLen++] = Bit & 0xff;
  1543.     }
  1544.  
  1545.     Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], !!(*ArgStr[2].str.p_str == '$'), UInt16, &OK, &Flags) - (EProgCounter() + CodeLen + 1);
  1546.     if (!mSymbolQuestionable(Flags) && ((Addr < -128) || (Addr > 127)))
  1547.     {
  1548.       WrError(ErrNum_JmpDistTooBig);
  1549.       CodeLen = 0;
  1550.     }
  1551.     else
  1552.       BAsmCode[CodeLen++] = Addr & 0xff;
  1553.   }
  1554. }
  1555.  
  1556. /*-------------------------------------------------------------------------*/
  1557. /* dynamic code table handling */
  1558.  
  1559. static void AddFixed(const char *NName, Word NCode)
  1560. {
  1561.   AddInstTable(InstTable, NName, NCode, DecodeFixed);
  1562. }
  1563.  
  1564. static void InitFields(void)
  1565. {
  1566.   InstTable = CreateInstTable(201);
  1567.  
  1568.   add_null_pseudo(InstTable);
  1569.  
  1570.   AddInstTable(InstTable, "MOV", 0, DecodeMOV);
  1571.   AddInstTable(InstTable, "XCH", 0, DecodeXCH);
  1572.   AddInstTable(InstTable, "MOVW", 0, DecodeMOVW);
  1573.  
  1574.   AddInstTable(InstTable, "ADD"  , 0, DecodeALU);
  1575.   AddInstTable(InstTable, "ADDC" , 1, DecodeALU);
  1576.   AddInstTable(InstTable, "SUB"  , 2, DecodeALU);
  1577.   AddInstTable(InstTable, "SUBC" , 3, DecodeALU);
  1578.   AddInstTable(InstTable, "AND"  , 4, DecodeALU);
  1579.   AddInstTable(InstTable, "OR"   , 6, DecodeALU);
  1580.   AddInstTable(InstTable, "XOR"  , 5, DecodeALU);
  1581.   AddInstTable(InstTable, "CMP"  , 7, DecodeALU);
  1582.  
  1583.   AddInstTable(InstTable, "ADDW", 1, DecodeALU16);
  1584.   AddInstTable(InstTable, "SUBW", 2, DecodeALU16);
  1585.   AddInstTable(InstTable, "CMPW", 3, DecodeALU16);
  1586.  
  1587.   AddInstTable(InstTable, "MULU" , 0x08, DecodeMULDIV);
  1588.   AddInstTable(InstTable, "DIVUW", 0x18, DecodeMULDIV);
  1589.  
  1590.   AddInstTable(InstTable, "INC", 0, DecodeINCDEC);
  1591.   AddInstTable(InstTable, "DEC", 1, DecodeINCDEC);
  1592.  
  1593.   AddInstTable(InstTable, "INCW", 0, DecodeINCDECW);
  1594.   AddInstTable(InstTable, "DECW", 1, DecodeINCDECW);
  1595.  
  1596.   AddInstTable(InstTable, "ROR"  , 0x040, DecodeShift8);
  1597.   AddInstTable(InstTable, "ROL"  , 0x140, DecodeShift8);
  1598.   AddInstTable(InstTable, "RORC" , 0x000, DecodeShift8);
  1599.   AddInstTable(InstTable, "ROLC" , 0x100, DecodeShift8);
  1600.   AddInstTable(InstTable, "SHR"  , 0x080, DecodeShift8);
  1601.   AddInstTable(InstTable, "SHL"  , 0x180, DecodeShift8);
  1602.  
  1603.   AddInstTable(InstTable, "SHRW" , 0x0c0, DecodeShift16);
  1604.   AddInstTable(InstTable, "SHLW" , 0x1c0, DecodeShift16);
  1605.  
  1606.   AddInstTable(InstTable, "ROR4" , 0, DecodeShift4);
  1607.   AddInstTable(InstTable, "ROL4" , 1, DecodeShift4);
  1608.  
  1609.   AddInstTable(InstTable, "POP"  , 0, DecodePUSHPOP);
  1610.   AddInstTable(InstTable, "PUSH" , 1, DecodePUSHPOP);
  1611.  
  1612.   AddInstTable(InstTable, "CALL" , 0, DecodeCALL);
  1613.   AddInstTable(InstTable, "CALLF", 0, DecodeCALLF);
  1614.   AddInstTable(InstTable, "CALLT", 0, DecodeCALLT);
  1615.  
  1616.   AddInstTable(InstTable, "BR"   , 0, DecodeBR);
  1617.  
  1618.   AddInstTable(InstTable, "BC"   , 0x83, DecodeBranch);
  1619.   AddInstTable(InstTable, "BL"   , 0x83, DecodeBranch);
  1620.   AddInstTable(InstTable, "BNC"  , 0x82, DecodeBranch);
  1621.   AddInstTable(InstTable, "BNL"  , 0x82, DecodeBranch);
  1622.   AddInstTable(InstTable, "BZ"   , 0x81, DecodeBranch);
  1623.   AddInstTable(InstTable, "BE"   , 0x81, DecodeBranch);
  1624.   AddInstTable(InstTable, "BNZ"  , 0x80, DecodeBranch);
  1625.   AddInstTable(InstTable, "BNE"  , 0x80, DecodeBranch);
  1626.  
  1627.   AddInstTable(InstTable, "DBNZ" , 0, DecodeDBNZ);
  1628.  
  1629.   AddInstTable(InstTable, "SEL", 0, DecodeSEL);
  1630.  
  1631.   AddInstTable(InstTable, "MOV1", 0, DecodeMOV1);
  1632.   AddInstTable(InstTable, "AND1", 0x20, DecodeANDOR1);
  1633.   AddInstTable(InstTable, "OR1" , 0x40, DecodeANDOR1);
  1634.   AddInstTable(InstTable, "XOR1" , 0, DecodeXOR1);
  1635.  
  1636.   AddInstTable(InstTable, "SET1", 0x80, DecodeBit1);
  1637.   AddInstTable(InstTable, "CLR1", 0x90, DecodeBit1);
  1638.   AddInstTable(InstTable, "NOT1", 0x70, DecodeBit1);
  1639.  
  1640.   AddInstTable(InstTable, "BT"    , 0x80, DecodeBrBit);
  1641.   AddInstTable(InstTable, "BF"    , 0x90, DecodeBrBit);
  1642.   AddInstTable(InstTable, "BTCLR" , 0x60, DecodeBrBit);
  1643.  
  1644.   AddFixed("NOP",   0x00);
  1645.   AddFixed("DI",    0x4a);
  1646.   AddFixed("EI",    0x4b);
  1647.   AddFixed("BRK",   0x5e);
  1648.   AddFixed("RET",   0x56);
  1649.   AddFixed("RETI",  0x57);
  1650.   AddFixed("RETB",  0x5f);
  1651.   AddFixed("ADJBA", 0x0e);
  1652.   AddFixed("ADJBS", 0x0f);
  1653.  
  1654.   AddInstTable(InstTable, "BIT", 0, DecodeBIT);
  1655.   AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
  1656. }
  1657.  
  1658. static void DeinitFields(void)
  1659. {
  1660.   DestroyInstTable(InstTable);
  1661. }
  1662.  
  1663. /*-------------------------------------------------------------------------*/
  1664. /* interface to common layer */
  1665.  
  1666. static void MakeCode_78K2(void)
  1667. {
  1668.   OpSize = eSymbolSizeUnknown;
  1669.  
  1670.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  1671.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  1672. }
  1673.  
  1674. static void InitCode_78K2(void)
  1675. {
  1676.   Reg_PM6 = 0;
  1677.   Reg_P6  = 0;
  1678. }
  1679.  
  1680. static Boolean IsDef_78K2(void)
  1681. {
  1682.   return Memo("BIT");
  1683. }
  1684.  
  1685. static void SwitchFrom_78K2(void)
  1686. {
  1687.   DeinitFields();
  1688. }
  1689.  
  1690. static void SwitchTo_78K2(void)
  1691. {
  1692.   static const ASSUMERec ASSUME78K2s[] =
  1693.   {
  1694.     {"P6"  , &Reg_P6  , 0,  0xf,  0x10, NULL},
  1695.     {"PM6" , &Reg_PM6 , 0,  0xf,  0x10, NULL}
  1696.   };
  1697.   const TFamilyDescr *pDescr;
  1698.  
  1699.   pDescr = FindFamilyByName("78K2");
  1700.  
  1701.   TurnWords = False;
  1702.   SetIntConstMode(eIntConstModeIntel);
  1703.  
  1704.   PCSymbol = "PC";
  1705.   HeaderID = pDescr->Id;
  1706.   NOPCode = 0x00;
  1707.   DivideChars = ",";
  1708.   HasAttrs = False;
  1709.  
  1710.   ValidSegs = 1 << SegCode;
  1711.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  1712.   SegLimits[SegCode] = 0xfffff;
  1713.  
  1714.   pASSUMERecs = ASSUME78K2s;
  1715.   ASSUMERecCnt = sizeof(ASSUME78K2s) / sizeof(ASSUME78K2s[0]);
  1716.  
  1717.   MakeCode = MakeCode_78K2; IsDef = IsDef_78K2;
  1718.   SwitchFrom = SwitchFrom_78K2; InitFields();
  1719. }
  1720.  
  1721. void code78k2_init(void)
  1722. {
  1723.   CPU78214 = AddCPU("78214", SwitchTo_78K2);
  1724.  
  1725.   AddInitPassProc(InitCode_78K2);
  1726. }
  1727.