Subversion Repositories pentevo

Rev

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

  1. /* codemsp.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator MSP430                                                      */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include <ctype.h>
  14. #include <string.h>
  15.  
  16. #include "nls.h"
  17. #include "be_le.h"
  18. #include "strutil.h"
  19. #include "bpemu.h"
  20. #include "chunks.h"
  21. #include "errmsg.h"
  22. #include "asmdef.h"
  23. #include "asmsub.h"
  24. #include "asmcode.h"
  25. #include "asmpars.h"
  26. #include "asmallg.h"
  27. #include "onoff_common.h"
  28. #include "chartrans.h"
  29. #include "asmitree.h"
  30. #include "codepseudo.h"
  31. #include "codevars.h"
  32.  
  33. typedef struct
  34. {
  35.   Boolean MayByte;
  36.   Word Code;
  37. } OneOpOrder;
  38.  
  39. typedef enum
  40. {
  41.   eModeReg = 0,
  42.   eModeRegDisp = 1,
  43.   eModeIReg = 2,
  44.   eModeIRegAutoInc = 3,
  45.   eModeNone = 0xff
  46. } tMode;
  47.  
  48. #define MModeReg (1 << eModeReg)
  49. #define MModeRegDisp (1 << eModeRegDisp)
  50. #define MModeIReg (1 << eModeIReg)
  51. #define MModeIRegAutoInc (1 << eModeIRegAutoInc)
  52. #define MModeAs 15
  53. #define MModeAd 3
  54.  
  55. typedef enum
  56. {
  57.   eExtModeNo = 0,
  58.   eExtModeYes = 1
  59. } tExtMode;
  60.  
  61. typedef enum
  62. {
  63.   eOpSizeB = 0,
  64.   eOpSizeW = 1,
  65.   eOpSizeA = 2,
  66.   eOpSizeCnt,
  67.   eOpSizeDefault = eOpSizeW
  68. } tOpSize;
  69.  
  70. #define RegPC 0
  71. #define RegSP 1
  72. #define RegSR 2
  73. #define RegCG1 2
  74. #define RegCG2 3
  75.  
  76. #define REG_PC 0
  77. #define REG_SP 1
  78. #define REG_SR 2
  79.  
  80. typedef struct
  81. {
  82.   Word Mode, Part, Cnt;
  83.   LongWord Val;
  84.   Boolean WasImm, WasAbs;
  85. } tAdrParts;
  86.  
  87. /*  float exp (8bit bias 128) sign mant (impl. norm.)
  88.    double exp (8bit bias 128) sign mant (impl. norm.) */
  89.  
  90. static CPUVar CPUMSP430, CPUMSP430X;
  91.  
  92. static OneOpOrder *OneOpOrders;
  93.  
  94. static tOpSize OpSize;
  95. static Word PCDist, MultPrefix;
  96. static IntType AdrIntType, DispIntType;
  97. static const IntType OpSizeIntTypes[eOpSizeCnt] = { Int8, Int16, Int20 };
  98.  
  99. /*-------------------------------------------------------------------------*/
  100.  
  101. static void ResetAdr(tAdrParts *pAdrParts)
  102. {
  103.   pAdrParts->Mode = eModeNone;
  104.   pAdrParts->Part = 0;
  105.   pAdrParts->Cnt = 0;
  106.   pAdrParts->WasImm =
  107.   pAdrParts->WasAbs = False;
  108. }
  109.  
  110. static Boolean ChkAdr(Byte Mask, tAdrParts *pAdrParts)
  111. {
  112.   if ((pAdrParts->Mode != 0xff) && ((Mask & (1 << pAdrParts->Mode)) == 0))
  113.   {
  114.     ResetAdr(pAdrParts);
  115.     WrError(ErrNum_InvAddrMode);
  116.     return False;
  117.   }
  118.   return True;
  119. }
  120.  
  121. /*!------------------------------------------------------------------------
  122.  * \fn     DecodeRegCore(const char *pArg, Word *pResult)
  123.  * \brief  check whether argument is a CPU register
  124.  * \param  pArg argument to check
  125.  * \param  pResult numeric register value if yes
  126.  * \return True if yes
  127.  * ------------------------------------------------------------------------ */
  128.  
  129. static Boolean DecodeRegCore(const char *pArg, Word *pResult)
  130. {
  131.   if (!as_strcasecmp(pArg, "PC"))
  132.   {
  133.     *pResult = REGSYM_FLAG_ALIAS | REG_PC; return True;
  134.   }
  135.   else if (!as_strcasecmp(pArg,"SP"))
  136.   {
  137.     *pResult = REGSYM_FLAG_ALIAS | REG_SP; return True;
  138.   }
  139.   else if (!as_strcasecmp(pArg, "SR"))
  140.   {
  141.     *pResult = REGSYM_FLAG_ALIAS | REG_SR; return True;
  142.   }
  143.   if ((as_toupper(*pArg) == 'R') && (strlen(pArg) >= 2) && (strlen(pArg) <= 3))
  144.   {
  145.     Boolean OK;
  146.  
  147.     *pResult = ConstLongInt(pArg + 1, &OK, 10);
  148.     return OK && (*pResult < 16);
  149.   }
  150.  
  151.   return False;
  152. }
  153.  
  154. /*!------------------------------------------------------------------------
  155.  * \fn     DissectReg_MSP(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  156.  * \brief  dissect register symbols - MSP variant
  157.  * \param  pDest destination buffer
  158.  * \param  DestSize destination buffer size
  159.  * \param  Value numeric register value
  160.  * \param  InpSize register size
  161.  * ------------------------------------------------------------------------ */
  162.  
  163. static void DissectReg_MSP(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  164. {
  165.   switch (InpSize)
  166.   {
  167.     case eSymbolSize8Bit:
  168.       switch (Value)
  169.       {
  170.         case REGSYM_FLAG_ALIAS | REG_PC:
  171.           as_snprintf(pDest, DestSize, "PC");
  172.           break;
  173.         case REGSYM_FLAG_ALIAS | REG_SP:
  174.           as_snprintf(pDest, DestSize, "SP");
  175.           break;
  176.         case REGSYM_FLAG_ALIAS | REG_SR:
  177.           as_snprintf(pDest, DestSize, "SR");
  178.           break;
  179.         default:
  180.           as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
  181.       }
  182.       break;
  183.     default:
  184.       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
  185.   }
  186. }
  187.  
  188. /*!------------------------------------------------------------------------
  189.  * \fn     DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
  190.  * \brief  check whether argument is a CPU register or register alias
  191.  * \param  pArg argument to check
  192.  * \param  pResult numeric register value if yes
  193.  * \param  MustBeReg excpecting register as arg
  194.  * \return True if yes
  195.  * ------------------------------------------------------------------------ */
  196.  
  197. static Boolean DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
  198. {
  199.   tRegDescr RegDescr;
  200.   tEvalResult EvalResult;
  201.   tRegEvalResult RegEvalResult;
  202.  
  203.   if (DecodeRegCore(pArg->str.p_str, pResult))
  204.   {
  205.     *pResult &= ~REGSYM_FLAG_ALIAS;
  206.     return True;
  207.   }
  208.  
  209.   RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize8Bit, MustBeReg);
  210.   *pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
  211.   return (RegEvalResult == eIsReg);
  212. }
  213.  
  214. static void FillAdrPartsImm(tAdrParts *pAdrParts, LongWord Value, Boolean ForceLong)
  215. {
  216.   ResetAdr(pAdrParts);
  217.   pAdrParts->WasImm = True;
  218.   pAdrParts->Val = Value;
  219.  
  220.   /* assume no usage of constant generators */
  221.  
  222.   pAdrParts->Part = RegPC;
  223.  
  224.   /* constant generators allowed at all? */
  225.  
  226.   if (!ForceLong)
  227.   {
  228.     /* special treatment for -1 since it depends on the operand size: */
  229.  
  230.     if ((Value == 0xffffffff)
  231.      || ((OpSize == eOpSizeB) && (Value == 0xff))
  232.      || ((OpSize == eOpSizeW) && (Value == 0xffff))
  233.      || ((OpSize == eOpSizeA) && (Value == 0xfffff)))
  234.     {
  235.       pAdrParts->Cnt = 0;
  236.       pAdrParts->Part = RegCG2;
  237.       pAdrParts->Mode = eModeIRegAutoInc;
  238.     }
  239.     else switch (Value)
  240.     {
  241.       case 0:
  242.         pAdrParts->Part = RegCG2;
  243.         pAdrParts->Mode = eModeReg;
  244.         break;
  245.       case 1:
  246.         pAdrParts->Part = RegCG2;
  247.         pAdrParts->Mode = eModeRegDisp;
  248.         break;
  249.       case 2:
  250.         pAdrParts->Part = RegCG2;
  251.         pAdrParts->Mode = eModeIReg;
  252.         break;
  253.       case 4:
  254.         pAdrParts->Part = RegCG1;
  255.         pAdrParts->Mode = eModeIReg;
  256.         break;
  257.       case 8:
  258.         pAdrParts->Part = RegCG1;
  259.         pAdrParts->Mode = eModeIRegAutoInc;
  260.         break;
  261.       default:
  262.         break;
  263.     }
  264.   }
  265.  
  266.   /* constant generators not used, in one or the other way -> use
  267.      @PC++ to dispose constant */
  268.  
  269.   if (pAdrParts->Part == RegPC)
  270.   {
  271.     pAdrParts->Cnt = 1;
  272.     pAdrParts->Mode = eModeIRegAutoInc;
  273.   }
  274. }
  275.  
  276. static Boolean DecodeAdr(const tStrComp *pArg, tExtMode ExtMode, Byte Mask, Boolean MayImm, tAdrParts *pAdrParts)
  277. {
  278.   LongWord AdrWord, CurrPC;
  279.   Word Reg;
  280.   Boolean OK;
  281.   char *p;
  282.   IntType ThisAdrIntType = (ExtMode == eExtModeYes) ? AdrIntType : UInt16;
  283.   IntType ThisDispIntType = (ExtMode == eExtModeYes) ? DispIntType : Int16;
  284.   int ArgLen;
  285.  
  286.   ResetAdr(pAdrParts);
  287.  
  288.   /* immediate */
  289.  
  290.   if (*pArg->str.p_str == '#')
  291.   {
  292.     if (!MayImm) WrError(ErrNum_InvAddrMode);
  293.     else
  294.     {
  295.       int ForceLong = (pArg->str.p_str[1] == '>') ? 1 : 0;
  296.  
  297.       AdrWord = EvalStrIntExpressionOffs(pArg, 1 + ForceLong, OpSizeIntTypes[OpSize], &OK);
  298.       if (OK)
  299.       {
  300.         FillAdrPartsImm(pAdrParts, AdrWord, ForceLong);
  301.       }
  302.     }
  303.     return ChkAdr(Mask, pAdrParts);
  304.   }
  305.  
  306.   /* absolut */
  307.  
  308.   if (*pArg->str.p_str == '&')
  309.   {
  310.     pAdrParts->Val = EvalStrIntExpressionOffs(pArg, 1, ThisAdrIntType, &OK);
  311.     if (OK)
  312.     {
  313.       pAdrParts->WasAbs = True;
  314.       pAdrParts->Mode = eModeRegDisp;
  315.       pAdrParts->Part = RegCG1; /* == 0 with As/Ad=1 */
  316.       pAdrParts->Cnt = 1;
  317.     }
  318.     return ChkAdr(Mask, pAdrParts);
  319.   }
  320.  
  321.   /* Register */
  322.  
  323.   switch (DecodeReg(pArg, &Reg, False))
  324.   {
  325.     case eIsReg:
  326.       if (Reg == RegCG2) WrStrErrorPos(ErrNum_InvReg, pArg);
  327.       else
  328.       {
  329.         pAdrParts->Mode = eModeReg;
  330.         pAdrParts->Part = Reg;
  331.       }
  332.       return ChkAdr(Mask, pAdrParts);
  333.     case eIsNoReg:
  334.       break;
  335.     case eRegAbort:
  336.       return False;
  337.   }
  338.  
  339.   /* Displacement */
  340.  
  341.   ArgLen = strlen(pArg->str.p_str);
  342.   if ((*pArg->str.p_str) && (pArg->str.p_str[ArgLen - 1] == ')'))
  343.   {
  344.     tStrComp Arg = *pArg;
  345.  
  346.     StrCompShorten(&Arg, 1);
  347.     p = RQuotPos(Arg.str.p_str, '(');
  348.     if (p)
  349.     {
  350.       tStrComp RegComp, OffsComp;
  351.       char Save;
  352.  
  353.       Save = StrCompSplitRef(&OffsComp, &RegComp, &Arg, p);
  354.       if (DecodeReg(&RegComp, &Reg, True) == eIsReg)
  355.       {
  356.         pAdrParts->Val = EvalStrIntExpression(&OffsComp, ThisDispIntType, &OK);
  357.         if (OK)
  358.         {
  359.           if ((Reg == 2) || (Reg == 3)) WrStrErrorPos(ErrNum_InvReg, &RegComp);
  360.           else if ((pAdrParts->Val == 0) && ((Mask & 4) != 0))
  361.           {
  362.             pAdrParts->Part = Reg;
  363.             pAdrParts->Mode = eModeIReg;
  364.           }
  365.           else
  366.           {
  367.             pAdrParts->Part = Reg;
  368.             pAdrParts->Cnt = 1;
  369.             pAdrParts->Mode = eModeRegDisp;
  370.           }
  371.         }
  372.       }
  373.       *p = Save;
  374.     }
  375.     pArg->str.p_str[ArgLen - 1] = ')';
  376.  
  377.     if (pAdrParts->Mode != eModeNone)
  378.       return ChkAdr(Mask, pAdrParts);
  379.   }
  380.  
  381.   /* indirekt mit/ohne Autoinkrement */
  382.  
  383.   if ((*pArg->str.p_str == '@') || (*pArg->str.p_str == '*'))
  384.   {
  385.     Boolean AutoInc = False;
  386.     tStrComp Arg;
  387.  
  388.     StrCompRefRight(&Arg, pArg, 1);
  389.     ArgLen = strlen(Arg.str.p_str);
  390.     if (Arg.str.p_str[ArgLen - 1] == '+')
  391.     {
  392.       AutoInc = True;
  393.       StrCompShorten(&Arg, 1);
  394.     }
  395.     if (DecodeReg(&Arg, &Reg, True) != eIsReg);
  396.     else if ((Reg == 2) || (Reg == 3)) WrStrErrorPos(ErrNum_InvReg, &Arg);
  397.     else if (!AutoInc && ((Mask & MModeIReg) == 0))
  398.     {
  399.       pAdrParts->Part = Reg;
  400.       pAdrParts->Val = 0;
  401.       pAdrParts->Cnt = 1;
  402.       pAdrParts->Mode = eModeRegDisp;
  403.     }
  404.     else
  405.     {
  406.       pAdrParts->Part = Reg;
  407.       pAdrParts->Mode = AutoInc ? eModeIRegAutoInc : eModeIReg;
  408.     }
  409.     return ChkAdr(Mask, pAdrParts);
  410.   }
  411.  
  412.   /* bleibt PC-relativ aka 'symbolic mode': */
  413.  
  414.   if (!PCDist)
  415.   {
  416.     fprintf(stderr, "internal error: PCDist not set for '%s'\n", OpPart.str.p_str);
  417.     exit(10);
  418.   }
  419.   CurrPC = EProgCounter() + PCDist;
  420.  
  421.   /* extended instruction (on 430X): use the full 20 bit displacement: */
  422.  
  423.   if (ExtMode == eExtModeYes)
  424.   {
  425.     AdrWord = (EvalStrIntExpression(pArg, UInt20, &OK) - CurrPC) & 0xfffff;
  426.   }
  427.  
  428.   /* non-extended instruction on 430X: if the current PC is within the
  429.      first 64K, bits 16..19 will be cleared after addition, i.e. the
  430.      target address must also be within the first 64K: */
  431.  
  432.   else if (MomCPU >= CPUMSP430X)
  433.   {
  434.     if (CurrPC <= 0xffff)
  435.     {
  436.       AdrWord = (EvalStrIntExpression(pArg, UInt16, &OK) - CurrPC) & 0xffff;
  437.     }
  438.     else
  439.     {
  440.       AdrWord = (EvalStrIntExpression(pArg, UInt20, &OK) - CurrPC) & 0xfffff;
  441.       if ((AdrWord > 0x7fff) && (AdrWord < 0xf8000))
  442.       {
  443.         WrError(ErrNum_OverRange);
  444.         OK = False;
  445.       }
  446.     }
  447.   }
  448.  
  449.   /* non-extended instruction on 430: all within 64K with wraparound */
  450.  
  451.   else
  452.   {
  453.     AdrWord = (EvalStrIntExpression(pArg, UInt16, &OK) - CurrPC) & 0xffff;
  454.   }
  455.  
  456.   if (OK)
  457.   {
  458.     pAdrParts->Part = RegPC;
  459.     pAdrParts->Mode = eModeRegDisp;
  460.     pAdrParts->Cnt = 1;
  461.     pAdrParts->Val = AdrWord;
  462.   }
  463.  
  464.   return ChkAdr(Mask, pAdrParts);
  465. }
  466.  
  467. static Word GetBW(void)
  468. {
  469.   return (OpSize == eOpSizeB) || (OpSize == eOpSizeA) ? 0x0040 : 0x0000;
  470. }
  471.  
  472. static Word GetAL(void)
  473. {
  474.   return (OpSize == eOpSizeW) || (OpSize == eOpSizeB) ? 0x0040 : 0x0000;
  475. }
  476.  
  477. static Word GetMult(const tStrComp *pArg, Boolean *pOK)
  478. {
  479.   Word Result = 0x0000;
  480.  
  481.   switch (DecodeReg(pArg, &Result, False))
  482.   {
  483.     case eIsReg:
  484.       *pOK = True;
  485.       return Result | 0x0080;
  486.     case eIsNoReg:
  487.       break;
  488.     case eRegAbort:
  489.       *pOK = False;
  490.       return 0;
  491.   }
  492.  
  493.   if (*pArg->str.p_str == '#')
  494.   {
  495.     tSymbolFlags Flags;
  496.  
  497.     Result = EvalStrIntExpressionOffsWithFlags(pArg, 1, UInt5, pOK, &Flags);
  498.     if (*pOK)
  499.     {
  500.       if (mFirstPassUnknown(Flags))
  501.         Result = 1;
  502.       if (!ChkRange(Result, 1, 16))
  503.         *pOK = False;
  504.       else
  505.         Result--;
  506.     }
  507.   }
  508.   else
  509.     *pOK = False;
  510.   return Result;
  511. }
  512.  
  513. /*-------------------------------------------------------------------------*/
  514.  
  515. static void PutByte(Word Value)
  516. {
  517.   if (CodeLen & 1)
  518.     WAsmCode[CodeLen >> 1] = (Value << 8) | BAsmCode[CodeLen - 1];
  519.   else
  520.     BAsmCode[CodeLen] = Value;
  521.   CodeLen++;
  522. }
  523.  
  524. static void AppendAdrVals(const tAdrParts *pParts)
  525. {
  526.   Word i;
  527.  
  528.   for (i = 0; i < pParts->Cnt; i++)
  529.   {
  530.     WAsmCode[CodeLen >> 1] = pParts->Val;
  531.     CodeLen += 2;
  532.   }
  533. }
  534.  
  535. static void ConstructTwoOp(Word Code, const tAdrParts *pSrcParts, const tAdrParts *pDestParts)
  536. {
  537.   WAsmCode[CodeLen >> 1] = Code | (pSrcParts->Part << 8) | (pDestParts->Mode << 7)
  538.                          | GetBW() | (pSrcParts->Mode << 4) | pDestParts->Part;
  539.   CodeLen += 2;
  540.   AppendAdrVals(pSrcParts);
  541.   AppendAdrVals(pDestParts);
  542. }
  543.  
  544. static void ConstructTwoOpX(Word Code, const tAdrParts *pSrcParts, const tAdrParts *pDestParts)
  545. {
  546.   Word Prefix = 0x1800 | GetAL();
  547.  
  548.   if ((eModeReg != pSrcParts->Mode) || (eModeReg != pDestParts->Mode))
  549.   {
  550.     if (pSrcParts->Cnt)
  551.       Prefix |= ((pSrcParts->Val >> 16) & 15) << 7;
  552.     if (pDestParts->Cnt)
  553.       Prefix |= ((pDestParts->Val >> 16) & 15);
  554.   }
  555.  
  556.   /* take over multiply prefix for register<->register ops only */
  557.  
  558.   else
  559.   {
  560.     Prefix |= MultPrefix;
  561.     MultPrefix = 0;
  562.   }
  563.   WAsmCode[CodeLen >> 1] = Prefix; CodeLen += 2;
  564.   ConstructTwoOp(Code, pSrcParts, pDestParts);
  565. }
  566.  
  567. static void DecodeFixed(Word Code)
  568. {
  569.   if (!ChkArgCnt(0, 0));
  570.   else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
  571.   else if (OpSize != eOpSizeDefault) WrError(ErrNum_InvOpSize);
  572.   else
  573.   {
  574.     if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  575.     WAsmCode[0] = Code; CodeLen = 2;
  576.   }
  577. }
  578.  
  579. static void DecodeTwoOp(Word Code)
  580. {
  581.   tAdrParts SrcParts, DestParts;
  582.  
  583.   if (!ChkArgCnt(2, 2));
  584.   else if (OpSize > eOpSizeW) WrError(ErrNum_InvOpSize);
  585.   else
  586.   {
  587.     PCDist = 2;
  588.     if (DecodeAdr(&ArgStr[1], eExtModeNo, 15, True, &SrcParts))
  589.     {
  590.       PCDist += SrcParts.Cnt << 1;
  591.       if (DecodeAdr(&ArgStr[2], eExtModeNo, 3, False, &DestParts))
  592.       {
  593.         if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  594.         ConstructTwoOp(Code, &SrcParts, &DestParts);
  595.       }
  596.     }
  597.   }
  598. }
  599.  
  600. static void DecodeTwoOpX(Word Code)
  601. {
  602.   tAdrParts SrcParts, DestParts;
  603.  
  604.   Code &= ~1;
  605.  
  606.   if (!ChkArgCnt(2, 2))
  607.     return;
  608.  
  609.   PCDist = 4;
  610.   if (DecodeAdr(&ArgStr[1], eExtModeYes, MModeAs, True, &SrcParts))
  611.   {
  612.     PCDist += SrcParts.Cnt << 1;
  613.     if (DecodeAdr(&ArgStr[2], eExtModeYes, MModeAd, False, &DestParts))
  614.     {
  615.       if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  616.       ConstructTwoOpX(Code, &SrcParts, &DestParts);
  617.     }
  618.   }
  619. }
  620.  
  621. static void DecodeEmulOneToTwo(Word Code)
  622. {
  623.   Byte SrcSpec;
  624.   tAdrParts SrcParts, DestParts;
  625.  
  626.   /* separate src spec & opcode */
  627.  
  628.   SrcSpec = Lo(Code);
  629.   Code &= 0xff00;
  630.  
  631.   if (!ChkArgCnt(1, 1))
  632.     return;
  633.  
  634.   if (OpSize > eOpSizeW)
  635.   {
  636.     WrError(ErrNum_InvOpSize);
  637.     return;
  638.   }
  639.  
  640.   /* Decode operand:
  641.       - Ad modes always allowed
  642.       - for Src == Dest, also allow @Rn+: */
  643.  
  644.   PCDist = 2;
  645.   if (!DecodeAdr(&ArgStr[1], eExtModeNo, MModeAd | ((SrcSpec == 0xaa) ? MModeIRegAutoInc : 0), False, &DestParts))
  646.     return;
  647.  
  648.   /* filter immediate out separately (we get it as d(PC): */
  649.  
  650.   if (DestParts.WasImm)
  651.   {
  652.     WrError(ErrNum_InvAddrMode);
  653.     return;
  654.   }
  655.  
  656.   /* deduce src operand: 0xaa = special value for Src == Dest: */
  657.  
  658.   if (SrcSpec == 0xaa)
  659.   {
  660.     /* default assumption: */
  661.  
  662.     SrcParts = DestParts;
  663.  
  664.     /* @Rn+: is transformed to @Rn+,-opsize(Rn): */
  665.  
  666.     if (SrcParts.Mode == eModeIRegAutoInc)
  667.     {
  668.       static const Byte MemLen[3] = { 1, 2, 4 };
  669.  
  670.       DestParts.Mode = eModeRegDisp;
  671.       DestParts.Val = (0 - MemLen[OpSize]) & 0xffff;
  672.       DestParts.Cnt = 1;
  673.     }
  674.  
  675.     /* for PC-relative addressing, fix up destination displacement and
  676.        complain on displacement overflow: */
  677.  
  678.     else if ((DestParts.Mode == eModeRegDisp) && (DestParts.Part == RegPC))
  679.     {
  680.       LongWord NewDist = DestParts.Val - 2;
  681.  
  682.       if ((NewDist & 0x8000) != (DestParts.Val & 0x8000))
  683.       {
  684.         WrError(ErrNum_DistTooBig);
  685.         return;
  686.       }
  687.       DestParts.Val = NewDist;
  688.     }
  689.  
  690.     /* transform 0(Rn) as Dest back to @Rn as Src: */
  691.  
  692.     else if ((SrcParts.Mode == eModeRegDisp) && (DestParts.Val == 0))
  693.     {
  694.       SrcParts.Mode = eModeIReg;
  695.       SrcParts.Cnt = 0;
  696.     }
  697.   }
  698.  
  699.   /* Src == other (constant) value: 0xff means -1: */
  700.  
  701.   else
  702.     FillAdrPartsImm(&SrcParts, SrcSpec == 0xff ? 0xffffffff : SrcSpec, False);
  703.  
  704.   /* assemble like 2-op instruction: */
  705.  
  706.   ConstructTwoOp(Code, &SrcParts, &DestParts);
  707. }
  708.  
  709. static void DecodeBR(Word Code)
  710. {
  711.   tAdrParts DstParts, SrcParts;
  712.  
  713.   PCDist = 2;
  714.   if (!ChkArgCnt(1, 1));
  715.   else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
  716.   else if (DecodeAdr(&ArgStr[1], eExtModeNo, MModeAs, True, &SrcParts))
  717.   {
  718.     if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  719.     ResetAdr(&DstParts);
  720.     DstParts.Mode = eModeReg;
  721.     DstParts.Part = RegPC;
  722.     ConstructTwoOp(Code, &SrcParts, &DstParts);
  723.   }
  724. }
  725.  
  726. static void DecodeEmulOneToTwoX(Word Code)
  727. {
  728.   Byte SrcSpec;
  729.   tAdrParts SrcParts, DestParts;
  730.  
  731.   /* separate src spec & opcode */
  732.  
  733.   SrcSpec = Lo(Code);
  734.   Code &= 0xff00;
  735.  
  736.   if (!ChkArgCnt(1, 1))
  737.     return;
  738.  
  739.   /* Decode operand:
  740.       - Ad modes always allowed
  741.       - for Src == Dest, also allow @Rn+: */
  742.  
  743.   PCDist = 4;
  744.   if (!DecodeAdr(&ArgStr[1], eExtModeYes, MModeAd | ((SrcSpec == 0xaa) ? MModeIRegAutoInc : 0), False, &DestParts))
  745.     return;
  746.  
  747.   /* filter immediate out separately (we get it as d(PC): */
  748.  
  749.   if (DestParts.WasImm)
  750.   {
  751.     WrError(ErrNum_InvAddrMode);
  752.     return;
  753.   }
  754.  
  755.   /* deduce src operand: 0xaa = special value for Src == Dest: */
  756.  
  757.   if (SrcSpec == 0xaa)
  758.   {
  759.     /* default assumption: */
  760.  
  761.     SrcParts = DestParts;
  762.  
  763.     /* @Rn+: is transformed to @Rn+,-opsize(Rn): */
  764.  
  765.     if (SrcParts.Mode == eModeIRegAutoInc)
  766.     {
  767.       static const Byte MemLen[3] = { 1, 2, 4 };
  768.  
  769.       DestParts.Mode = eModeRegDisp;
  770.       DestParts.Val = (0 - MemLen[OpSize]) & 0xfffff;
  771.       DestParts.Cnt = 1;
  772.     }
  773.  
  774.     /* for PC-relative addressing, fix up destination displacement and
  775.        complain on displacement overflow: */
  776.  
  777.     else if ((DestParts.Mode == eModeRegDisp) && (DestParts.Part == RegPC))
  778.     {
  779.       LongWord NewDist = DestParts.Val - 2;
  780.  
  781.       if ((NewDist & 0x8000) != (DestParts.Val & 0x8000))
  782.       {
  783.         WrError(ErrNum_DistTooBig);
  784.         return;
  785.       }
  786.       DestParts.Val = NewDist;
  787.     }
  788.  
  789.     /* transform 0(Rn) as Dest back to @Rn as Src: */
  790.  
  791.     else if ((SrcParts.Mode == eModeRegDisp) && (DestParts.Val == 0))
  792.     {
  793.       SrcParts.Mode = eModeIReg;
  794.       SrcParts.Cnt = 0;
  795.     }
  796.   }
  797.  
  798.   /* Src == other (constant) value: 0xff means -1: */
  799.  
  800.   else
  801.     FillAdrPartsImm(&SrcParts, SrcSpec == 0xff ? 0xffffffff : SrcSpec, False);
  802.  
  803.   /* assemble like 2-op instruction: */
  804.  
  805.   ConstructTwoOpX(Code, &SrcParts, &DestParts);
  806. }
  807.  
  808. static void DecodePOP(Word Code)
  809. {
  810.   tAdrParts DstParts, SrcParts;
  811.  
  812.   PCDist = 2;
  813.   if (ChkArgCnt(1, 1)
  814.    && DecodeAdr(&ArgStr[1], eExtModeNo, MModeAd, True, &DstParts))
  815.   {
  816.     if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  817.     ResetAdr(&SrcParts);
  818.     SrcParts.Mode = eModeIRegAutoInc;
  819.     SrcParts.Part = RegSP;
  820.     ConstructTwoOp(Code, &SrcParts, &DstParts);
  821.   }
  822. }
  823.  
  824. static void DecodePOPX(Word Code)
  825. {
  826.   tAdrParts DstParts, SrcParts;
  827.  
  828.   PCDist = 4;
  829.   if (ChkArgCnt(1, 1)
  830.    && DecodeAdr(&ArgStr[1], eExtModeYes, MModeAd, True, &DstParts))
  831.   {
  832.     if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  833.     ResetAdr(&SrcParts);
  834.     SrcParts.Mode = eModeIRegAutoInc;
  835.     SrcParts.Part = RegSP;
  836.     ConstructTwoOpX(Code, &SrcParts, &DstParts);
  837.   }
  838. }
  839.  
  840. static void DecodeOneOp(Word Index)
  841. {
  842.   const OneOpOrder *pOrder = OneOpOrders + Index;
  843.  
  844.   if (!ChkArgCnt(1, 1));
  845.   else if (OpSize > eOpSizeW) WrError(ErrNum_InvOpSize);
  846.   else if ((OpSize == eOpSizeB) && (!pOrder->MayByte)) WrError(ErrNum_InvOpSize);
  847.   else
  848.   {
  849.     tAdrParts AdrParts;
  850.  
  851.     PCDist = 2;
  852.     if (DecodeAdr(&ArgStr[1], eExtModeNo, 15, True, &AdrParts))
  853.     {
  854.       if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  855.       WAsmCode[0] = pOrder->Code | GetBW() | (AdrParts.Mode << 4) | AdrParts.Part; CodeLen += 2;
  856.       AppendAdrVals(&AdrParts);
  857.     }
  858.   }
  859. }
  860.  
  861. static void DecodeOneOpX(Word Index)
  862. {
  863.   const OneOpOrder *pOrder = OneOpOrders + Index;
  864.  
  865.   if (!ChkArgCnt(1, 1));
  866.   else if ((OpSize == eOpSizeB) && (!pOrder->MayByte)) WrError(ErrNum_InvOpSize);
  867.   else
  868.   {
  869.     tAdrParts AdrParts;
  870.  
  871.     PCDist = 4;
  872.     if (DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts))
  873.     {
  874.       /* B/W for 20 bit size is 0 instead of 1 for SXT/SWPB */
  875.  
  876.       Word ActBW = pOrder->MayByte ? GetBW() : 0;
  877.  
  878.       if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  879.       WAsmCode[CodeLen >> 1] = 0x1800 | GetAL();
  880.  
  881.       /* put bits 16:19 of operand into bits 0:3 or 7:10 of extension word? */
  882.  
  883.       if (AdrParts.Cnt)
  884.         WAsmCode[CodeLen >> 1] |= (((AdrParts.Val >> 16) & 15) << 7);
  885.  
  886.       /* repeat only supported for register op */
  887.  
  888.       if (AdrParts.Mode == eModeReg)
  889.       {
  890.         WAsmCode[CodeLen >> 1] |= MultPrefix;
  891.         MultPrefix = 0;
  892.       }
  893.       CodeLen += 2;
  894.       WAsmCode[CodeLen >> 1] = pOrder->Code | ActBW | (AdrParts.Mode << 4) | AdrParts.Part; CodeLen += 2;
  895.       AppendAdrVals(&AdrParts);
  896.     }
  897.   }
  898. }
  899.  
  900. static void DecodeMOVA(Word Code)
  901. {
  902.   tAdrParts AdrParts;
  903.  
  904.   UNUSED(Code);
  905.  
  906.   OpSize = eOpSizeA;
  907.   if (!ChkArgCnt(2, 2));
  908.   else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
  909.   else
  910.   {
  911.     PCDist = 2;
  912.     DecodeAdr(&ArgStr[2], eExtModeYes, 15, False, &AdrParts);
  913.     if (AdrParts.WasAbs)
  914.     {
  915.       if (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg)
  916.       {
  917.         if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  918.         WAsmCode[0] = 0x0060 | (WAsmCode[0] << 8) | ((AdrParts.Val >> 16) & 0x0f);
  919.         WAsmCode[1] = AdrParts.Val & 0xffff;
  920.         CodeLen = 4;
  921.       }
  922.     }
  923.     else switch (AdrParts.Mode)
  924.     {
  925.       case eModeReg:
  926.         WAsmCode[0] = AdrParts.Part;
  927.         DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts);
  928.         if (AdrParts.WasImm)
  929.         {
  930.           if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  931.           WAsmCode[0] |= ((AdrParts.Val >> 8) & 0x0f00) | 0x0080;
  932.           WAsmCode[1] = AdrParts.Val & 0xffff;
  933.           CodeLen = 4;
  934.         }
  935.         else if (AdrParts.WasAbs)
  936.         {
  937.           if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  938.           WAsmCode[0] |= ((AdrParts.Val >> 8) & 0x0f00) | 0x0020;
  939.           WAsmCode[1] = AdrParts.Val & 0xffff;
  940.           CodeLen = 4;
  941.         }
  942.         else switch (AdrParts.Mode)
  943.         {
  944.           case eModeReg:
  945.            if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  946.             WAsmCode[0] |= (AdrParts.Part << 8) | 0x00c0;
  947.             CodeLen = 2;
  948.             break;
  949.           case eModeIReg:
  950.             if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  951.             WAsmCode[0] |= (AdrParts.Part << 8) | 0x0000;
  952.             CodeLen = 2;
  953.             break;
  954.           case eModeIRegAutoInc:
  955.             if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  956.             WAsmCode[0] |= (AdrParts.Part << 8) | 0x0010;
  957.             CodeLen = 2;
  958.             break;
  959.           case eModeRegDisp:
  960.             if (ChkRange(AdrParts.Val, 0, 0xffff))
  961.             {
  962.               if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  963.               WAsmCode[0] |= (AdrParts.Part << 8) | 0x0030;
  964.               WAsmCode[1] = AdrParts.Val & 0xffff;
  965.               CodeLen = 4;
  966.             }
  967.             break;
  968.         }
  969.         break;
  970.  
  971.       /* 'MOVA ...,@Rn' is not defined, treat like 'MOVA ...,0(Rn)' */
  972.  
  973.       case eModeIReg:
  974.         AdrParts.Mode = eModeRegDisp;
  975.         AdrParts.Val = 0;
  976.         /* fall-thru */
  977.       case eModeRegDisp:
  978.         if (ChkRange(AdrParts.Val, 0, 0xffff)
  979.          && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
  980.         {
  981.           if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  982.           WAsmCode[0] = 0x0070 | (WAsmCode[0] << 8) | AdrParts.Part;
  983.           WAsmCode[1] = AdrParts.Val & 0xffff;
  984.           CodeLen = 4;
  985.         }
  986.         break;
  987.     }
  988.   }
  989. }
  990.  
  991. static void DecodeBRA(Word Code)
  992. {
  993.   if (ChkArgCnt(1, 1))
  994.   {
  995.     const char PCArg[] = "PC";
  996.  
  997.     AppendArg(strlen(PCArg));
  998.     strcpy(ArgStr[ArgCnt].str.p_str, PCArg);
  999.     DecodeMOVA(Code);
  1000.   }
  1001. }
  1002.  
  1003. static void DecodeCLRA(Word Code)
  1004. {
  1005.   if (ChkArgCnt(1, 1)
  1006.    && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
  1007.   {
  1008.     WAsmCode[0] |= Code;
  1009.     CodeLen = 2;
  1010.   }
  1011. }
  1012.  
  1013. static void DecodeTSTA(Word Code)
  1014. {
  1015.   if (ChkArgCnt(1, 1)
  1016.    && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
  1017.   {
  1018.     WAsmCode[0] |= Code;
  1019.     WAsmCode[1] = 0x0000;
  1020.     CodeLen = 4;
  1021.   }
  1022. }
  1023.  
  1024. static void DecodeDECDA_INCDA(Word Code)
  1025. {
  1026.   if (ChkArgCnt(1, 1)
  1027.    && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
  1028.   {
  1029.     WAsmCode[0] |= Code;
  1030.     WAsmCode[1] = 2;
  1031.     CodeLen = 4;
  1032.   }
  1033. }
  1034.  
  1035. static void DecodeADDA_SUBA_CMPA(Word Code)
  1036. {
  1037.   OpSize = eOpSizeA;
  1038.  
  1039.   if (!ChkArgCnt(2, 2));
  1040.   else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
  1041.   else if (DecodeReg(&ArgStr[2], &WAsmCode[0], False) == eIsReg)
  1042.   {
  1043.     tAdrParts AdrParts;
  1044.  
  1045.     DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts);
  1046.     if (AdrParts.WasImm)
  1047.     {
  1048.       if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  1049.       WAsmCode[0] |= Code | ((AdrParts.Val >> 8) & 0xf00);
  1050.       WAsmCode[1] = AdrParts.Val & 0xffff;
  1051.       CodeLen = 4;
  1052.     }
  1053.     else if (eModeReg == AdrParts.Mode)
  1054.     {
  1055.       if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  1056.       WAsmCode[0] |= Code | 0x0040 | (AdrParts.Part << 8);
  1057.       CodeLen = 2;
  1058.     }
  1059.     else
  1060.       WrError(ErrNum_InvOpSize);
  1061.   }
  1062. }
  1063.  
  1064. static void DecodeRxM(Word Code)
  1065. {
  1066.   if (!ChkArgCnt(2, 2));
  1067.   else if (OpSize == eOpSizeB) WrError(ErrNum_InvOpSize);
  1068.   else if (DecodeReg(&ArgStr[2], &WAsmCode[0], True) != eIsReg);
  1069.   else if (ArgStr[1].str.p_str[0] != '#') WrError(ErrNum_OnlyImmAddr);
  1070.   else
  1071.   {
  1072.     Word Mult;
  1073.     tSymbolFlags Flags;
  1074.     Boolean OK;
  1075.  
  1076.     Mult = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, UInt3, &OK, &Flags);
  1077.     if (OK)
  1078.     {
  1079.       if (mFirstPassUnknown(Flags))
  1080.         Mult = 1;
  1081.       if (ChkRange(Mult, 1, 4))
  1082.       {
  1083.         if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  1084.         WAsmCode[0] |= Code | ((Mult - 1) << 10) | (GetAL() >> 2);
  1085.         CodeLen = 2;
  1086.       }
  1087.     }
  1088.   }
  1089. }
  1090.  
  1091. static void DecodeCALLA(Word Code)
  1092. {
  1093.   tAdrParts AdrParts;
  1094.  
  1095.   UNUSED(Code);
  1096.  
  1097.   OpSize = eOpSizeA;
  1098.   PCDist = 2;
  1099.   if (!ChkArgCnt(1, 1));
  1100.   else if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
  1101.   else if (DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts))
  1102.   {
  1103.     if (AdrParts.WasImm)
  1104.     {
  1105.       WAsmCode[0] = 0x13b0 | ((AdrParts.Val >> 16) & 15);
  1106.       WAsmCode[1] = AdrParts.Val & 0xffff;
  1107.       CodeLen = 4;
  1108.     }
  1109.     else if (AdrParts.WasAbs)
  1110.     {
  1111.       WAsmCode[0] = 0x1380 | ((AdrParts.Val >> 16) & 15);
  1112.       WAsmCode[1] = AdrParts.Val & 0xffff;
  1113.       CodeLen = 4;
  1114.     }
  1115.     else if ((AdrParts.Mode == eModeRegDisp) && (AdrParts.Part == RegPC))
  1116.     {
  1117.       WAsmCode[0] = 0x1390 | ((AdrParts.Val >> 16) & 15);
  1118.       WAsmCode[1] = AdrParts.Val & 0xffff;
  1119.       CodeLen = 4;
  1120.     }
  1121.     else if ((AdrParts.Mode == eModeRegDisp) && (((AdrParts.Val & 0xfffff) > 0x7fff) && ((AdrParts.Val & 0xfffff) < 0xf8000))) WrError(ErrNum_OverRange);
  1122.     else
  1123.     {
  1124.       WAsmCode[CodeLen >> 1] = 0x1340 | (AdrParts.Mode << 4) | (AdrParts.Part); CodeLen += 2;
  1125.       AppendAdrVals(&AdrParts);
  1126.     }
  1127.   }
  1128. }
  1129.  
  1130. static void DecodePUSHM_POPM(Word Code)
  1131. {
  1132.   if (!ChkArgCnt(2, 2));
  1133.   else if (OpSize == 0) WrError(ErrNum_InvOpSize);
  1134.   else if (DecodeReg(&ArgStr[2], &WAsmCode[0], True) != eIsReg);
  1135.   else if (ArgStr[1].str.p_str[0] != '#') WrError(ErrNum_OnlyImmAddr);
  1136.   else
  1137.   {
  1138.     Boolean OK;
  1139.     Word Cnt;
  1140.     tSymbolFlags Flags;
  1141.  
  1142.     Cnt = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, UInt5, &OK, &Flags);
  1143.     if (mFirstPassUnknown(Flags))
  1144.       Cnt = 1;
  1145.     if (OK && ChkRange(Cnt, 1, 16))
  1146.     {
  1147.       Cnt--;
  1148.       if (Code & 0x0200)
  1149.         WAsmCode[0] = (WAsmCode[0] - Cnt) & 15;
  1150.       WAsmCode[0] |= Code | (Cnt << 4) | (GetAL() << 2);
  1151.       CodeLen = 2;
  1152.     }
  1153.   }
  1154. }
  1155.  
  1156. static void DecodeJmp(Word Code)
  1157. {
  1158.   Integer AdrInt;
  1159.   tSymbolFlags Flags;
  1160.   Boolean OK;
  1161.  
  1162.   if (!ChkArgCnt(1, 1));
  1163.   else if (OpSize != eOpSizeDefault) WrError(ErrNum_InvOpSize);
  1164.   {
  1165.     AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &OK, &Flags) - (EProgCounter() + 2);
  1166.     if (OK)
  1167.     {
  1168.       if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
  1169.       else if (!mSymbolQuestionable(Flags) && ((AdrInt < -1024) || (AdrInt > 1022))) WrError(ErrNum_JmpDistTooBig);
  1170.       else
  1171.       {
  1172.         if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
  1173.         WAsmCode[0] = Code | ((AdrInt >> 1) & 0x3ff);
  1174.         CodeLen = 2;
  1175.       }
  1176.     }
  1177.   }
  1178. }
  1179.  
  1180. static void DecodeBYTE(Word Index)
  1181. {
  1182.   TempResult t;
  1183.  
  1184.   UNUSED(Index);
  1185.  
  1186.   as_tempres_ini(&t);
  1187.   if (ChkArgCnt(1, ArgCntMax))
  1188.   {
  1189.     Boolean OK = True;
  1190.     tStrComp *pArg;
  1191.  
  1192.     forallargs(pArg, OK)
  1193.     {
  1194.       KillBlanks(pArg->str.p_str);
  1195.       EvalStrExpression(pArg, &t);
  1196.       switch (t.Typ)
  1197.       {
  1198.         case TempInt:
  1199.           if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xff;
  1200.           if (!RangeCheck(t.Contents.Int, Int8)) WrStrErrorPos(ErrNum_OverRange, pArg);
  1201.           else if (SetMaxCodeLen(CodeLen + 1))
  1202.           {
  1203.             WrStrErrorPos(ErrNum_CodeOverflow, pArg);
  1204.             OK = False;
  1205.           }
  1206.           else
  1207.             PutByte(t.Contents.Int);
  1208.           break;
  1209.         case TempString:
  1210.         {
  1211.           if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &t.Contents.str, pArg))
  1212.             OK = False;
  1213.           else
  1214.           {
  1215.             unsigned l = t.Contents.str.len;
  1216.  
  1217.             if (SetMaxCodeLen(l + CodeLen))
  1218.             {
  1219.               WrStrErrorPos(ErrNum_CodeOverflow, pArg);
  1220.               OK = False;
  1221.             }
  1222.             else
  1223.             {
  1224.               char *pEnd = t.Contents.str.p_str + l, *p;
  1225.  
  1226.               for (p = t.Contents.str.p_str; p < pEnd; PutByte(*(p++)));
  1227.             }
  1228.           }
  1229.           break;
  1230.         }
  1231.         case TempFloat:
  1232.           WrStrErrorPos(ErrNum_StringOrIntButFloat, pArg);
  1233.           /* fall-through */
  1234.         default:
  1235.           OK = False;
  1236.           break;
  1237.       }
  1238.     }
  1239.     if (!OK)
  1240.       CodeLen = 0;
  1241.   }
  1242.   as_tempres_free(&t);
  1243. }
  1244.  
  1245. static void DecodeWORD(Word Index)
  1246. {
  1247.   int z;
  1248.   Word HVal16;
  1249.   Boolean OK;
  1250.  
  1251.   UNUSED(Index);
  1252.  
  1253.   if (ChkArgCnt(1, ArgCntMax))
  1254.   {
  1255.     z = 1; OK = True;
  1256.     do
  1257.     {
  1258.       HVal16 = EvalStrIntExpression(&ArgStr[z], Int16, &OK);
  1259.       if (OK)
  1260.       {
  1261.         WAsmCode[CodeLen >> 1] = HVal16;
  1262.         CodeLen += 2;
  1263.       }
  1264.       z++;
  1265.     }
  1266.     while ((z <= ArgCnt) && (OK));
  1267.     if (!OK) CodeLen = 0;
  1268.   }
  1269. }
  1270.  
  1271. static void DecodeBSS(Word Index)
  1272. {
  1273.   Word HVal16;
  1274.   Boolean OK;
  1275.  
  1276.   UNUSED(Index);
  1277.  
  1278.   if (ChkArgCnt(1, 1))
  1279.   {
  1280.     tSymbolFlags Flags;
  1281.  
  1282.     HVal16 = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags);
  1283.     if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
  1284.     else if (OK)
  1285.     {
  1286.       if (!HVal16) WrError(ErrNum_NullResMem);
  1287.       DontPrint = True; CodeLen = HVal16;
  1288.       BookKeeping();
  1289.     }
  1290.   }
  1291. }
  1292.  
  1293. static void DecodeRPT(Word Code)
  1294. {
  1295.   char *pOpPart, *pArgPart1, *pAttrPart;
  1296.   Boolean OK;
  1297.  
  1298.   /* fundamentals */
  1299.  
  1300.   if (!ChkArgCnt(1, ArgCntMax))
  1301.     return;
  1302.   if (*AttrPart.str.p_str != '\0')
  1303.   {
  1304.     WrError(ErrNum_UseLessAttr);
  1305.     return;
  1306.   }
  1307.  
  1308.   /* multiplier argument */
  1309.  
  1310.   pOpPart = FirstBlank(ArgStr[1].str.p_str);
  1311.   if (!pOpPart)
  1312.   {
  1313.     WrError(ErrNum_CannotSplitArg);
  1314.     return;
  1315.   }
  1316.   *pOpPart++ = '\0';
  1317.   MultPrefix = Code | GetMult(&ArgStr[1], &OK);
  1318.   if (!OK)
  1319.     return;
  1320.  
  1321.   /* new OpPart: */
  1322.  
  1323.   KillPrefBlanks(pOpPart);
  1324.   pArgPart1 = FirstBlank(pOpPart);
  1325.   if (!pArgPart1)
  1326.   {
  1327.     WrError(ErrNum_CannotSplitArg);
  1328.     return;
  1329.   }
  1330.   *pArgPart1++ = '\0';
  1331.   strcpy(OpPart.str.p_str, pOpPart);
  1332.   UpString(OpPart.str.p_str);
  1333.   KillPrefBlanks(pArgPart1);
  1334.   strmov(ArgStr[1].str.p_str, pArgPart1);
  1335.  
  1336.   /* split off new attribute part: */
  1337.  
  1338.   pAttrPart = strrchr(OpPart.str.p_str, '.');
  1339.   if (pAttrPart)
  1340.   {
  1341.     AttrPart.Pos.Len = strmemcpy(AttrPart.str.p_str, STRINGSIZE, pAttrPart + 1, strlen(pAttrPart + 1));
  1342.     *pAttrPart = '\0';
  1343.   }
  1344.   else
  1345.     StrCompReset(&AttrPart);
  1346.  
  1347.   /* prefix 0x0000 is rptc #1 and effectively a NOP prefix: */
  1348.  
  1349.   MakeCode();
  1350.   if (MultPrefix)
  1351.   {
  1352.     WrError(ErrNum_NotRepeatable);
  1353.     CodeLen = 0;
  1354.   }
  1355. }
  1356.  
  1357. /*-------------------------------------------------------------------------*/
  1358.  
  1359. #define AddFixed(NName, NCode) \
  1360.         AddInstTable(InstTable, NName, NCode, DecodeFixed)
  1361.  
  1362. static void AddTwoOp(const char *NName, Word NCode)
  1363. {
  1364.   AddInstTable(InstTable, NName, NCode, DecodeTwoOp);
  1365.   if (MomCPU >= CPUMSP430X)
  1366.   {
  1367.     char XName[20];
  1368.  
  1369.     as_snprintf(XName, sizeof(XName), "%sX", NName);
  1370.     AddInstTable(InstTable, XName, NCode, DecodeTwoOpX);
  1371.   }
  1372. }
  1373.  
  1374. static void AddEmulOneToTwo(const char *NName, Word NCode)
  1375. {
  1376.   AddInstTable(InstTable, NName, NCode, DecodeEmulOneToTwo);
  1377. }
  1378.  
  1379. static void AddEmulOneToTwoX(const char *NName, Word NCode)
  1380. {
  1381.   AddInstTable(InstTable, NName, NCode, DecodeEmulOneToTwoX);
  1382. }
  1383.  
  1384. static void AddOneOp(const char *NName, Boolean NMay, Boolean AllowX, Word NCode)
  1385. {
  1386.   order_array_rsv_end(OneOpOrders, OneOpOrder);
  1387.   OneOpOrders[InstrZ].MayByte = NMay;
  1388.   OneOpOrders[InstrZ].Code = NCode;
  1389.   AddInstTable(InstTable, NName, InstrZ, DecodeOneOp);
  1390.   if ((MomCPU >= CPUMSP430X) && AllowX)
  1391.   {
  1392.     char XName[20];
  1393.  
  1394.     as_snprintf(XName, sizeof(XName), "%sX", NName);
  1395.     AddInstTable(InstTable, XName, InstrZ, DecodeOneOpX);
  1396.   }
  1397.   InstrZ++;
  1398. }
  1399.  
  1400. #define AddJmp(NName, NCode) \
  1401.         AddInstTable(InstTable, NName, NCode, DecodeJmp)
  1402.  
  1403. static void InitFields(void)
  1404. {
  1405.   InstTable = CreateInstTable(207);
  1406.   SetDynamicInstTable(InstTable);
  1407.  
  1408.   AddFixed("RETI", 0x1300);
  1409.   AddFixed("CLRC", 0xc312);
  1410.   AddFixed("CLRN", 0xc222);
  1411.   AddFixed("CLRZ", 0xc322);
  1412.   AddFixed("DINT", 0xc232);
  1413.   AddFixed("EINT", 0xd232);
  1414.   AddFixed("NOP" , NOPCode);
  1415.   AddFixed("RET" , 0x4130);
  1416.   AddFixed("SETC", 0xd312);
  1417.   AddFixed("SETN", 0xd222);
  1418.   AddFixed("SETZ", 0xd322);
  1419.  
  1420.   AddTwoOp("MOV" , 0x4000); AddTwoOp("ADD" , 0x5000);
  1421.   AddTwoOp("ADDC", 0x6000); AddTwoOp("SUBC", 0x7000);
  1422.   AddTwoOp("SUB" , 0x8000); AddTwoOp("CMP" , 0x9000);
  1423.   AddTwoOp("DADD", 0xa000); AddTwoOp("BIT" , 0xb000);
  1424.   AddTwoOp("BIC" , 0xc000); AddTwoOp("BIS" , 0xd000);
  1425.   AddTwoOp("XOR" , 0xe000); AddTwoOp("AND" , 0xf000);
  1426.  
  1427.   AddEmulOneToTwo("ADC" , 0x6000); /* ADDC #0, dst */
  1428.   AddInstTable(InstTable, "BR", 0x4000, DecodeBR); /* MOV dst, PC */
  1429.   AddEmulOneToTwo("CLR" , 0x4000); /* MOV #0, dst */
  1430.   AddEmulOneToTwo("DADC", 0xa000); /* DADD #0, dst */
  1431.   AddEmulOneToTwo("DEC" , 0x8001); /* SUB #1, dst */
  1432.   AddEmulOneToTwo("DECD", 0x8002); /* SUB #2, dst */
  1433.   AddEmulOneToTwo("INC" , 0x5001); /* ADD #1, dst */
  1434.   AddEmulOneToTwo("INCD", 0x5002); /* ADD #2, dst */
  1435.   AddEmulOneToTwo("INV" , 0xe0ff); /* XOR #-1, dst */
  1436.   AddInstTable(InstTable, "POP", 0x4000, DecodePOP); /* MOV @SP+,dst */
  1437.   AddEmulOneToTwo("RLA" , 0x50aa); /* ADD dst, dst */
  1438.   AddEmulOneToTwo("RLC" , 0x60aa); /* ADDC dst, dst */
  1439.   AddEmulOneToTwo("SBC" , 0x7000); /* SUBC #0, dst */
  1440.   AddEmulOneToTwo("TST" , 0x9000); /* CMP #0, dst */
  1441.  
  1442.   InstrZ = 0;
  1443.   AddOneOp("RRC" , True , True , 0x1000); AddOneOp("RRA" , True , True , 0x1100);
  1444.   AddOneOp("PUSH", True , True , 0x1200); AddOneOp("SWPB", False, True , 0x1080);
  1445.   AddOneOp("CALL", False, False, 0x1280); AddOneOp("SXT" , False, True , 0x1180);
  1446.  
  1447.   if (MomCPU >= CPUMSP430X)
  1448.   {
  1449.     /* what about  RRUX? */
  1450.  
  1451.     AddInstTable(InstTable, "MOVA", 0x0000, DecodeMOVA);
  1452.     AddInstTable(InstTable, "ADDA", 0x00a0, DecodeADDA_SUBA_CMPA);
  1453.     AddInstTable(InstTable, "CMPA", 0x0090, DecodeADDA_SUBA_CMPA);
  1454.     AddInstTable(InstTable, "SUBA", 0x00b0, DecodeADDA_SUBA_CMPA);
  1455.  
  1456.     AddInstTable(InstTable, "RRCM", 0x0040, DecodeRxM);
  1457.     AddInstTable(InstTable, "RRAM", 0x0140, DecodeRxM);
  1458.     AddInstTable(InstTable, "RLAM", 0x0240, DecodeRxM);
  1459.     AddInstTable(InstTable, "RRUM", 0x0340, DecodeRxM);
  1460.  
  1461.     AddInstTable(InstTable, "CALLA", 0x0000, DecodeCALLA);
  1462.  
  1463.     AddInstTable(InstTable, "PUSHM", 0x1400, DecodePUSHM_POPM);
  1464.     AddInstTable(InstTable, "POPM",  0x1600, DecodePUSHM_POPM);
  1465.  
  1466.     AddEmulOneToTwoX("ADCX", 0x6000); /* ADDCX #0, dst */
  1467.     AddInstTable(InstTable, "BRA", 0x4000, DecodeBRA); /* MOVA dst, PC */
  1468.     AddFixed("RETA", 0x0110); /* MOVA @SP+,PC */
  1469.     AddInstTable(InstTable, "CLRA", 0x4300, DecodeCLRA); /* MOV #0,Rdst */
  1470.     AddEmulOneToTwoX("CLRX", 0x4000); /* MOVX #0, dest */
  1471.     AddEmulOneToTwoX("DADCX", 0xa000); /* DADDX #0, dst */
  1472.     AddEmulOneToTwoX("DECX" , 0x8001); /* SUBX #1, dst */
  1473.     AddInstTable(InstTable, "DECDA", 0x00b0, DecodeDECDA_INCDA); /* SUBA #2,Rdst */
  1474.     AddEmulOneToTwoX("DECDX", 0x8002); /* SUBX #2, dst */
  1475.     AddEmulOneToTwoX("INCX" , 0x5001); /* SUBX #1, dst */
  1476.     AddInstTable(InstTable, "INCDA", 0x00a0, DecodeDECDA_INCDA); /* SUBA #2,Rdst */
  1477.     AddEmulOneToTwoX("INCDX", 0x5002); /* SUBX #2, dst */
  1478.     AddEmulOneToTwoX("INVX" , 0xe0ff); /* XORX #-1, dst */
  1479.     AddEmulOneToTwoX("RLAX" , 0x50aa); /* ADDX dst, dst */
  1480.     AddEmulOneToTwoX("RLCX" , 0x60aa); /* ADDCX dst, dst */
  1481.     AddEmulOneToTwoX("SBCX" , 0x7000); /* SUBCX #0, dst */
  1482.     AddInstTable(InstTable, "TSTA" , 0x0090, DecodeTSTA); /* CMPA #0,Rdst */
  1483.     AddEmulOneToTwoX("TSTX" , 0x9000); /* CMPX #0, dst */
  1484.     AddInstTable(InstTable, "POPX", 0x4000, DecodePOPX); /* MOVX @SP+,dst */
  1485.  
  1486.     AddInstTable(InstTable, "RPTC", 0x0000, DecodeRPT);
  1487.     AddInstTable(InstTable, "RPTZ", 0x0100, DecodeRPT);
  1488.   }
  1489.  
  1490.   AddJmp("JNE" , 0x2000); AddJmp("JNZ" , 0x2000);
  1491.   AddJmp("JE"  , 0x2400); AddJmp("JZ"  , 0x2400);
  1492.   AddJmp("JNC" , 0x2800); AddJmp("JC"  , 0x2c00);
  1493.   AddJmp("JN"  , 0x3000); AddJmp("JGE" , 0x3400);
  1494.   AddJmp("JL"  , 0x3800); AddJmp("JMP" , 0x3C00);
  1495.   AddJmp("JEQ" , 0x2400); AddJmp("JLO" , 0x2800);
  1496.   AddJmp("JHS" , 0x2c00);
  1497.  
  1498.   AddInstTable(InstTable, "WORD", 0, DecodeWORD);
  1499.  
  1500.   AddInstTable(InstTable, "REG", 0, CodeREG);
  1501. }
  1502.  
  1503. static void DeinitFields(void)
  1504. {
  1505.   order_array_free(OneOpOrders);
  1506.  
  1507.   DestroyInstTable(InstTable);
  1508. }
  1509.  
  1510. /*-------------------------------------------------------------------------*/
  1511.  
  1512. /*!------------------------------------------------------------------------
  1513.  * \fn     InternSymbol_MSP(char *pArg, TempResult *pResult)
  1514.  * \brief  handle built-in (register) symbols for MSP
  1515.  * \param  pArg source argument
  1516.  * \param  pResult result buffer
  1517.  * ------------------------------------------------------------------------ */
  1518.  
  1519. static void InternSymbol_MSP(char *pArg, TempResult *pResult)
  1520. {
  1521.   Word RegNum;
  1522.  
  1523.   if (DecodeRegCore(pArg, &RegNum))
  1524.   {
  1525.     pResult->Typ = TempReg;
  1526.     pResult->DataSize = eSymbolSize8Bit;
  1527.     pResult->Contents.RegDescr.Reg = RegNum;
  1528.     pResult->Contents.RegDescr.Dissect = DissectReg_MSP;
  1529.     pResult->Contents.RegDescr.compare = NULL;
  1530.   }
  1531. }
  1532.  
  1533. static Boolean DecodeAttrPart_MSP(void)
  1534. {
  1535.   if (strlen(AttrPart.str.p_str) > 1)
  1536.   {
  1537.     WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
  1538.     return False;
  1539.   }
  1540.   switch (as_toupper(*AttrPart.str.p_str))
  1541.   {
  1542.     case '\0':
  1543.       break;
  1544.     case 'B':
  1545.       AttrPartOpSize[0] = eSymbolSize8Bit;
  1546.       break;
  1547.     case 'W':
  1548.       AttrPartOpSize[0] = eSymbolSize16Bit;
  1549.       break;
  1550.     case 'A':
  1551.       if (MomCPU >= CPUMSP430X)
  1552.       {
  1553.         AttrPartOpSize[0] = eSymbolSize24Bit; /* TODO: should be 20 bits */
  1554.         break;
  1555.       }
  1556.       /* else fall-through */
  1557.     default:
  1558.       WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
  1559.       return False;
  1560.   }
  1561.   return True;
  1562. }
  1563.  
  1564. static void MakeCode_MSP(void)
  1565. {
  1566.   CodeLen = 0; DontPrint = False; PCDist = 0;
  1567.  
  1568.   /* to be ignored: */
  1569.  
  1570.   if (Memo("")) return;
  1571.  
  1572.   /* process attribute */
  1573.  
  1574.   switch (AttrPartOpSize[0])
  1575.   {
  1576.     case eSymbolSize24Bit:
  1577.       OpSize = eOpSizeA;
  1578.       break;
  1579.     case eSymbolSize16Bit:
  1580.       OpSize = eOpSizeW;
  1581.       break;
  1582.     case eSymbolSize8Bit:
  1583.       OpSize = eOpSizeB;
  1584.       break;
  1585.     default:
  1586.       OpSize = eOpSizeDefault;
  1587.       break;
  1588.   }
  1589.  
  1590.   /* insns not requiring word alignment */
  1591.  
  1592.   if (Memo("BYTE"))
  1593.   {
  1594.     DecodeBYTE(0);
  1595.     return;
  1596.   }
  1597.   if (Memo("BSS"))
  1598.   {
  1599.     DecodeBSS(0);
  1600.     return;
  1601.   }
  1602.  
  1603.   /* For all other (pseudo) instructions, optionally pad to even */
  1604.  
  1605.   if (Odd(EProgCounter()))
  1606.   {
  1607.     if (DoPadding)
  1608.       InsertPadding(1, False);
  1609.     else
  1610.       WrError(ErrNum_AddrNotAligned);
  1611.   }
  1612.  
  1613.   /* all the rest from table */
  1614.  
  1615.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  1616.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  1617. }
  1618.  
  1619. static Boolean IsDef_MSP(void)
  1620. {
  1621.   return Memo("REG");
  1622. }
  1623.  
  1624. static void SwitchTo_MSP(void)
  1625. {
  1626.   TurnWords = False; SetIntConstMode(eIntConstModeIntel);
  1627.  
  1628.   PCSymbol = "$"; HeaderID = 0x4a; NOPCode = 0x4303; /* = MOV #0,#0 */
  1629.   DivideChars = ","; HasAttrs = True; AttrChars = ".";
  1630.  
  1631.   ValidSegs = 1 << SegCode;
  1632.   Grans[SegCode] = 1; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
  1633.   AdrIntType = (MomCPU == CPUMSP430X) ? UInt20 : UInt16;
  1634.   DispIntType = (MomCPU == CPUMSP430X) ? Int20 : Int16;
  1635.   SegLimits[SegCode] = IntTypeDefs[AdrIntType].Max;
  1636.  
  1637.   AddONOFF(DoPaddingName, &DoPadding, DoPaddingName, False);
  1638.  
  1639.   DecodeAttrPart = DecodeAttrPart_MSP;
  1640.   MakeCode = MakeCode_MSP;
  1641.   IsDef = IsDef_MSP;
  1642.   InternSymbol = InternSymbol_MSP;
  1643.   DissectReg = DissectReg_MSP;
  1644.   SwitchFrom = DeinitFields; InitFields();
  1645.  
  1646.   MultPrefix = 0x0000;
  1647. }
  1648.  
  1649. void codemsp_init(void)
  1650. {
  1651.   CPUMSP430 = AddCPU("MSP430", SwitchTo_MSP);
  1652.   CPUMSP430X = AddCPU("MSP430X", SwitchTo_MSP);
  1653. }
  1654.