Subversion Repositories pentevo

Rev

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

  1. /* codeh16.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Code Generator Hitachi H16                                                */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include <string.h>
  14. #include <ctype.h>
  15.  
  16. #include "bpemu.h"
  17. #include "strutil.h"
  18. #include "chunks.h"
  19. #include "headids.h"
  20. #include "asmdef.h"
  21. #include "asmsub.h"
  22. #include "asmpars.h"
  23. #include "asmallg.h"
  24. #include "onoff_common.h"
  25. #include "asmitree.h"
  26. #include "asmstructs.h"
  27. #include "codepseudo.h"
  28. #include "motpseudo.h"
  29. #include "codevars.h"
  30. #include "errmsg.h"
  31. #include "nls.h"
  32.  
  33. #include "codeh16.h"
  34.  
  35. /*---------------------------------------------------------------------------*/
  36.  
  37. static CPUVar CPU641016;
  38. static tSymbolSize OpSize;
  39. static tStrComp FormatPart;
  40.  
  41. #define REG_SP 15
  42.  
  43. typedef enum
  44. {
  45.   eAdrModeNone = -1,
  46.   eAdrModeReg = 0,
  47.   eAdrModeIReg = 1,
  48.   eAdrModePost = 2,
  49.   eAdrModePre = 3,
  50.   eAdrModeImm = 4,
  51.   eAdrModeAbs = 5,
  52.   eAdrModeIRegScale = 6,
  53.   eAdrModeIdxScale = 7,
  54.   eAdrModePCIdxScale = 8,
  55.   eAdrModePCRel = 9,
  56.   eAdrModeDoubleIndir = 10
  57. } tAdrMode;
  58.  
  59. #define MModeReg (1 << eAdrModeReg)
  60. #define MModeIReg (1 << eAdrModeIReg)
  61. #define MModePost (1 << eAdrModePost)
  62. #define MModePre (1 << eAdrModePre)
  63. #define MModeImm (1 << eAdrModeImm)
  64. #define MModeAbs (1 << eAdrModeAbs)
  65. #define MModeIRegScale (1 << eAdrModeIRegScale)
  66. #define MModeIdxScale (1 << eAdrModeIdxScale)
  67. #define MModePCIdxScale (1 << eAdrModePCIdxScale)
  68. #define MModePCRel (1 << eAdrModePCRel)
  69. #define MModeDoubleIndir (1 << eAdrModeDoubleIndir)
  70. #define MModeAll (MModeReg | MModeIReg | MModePost | MModePre | MModeImm | MModeAbs | MModeIRegScale | MModeIdxScale | MModePCIdxScale | MModePCRel | MModeDoubleIndir)
  71.  
  72. typedef enum
  73. {
  74.   eFormatNone,
  75.   eFormatG,
  76.   eFormatQ,
  77.   eFormatR,
  78.   eFormatRQ,
  79.   eFormatF  /* no source-side format; used for MOV->MOVF conversion */
  80. } tFormat;
  81.  
  82. #ifdef __cplusplus
  83. # include "codeh16.hpp"
  84. #endif
  85.  
  86. typedef struct
  87. {
  88.   tAdrMode Mode;
  89.   unsigned Cnt;
  90.   Byte Vals[10];
  91. } tAdrVals;
  92.  
  93. #define NOREG 255
  94. #define PCREG 254
  95. #define NormalReg(Reg) ((Reg) <= 15)
  96. #define DefIndexRegSize eSymbolSize32Bit /* correct? */
  97.  
  98. #define PREFIX_CRn 0x70
  99. #define PREFIX_PRn 0x74
  100.  
  101. #define eSymbolSize5Bit ((tSymbolSize)-2)  /* for shift cnt/bit pos arg */
  102. #define eSymbolSize4Bit ((tSymbolSize)-3)  /* for bit pos arg */
  103. #define eSymbolSize3Bit ((tSymbolSize)-4)  /* for bit pos arg */
  104.  
  105. typedef struct
  106. {
  107.   LongInt OuterDisp, InnerDisp;
  108.   Boolean OuterDispPresent, InnerDispPresent;
  109.   tSymbolSize OuterDispSize, InnerDispSize;
  110.   Byte BaseReg, IndexReg, InnerReg;
  111.   ShortInt BaseRegIncr, IndexRegSize;
  112.   Byte IndexRegScale;
  113.   Byte RegPrefix;
  114. } tAdrComps;
  115.  
  116. /*---------------------------------------------------------------------------*/
  117.  
  118. /*!------------------------------------------------------------------------
  119.  * \fn     SetOpSize(tSymbolSize NewOpSize)
  120.  * \brief  set (instruction) operand size; complain if size mismatch
  121.  * \param  NewOpSize size to set
  122.  * \return True if setting/confirmation succeeded
  123.  * ------------------------------------------------------------------------ */
  124.  
  125. static Boolean SetOpSize(tSymbolSize NewOpSize)
  126. {
  127.   if ((OpSize != eSymbolSizeUnknown) && (NewOpSize != OpSize))
  128.   {
  129.     WrError(ErrNum_ConfOpSizes);
  130.     return False;
  131.   }
  132.   OpSize = NewOpSize;
  133.   return True;
  134. }
  135.  
  136. /*!------------------------------------------------------------------------
  137.  * \fn     ChkOpSize(tSymbolSize DefaultSize, Word Mask)
  138.  * \brief  possibly set & check instruction operand size
  139.  * \param  DefaultSize size to set if size is unknown so far
  140.  * \param  Mask bit mask of allowed sizes (8/16/32 -> bit 0/1/2)
  141.  * \return True if operand size is OK
  142.  * ------------------------------------------------------------------------ */
  143.  
  144. static Boolean ChkOpSize(tSymbolSize DefaultSize, Word Mask)
  145. {
  146.   if (OpSize == eSymbolSizeUnknown)
  147.     OpSize = DefaultSize;
  148.   if (!((Mask >> OpSize) & 1))
  149.   {
  150.     WrError(ErrNum_InvOpSize);
  151.     return False;
  152.   }
  153.   return True;
  154. }
  155.  
  156. /*!------------------------------------------------------------------------
  157.  * \fn     DecodeFormat(unsigned FormatMask)
  158.  * \brief  decode instruction's format to internal enum
  159.  * \param  FormatMask bit mask of allowed formats
  160.  * \return resulting format or FormatNone if unknown/disallowed
  161.  * ------------------------------------------------------------------------ */
  162.  
  163. static tFormat DecodeFormat(unsigned FormatMask)
  164. {
  165.   static const char Formats[][3] = { "G", "Q", "R", "RQ", "" };
  166.   tFormat Result;
  167.  
  168.   FormatMask >>= 1;
  169.   for (Result = (tFormat)0; *Formats[Result]; Result++, FormatMask >>= 1)
  170.     if ((FormatMask & 1) && !as_strcasecmp(FormatPart.str.p_str, Formats[Result]))
  171.       return Result + 1;
  172.   return eFormatNone;
  173. }
  174.  
  175. /*!------------------------------------------------------------------------
  176.  * \fn     ChkEmptyFormat(void)
  177.  * \brief  check whether no format spec was given and complain if there is one
  178.  * \return True if no format spec was given
  179.  * ------------------------------------------------------------------------ */
  180.  
  181. static Boolean ChkEmptyFormat(void)
  182. {
  183.   if (*FormatPart.str.p_str)
  184.   {
  185.     WrStrErrorPos(ErrNum_InvFormat, &FormatPart);
  186.     return False;
  187.   }
  188.   return True;
  189. }
  190.  
  191. /*!------------------------------------------------------------------------
  192.  * \fn     ResetAdrVals(tAdrVals *pAdrVals)
  193.  * \brief  reset tAdrVals structure to initial state
  194.  * \param  pAdrVals struct to reset
  195.  * ------------------------------------------------------------------------ */
  196.  
  197. static void ResetAdrVals(tAdrVals *pAdrVals)
  198. {
  199.   pAdrVals->Mode = eAdrModeNone;
  200.   pAdrVals->Cnt = 0;
  201. }
  202.  
  203. /*!------------------------------------------------------------------------
  204.  * \fn     AppendAdrVals(tAdrVals *pAdrVals, Byte Value)
  205.  * \brief  append another byte to tAdrVals' expansion byte list; check for overflow
  206.  * \param  pAdrVals AdrVals to extend
  207.  * \param  Value new value to append
  208.  * ------------------------------------------------------------------------ */
  209.  
  210. static void AppendAdrVals(tAdrVals *pAdrVals, Byte Value)
  211. {
  212.   if (pAdrVals->Cnt >= (sizeof(pAdrVals->Vals) / sizeof(*pAdrVals->Vals)))
  213.   {
  214.     WrError(ErrNum_CodeOverflow);
  215.     return;
  216.   }
  217.   pAdrVals->Vals[pAdrVals->Cnt++] = Value;
  218. }
  219.  
  220. /*!------------------------------------------------------------------------
  221.  * \fn     AppendRegPrefix(tAdrVals *pAdrVals, Byte RegPrefix)
  222.  * \brief  append register prefix to tAdrVals if not a global bank register
  223.  * \param  pAdrVals AdrVals to extend
  224.  * \param  RegPrefix register prefix (0x70/0x74 or 0x00 for no prefix)
  225.  * ------------------------------------------------------------------------ */
  226.  
  227. static void AppendRegPrefix(tAdrVals *pAdrVals, Byte RegPrefix)
  228. {
  229.   if (RegPrefix)
  230.     AppendAdrVals(pAdrVals, RegPrefix);
  231. }
  232.  
  233. /*!------------------------------------------------------------------------
  234.  * \fn     AppendBySize(Byte *pDest, LongInt Value, tSymbolSize OpSize)
  235.  * \brief  append an integer value to byte array, BE order
  236.  * \param  pDest where to write
  237.  * \param  Value integer value to append
  238.  * \param  OpSize operand size of value (3/4/5/8/16/32 bits)
  239.  * \return # of bytes appended
  240.  * ------------------------------------------------------------------------ */
  241.  
  242. static unsigned GetH16SymbolSizeBytes(tSymbolSize Size)
  243. {
  244.   return (Size <= eSymbolSize5Bit) ? 1 : GetSymbolSizeBytes(Size);
  245. }
  246.  
  247. static unsigned AppendBySize(Byte *pDest, LongInt Value, tSymbolSize OpSize)
  248. {
  249.   int z;
  250.   unsigned Cnt = GetH16SymbolSizeBytes(OpSize);
  251.  
  252.   for (z = Cnt - 1; z >= 0; z--)
  253.   {
  254.     pDest[z] = Value & 0xff;
  255.     Value >>= 8;
  256.   }
  257.   return Cnt;
  258. }
  259.  
  260. /*!------------------------------------------------------------------------
  261.  * \fn     AppendToAdrValsBySize(tAdrVals *pAdrVals, LongInt Value, tSymbolSize OpSize)
  262.  * \brief  append an integer value to tAdrVals
  263.  * \param  pAdrVals AdrVals to extend
  264.  * \param  Value integer value to append
  265.  * \param  OpSize operand size of value (3/4/5/8/16/32 bits)
  266.  * ------------------------------------------------------------------------ */
  267.  
  268. static void AppendToAdrValsBySize(tAdrVals *pAdrVals, LongInt Value, tSymbolSize OpSize)
  269. {
  270.   unsigned Cnt = GetH16SymbolSizeBytes(OpSize);
  271.  
  272.   if ((pAdrVals->Cnt + Cnt) > (sizeof(pAdrVals->Vals) / sizeof(*pAdrVals->Vals)))
  273.   {
  274.     WrError(ErrNum_CodeOverflow);
  275.     return;
  276.   }
  277.   AppendBySize(pAdrVals->Vals + pAdrVals->Cnt, Value, OpSize);
  278.   pAdrVals->Cnt += Cnt;
  279. }
  280.  
  281. /*!------------------------------------------------------------------------
  282.  * \fn     ResetAdrComps(tAdrComps *pComps)
  283.  * \brief  reset indirect address parser context to empty state
  284.  * \param  pComps context to reset
  285.  * ------------------------------------------------------------------------ */
  286.  
  287. static void ResetAdrComps(tAdrComps *pComps)
  288. {
  289.   pComps->OuterDisp = pComps->InnerDisp = 0;
  290.   pComps->OuterDispPresent = pComps->InnerDispPresent = False;
  291.   pComps->OuterDispSize = pComps->InnerDispSize = eSymbolSizeUnknown;
  292.   pComps->BaseReg = pComps->IndexReg = pComps->InnerReg = NOREG;
  293.   pComps->IndexRegScale = pComps->BaseRegIncr = 0;
  294.   pComps->IndexRegSize = DefIndexRegSize;
  295.   pComps->RegPrefix = 0x00;
  296. }
  297.  
  298. /*!------------------------------------------------------------------------
  299.  * \fn     SplitOpSize(tStrComp *pArg, tSymbolSize *pSize)
  300.  * \brief  split off explicit size spec from argument
  301.  * \param  pArg argument to treat
  302.  * \param  pSize resulting size if suffix was present
  303.  * \return True if a suffix was split off
  304.  * ------------------------------------------------------------------------ */
  305.  
  306. static Boolean SplitOpSize(tStrComp *pArg, tSymbolSize *pSize)
  307. {
  308.   static const char Suffixes[][4] = { ".B", ":8", ".W", ":16", ".L", ":32" };
  309.   int l = strlen(pArg->str.p_str), l2;
  310.   unsigned z;
  311.  
  312.   for (z = 0; z < sizeof(Suffixes) / sizeof(*Suffixes); z++)
  313.   {
  314.     l2 = strlen(Suffixes[z]);
  315.     if ((l > l2) && !as_strcasecmp(pArg->str.p_str + l - l2, Suffixes[z]))
  316.     {
  317.       StrCompShorten(pArg, l2);
  318.       *pSize = (tSymbolSize)(z / 2);
  319.       return True;
  320.     }
  321.   }
  322.   return False;
  323. }
  324.  
  325. /*!------------------------------------------------------------------------
  326.  * \fn     SplitScale(tStrComp *pArg, Byte *pScale)
  327.  * \brief  split off scaling option from (register) argument
  328.  * \param  pArg argument to treat
  329.  * \param  pScale resulting scale if suffix was present
  330.  * \return True if a suffix was split off
  331.  * ------------------------------------------------------------------------ */
  332.  
  333. static const char ScaleSuffixes[][3] = { "*1", "*2", "*4", "*8" };
  334.  
  335. static char SplitScale(tStrComp *pArg, Byte *pScale)
  336. {
  337.   int l = strlen(pArg->str.p_str);
  338.   unsigned z;
  339.  
  340.   if (l >= 2)
  341.     for (z = 0; z < sizeof(ScaleSuffixes) / sizeof(*ScaleSuffixes); z++)
  342.       if (!as_strcasecmp(pArg->str.p_str + l - 2, ScaleSuffixes[z]))
  343.       {
  344.         StrCompShorten(pArg, 2);
  345.         *pScale = z;
  346.         return *ScaleSuffixes[z];
  347.       }
  348.   return '\0';
  349. }
  350.  
  351. /*!------------------------------------------------------------------------
  352.  * \fn     AppendScale(tStrComp *pArg, Byte Scale)
  353.  * \brief  append scaling option to (register) argument
  354.  * \param  pArg argument to augment by scaling
  355.  * \param  Scale Scale to append
  356.  * ------------------------------------------------------------------------ */
  357.  
  358. static void AppendScale(tStrComp *pArg, Byte Scale)
  359. {
  360.   strcat(pArg->str.p_str, ScaleSuffixes[Scale]);
  361.   pArg->Pos.Len += 2;
  362. }
  363.  
  364. /*!------------------------------------------------------------------------
  365.  * \fn     DecodeRegCore(const char *pArg, Byte *pResult, Byte *pPrefix)
  366.  * \brief  check whether argument is a register and return register # if yes
  367.  * \param  pArg argument to check
  368.  * \param  pResult register # if argument is a valid (general) register
  369.  * \param  pPrefix prefix for previous/current bank registers; 0 for global bank registers
  370.  * \return True if argument is a register
  371.  * ------------------------------------------------------------------------ */
  372.  
  373. static Boolean DecodeRegCore(const char *pArg, Byte *pResult, Byte *pPrefix)
  374. {
  375.   Boolean OK;
  376.  
  377.   if (!as_strcasecmp(pArg, "SP"))
  378.   {
  379.     *pResult = REGSYM_FLAG_ALIAS | REG_SP;
  380.     *pPrefix = 0x00;
  381.     return True;
  382.   }
  383.  
  384.   if ((strlen(pArg) > 1)
  385.    && (as_toupper(*pArg) == 'R'))
  386.     *pPrefix = 0x00;
  387.   else if ((strlen(pArg) > 2)
  388.    && (as_toupper(*pArg) == 'C')
  389.    && (as_toupper(pArg[1]) == 'R'))
  390.     *pPrefix = PREFIX_CRn;
  391.   else if ((strlen(pArg) > 2)
  392.    && (as_toupper(*pArg) == 'P')
  393.    && (as_toupper(pArg[1]) == 'R'))
  394.     *pPrefix = PREFIX_PRn;
  395.   else
  396.     return False;
  397.  
  398.   *pResult = ConstLongInt(pArg + 1 + !!*pPrefix, &OK, 10);
  399.   return (OK && (*pResult <= 15));
  400. }
  401.  
  402. /*!------------------------------------------------------------------------
  403.  * \fn     DissectReg_H16(char *pDest, size_t DestSize, tRegInt Reg, tSymbolSize Size)
  404.  * \brief  dissect register symbols - H16 variant
  405.  * \param  pDest destination buffer
  406.  * \param  DestSize size of destination buffer
  407.  * \param  Reg register number
  408.  * \param  Size register size
  409.  * ------------------------------------------------------------------------ */
  410.  
  411. static void DissectReg_H16(char *pDest, size_t DestSize, tRegInt Reg, tSymbolSize Size)
  412. {
  413.   switch (Size)
  414.   {
  415.     case eSymbolSize32Bit:
  416.       if (Reg == (REGSYM_FLAG_ALIAS | REG_SP))
  417.         as_snprintf(pDest, DestSize, "SP");
  418.       else
  419.       {
  420.         if (Hi(Reg) == PREFIX_CRn)
  421.           as_snprintf(pDest, DestSize, "CR");
  422.         else if (Hi(Reg) == PREFIX_PRn)
  423.           as_snprintf(pDest, DestSize, "PR");
  424.         else if (!Hi(Reg))
  425.           as_snprintf(pDest, DestSize, "R");
  426.         else
  427.           as_snprintf(pDest, DestSize, "%u-", Hi(Reg));
  428.         as_snprcatf(pDest, DestSize, "%u", Lo(Reg));
  429.       }
  430.       break;
  431.     default:
  432.       as_snprintf(pDest, DestSize, "%d-%u", Size, Reg);
  433.   }
  434. }
  435.  
  436. /*!------------------------------------------------------------------------
  437.  * \fn     compare_reg_h16(tRegInt reg1_num, tSymbolSize reg1_size, tRegInt reg2_num, tRegInt reg2_size)
  438.  * \brief  compare two register symbols
  439.  * \param  reg1_num 1st register's number
  440.  * \param  reg1_size 1st register's data size
  441.  * \param  reg2_num 2nd register's number
  442.  * \param  reg2_size 2nd register's data size
  443.  * \return 0, -1, 1, -2
  444.  * ------------------------------------------------------------------------ */
  445.  
  446. static int compare_reg_h16(tRegInt reg1_num, tSymbolSize size1, tRegInt reg2_num, tSymbolSize size2)
  447. {
  448.   if ((size1 != eSymbolSize32Bit)
  449.    || (size2 != eSymbolSize32Bit)
  450.    || (Hi(reg1_num) != Hi(reg2_num)))
  451.     return -2;
  452.  
  453.   reg1_num = Lo(reg1_num) & ~REGSYM_FLAG_ALIAS;
  454.   reg2_num = Lo(reg2_num) & ~REGSYM_FLAG_ALIAS;
  455.  
  456.   if (reg1_num < reg2_num)
  457.     return -1;
  458.   else if (reg1_num > reg2_num)
  459.     return 1;
  460.   else
  461.     return 0;
  462. }
  463.  
  464. /*!------------------------------------------------------------------------
  465.  * \fn     DecodeReg(const tStrComp *pArg, Byte *pReg, Byte *pPrefix, Boolean AllowPrefix, Boolean MustBeReg)
  466.  * \brief  check whether argument is CPU register or register alias
  467.  * \param  pArg source argument
  468.  * \param  pReg register number
  469.  * \param  pPrefix prefix for previous/current bank registers; 0 for global bank registers
  470.  * \param  AllowPrefix allow previous/current bank registers
  471.  * \param  MustBeReg argument must be register
  472.  * \return True if argument is a register
  473.  * ------------------------------------------------------------------------ */
  474.  
  475. static tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pReg, Byte *pPrefix, Boolean AllowPrefix, Boolean MustBeReg)
  476. {
  477.   tRegDescr RegDescr;
  478.   tEvalResult EvalResult;
  479.   tRegEvalResult RegEvalResult;
  480.  
  481.   if (DecodeRegCore(pArg->str.p_str, pReg, pPrefix))
  482.     RegEvalResult = eIsReg;
  483.   else
  484.   {
  485.     RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
  486.     *pPrefix = Hi(RegDescr.Reg);
  487.     *pReg = Lo(RegDescr.Reg);
  488.   }
  489.  
  490.   if (RegEvalResult == eIsReg)
  491.   {
  492.     if (!AllowPrefix && *pPrefix)
  493.     {
  494.       WrStrErrorPos(ErrNum_InvReg, pArg);
  495.       RegEvalResult = MustBeReg ? eIsNoReg : eRegAbort;
  496.     }
  497.   }
  498.   *pReg &= ~REGSYM_FLAG_ALIAS;
  499.   return RegEvalResult;
  500. }
  501.  
  502. /*!------------------------------------------------------------------------
  503.  * \fn     DecodeRegList(Word *pDest, int StartIdx, int StopIdx)
  504.  * \brief  parse a register list
  505.  * \param  pDest destination buffer for register bit field
  506.  * \param  StartIdx index of first argument of list
  507.  * \param  StopIdx index of last argument of list
  508.  * \return True if parsing succeeded
  509.  * ------------------------------------------------------------------------ */
  510.  
  511. static Boolean DecodeRegList(Word *pDest, int StartIdx, int StopIdx)
  512. {
  513.   int Index;
  514.   char *pSep;
  515.   Byte RegStart, RegStop, Prefix;
  516.   Word Mask;
  517.  
  518.   *pDest = 0;
  519.   for (Index = StartIdx; Index <= StopIdx; Index++)
  520.   {
  521.     pSep = strchr(ArgStr[Index].str.p_str, '-');
  522.     if (pSep)
  523.     {
  524.       tStrComp StartComp, StopComp;
  525.  
  526.       StrCompSplitRef(&StartComp, &StopComp, &ArgStr[Index], pSep);
  527.       KillPostBlanksStrComp(&StartComp);
  528.       KillPrefBlanksStrCompRef(&StopComp);
  529.       if (!DecodeReg(&StartComp, &RegStart, &Prefix, False, True))
  530.         return False;
  531.       if (!DecodeReg(&StopComp, &RegStop, &Prefix, False, True))
  532.         return False;
  533.       if (RegStart > RegStop)
  534.       {
  535.         Prefix = RegStart;
  536.         RegStart = RegStop;
  537.         RegStop = Prefix;
  538.       }
  539.       Mask = ((1ul << (RegStop + 1)) - 1) & ~((1ul << (RegStart)) - 1);
  540.     }
  541.     else
  542.     {
  543.       if (!DecodeReg(&ArgStr[Index], &RegStart, &Prefix, False, True))
  544.         return False;
  545.       Mask = 1ul << RegStart;
  546.     }
  547.     if (*pDest & Mask)
  548.     {
  549.       WrStrErrorPos(ErrNum_DoubleReg, &ArgStr[Index]);
  550.       return False;
  551.     }
  552.     *pDest |= Mask;
  553.   }
  554.   return True;
  555. }
  556.  
  557. /*!------------------------------------------------------------------------
  558.  * \fn     DecodeRegWithSize(const tStrComp *pArg, Byte *pReg, tSymbolSize *pSize, Byte *pPrefix, Boolean MustBeReg)
  559.  * \brief  check whether argument is register with possible size spec
  560.  * \param  pArg argument to check
  561.  * \param  pReg returns register # if argument is a register
  562.  * \param  pSize returns size spec if argument is a register (may be SizeUnknown)
  563.  * \param  pPrefix prefix for previous/current bank registers; 0 for global bank registers
  564.  * \param  MustBeReg argument must be register
  565.  * \return RegEval result
  566.  * ------------------------------------------------------------------------ */
  567.  
  568. static tRegEvalResult DecodeRegWithSize(const tStrComp *pArg, Byte *pReg, tSymbolSize *pSize, Byte *pPrefix, Boolean MustBeReg)
  569. {
  570.   String Str;
  571.   tStrComp Copy;
  572.  
  573.   StrCompMkTemp(&Copy, Str, sizeof(Str));
  574.   StrCompCopy(&Copy, pArg);
  575.   if (!SplitOpSize(&Copy, pSize))
  576.     *pSize = eSymbolSizeUnknown;
  577.   return DecodeReg(&Copy, pReg, pPrefix, True, MustBeReg);
  578. }
  579.  
  580. /*!------------------------------------------------------------------------
  581.  * \fn     CheckSup(const tStrComp *pArg)
  582.  * \brief  check whether supervisor mode is enabled and warn if not
  583.  * \param  pArg possible argument to print if sup mode is not enabled
  584.  * \return True (only a warning, no error)
  585.  * ------------------------------------------------------------------------ */
  586.  
  587. static Boolean CheckSup(const tStrComp *pArg)
  588. {
  589.   if (!SupAllowed)
  590.     WrStrErrorPos(ErrNum_PrivOrder, pArg);
  591.   return True;
  592. }
  593.  
  594. /*!------------------------------------------------------------------------
  595.  * \fn     DecodeCReg(const tStrComp *pArg, Byte *pResult)
  596.  * \brief  check whether argument id a control register
  597.  * \param  pArg argument to check
  598.  * \param  pResult control register # if argument is a control register
  599.  * \return True if argument is a control register
  600.  * ------------------------------------------------------------------------ */
  601.  
  602. typedef struct
  603. {
  604.   const char *pName;
  605.   Byte Code;
  606.   tSymbolSize Size;
  607. } tCReg;
  608.  
  609. static const tCReg CRegs[] =
  610. {
  611.   { "CCR"  , 0x20, eSymbolSize8Bit  },
  612.   { "VBNR" , 0x01, eSymbolSize8Bit  },
  613.   { "CBNR" , 0x40, eSymbolSize32Bit },
  614.   { "BSP"  , 0x41, eSymbolSize32Bit },
  615.   { "BMR"  , 0x80, eSymbolSize8Bit  },
  616.   { "GBNR" , 0x81, eSymbolSize8Bit  },
  617.   { "SR"   , 0xa0, eSymbolSize16Bit },
  618.   { "EBR"  , 0xc0, eSymbolSize32Bit },
  619.   { "RBR"  , 0xc1, eSymbolSize32Bit },
  620.   { "USP"  , 0xc2, eSymbolSize32Bit },
  621.   { "IBR"  , 0xc3, eSymbolSize32Bit },
  622.   { NULL   , 0x00, eSymbolSizeUnknown },
  623. };
  624.  
  625. static Boolean DecodeCReg(const tStrComp *pArg, Byte *pResult)
  626. {
  627.   const tCReg *pReg;
  628.  
  629.   for (pReg = CRegs; pReg->pName; pReg++)
  630.     if (!as_strcasecmp(pArg->str.p_str, pReg->pName))
  631.     {
  632.       if ((pReg->Code & 0x80) && !CheckSup(pArg))
  633.         return False;
  634.       if (!SetOpSize(pReg->Size))
  635.         return False;
  636.       *pResult = pReg->Code;
  637.       return True;
  638.     }
  639.   WrStrErrorPos(ErrNum_InvCtrlReg, pArg);
  640.   return False;
  641. }
  642.  
  643. /*!------------------------------------------------------------------------
  644.  * \fn     DeduceSize(LongInt Value)
  645.  * \brief  deduce minimum operand size needed to represent value, assuming sign-extension
  646.  * \param  Value value to judge
  647.  * \return resulting minimum size
  648.  * ------------------------------------------------------------------------ */
  649.  
  650. static tSymbolSize DeduceSize(LongInt Value)
  651. {
  652.   if ((Value >= -128) && (Value <= 127))
  653.     return eSymbolSize8Bit;
  654.   if ((Value >= -32768) && (Value <= 32767))
  655.     return eSymbolSize16Bit;
  656.   return eSymbolSize32Bit;
  657. }
  658.  
  659. /*!------------------------------------------------------------------------
  660.  * \fn     DeduceSize8_32(LongInt Value)
  661.  * \brief  similar to DeduceSize, but excluding 16 bits
  662.  * \param  Value value to judge
  663.  * \return resulting minimum size
  664.  * ------------------------------------------------------------------------ */
  665.  
  666. static tSymbolSize DeduceSize8_32(LongInt Value)
  667. {
  668.   if ((Value >= -128) && (Value <= 127))
  669.     return eSymbolSize8Bit;
  670.   return eSymbolSize32Bit;
  671. }
  672.  
  673. /*!------------------------------------------------------------------------
  674.  * \fn     ChkSize(LongInt Value, tSymbolSize OpSize)
  675.  * \brief  check whether given value can be represented with given size, assuming sign extension
  676.  * \param  Value value to judge
  677.  * \param  OpSize proposed operand size
  678.  * \return True if value can be represented with this size
  679.  * ------------------------------------------------------------------------ */
  680.  
  681. static Boolean ChkSize(LongInt Value, tSymbolSize OpSize)
  682. {
  683.   switch (OpSize)
  684.   {
  685.     case eSymbolSize8Bit: return ChkRange(Value, -128, 127);
  686.     case eSymbolSize16Bit: return ChkRange(Value, -32768, 32767);
  687.     default: return True;
  688.   }
  689. }
  690.  
  691. /*!------------------------------------------------------------------------
  692.  * \fn     DeduceSize16M(LongInt Value)
  693.  * \brief  deduce minimum size to represent memory address, assuming sign-extension
  694.  * \param  Value address to judge
  695.  * \return minimum operand size (8/16/32)
  696.  * ------------------------------------------------------------------------ */
  697.  
  698. static tSymbolSize DeduceSize16M(LongInt Value)
  699. {
  700.   LongWord TmpVal;
  701.  
  702.   TmpVal = Value & 0xff;
  703.   if (TmpVal & 0x80) TmpVal |= 0xffffff00;
  704.   if ((TmpVal & 0xffffff) == ((LongWord)Value & 0xffffff))
  705.     return eSymbolSize8Bit;
  706.  
  707.   TmpVal = Value & 0xffff;
  708.   if (TmpVal & 0x8000) TmpVal |= 0xff0000;
  709.   if ((TmpVal & 0xffffff) == ((LongWord)Value & 0xffffff))
  710.     return eSymbolSize16Bit;
  711.  
  712.   return eSymbolSize32Bit;
  713. }
  714.  
  715. /*!------------------------------------------------------------------------
  716.  * \fn     ChkSize16M(LongInt Value, tSymbolSize OpSize)
  717.  * \brief  check whether given memory address can be represented with given size, assuming sign extension
  718.  * \param  Value address to judge
  719.  * \param  OpSize proposed operand size
  720.  * \return True if value can be represented with this size
  721.  * ------------------------------------------------------------------------ */
  722.  
  723. static Boolean ChkSize16M(LongInt Value, tSymbolSize OpSize)
  724. {
  725.   LongWord TmpVal;
  726.   Boolean OK;
  727.  
  728.   switch (OpSize)
  729.   {
  730.     case eSymbolSize8Bit:
  731.       TmpVal = Value & 0xff;
  732.       if (TmpVal & 0x80) TmpVal |= 0xffffff00;
  733.       break;
  734.     case eSymbolSize16Bit:
  735.       TmpVal = Value & 0xffff;
  736.       if (TmpVal & 0x8000) TmpVal |= 0xff0000;
  737.       break;
  738.     default:
  739.       TmpVal = Value;
  740.   }
  741.   OK = (Value & 0xffffff) == (TmpVal & 0xffffff);
  742.   if (!OK)
  743.     WrError(ErrNum_OverRange);
  744.   return OK;
  745. }
  746.  
  747. /*!------------------------------------------------------------------------
  748.  * \fn     DeduceSizePCRel(LongInt AbsAddr, LongInt DispAddr)
  749.  * \brief  deduce minimum size to represent memory address as distance, assuming PC-relative addressing
  750.  * \param  AbsAddr absolute memory addess in question
  751.  * \param  DispAddr address of PC-relative displacement in code
  752.  * \return minimum displacement size (8/16/32)
  753.  * ------------------------------------------------------------------------ */
  754.  
  755. static tSymbolSize DeduceSizePCRel(LongInt AbsAddr, LongInt DispAddr)
  756. {
  757.   LongInt PCValue, Dist;
  758.  
  759.   PCValue = DispAddr + 1;
  760.   Dist = PCValue - AbsAddr;
  761.   if ((Dist >= -128) && (Dist <= 127))
  762.     return eSymbolSize8Bit;
  763.   PCValue = DispAddr + 2;
  764.   Dist = PCValue - AbsAddr;
  765.   if ((Dist >= -32768) && (Dist <= 32767))
  766.     return eSymbolSize16Bit;
  767.   return eSymbolSize32Bit;
  768. }
  769.  
  770. /*!------------------------------------------------------------------------
  771.  * \fn     ChkSizePCRelDisplacement(LongInt *pAbsAddr, tSymbolSize SymbolSize, LongInt DispAddr)
  772.  * \brief  check whether given address can be represented with given size, assuming PC-relative addressing
  773.  * \param  pAbsAddr (in) absolute memory addess in question (out) resulting displacement
  774.  * \param  SymbolSize proposed displacement size
  775.  * \param  DispAddr address of PC-relative displacement in code
  776.  * \return True if value can be represented with this size and displacement was computed
  777.  * ------------------------------------------------------------------------ */
  778.  
  779. static Boolean ChkSizePCRelDisplacement(LongInt *pAbsAddr, tSymbolSize SymbolSize, LongInt DispAddr)
  780. {
  781.   switch (SymbolSize)
  782.   {
  783.     case eSymbolSize8Bit:
  784.       *pAbsAddr -= DispAddr + 1;
  785.       return ChkRange(*pAbsAddr, -128, 127);
  786.     case eSymbolSize16Bit:
  787.       *pAbsAddr -= DispAddr + 2;
  788.       return ChkRange(*pAbsAddr, -32768, 32767);
  789.     case eSymbolSize32Bit:
  790.       *pAbsAddr -= DispAddr + 4;
  791.       return True;
  792.     default:
  793.       return False;
  794.   }
  795. }
  796.  
  797. /*!------------------------------------------------------------------------
  798.  * \fn     ChkSizePCRelBranch(const tStrComp *pArg, LongInt *pAbsAddr, tSymbolSize SymbolSize, tSymbolFlags Flags, LongInt DispAddr)
  799.  * \brief  same as ChkSizePCRel(), but use error messages appropriate for branches
  800.  * \param  pAbsAddr (in) destination address of branch  (out) resulting displacement
  801.  * \param  SymbolSize proposed displacement size
  802.  * \param  Flags symbol flags returned along with pAbsAddr
  803.  * \param  DispAddr address of PC-relative displacement in code
  804.  * \return True if displacement can be represented with this size and was computed
  805.  * ------------------------------------------------------------------------ */
  806.  
  807. static Boolean ChkSizePCRelBranch(const tStrComp *pArg, LongInt *pAbsAddr, tSymbolSize SymbolSize, tSymbolFlags Flags, LongInt DispAddr)
  808. {
  809.   Boolean OK;
  810.  
  811.   switch (SymbolSize)
  812.   {
  813.     case eSymbolSize8Bit:
  814.       *pAbsAddr -= DispAddr + 1;
  815.       OK = mSymbolQuestionable(Flags) || RangeCheck(*pAbsAddr, SInt8);
  816.       break;
  817.     case eSymbolSize16Bit:
  818.       *pAbsAddr -= DispAddr + 2;
  819.       OK = mSymbolQuestionable(Flags) || RangeCheck(*pAbsAddr, SInt16);
  820.       break;
  821.     case eSymbolSize32Bit:
  822.       *pAbsAddr -= DispAddr + 4;
  823.       OK = True;
  824.       break;
  825.     default:
  826.       OK = False;
  827.   }
  828.   if (!OK)
  829.     WrStrErrorPos(ErrNum_JmpDistTooBig, pArg);
  830.   return OK;
  831. }
  832.  
  833. /*!------------------------------------------------------------------------
  834.  * \fn     SetRegPrefix(Byte *pDest, Byte Src, const tStrComp *pArg)
  835.  * \brief  set (new) previous/current bank register prefix
  836.  * \param  pDest current prefix
  837.  * \param  Src new prefix to set/confirm
  838.  * \param  pArg argument to print in error msg if bank mismatch
  839.  * \return True if register bank was set or confirmed
  840.  * ------------------------------------------------------------------------ */
  841.  
  842. static Boolean SetRegPrefix(Byte *pDest, Byte Src, const tStrComp *pArg)
  843. {
  844.   if (*pDest && (*pDest != Src))
  845.   {
  846.     WrStrErrorPos(ErrNum_RegBankMismatch, pArg);
  847.     return False;
  848.   }
  849.   *pDest = Src;
  850.   return True;
  851. }
  852.  
  853. /*!------------------------------------------------------------------------
  854.  * \fn     EvalArg(const tStrComp *pArg, int Offset, tSymbolSize OpSize, Boolean *pOK)
  855.  * \brief  evaluate integer expression accoring to operand size
  856.  * \param  pArg argument to evaluate
  857.  * \param  Offset offset into argument where expression begins
  858.  * \param  OpSize operand size to use
  859.  * \param  pOK returns True if evaluation succeeded
  860.  * \return result of evaluation
  861.  * ------------------------------------------------------------------------ */
  862.  
  863. static LongInt EvalArg(const tStrComp *pArg, int Offset, tSymbolSize OpSize, Boolean *pOK)
  864. {
  865.   switch ((int)OpSize)
  866.   {
  867.     case eSymbolSize8Bit:
  868.       return EvalStrIntExpressionOffs(pArg, Offset, Int8, pOK);
  869.     case eSymbolSize16Bit:
  870.       return EvalStrIntExpressionOffs(pArg, Offset, Int16, pOK);
  871.     case eSymbolSize32Bit:
  872.       return EvalStrIntExpressionOffs(pArg, Offset, Int32, pOK);
  873.     case eSymbolSize5Bit:
  874.       return EvalStrIntExpressionOffs(pArg, Offset, UInt5, pOK);
  875.     case eSymbolSize4Bit:
  876.       return EvalStrIntExpressionOffs(pArg, Offset, UInt4, pOK);
  877.     case eSymbolSize3Bit:
  878.       return EvalStrIntExpressionOffs(pArg, Offset, UInt3, pOK);
  879.     default:
  880.       *pOK = False;
  881.       return 0;
  882.   }
  883. }
  884.  
  885. /*!------------------------------------------------------------------------
  886.  * \fn     ValidBaseRegSize(tSymbolSize Size)
  887.  * \brief  check whether operand size is appropriate for base reg in indirect expression
  888.  * \param  Size operand size to check
  889.  * \return True if OK
  890.  * ------------------------------------------------------------------------ */
  891.  
  892. static Boolean ValidBaseRegSize(tSymbolSize Size)
  893. {
  894.   return (Size == eSymbolSizeUnknown) /* no size given: regarded as 32 bits */
  895.       || (Size == eSymbolSize32Bit);
  896. }
  897.  
  898. /*!------------------------------------------------------------------------
  899.  * \fn     ValidIndexRegSize(tSymbolSize Size)
  900.  * \brief  check whether operand size is appropriate for indirect reg in indirect expression
  901.  * \param  Size operand size to check
  902.  * \return True if OK
  903.  * ------------------------------------------------------------------------ */
  904.  
  905. static Boolean ValidIndexRegSize(tSymbolSize Size)
  906. {
  907.   return (Size == eSymbolSizeUnknown) /* no size given: regarded as default index reg size */
  908.       || (Size == eSymbolSize16Bit)
  909.       || (Size == eSymbolSize32Bit);
  910. }
  911.  
  912. /*!------------------------------------------------------------------------
  913.  * \fn     ClassComp(tStrComp *pArg, tAdrComps *pComps)
  914.  * \brief  classify/parse argument of indirect address expression
  915.  * \param  pComps indirect address evaluation context to update/augment
  916.  * \param  pArg argument to parse
  917.  * \return True if parsing and context update succeeded
  918.  * ------------------------------------------------------------------------ */
  919.  
  920. static Boolean ClassCompList(tAdrComps *pComps, tStrComp *pArg);
  921.  
  922. static Boolean ClassComp(tStrComp *pArg, tAdrComps *pComps)
  923. {
  924.   tSymbolSize OpSize;
  925.   Byte Reg, Scale, Prefix;
  926.   char Save;
  927.   LongInt Value;
  928.   Boolean OK;
  929.  
  930.   KillPrefBlanksStrCompRef(pArg);
  931.   KillPostBlanksStrComp(pArg);
  932.  
  933.   if (!as_strcasecmp(pArg->str.p_str, "PC"))
  934.   {
  935.     if (pComps->BaseReg == NOREG)
  936.     {
  937.       pComps->BaseReg = PCREG;
  938.       pComps->BaseRegIncr = 0;
  939.       return True;
  940.     }
  941.     else if (pComps->IndexReg == NOREG)
  942.     {
  943.       pComps->IndexReg = pComps->BaseReg;
  944.       pComps->IndexRegScale = 0;
  945.       pComps->IndexRegSize = eSymbolSize32Bit;
  946.       pComps->BaseReg = PCREG;
  947.       pComps->BaseRegIncr = 0;
  948.       return True;
  949.     }
  950.     else
  951.       return False;
  952.   }
  953.   if (*pArg->str.p_str == '@')
  954.   {
  955.     tAdrComps InnerComps;
  956.     tStrComp InnerList;
  957.  
  958.     if (pComps->InnerReg != NOREG)
  959.       return False;
  960.  
  961.     StrCompRefRight(&InnerList, pArg, 1);
  962.     if (!ClassCompList(&InnerComps, &InnerList))
  963.       return False;
  964.     if (!InnerComps.InnerDispPresent
  965.       && (InnerComps.InnerReg == NOREG)
  966.       && (InnerComps.IndexReg == NOREG)
  967.       && (InnerComps.BaseReg != NOREG)
  968.       && !InnerComps.BaseRegIncr)
  969.     {
  970.       pComps->InnerReg = InnerComps.BaseReg;
  971.       pComps->InnerDispPresent = InnerComps.OuterDispPresent;
  972.       pComps->InnerDisp = InnerComps.OuterDisp;
  973.       pComps->InnerDispSize = InnerComps.OuterDispSize;
  974.     }
  975.  
  976.     return True;
  977.   }
  978.   switch (DecodeRegWithSize(pArg, &Reg, &OpSize, &Prefix, False))
  979.   {
  980.     case eIsReg:
  981.       if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
  982.         return False;
  983.       if ((pComps->BaseReg == NOREG) && (OpSize == eSymbolSizeUnknown))
  984.       {
  985.         pComps->BaseReg = Reg;
  986.         pComps->BaseRegIncr = 0;
  987.         return True;
  988.       }
  989.       else if ((pComps->IndexReg == NOREG) && ValidIndexRegSize(OpSize))
  990.       {
  991.         pComps->IndexReg = Reg;
  992.         pComps->IndexRegScale = 0;
  993.         if (OpSize != eSymbolSizeUnknown)
  994.           pComps->IndexRegSize = OpSize;
  995.         return True;
  996.       }
  997.       else
  998.         return False;
  999.     case eIsNoReg:
  1000.       break;
  1001.     case eRegAbort:
  1002.       return False;
  1003.   }
  1004.   if (*pArg->str.p_str == '-')
  1005.   {
  1006.     tStrComp RegComp;
  1007.  
  1008.     StrCompRefRight(&RegComp, pArg, 1);
  1009.     switch (DecodeReg(&RegComp, &Reg, &Prefix, True, False))
  1010.     {
  1011.       case eIsReg:
  1012.         if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
  1013.           return False;
  1014.         if (pComps->BaseReg == NOREG)
  1015.         {
  1016.           pComps->BaseReg = Reg;
  1017.           pComps->BaseRegIncr = -1;
  1018.           return True;
  1019.         }
  1020.         else
  1021.           return False;
  1022.       case eRegAbort:
  1023.         return False;
  1024.       case eIsNoReg:
  1025.         break;
  1026.     }
  1027.   }
  1028.   if (pArg->str.p_str[pArg->Pos.Len - 1] == '+')
  1029.   {
  1030.     pArg->str.p_str[pArg->Pos.Len - 1] = '\0';
  1031.     switch (DecodeReg(pArg, &Reg, &Prefix, True, False))
  1032.     {
  1033.       case eIsReg:
  1034.         if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
  1035.           return False;
  1036.         if (pComps->BaseReg == NOREG)
  1037.         {
  1038.           pComps->BaseReg = Reg;
  1039.           pComps->BaseRegIncr = +1;
  1040.           return True;
  1041.         }
  1042.         else
  1043.           return False;
  1044.       case eRegAbort:
  1045.         return False;
  1046.       case eIsNoReg:
  1047.         pArg->str.p_str[pArg->Pos.Len - 1] = '+';
  1048.         break;
  1049.     }
  1050.   }
  1051.   Save = SplitScale(pArg, &Scale);
  1052.   if (Save)
  1053.   {
  1054.     switch (DecodeRegWithSize(pArg, &Reg, &OpSize, &Prefix, False))
  1055.     {
  1056.       case eIsReg:
  1057.         if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
  1058.           return False;
  1059.         if ((pComps->IndexReg == NOREG) && ValidIndexRegSize(OpSize))
  1060.         {
  1061.           pComps->IndexReg = Reg;
  1062.           pComps->IndexRegScale = Scale;
  1063.           if (OpSize != eSymbolSizeUnknown)
  1064.             pComps->IndexRegSize = OpSize;
  1065.         }
  1066.         else if (pComps->BaseReg == NOREG)
  1067.         {
  1068.           if ((Scale == 0) && ValidBaseRegSize(OpSize))
  1069.             pComps->BaseReg = Reg;
  1070.           else if ((Scale != 0) && (pComps->IndexRegScale == 0) && (pComps->IndexRegSize == eSymbolSize32Bit))
  1071.           {
  1072.             pComps->BaseReg = pComps->IndexReg;
  1073.             pComps->IndexReg = Reg;
  1074.             pComps->IndexRegScale = Scale;
  1075.             pComps->IndexRegSize = (OpSize == eSymbolSizeUnknown) ? DefIndexRegSize : OpSize;
  1076.           }
  1077.           else
  1078.             return False;
  1079.         }
  1080.         else
  1081.           return False;
  1082.         return True;
  1083.       case eIsNoReg:
  1084.         AppendScale(pArg, Scale);
  1085.         break;
  1086.       case eRegAbort:
  1087.         return False;
  1088.     }
  1089.   }
  1090.  
  1091.   if (!SplitOpSize(pArg, &OpSize))
  1092.     OpSize = eSymbolSizeUnknown;
  1093.   Value = EvalArg(pArg, 0, eSymbolSize32Bit, &OK);
  1094.   if (!OK)
  1095.     return False;
  1096.   pComps->OuterDispPresent = True;
  1097.   if (OpSize > pComps->OuterDispSize)
  1098.     pComps->OuterDispSize = OpSize;
  1099.   pComps->OuterDisp += Value;
  1100.   return True;
  1101. }
  1102.  
  1103. /*!------------------------------------------------------------------------
  1104.  * \fn     ClassCompList(tAdrComps *pComps, tStrComp *pArg)
  1105.  * \brief  classify/parse argument list of indirect address expression
  1106.  * \param  pComps indirect address evaluation context to fill
  1107.  * \param  pArg address expression argument
  1108.  * \return True if parsing succeeded
  1109.  * ------------------------------------------------------------------------ */
  1110.  
  1111. static Boolean ClassCompList(tAdrComps *pComps, tStrComp *pArg)
  1112. {
  1113.   ResetAdrComps(pComps);
  1114.  
  1115.   if (IsIndirect(pArg->str.p_str))
  1116.   {
  1117.     char *pSplit;
  1118.     tStrComp Remainder;
  1119.  
  1120.     StrCompIncRefLeft(pArg, 1);
  1121.     StrCompShorten(pArg, 1);
  1122.     do
  1123.     {
  1124.       pSplit = QuotPos(pArg->str.p_str, ',');
  1125.       if (pSplit)
  1126.         StrCompSplitRef(pArg, &Remainder, pArg, pSplit);
  1127.       if (!ClassComp(pArg, pComps))
  1128.       {
  1129.         WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  1130.         return False;
  1131.       }
  1132.       if (pSplit)
  1133.         *pArg = Remainder;
  1134.     }
  1135.     while (pSplit);
  1136.   }
  1137.   else
  1138.   {
  1139.     if (!ClassComp(pArg, pComps))
  1140.     {
  1141.       WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  1142.       return False;
  1143.     }
  1144.   }
  1145.   return True;
  1146. }
  1147.  
  1148. /*!------------------------------------------------------------------------
  1149.  * \fn     DecodeAdr(const tStrComp *pArg, unsigned Mask, tAdrVals *pAdrVals, LongInt EAAddr)
  1150.  * \brief  parse address expression
  1151.  * \param  pArg expression to parse
  1152.  * \param  Mask bit mask of allowed addressing modes
  1153.  * \param  pAdrVals returns parsed addressing mode
  1154.  * \param  EAAddr position of associared EA byte in code (needed for PC-relative addressing)
  1155.  * \return True if parsing succeeded
  1156.  * ------------------------------------------------------------------------ */
  1157.  
  1158. static Boolean DecodeAdr(const tStrComp *pArg, unsigned Mask, tAdrVals *pAdrVals, LongInt EAAddr)
  1159. {
  1160.   Byte Reg, Prefix;
  1161.   tStrComp Arg;
  1162.  
  1163.   ResetAdrVals(pAdrVals);
  1164.  
  1165.   StrCompRefRight(&Arg, pArg, 0);
  1166.   while (True)
  1167.   {
  1168.     if (!as_strncasecmp(Arg.str.p_str, "<CRn>", 5)
  1169.      || !as_strncasecmp(Arg.str.p_str, "<PRn>", 5))
  1170.     {
  1171.       AppendAdrVals(pAdrVals, (toupper(Arg.str.p_str[1]) == 'C') ? PREFIX_CRn : PREFIX_PRn);
  1172.       StrCompIncRefLeft(&Arg, 5);
  1173.       KillPrefBlanksStrCompRef(&Arg);
  1174.     }
  1175.     else
  1176.       break;
  1177.   }
  1178.  
  1179.   switch (DecodeReg(&Arg, &Reg, &Prefix, True, False))
  1180.   {
  1181.     case eIsReg:
  1182.       pAdrVals->Mode = eAdrModeReg;
  1183.       AppendRegPrefix(pAdrVals, Prefix);
  1184.       AppendAdrVals(pAdrVals, 0x40 | Reg);
  1185.       goto Check;
  1186.     case eIsNoReg:
  1187.       break;
  1188.     case eRegAbort:
  1189.       return False;
  1190.   }
  1191.  
  1192.   if (*Arg.str.p_str == '#')
  1193.   {
  1194.     tSymbolSize ImmOpSize;
  1195.     LongInt ArgVal;
  1196.     Boolean OK;
  1197.  
  1198.     if (!SplitOpSize(&Arg, &ImmOpSize))
  1199.       ImmOpSize = OpSize;
  1200.     ArgVal = EvalArg(&Arg, 1, ImmOpSize, &OK);
  1201.     if (OK)
  1202.     {
  1203.       AppendAdrVals(pAdrVals, 0x70 | (ImmOpSize + 1));
  1204.       AppendToAdrValsBySize(pAdrVals, ArgVal, ImmOpSize);
  1205.       pAdrVals->Mode = eAdrModeImm;
  1206.     }
  1207.     goto Check;
  1208.   }
  1209.  
  1210.   if (*Arg.str.p_str == '@')
  1211.   {
  1212.     tStrComp IndirComp;
  1213.     tAdrComps Comps;
  1214.  
  1215.     StrCompRefRight(&IndirComp, &Arg, 1);
  1216.     if (!ClassCompList(&Comps, &IndirComp))
  1217.       return False;
  1218.  
  1219.     /* only base register, no indirection, and optional displacement: */
  1220.  
  1221.     if (!Comps.InnerDispPresent
  1222.      && (Comps.InnerReg == NOREG)
  1223.      && (Comps.IndexReg == NOREG)
  1224.      && NormalReg(Comps.BaseReg)
  1225.      && !Comps.BaseRegIncr)
  1226.     {
  1227.       if (Comps.OuterDispPresent)
  1228.       {
  1229.         if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1230.           Comps.OuterDispSize = DeduceSize(Comps.OuterDisp);
  1231.         if (!ChkSize(Comps.OuterDisp, Comps.OuterDispSize))
  1232.           goto Check;
  1233.         AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1234.         AppendAdrVals(pAdrVals, ((Comps.OuterDispSize + 1) << 4) | Comps.BaseReg);
  1235.         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1236.       }
  1237.       else
  1238.         AppendAdrVals(pAdrVals, 0x00 | Comps.BaseReg);
  1239.       pAdrVals->Mode = eAdrModeIReg;
  1240.       goto Check;
  1241.     }
  1242.  
  1243.     /* postinc/predec */
  1244.  
  1245.     if (!Comps.InnerDispPresent
  1246.      && !Comps.OuterDispPresent
  1247.      && (Comps.InnerReg == NOREG)
  1248.      && (Comps.IndexReg == NOREG)
  1249.      && NormalReg(Comps.BaseReg)
  1250.      && Comps.BaseRegIncr)
  1251.     {
  1252.       if (Comps.BaseRegIncr > 0)
  1253.       {
  1254.         AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1255.         AppendAdrVals(pAdrVals, 0x50 | Comps.BaseReg);
  1256.         pAdrVals->Mode = eAdrModePost;
  1257.       }
  1258.       else
  1259.       {
  1260.         AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1261.         AppendAdrVals(pAdrVals, 0x60 | Comps.BaseReg);
  1262.         pAdrVals->Mode = eAdrModePre;
  1263.       }
  1264.       goto Check;
  1265.     }
  1266.  
  1267.     /* absolute */
  1268.  
  1269.     if (!Comps.InnerDispPresent
  1270.      && Comps.OuterDispPresent
  1271.      && (Comps.InnerReg == NOREG)
  1272.      && (Comps.IndexReg == NOREG)
  1273.      && (Comps.BaseReg == NOREG))
  1274.     {
  1275.       if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1276.         Comps.OuterDispSize = DeduceSize16M(Comps.OuterDisp);
  1277.       if (!ChkSize16M(Comps.OuterDisp, Comps.OuterDispSize))
  1278.         goto Check;
  1279.       AppendAdrVals(pAdrVals, 0x74 | (Comps.OuterDispSize + 1));
  1280.       AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1281.       pAdrVals->Mode = eAdrModeAbs;
  1282.       goto Check;
  1283.     }
  1284.  
  1285.     /* register indirect with scale */
  1286.  
  1287.     if (!Comps.InnerDispPresent
  1288.      && (Comps.InnerReg == NOREG)
  1289.      && (Comps.BaseReg == NOREG)
  1290.      && NormalReg(Comps.IndexReg)
  1291.      && (Comps.IndexRegSize == eSymbolSize32Bit))
  1292.     {
  1293.       Byte EAVal = 0x78;
  1294.  
  1295.       if (Comps.OuterDispPresent)
  1296.       {
  1297.         if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1298.           Comps.OuterDispSize = DeduceSize(Comps.OuterDisp);
  1299.         if (!ChkSize(Comps.OuterDisp, Comps.OuterDispSize))
  1300.           goto Check;
  1301.         EAVal |= (1 + Comps.OuterDispSize);
  1302.       }
  1303.       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1304.       AppendAdrVals(pAdrVals, EAVal);
  1305.       AppendAdrVals(pAdrVals, (Comps.IndexRegScale << 4) | Comps.IndexReg);
  1306.       if (Comps.OuterDispPresent)
  1307.         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1308.       pAdrVals->Mode = eAdrModeIRegScale;
  1309.       goto Check;
  1310.     }
  1311.  
  1312.     /* register indirect with (scaled) index */
  1313.  
  1314.     if (!Comps.InnerDispPresent
  1315.      && (Comps.InnerReg == NOREG)
  1316.      && NormalReg(Comps.BaseReg)
  1317.      && NormalReg(Comps.IndexReg))
  1318.     {
  1319.       Byte Exp1Val = ((Comps.IndexRegSize - 1) << 6) | Comps.BaseReg;
  1320.  
  1321.       if (Comps.OuterDispPresent)
  1322.       {
  1323.         if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1324.           Comps.OuterDispSize = DeduceSize(Comps.OuterDisp);
  1325.         if (!ChkSize(Comps.OuterDisp, Comps.OuterDispSize))
  1326.           goto Check;
  1327.         Exp1Val |= (1 + Comps.OuterDispSize) << 4;
  1328.       }
  1329.       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1330.       AppendAdrVals(pAdrVals, 0x7c);
  1331.       AppendAdrVals(pAdrVals, Exp1Val);
  1332.       AppendAdrVals(pAdrVals, (Comps.IndexRegScale << 4) | Comps.IndexReg);
  1333.       if (Comps.OuterDispPresent)
  1334.         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1335.       pAdrVals->Mode = eAdrModeIdxScale;
  1336.       goto Check;
  1337.     }
  1338.  
  1339.     /* PC-relative with (scaled) index */
  1340.  
  1341.     if (!Comps.InnerDispPresent
  1342.      && (Comps.InnerReg == NOREG)
  1343.      && (Comps.BaseReg == PCREG)
  1344.      && NormalReg(Comps.IndexReg))
  1345.     {
  1346.       Byte Exp1Val = ((Comps.IndexRegSize - 1) << 6);
  1347.  
  1348.       if (Comps.OuterDispPresent)
  1349.       {
  1350.         if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1351.           Comps.OuterDispSize = DeduceSizePCRel(Comps.OuterDisp, EAAddr + 3);
  1352.         if (!ChkSizePCRelDisplacement(&Comps.OuterDisp, Comps.OuterDispSize, EAAddr + 3))
  1353.           goto Check;
  1354.         Exp1Val |= (1 + Comps.OuterDispSize) << 4;
  1355.       }
  1356.       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1357.       AppendAdrVals(pAdrVals, 0x7d);
  1358.       AppendAdrVals(pAdrVals, Exp1Val);
  1359.       AppendAdrVals(pAdrVals, (Comps.IndexRegScale << 4) | Comps.IndexReg);
  1360.       if (Comps.OuterDispPresent)
  1361.         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1362.       pAdrVals->Mode = eAdrModePCIdxScale;
  1363.       goto Check;
  1364.     }
  1365.  
  1366.     /* PC-relative */
  1367.  
  1368.     if (!Comps.InnerDispPresent
  1369.      && (Comps.InnerReg == NOREG)
  1370.      && (Comps.BaseReg == PCREG)
  1371.      && (Comps.IndexReg == NOREG))
  1372.     {
  1373.       Byte Exp1Val = 0x80;
  1374.  
  1375.       if (Comps.OuterDispPresent)
  1376.       {
  1377.         if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1378.           Comps.OuterDispSize = DeduceSizePCRel(Comps.OuterDisp, EAAddr + 2);
  1379.         if (!ChkSizePCRelDisplacement(&Comps.OuterDisp, Comps.OuterDispSize, EAAddr + 2))
  1380.           goto Check;
  1381.         Exp1Val |= (1 + Comps.OuterDispSize) << 4;
  1382.       }
  1383.       AppendRegPrefix(pAdrVals, Comps.RegPrefix); /* should never occur, no Rn in expression */
  1384.       AppendAdrVals(pAdrVals, 0x7d);
  1385.       AppendAdrVals(pAdrVals, Exp1Val);
  1386.       if (Comps.OuterDispPresent)
  1387.         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1388.       pAdrVals->Mode = eAdrModePCRel;
  1389.       goto Check;
  1390.     }
  1391.  
  1392.     /* Register double indirect */
  1393.  
  1394.     if (NormalReg(Comps.InnerReg)
  1395.      && (Comps.BaseReg == NOREG)
  1396.      && (Comps.IndexReg == NOREG))
  1397.     {
  1398.       /* no disp not allowed -> convert zero-disp to 8 bits */
  1399.  
  1400.       if (Comps.OuterDispSize == eSymbolSizeUnknown)
  1401.         Comps.OuterDispSize = DeduceSize8_32(Comps.OuterDisp);
  1402.       if (Comps.InnerDispSize == eSymbolSizeUnknown)
  1403.         Comps.InnerDispSize = DeduceSize8_32(Comps.InnerDisp);
  1404.       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
  1405.       AppendAdrVals(pAdrVals, 0x7e);
  1406.       AppendAdrVals(pAdrVals, Comps.InnerReg | ((Comps.InnerDispSize + 1) << 4) | ((Comps.OuterDispSize + 1) << 6));
  1407.       AppendToAdrValsBySize(pAdrVals, Comps.InnerDisp, Comps.InnerDispSize);
  1408.       AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
  1409.       pAdrVals->Mode = eAdrModeDoubleIndir;
  1410.       goto Check;
  1411.     }
  1412.  
  1413.     WrStrErrorPos(ErrNum_InvAddrMode, &Arg);
  1414.   }
  1415.  
  1416.   /* None of this.  Should we treat it as absolute? */
  1417.  
  1418.   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  1419.  
  1420. Check:
  1421.   if ((pAdrVals->Mode != eAdrModeNone)
  1422.    && !((Mask >> pAdrVals->Mode) & 1))
  1423.   {
  1424.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  1425.     ResetAdrVals(pAdrVals);
  1426.     return False;
  1427.   }
  1428.   return True;
  1429. }
  1430.  
  1431. /*!------------------------------------------------------------------------
  1432.  * \fn     GlobalBankReg(const tAdrVals *pAdrVals)
  1433.  * \brief  check whether parsed address expression is a global bank register
  1434.  * \param  pAdrVals parsed expression
  1435.  * \return True if it is a global bank register
  1436.  * ------------------------------------------------------------------------ */
  1437.  
  1438. static Boolean GlobalBankReg(const tAdrVals *pAdrVals)
  1439. {
  1440.   return (pAdrVals->Mode == eAdrModeReg)
  1441.       && (pAdrVals->Cnt == 1);
  1442. }
  1443.  
  1444. /*!------------------------------------------------------------------------
  1445.  * \fn     ImmValS8(const tAdrVals *pAdrVals)
  1446.  * \brief  check whether parsed address expression is an immediate value representable as 8 bits,
  1447.            assuming sign extension
  1448.  * \param  pAdrVals parsed expression
  1449.  * \return True if immediate & value range OK
  1450.  * ------------------------------------------------------------------------ */
  1451.  
  1452. static Boolean ImmValS8(const tAdrVals *pAdrVals)
  1453. {
  1454.   Byte Sign;
  1455.   unsigned z;
  1456.  
  1457.   if ((pAdrVals->Mode != eAdrModeImm)
  1458.    || (pAdrVals->Cnt < 1))
  1459.     return False;
  1460.  
  1461.   Sign = (pAdrVals->Vals[pAdrVals->Cnt - 1] & 0x80) ? 0xff: 0x00;
  1462.   for (z = 1; z < pAdrVals->Cnt - 1; z++)
  1463.     if (pAdrVals->Vals[z] != Sign)
  1464.       return False;
  1465.  
  1466.   return True;
  1467. }
  1468.  
  1469. /*!------------------------------------------------------------------------
  1470.  * \fn     ImmValS4(const tAdrVals *pAdrVals)
  1471.  * \brief  check whether parsed address expression is an immediate value representable as 4 bits,
  1472.            assuming sign extension
  1473.  * \param  pAdrVals parsed expression
  1474.  * \return True if immediate & value range OK
  1475.  * ------------------------------------------------------------------------ */
  1476.  
  1477. static Boolean ImmValS4(const tAdrVals *pAdrVals)
  1478. {
  1479.   Byte Sign;
  1480.  
  1481.   if (!ImmValS8(pAdrVals))
  1482.     return False;
  1483.  
  1484.   Sign = (pAdrVals->Vals[pAdrVals->Cnt - 1] & 0x08) ? 0xf0: 0x00;
  1485.   return (pAdrVals->Vals[pAdrVals->Cnt - 1] & 0xf0) == Sign;
  1486. }
  1487.  
  1488. /*!------------------------------------------------------------------------
  1489.  * \fn     AppendAdrValsToCode(const tAdrVals *pAdrVals)
  1490.  * \brief  append parsed address expression to instruction's code
  1491.  * \param  pAdrVals parsed expression
  1492.  * ------------------------------------------------------------------------ */
  1493.  
  1494. static void AppendAdrValsToCode(const tAdrVals *pAdrVals)
  1495. {
  1496.   memcpy(&BAsmCode[CodeLen], pAdrVals->Vals, pAdrVals->Cnt);
  1497.   CodeLen += pAdrVals->Cnt;
  1498. }
  1499.  
  1500. /*!------------------------------------------------------------------------
  1501.  * \fn     AppendAdrValPair(tAdrVals *pSrcAdrVals, const tAdrVals *pDestAdrVals)
  1502.  * \brief  append source & destination address expression to instruction's code
  1503.  * \param  pSrcAdrVals parsed source address expression
  1504.  * \param  pDestAdrVals parsed destination address expression
  1505.  * ------------------------------------------------------------------------ */
  1506.  
  1507. static void AppendAdrValPair(tAdrVals *pSrcAdrVals, const tAdrVals *pDestAdrVals)
  1508. {
  1509.   Byte *pEASrc = &BAsmCode[CodeLen];
  1510.  
  1511.   AppendAdrValsToCode(pSrcAdrVals);
  1512.   if (pDestAdrVals->Vals[0] == 0x40) /* EA=0x40 -> R0 -> accumulator mode */
  1513.     *pEASrc |= 0x80;
  1514.   else
  1515.     AppendAdrValsToCode(pDestAdrVals);
  1516. }
  1517.  
  1518. /*--------------------------------------------------------------------------*/
  1519. /* Bit Symbol Handling */
  1520.  
  1521. /*
  1522.  * Compact representation of bits and bit fields in symbol table:
  1523.  * bits 0..2/3/4: (start) bit position
  1524.  * bits 3/4/5...26/27/28: register address
  1525.  * bits 30/31: register size (0/1/2 for 8/16/32 bits)
  1526.  */
  1527.  
  1528. /*!------------------------------------------------------------------------
  1529.  * \fn     EvalBitPosition(const char *pBitArg, Boolean *pOK, tSymbolSize OpSize)
  1530.  * \brief  evaluate constant bit position, with bit range depending on operand size
  1531.  * \param  pBitArg bit position argument
  1532.  * \param  pOK returns True if OK
  1533.  * \param  OpSize operand size (0,1,2 -> 8,16,32 bits)
  1534.  * \return bit position as number
  1535.  * ------------------------------------------------------------------------ */
  1536.  
  1537. static Byte EvalBitPosition(const tStrComp *pBitArg, Boolean *pOK, tSymbolSize OpSize)
  1538. {
  1539.   int Offset = !!(*pBitArg->str.p_str == '#');
  1540.  
  1541.   switch (OpSize)
  1542.   {
  1543.     case eSymbolSize8Bit:
  1544.       return EvalStrIntExpressionOffs(pBitArg, Offset, UInt3, pOK);
  1545.     case eSymbolSize16Bit:
  1546.       return EvalStrIntExpressionOffs(pBitArg, Offset, UInt4, pOK);
  1547.     case eSymbolSize32Bit:
  1548.       return EvalStrIntExpressionOffs(pBitArg, Offset, UInt5, pOK);
  1549.     default:
  1550.       WrError(ErrNum_InvOpSize);
  1551.       *pOK = False;
  1552.       return 0;
  1553.   }
  1554. }
  1555.  
  1556. /*!------------------------------------------------------------------------
  1557.  * \fn     AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address)
  1558.  * \brief  build the compact internal representation of a bit field symbol
  1559.  * \param  BitPos bit position in word
  1560.  * \param  Width width of bit field
  1561.  * \param  OpSize operand size (8/16/32 bit)
  1562.  * \param  Address register address
  1563.  * \return compact representation
  1564.  * ------------------------------------------------------------------------ */
  1565.  
  1566. static LongWord AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address)
  1567. {
  1568.   int AddrShift = 3 + OpSize;
  1569.  
  1570.   return BitPos
  1571.        | ((Address & 0xfffffful) << AddrShift)
  1572.        | ((LongWord)OpSize << 30);
  1573. }
  1574.  
  1575. /*!------------------------------------------------------------------------
  1576.  * \fn     DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize)
  1577.  * \brief  transform compact represenation of bit (field) symbol into components
  1578.  * \param  BitSymbol compact storage
  1579.  * \param  pAddress (I/O) register address
  1580.  * \param  pBitPos (start) bit position
  1581.  * \param  pOpSize returns register size (0/1/2 for 8/16/32 bits)
  1582.  * \return constant True
  1583.  * ------------------------------------------------------------------------ */
  1584.  
  1585. static Boolean DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize)
  1586. {
  1587.   *pOpSize = (tSymbolSize)((BitSymbol >> 30) & 3);
  1588.   switch (*pOpSize)
  1589.   {
  1590.     case eSymbolSize8Bit:
  1591.       *pAddress = (BitSymbol >> 3) & 0xfffffful;
  1592.       *pBitPos = BitSymbol & 7;
  1593.       break;
  1594.     case eSymbolSize16Bit:
  1595.       *pAddress = (BitSymbol >> 4) & 0xfffffful;
  1596.       *pBitPos = BitSymbol & 15;
  1597.       break;
  1598.     case eSymbolSize32Bit:
  1599.       *pAddress = (BitSymbol >> 5) & 0xfffffful;
  1600.       *pBitPos = BitSymbol & 31;
  1601.       break;
  1602.     default:
  1603.       *pAddress = 0;
  1604.       *pBitPos = 0;
  1605.   }
  1606.   return True;
  1607. }
  1608.  
  1609. /*!------------------------------------------------------------------------
  1610.  * \fn     DissectBit_H16(char *pDest, size_t DestSize, LargeWord Inp)
  1611.  * \brief  dissect compact storage of bit (field) into readable form for listing
  1612.  * \param  pDest destination for ASCII representation
  1613.  * \param  DestSize destination buffer size
  1614.  * \param  Inp compact storage
  1615.  * ------------------------------------------------------------------------ */
  1616.  
  1617. static void DissectBit_H16(char *pDest, size_t DestSize, LargeWord Inp)
  1618. {
  1619.   Byte BitPos;
  1620.   LongWord Address;
  1621.   tSymbolSize OpSize;
  1622.   char Attribute;
  1623.  
  1624.   DissectBitSymbol(Inp, &Address, &BitPos, &OpSize);
  1625.   Attribute = "bwl"[OpSize];
  1626.  
  1627.   as_snprintf(pDest, DestSize, "$%lx(%c).%u", (unsigned long)Address, Attribute, (unsigned)BitPos);
  1628. }
  1629.  
  1630. /*!------------------------------------------------------------------------
  1631.  * \fn     ExpandH16Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
  1632.  * \brief  expands bit definition when a structure is instantiated
  1633.  * \param  pVarName desired symbol name
  1634.  * \param  pStructElem element definition
  1635.  * \param  Base base address of instantiated structure
  1636.  * ------------------------------------------------------------------------ */
  1637.  
  1638. static void ExpandH16Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
  1639. {
  1640.   tSymbolSize OpSize = (pStructElem->OpSize < 0) ? eSymbolSize8Bit : pStructElem->OpSize;
  1641.   LongWord Address = Base + pStructElem->Offset;
  1642.  
  1643.   if (!ChkRange(Address, 0, 0xfffffful)
  1644.    || !ChkRange(pStructElem->BitPos, 0, (8 << OpSize) - 1))
  1645.     return;
  1646.  
  1647.   PushLocHandle(-1);
  1648.   EnterIntSymbol(pVarName, AssembleBitSymbol(pStructElem->BitPos, OpSize, Address), SegBData, False);
  1649.   PopLocHandle();
  1650.   /* TODO: MakeUseList? */
  1651. }
  1652.  
  1653. /*!------------------------------------------------------------------------
  1654.  * \fn     DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, tSymbolSize OpSize)
  1655.  * \brief  encode a bit symbol, address & bit position separated
  1656.  * \param  pResult resulting encoded bit
  1657.  * \param  pRegArg register argument
  1658.  * \param  pBitArg bit argument
  1659.  * \param  OpSize register size (0/1/2 = 8/16/32 bit)
  1660.  * \return True if success
  1661.  * ------------------------------------------------------------------------ */
  1662.  
  1663. static Boolean DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, tSymbolSize OpSize)
  1664. {
  1665.   Boolean OK;
  1666.   LongWord Addr;
  1667.   Byte BitPos;
  1668.  
  1669.   BitPos = EvalBitPosition(pBitArg, &OK, OpSize);
  1670.   if (!OK)
  1671.     return False;
  1672.  
  1673.   Addr = EvalStrIntExpressionOffs(pRegArg, !!(*pRegArg->str.p_str == '@'), UInt24, &OK);
  1674.   if (!OK)
  1675.     return False;
  1676.  
  1677.   *pResult = AssembleBitSymbol(BitPos, OpSize, Addr);
  1678.  
  1679.   return True;
  1680. }
  1681.  
  1682. /*!------------------------------------------------------------------------
  1683.  * \fn     DecodeBitArg(LongWord *pResult, int Start, int Stop)
  1684.  * \brief  encode a bit symbol from instruction argument(s)
  1685.  * \param  pResult resulting encoded bit
  1686.  * \param  Start first argument
  1687.  * \param  Stop last argument
  1688.  * \param  OpSize register size (0/1/2 = 8/16/32 bit)
  1689.  * \return True if success
  1690.  * ------------------------------------------------------------------------ */
  1691.  
  1692. static Boolean DecodeBitArg(LongWord *pResult, int Start, int Stop, tSymbolSize OpSize)
  1693. {
  1694.   *pResult = 0;
  1695.  
  1696.   /* Just one argument -> parse as bit argument */
  1697.  
  1698.   if (Start == Stop)
  1699.   {
  1700.     tEvalResult EvalResult;
  1701.  
  1702.     *pResult = EvalStrIntExpressionWithResult(&ArgStr[Start], UInt32, &EvalResult);
  1703.     if (EvalResult.OK)
  1704.       ChkSpace(SegBData, EvalResult.AddrSpaceMask);
  1705.     return EvalResult.OK;
  1706.   }
  1707.  
  1708.   /* Register & bit position are given as separate arguments:
  1709.      use same argument positions as for machine instructions */
  1710.  
  1711.   else if (Stop == Start + 1)
  1712.     return DecodeBitArg2(pResult, &ArgStr[Stop], &ArgStr[Start], OpSize);
  1713.  
  1714.   /* other # of arguments not allowed */
  1715.  
  1716.   else
  1717.   {
  1718.     WrError(ErrNum_WrongArgCnt);
  1719.     return False;
  1720.   }
  1721. }
  1722.  
  1723. /*!------------------------------------------------------------------------
  1724.  * \fn     DecodeStringReg(Word Code)
  1725.  * \brief  decode register argument for string instruction
  1726.  * \param  pComp argument to parse
  1727.  * \param  Mask bit mask of allowed addressing modes
  1728.  * \param  pResult returns (global) register number
  1729.  * ------------------------------------------------------------------------ */
  1730.  
  1731. static Boolean DecodeStringReg(tStrComp *pComp, unsigned Mask, Byte *pResult)
  1732. {
  1733.   tAdrVals AdrVals;
  1734.  
  1735.   if (!DecodeAdr(pComp, Mask, &AdrVals, EProgCounter() + 2))
  1736.     return False;
  1737.   switch (AdrVals.Mode)
  1738.   {
  1739.     case eAdrModeReg:
  1740.       if (!GlobalBankReg(&AdrVals))
  1741.       {
  1742.         WrStrErrorPos(ErrNum_InvReg, pComp);
  1743.         return False;
  1744.       }
  1745.       break;
  1746.     case eAdrModeIReg:
  1747.       if (AdrVals.Cnt != 1)
  1748.       {
  1749.         WrStrErrorPos(ErrNum_InvAddrMode, pComp);
  1750.         return False;
  1751.       }
  1752.       break;
  1753.     case eAdrModePost:
  1754.     case eAdrModePre:
  1755.       break;
  1756.     default:
  1757.       return False;
  1758.   }
  1759.   *pResult = AdrVals.Vals[0] & 15;
  1760.   return True;
  1761. }
  1762.  
  1763. /*!------------------------------------------------------------------------
  1764.  * \fn     ExtractDisp(const Byte *pVals, Byte SizeCode)
  1765.  * \brief  extract variable-length signed value
  1766.  * \param  pVals storage of value
  1767.  * \param  SizeCode # of bytes used (0..3 for 0/1/2/4 bytes)
  1768.  * \return effective value
  1769.  * ------------------------------------------------------------------------ */
  1770.  
  1771. static LongInt ExtractDisp(const Byte *pVals, Byte SizeCode)
  1772. {
  1773.   LongInt Result = 0;
  1774.  
  1775.   switch (SizeCode)
  1776.   {
  1777.     case 3:
  1778.       Result = (Result << 8) | (*pVals++);
  1779.       Result = (Result << 8) | (*pVals++);
  1780.       Result = (Result << 8) | (*pVals++);
  1781.       Result = (Result << 8) | (*pVals++);
  1782.       break;
  1783.     case 2:
  1784.       Result = (Result << 8) | (*pVals++);
  1785.       Result = (Result << 8) | (*pVals++);
  1786.       if (Result & 0x8000ul)
  1787.         Result -= 0x10000ul;
  1788.       break;
  1789.     case 1:
  1790.       Result = (Result << 8) | (*pVals++);
  1791.       if (Result & 0x80ul)
  1792.         Result -= 0x100;
  1793.       break;
  1794.     default:
  1795.       Result = 0;
  1796.   }
  1797.   return Result;
  1798. }
  1799.  
  1800. /*!------------------------------------------------------------------------
  1801.  * \fn     PCDistOK(const tAdrVals *pAdrVals, int Delta)
  1802.  * \brief  if expression is PC-relative, check whether change of distance does not change displacement size
  1803.  * \param  pAdrVals parsed address expression
  1804.  * \param  Delta displacement change
  1805.  * ------------------------------------------------------------------------ */
  1806.  
  1807. static Boolean PCDistOK(tAdrVals *pAdrVals, int Delta)
  1808. {
  1809.   Byte DispSizeCode;
  1810.   LongInt NewDisp;
  1811.   int DispOffs;
  1812.   tSymbolSize DispSize;
  1813.  
  1814.   /* only relevant for EA values that use PC-relative addressing: */
  1815.  
  1816.   if (pAdrVals->Vals[0] != 0x7d)
  1817.     return True;
  1818.   DispOffs = (pAdrVals->Vals[1] & 0x80) ? 2 : 3;
  1819.  
  1820.   /* extract displacement size Sd */
  1821.  
  1822.   DispSizeCode = (pAdrVals->Vals[1] >> 4) & 3;
  1823.   DispSize = (tSymbolSize)(DispSizeCode - 1);
  1824.  
  1825.   /* compute new displacement after correction */
  1826.  
  1827.   NewDisp = ExtractDisp(pAdrVals->Vals + DispOffs, DispSizeCode) + Delta;
  1828.  
  1829.   /* still fits size? */
  1830.  
  1831.   if (DeduceSize(NewDisp) != DispSize)
  1832.     return False;
  1833.  
  1834.   AppendBySize(pAdrVals->Vals + DispOffs, NewDisp, DispSize);
  1835.   return True;
  1836. }
  1837.  
  1838. /*!------------------------------------------------------------------------
  1839.  * \fn     NegSignedValOK(tAdrVals *pAdrVals)
  1840.  * \brief  tests whether negated (8 bit) immediate value still fits size
  1841.  * \param  pAdrVals parsed address expression
  1842.  * \return True if successfully inverted
  1843.  * ------------------------------------------------------------------------ */
  1844.  
  1845. static Boolean NegSigned8ValOK(tAdrVals *pAdrVals)
  1846. {
  1847.   Byte DispSizeCode;
  1848.   LongInt Value;
  1849.   tSymbolSize DispSize;
  1850.  
  1851.   /* only treats immediate argument: */
  1852.  
  1853.   if (pAdrVals->Mode != eAdrModeImm)
  1854.     return False;
  1855.  
  1856.   DispSizeCode = pAdrVals->Vals[0] & 3;
  1857.   if (!DispSizeCode)
  1858.     return False;
  1859.   DispSize = (tSymbolSize)(DispSizeCode - 1);
  1860.  
  1861.   /* extract immediate value */
  1862.  
  1863.   Value = ExtractDisp(pAdrVals->Vals + 1, DispSizeCode) * (-1);
  1864.  
  1865.   /* still fits size? */
  1866.  
  1867.   if (DeduceSize(Value) > eSymbolSize8Bit)
  1868.     return False;
  1869.  
  1870.   AppendBySize(pAdrVals->Vals + 1, Value, DispSize);
  1871.   return True;
  1872. }
  1873.  
  1874. /*---------------------------------------------------------------------------*/
  1875.  
  1876. /*!------------------------------------------------------------------------
  1877.  * \fn     DecodeMOV_ADD_SUB_CMP(Word Code)
  1878.  * \brief  instruction parser for MOV, ADD, CMP and SUB
  1879.  * \param  Code specific instruction code
  1880.  * ------------------------------------------------------------------------ */
  1881.  
  1882. static void DecodeMOV_ADD_SUB_CMP(Word Code)
  1883. {
  1884.   tAdrVals SrcAdrVals, DestAdrVals;
  1885.   tFormat Format;
  1886.   unsigned DestMask;
  1887.   Boolean IsSUB = (Code == 0x04),
  1888.           IsCMP = (Code == 0x08);
  1889.  
  1890.   if (!ChkOpSize(eSymbolSize16Bit, 7))
  1891.     return;
  1892.  
  1893.   /* Immediate is allowed as destination for CMP since the result is
  1894.      anyway discarded: */
  1895.  
  1896.   DestMask = MModeAll;
  1897.   if (!IsCMP)
  1898.     DestMask &= ~MModeImm;
  1899.  
  1900.   if (ChkArgCnt(2, 2)
  1901.    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
  1902.    && DecodeAdr(&ArgStr[2], DestMask, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  1903.   {
  1904.     /* TODO: auto-convert SUB:Q n,<ea> to ADD:q -n,<ea>? */
  1905.  
  1906.     if (!*FormatPart.str.p_str)
  1907.     {
  1908.       /* R format (all instructions) */
  1909.  
  1910.       if (GlobalBankReg(&SrcAdrVals) && GlobalBankReg(&DestAdrVals))
  1911.         Format = eFormatR;
  1912.  
  1913.       /* MOV R0,<ea> -> MOVF <ea> if PC-relative distance size does not change. */
  1914.  
  1915.       else if (GlobalBankReg(&SrcAdrVals) && (SrcAdrVals.Vals[0] == 0x40) && PCDistOK(&DestAdrVals, SrcAdrVals.Cnt))
  1916.         Format = eFormatF;
  1917.       else if (ImmValS4(&SrcAdrVals) && GlobalBankReg(&DestAdrVals))
  1918.         Format = eFormatRQ;
  1919.  
  1920.       /* SUB:Q #n,<ea> does not exist.  Convert to ADD:Q #-n,<ea> if possible..
  1921.          TODO: should not do this at all if immediate size >= 16 bit was forced.  */
  1922.  
  1923.       else if (ImmValS8(&SrcAdrVals) && (!IsSUB || NegSigned8ValOK(&SrcAdrVals)))
  1924.       {
  1925.         if (IsSUB)
  1926.         {
  1927.           Code = 0x00;
  1928.           IsSUB = False;
  1929.         }
  1930.         Format = eFormatQ;
  1931.       }
  1932.       else
  1933.         Format = eFormatG;
  1934.     }
  1935.     else if (!(Format = DecodeFormat((1 << eFormatG) | (1 << eFormatQ) | (1 << eFormatR) | (1 << eFormatRQ))))
  1936.     {
  1937.       WrStrErrorPos(ErrNum_InvFormat, &FormatPart);
  1938.       return;
  1939.     }
  1940.     switch (Format)
  1941.     {
  1942.       case eFormatG:
  1943.         BAsmCode[CodeLen++] = 0x00 | Code | OpSize;
  1944.         AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  1945.         break;
  1946.       case eFormatR:
  1947.         if (!GlobalBankReg(&SrcAdrVals)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1948.         else if (!GlobalBankReg(&DestAdrVals)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1949.         else
  1950.         {
  1951.           BAsmCode[CodeLen++] = 0x20 | Code | OpSize;
  1952.           BAsmCode[CodeLen++] = ((SrcAdrVals.Vals[0] & 15) << 4) | (DestAdrVals.Vals[0] & 15);
  1953.         }
  1954.         break;
  1955.       case eFormatRQ:
  1956.         if (SrcAdrVals.Mode != eAdrModeImm) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1957.         else if (!ImmValS4(&SrcAdrVals)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
  1958.         else if (!GlobalBankReg(&DestAdrVals)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1959.         else
  1960.         {
  1961.           BAsmCode[CodeLen++] = 0x30 | Code | OpSize;
  1962.           BAsmCode[CodeLen++] = ((DestAdrVals.Vals[0] & 15) << 4) | (SrcAdrVals.Vals[SrcAdrVals.Cnt - 1] & 15);
  1963.         }
  1964.         break;
  1965.       case eFormatQ:
  1966.         if (IsSUB) WrStrErrorPos(ErrNum_InvAddrMode, &AttrPart);
  1967.         else if (SrcAdrVals.Mode != eAdrModeImm) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1968.         else if (!ImmValS8(&SrcAdrVals)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
  1969.         else
  1970.         {
  1971.           BAsmCode[CodeLen++] = 0x10 | Code | OpSize;
  1972.           BAsmCode[CodeLen++] = SrcAdrVals.Vals[SrcAdrVals.Cnt - 1];
  1973.           AppendAdrValsToCode(&DestAdrVals);
  1974.         }
  1975.         break;
  1976.       case eFormatF:
  1977.         if (!GlobalBankReg(&SrcAdrVals) || (SrcAdrVals.Vals[0] != 0x40)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1978.         else
  1979.         {
  1980.           BAsmCode[CodeLen++] = 0x5c | OpSize;
  1981.           AppendAdrValsToCode(&DestAdrVals);
  1982.         }
  1983.         break;
  1984.       default:
  1985.         break;
  1986.     }
  1987.   }
  1988. }
  1989.  
  1990. /*!------------------------------------------------------------------------
  1991.  * \fn     DecodeSignExt(Word Code)
  1992.  * \brief  instruction parser for MOVS, ADDS, CMPS and SUBS
  1993.  * \param  Code specific instruction code
  1994.  * ------------------------------------------------------------------------ */
  1995.  
  1996. static void DecodeSignExt(Word Code)
  1997. {
  1998.   tSymbolSize SrcOpSize;
  1999.   tAdrVals SrcAdrVals, DestAdrVals;
  2000.   Boolean IsCMPS = (Code == 0x48);
  2001.   unsigned DestMask;
  2002.  
  2003.   /* Immediate is allowed as destination for CMPS since the result is
  2004.      anyway discarded: */
  2005.  
  2006.   DestMask = MModeAll;
  2007.   if (!IsCMPS)
  2008.     DestMask &= ~MModeImm;
  2009.  
  2010.   if (!ChkEmptyFormat()
  2011.    || !ChkOpSize(eSymbolSize16Bit, 7)
  2012.    || !ChkArgCnt(2, 2)
  2013.    || !DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1))
  2014.     return;
  2015.   SrcOpSize = OpSize;
  2016.   OpSize = eSymbolSize32Bit;
  2017.   if (DecodeAdr(&ArgStr[2], DestMask, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2018.   {
  2019.     BAsmCode[CodeLen++] = Code | SrcOpSize;
  2020.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2021.   }
  2022. }
  2023.  
  2024. /*!------------------------------------------------------------------------
  2025.  * \fn     DecodeTwo(Word Code)
  2026.  * \brief  instruction parser for generic two-operand instructions
  2027.  * \param  Code specific instruction code
  2028.  * ------------------------------------------------------------------------ */
  2029.  
  2030. static void DecodeTwo(Word Code)
  2031. {
  2032.   tAdrVals SrcAdrVals, DestAdrVals;
  2033.   Boolean Only8 = (Code & 3) == 3;
  2034.  
  2035.   if (ChkEmptyFormat()
  2036.    && ChkOpSize(Only8 ? eSymbolSize8Bit : eSymbolSize16Bit, Only8 ? 1 : 7)
  2037.    && ChkArgCnt(2, 2)
  2038.    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
  2039.    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2040.   {
  2041.     BAsmCode[CodeLen++] = Code | OpSize;
  2042.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2043.   }
  2044. }
  2045.  
  2046. /*!------------------------------------------------------------------------
  2047.  * \fn     DecodeOne(Word Code)
  2048.  * \brief  instruction parser for generic one-operand instructions
  2049.  * \param  Code specific instruction code
  2050.  * ------------------------------------------------------------------------ */
  2051.  
  2052. static void DecodeOne(Word Code)
  2053. {
  2054.   tAdrVals AdrVals;
  2055.   Boolean Only8 = !!(Code & 3);
  2056.   unsigned Mask;
  2057.  
  2058.   Mask = MModeAll;
  2059.   if (Code != 0x58) /* TST */
  2060.     Mask &= ~MModeImm;
  2061.  
  2062.   if (ChkEmptyFormat()
  2063.    && ChkOpSize(Only8 ? eSymbolSize8Bit : eSymbolSize16Bit, Only8 ? 1 : 7)
  2064.    && ChkArgCnt(1, 1)
  2065.    && DecodeAdr(&ArgStr[1], Mask, &AdrVals, EProgCounter() + 1))
  2066.   {
  2067.     BAsmCode[CodeLen++] = Code | OpSize;
  2068.     AppendAdrValsToCode(&AdrVals);
  2069.   }
  2070. }
  2071.  
  2072. /*!------------------------------------------------------------------------
  2073.  * \fn     DecodeMUL_DIV(Word Code)
  2074.  * \brief  instruction parser for multiply and divide instructions
  2075.  * \param  Code specific instruction code
  2076.  * ------------------------------------------------------------------------ */
  2077.  
  2078. static void DecodeMUL_DIV(Word Code)
  2079. {
  2080.   tAdrVals SrcAdrVals, DestAdrVals;
  2081.  
  2082.   if (!ChkEmptyFormat()
  2083.    || !ChkOpSize(eSymbolSize16Bit, 3)
  2084.    || !ChkArgCnt(2, 2)
  2085.    || !DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 2))
  2086.     return;
  2087.   OpSize++;
  2088.   if (!DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 2 + SrcAdrVals.Cnt))
  2089.     return;
  2090.   OpSize--;
  2091.  
  2092.   BAsmCode[CodeLen++] = 0xee | (Code & 0x01);
  2093.   BAsmCode[CodeLen++] = (Code & 0x70) | (OpSize << 4);
  2094.   AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2095. }
  2096.  
  2097. /*!------------------------------------------------------------------------
  2098.  * \fn     DecodeEXT(Word Code)
  2099.  * \brief  instruction parser for EXTS/EXTU
  2100.  * \param  Code specific instruction code
  2101.  * ------------------------------------------------------------------------ */
  2102.  
  2103. static void DecodeEXT(Word Code)
  2104. {
  2105.   Byte Reg, Prefix;
  2106.  
  2107.   if (ChkEmptyFormat()
  2108.    && ChkOpSize(eSymbolSize16Bit, 7)
  2109.    && ChkArgCnt(1, 1))
  2110.   {
  2111.     if (DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True))
  2112.     {
  2113.       OpSize = (OpSize == eSymbolSize8Bit) ? eSymbolSize32Bit : (OpSize - 1);
  2114.       BAsmCode[CodeLen++] = Code | OpSize;
  2115.       BAsmCode[CodeLen++] = Reg;
  2116.     }
  2117.   }
  2118. }
  2119.  
  2120. /*!------------------------------------------------------------------------
  2121.  * \fn     DecodeCInstr(Word Code)
  2122.  * \brief  instruction decoder for control-register related instructions
  2123.  * \param  Code specific instruction code
  2124.  * ------------------------------------------------------------------------ */
  2125.  
  2126. static void DecodeCInstr(Word Code)
  2127. {
  2128.   Byte CReg;
  2129.   unsigned Mask = MModeAll;
  2130.   int CIdx = 2, EAIdx = 1;
  2131.   tAdrVals AdrVals;
  2132.  
  2133.   if (0xfc == Code) /* STC */
  2134.   {
  2135.     CIdx = 1;
  2136.     EAIdx = 2;
  2137.     Mask &= ~MModeImm;
  2138.   }
  2139.  
  2140.   if (ChkEmptyFormat()
  2141.    && ChkArgCnt(2, 2)
  2142.    && DecodeCReg(&ArgStr[CIdx], &CReg)
  2143.    && DecodeAdr(&ArgStr[EAIdx], Mask, &AdrVals, EProgCounter() + 2))
  2144.   {
  2145.     BAsmCode[CodeLen++] = Code;
  2146.     BAsmCode[CodeLen++] = CReg;
  2147.     AppendAdrValsToCode(&AdrVals);
  2148.   }
  2149. }
  2150.  
  2151. /*!------------------------------------------------------------------------
  2152.  * \fn     DecodeBranch(Word Code)
  2153.  * \brief  instruction decoder for non-generic branch instructions
  2154.  * \param  Code specific instruction code
  2155.  * ------------------------------------------------------------------------ */
  2156.  
  2157. static void DecodeBranch(Word Code)
  2158. {
  2159.   LongInt Addr;
  2160.   Boolean OK;
  2161.   tSymbolFlags Flags;
  2162.  
  2163.   if (!ChkEmptyFormat()
  2164.    || !ChkArgCnt(1, 1))
  2165.     return;
  2166.  
  2167.   Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '@'), UInt24, &OK, &Flags);
  2168.   if (!OK)
  2169.     return;
  2170.  
  2171.   if (OpSize == eSymbolSizeUnknown)
  2172.     OpSize = DeduceSizePCRel(Addr, EProgCounter() + 1);
  2173.   if (!ChkSizePCRelBranch(&ArgStr[1], &Addr, OpSize, Flags, EProgCounter() + 1))
  2174.     return;
  2175.  
  2176.   BAsmCode[CodeLen++] = Code | OpSize;
  2177.   CodeLen += AppendBySize(BAsmCode + CodeLen, Addr, OpSize);
  2178. }
  2179.  
  2180. /*!------------------------------------------------------------------------
  2181.  * \fn     DecodeBranchGen(Word Code)
  2182.  * \brief  instruction decoder for generic branch instructions
  2183.  * \param  Code specific instruction code
  2184.  * ------------------------------------------------------------------------ */
  2185.  
  2186. static void DecodeBranchGen(Word Code)
  2187. {
  2188.   LongInt Addr;
  2189.   Boolean OK;
  2190.   tSymbolFlags Flags;
  2191.   tFormat Format;
  2192.  
  2193.   if (!ChkArgCnt(1, 1))
  2194.     return;
  2195.  
  2196.   if (!*FormatPart.str.p_str)
  2197.   {
  2198.     if (Code == 7)
  2199.     {
  2200.       DecodeBranch(0xa0);
  2201.       return;
  2202.     }
  2203.     if (Code == 6)
  2204.     {
  2205.       DecodeBranch(0xb0);
  2206.       return;
  2207.     }
  2208.   }
  2209.   else
  2210.   {
  2211.     Format = DecodeFormat(1 << eFormatG);
  2212.     if (!Format)
  2213.     {
  2214.       WrStrErrorPos(ErrNum_InvFormat, &FormatPart);
  2215.       return;
  2216.     }
  2217.   }
  2218.  
  2219.   Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '@'), UInt24, &OK, &Flags);
  2220.   if (!OK)
  2221.     return;
  2222.  
  2223.   if (OpSize == eSymbolSizeUnknown)
  2224.     OpSize = DeduceSizePCRel(Addr, EProgCounter() + 2);
  2225.   if (!ChkSizePCRelBranch(&ArgStr[1], &Addr, OpSize, Flags, EProgCounter() + 2))
  2226.     return;
  2227.  
  2228.   BAsmCode[CodeLen++] = 0xa4 | OpSize;
  2229.   BAsmCode[CodeLen++] = Code;
  2230.   CodeLen += AppendBySize(BAsmCode + CodeLen, Addr, OpSize);
  2231. }
  2232.  
  2233. /*!------------------------------------------------------------------------
  2234.  * \fn     DecodeFixed(Word Code)
  2235.  * \brief  instruction decoder for instructions without argument
  2236.  * \param  Code specific instruction code
  2237.  * ------------------------------------------------------------------------ */
  2238.  
  2239. static void DecodeFixed(Word Code)
  2240. {
  2241.   if (ChkEmptyFormat()
  2242.    && (!(Code & 0x8000) || CheckSup(&OpPart))
  2243.    && ChkArgCnt(0, 0))
  2244.     BAsmCode[CodeLen++] = Lo(Code);
  2245. }
  2246.  
  2247. /*!------------------------------------------------------------------------
  2248.  * \fn     Decode(Word Code)
  2249.  * \brief  instruction decoder for shift & rotate instructions
  2250.  * \param  Code specific instruction code
  2251.  * ------------------------------------------------------------------------ */
  2252.  
  2253. static void DecodeShift(Word Code)
  2254. {
  2255.   tAdrVals ShiftAdrVals, OpAdrVals;
  2256.   tSymbolSize SaveOpSize;
  2257.  
  2258.   if (!ChkEmptyFormat()
  2259.    || !ChkOpSize(eSymbolSize16Bit, 7)
  2260.    || !ChkArgCnt(2, 2)
  2261.    || !DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &OpAdrVals, EProgCounter() + 2))
  2262.     return;
  2263.   SaveOpSize = OpSize;
  2264.  
  2265.   OpSize = eSymbolSize5Bit;
  2266.   (void)DecodeAdr(&ArgStr[1], MModeImm | MModeReg, &ShiftAdrVals, EProgCounter() + 1);
  2267.   switch (ShiftAdrVals.Mode)
  2268.   {
  2269.     case eAdrModeReg:
  2270.       if (ShiftAdrVals.Cnt > 1) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  2271.       else
  2272.       {
  2273.         BAsmCode[CodeLen++] = 0x60 | SaveOpSize;
  2274.         BAsmCode[CodeLen++] = Code | (ShiftAdrVals.Vals[0] & 15);
  2275.         goto common;
  2276.       }
  2277.       break;
  2278.     case eAdrModeImm:
  2279.       BAsmCode[CodeLen++] = 0x64 | SaveOpSize;
  2280.       BAsmCode[CodeLen++] = Code | (ShiftAdrVals.Vals[1] & 31);
  2281.       goto common;
  2282.     default:
  2283.       break;
  2284.     common:
  2285.       AppendAdrValsToCode(&OpAdrVals);
  2286.   }
  2287. }
  2288.  
  2289. /*!------------------------------------------------------------------------
  2290.  * \fn     DecodeSET(Word Code)
  2291.  * \brief  instruction decoder for SET/cc instructions
  2292.  * \param  Code specific instruction code
  2293.  * ------------------------------------------------------------------------ */
  2294.  
  2295. static void DecodeSET(Word Code)
  2296. {
  2297.   tAdrVals AdrVals;
  2298.  
  2299.   if (ChkEmptyFormat()
  2300.    && ChkOpSize(eSymbolSize8Bit, 1)
  2301.    && ChkArgCnt(1, 1)
  2302.    && DecodeAdr(&ArgStr[1], MModeAll - MModeImm, &AdrVals, EProgCounter() + 2))
  2303.   {
  2304.     BAsmCode[CodeLen++] = 0xb7;
  2305.     BAsmCode[CodeLen++] = Code;
  2306.     AppendAdrValsToCode(&AdrVals);
  2307.   }
  2308. }
  2309.  
  2310. /*!------------------------------------------------------------------------
  2311.  * \fn     DecodeTRAP(Word Code)
  2312.  * \brief  instruction decoder for TRAP/cc instructions
  2313.  * \param  Code specific instruction code
  2314.  * ------------------------------------------------------------------------ */
  2315.  
  2316. static void DecodeTRAP(Word Code)
  2317. {
  2318.   if (ChkEmptyFormat()
  2319.    && ChkArgCnt(0, 0))
  2320.   {
  2321.     BAsmCode[CodeLen++] = 0xf3;
  2322.     BAsmCode[CodeLen++] = Code;
  2323.   }
  2324. }
  2325.  
  2326. /*!------------------------------------------------------------------------
  2327.  * \fn     DecodeSCB(Word Code)
  2328.  * \brief  instruction decoder for SCB/cc instructions
  2329.  * \param  Code specific instruction code
  2330.  * ------------------------------------------------------------------------ */
  2331.  
  2332. static void DecodeSCB(Word Code)
  2333. {
  2334.   LongInt Addr;
  2335.   Boolean OK;
  2336.   tSymbolFlags Flags;
  2337.   Byte Reg, Prefix;
  2338.  
  2339.   if (!ChkEmptyFormat()
  2340.    || !ChkArgCnt(2, 2))
  2341.     return;
  2342.  
  2343.   if (!DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True))
  2344.     return;
  2345.  
  2346.   Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], !!(*ArgStr[1].str.p_str == '@'), UInt24, &OK, &Flags);
  2347.   if (!OK)
  2348.     return;
  2349.  
  2350.   if (OpSize == eSymbolSizeUnknown)
  2351.     OpSize = DeduceSizePCRel(Addr, EProgCounter() + 2);
  2352.   if (!ChkSizePCRelBranch(&ArgStr[2], &Addr, OpSize, Flags, EProgCounter() + 2))
  2353.     return;
  2354.  
  2355.   BAsmCode[CodeLen++] = 0xb4 | OpSize;
  2356.   BAsmCode[CodeLen++] = (Reg << 4) | Code;
  2357.   CodeLen += AppendBySize(BAsmCode + CodeLen, Addr, OpSize);
  2358. }
  2359.  
  2360. /*!------------------------------------------------------------------------
  2361.  * \fn     DecodeJMP_JSR(Word Code)
  2362.  * \brief  instruction decoder for JMP and JSR instructions
  2363.  * \param  Code specific instruction code
  2364.  * ------------------------------------------------------------------------ */
  2365.  
  2366. static void DecodeJMP_JSR(Word Code)
  2367. {
  2368.   tAdrVals Arg;
  2369.  
  2370.   if (ChkEmptyFormat()
  2371.    && ChkArgCnt(1, 1)
  2372.    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModeImm, &Arg, EProgCounter() + 1))
  2373.   {
  2374.     BAsmCode[CodeLen++] = Code;
  2375.     AppendAdrValsToCode(&Arg);
  2376.   }
  2377. }
  2378.  
  2379. /*!------------------------------------------------------------------------
  2380.  * \fn     DecodeSWAP(Word Code)
  2381.  * \brief  instruction decoder for SWAP instruction
  2382.  * \param  Code specific instruction code
  2383.  * ------------------------------------------------------------------------ */
  2384.  
  2385. static void DecodeSWAP(Word Code)
  2386. {
  2387.   tAdrVals Arg;
  2388.  
  2389.   if (ChkEmptyFormat()
  2390.    && ChkOpSize(eSymbolSize16Bit, 3)
  2391.    && ChkArgCnt(1, 1)
  2392.    && DecodeAdr(&ArgStr[1], MModeAll - MModeImm, &Arg, EProgCounter() + 1))
  2393.   {
  2394.     BAsmCode[CodeLen++] = Code | OpSize;
  2395.     AppendAdrValsToCode(&Arg);
  2396.   }
  2397. }
  2398.  
  2399. /*!------------------------------------------------------------------------
  2400.  * \fn     DecodeXCH(Word Code)
  2401.  * \brief  instruction decoder for XCH instruction
  2402.  * \param  Code specific instruction code
  2403.  * ------------------------------------------------------------------------ */
  2404.  
  2405. static void DecodeXCH(Word Code)
  2406. {
  2407.   Byte RegX, RegY, PrefixX, PrefixY;
  2408.  
  2409.   if (ChkEmptyFormat()
  2410.    && ChkOpSize(eSymbolSize32Bit, 4)
  2411.    && ChkArgCnt(2, 2))
  2412.   {
  2413.     if (DecodeReg(&ArgStr[1], &RegX, &PrefixX, False, True)
  2414.      && DecodeReg(&ArgStr[2], &RegY, &PrefixY, False, True))
  2415.     {
  2416.       BAsmCode[CodeLen++] = Code;
  2417.       BAsmCode[CodeLen++] = (RegX << 4) | RegY;
  2418.     }
  2419.   }
  2420. }
  2421.  
  2422. /*!------------------------------------------------------------------------
  2423.  * \fn     DecodeLINK(Word Code)
  2424.  * \brief  instruction decoder for LINK instruction
  2425.  * \param  Code specific instruction code
  2426.  * ------------------------------------------------------------------------ */
  2427.  
  2428. static void DecodeLINK(Word Code)
  2429. {
  2430.   Byte Reg, Prefix;
  2431.  
  2432.   if (!ChkEmptyFormat()
  2433.    || !ChkArgCnt(2, 2))
  2434.     return;
  2435.   if (!DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True));
  2436.   else if (*ArgStr[2].str.p_str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[2]);
  2437.   else
  2438.   {
  2439.     Boolean OK;
  2440.     LongInt Val = EvalArg(&ArgStr[2], 1, (OpSize == eSymbolSizeUnknown) ? eSymbolSize32Bit : OpSize, &OK);
  2441.  
  2442.     if (OK)
  2443.     {
  2444.       if (OpSize == eSymbolSizeUnknown)
  2445.         OpSize = DeduceSize(Val);
  2446.       BAsmCode[CodeLen++] = Code | OpSize;
  2447.       BAsmCode[CodeLen++] = Reg;
  2448.       CodeLen += AppendBySize(BAsmCode + CodeLen, Val, OpSize);
  2449.     }
  2450.   }
  2451. }
  2452.  
  2453. /*!------------------------------------------------------------------------
  2454.  * \fn     DecodeUNLK(Word Code)
  2455.  * \brief  instruction decoder for UNLK instruction
  2456.  * \param  Code specific instruction code
  2457.  * ------------------------------------------------------------------------ */
  2458.  
  2459. static void DecodeUNLK(Word Code)
  2460. {
  2461.   Byte Reg, Prefix;
  2462.  
  2463.   if (!ChkEmptyFormat()
  2464.    || !ChkArgCnt(1, 1))
  2465.     return;
  2466.   if (DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True))
  2467.   {
  2468.     BAsmCode[CodeLen++] = Code;
  2469.     BAsmCode[CodeLen++] = Reg;
  2470.   }
  2471. }
  2472.  
  2473. /*!------------------------------------------------------------------------
  2474.  * \fn     DecodeTRAPA(Word Code)
  2475.  * \brief  instruction decoder for TRAPA instruction
  2476.  * \param  Code specific instruction code
  2477.  * ------------------------------------------------------------------------ */
  2478.  
  2479. static void DecodeTRAPA(Word Code)
  2480. {
  2481.   if (!ChkEmptyFormat()
  2482.    || !ChkArgCnt(1, 1))
  2483.     return;
  2484.   if (*ArgStr[1].str.p_str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
  2485.   else
  2486.   {
  2487.     Boolean OK;
  2488.     Byte Val = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt4, &OK);
  2489.  
  2490.     if (OK)
  2491.     {
  2492.       BAsmCode[CodeLen++] = Code;
  2493.       BAsmCode[CodeLen++] = Val;
  2494.     }
  2495.   }
  2496. }
  2497.  
  2498. /*!------------------------------------------------------------------------
  2499.  * \fn     DecodeRTD(Word Code)
  2500.  * \brief  instruction decoder for RTD instruction
  2501.  * \param  Code specific instruction code
  2502.  * ------------------------------------------------------------------------ */
  2503.  
  2504. static void DecodeRTD(Word Code)
  2505. {
  2506.   if (!ChkEmptyFormat()
  2507.    || !ChkArgCnt(1, 1))
  2508.     return;
  2509.   else if (*ArgStr[1].str.p_str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
  2510.   else
  2511.   {
  2512.     Boolean OK;
  2513.     LongInt Val = EvalArg(&ArgStr[1], 1, (OpSize == eSymbolSizeUnknown) ? eSymbolSize32Bit : OpSize, &OK);
  2514.  
  2515.     if (OK)
  2516.     {
  2517.       if (OpSize == eSymbolSizeUnknown)
  2518.         OpSize = DeduceSize(Val);
  2519.       BAsmCode[CodeLen++] = Code | OpSize;
  2520.       CodeLen += AppendBySize(BAsmCode + CodeLen, Val, OpSize);
  2521.     }
  2522.   }
  2523. }
  2524.  
  2525. /*!------------------------------------------------------------------------
  2526.  * \fn     DecodeLDM_STM(Word Code)
  2527.  * \brief  instruction decoder for LDM and STM instructions
  2528.  * \param  Code specific instruction code
  2529.  * ------------------------------------------------------------------------ */
  2530.  
  2531. static void DecodeLDM_STM(Word Code)
  2532. {
  2533.   Word RegList;
  2534.   tAdrVals AdrVals;
  2535.   Boolean IsLDM = !!(Code == 0x74);
  2536.  
  2537.   if (ChkEmptyFormat()
  2538.    && ChkOpSize(eSymbolSize16Bit, 7)
  2539.    && ChkArgCnt(2, ArgCntMax)
  2540.    && DecodeRegList(&RegList, 1 + IsLDM, ArgCnt - 1 + IsLDM)
  2541.    && DecodeAdr(&ArgStr[IsLDM ? 1 : ArgCnt], MModeAll - MModeImm - MModeReg, &AdrVals, EProgCounter() + 1))
  2542.   {
  2543.     BAsmCode[CodeLen++] = Code | OpSize;
  2544.     AppendAdrValsToCode(&AdrVals);
  2545.     BAsmCode[CodeLen++] = Hi(RegList);
  2546.     BAsmCode[CodeLen++] = Lo(RegList);
  2547.   }
  2548. }
  2549.  
  2550. /*!------------------------------------------------------------------------
  2551.  * \fn     DecodeCGBN(Word Code)
  2552.  * \brief  instruction decoder for CGBN instruction
  2553.  * \param  Code specific instruction code
  2554.  * ------------------------------------------------------------------------ */
  2555.  
  2556. static void DecodeCGBN(Word Code)
  2557. {
  2558.   tAdrVals AdrVals;
  2559.  
  2560.   if (ChkEmptyFormat()
  2561.    && CheckSup(&OpPart)
  2562.    && ChkOpSize(eSymbolSize8Bit, 1)
  2563.    && ChkArgCnt(1, ArgCntMax)
  2564.    && DecodeAdr(&ArgStr[1], MModeReg | MModeImm, &AdrVals, EProgCounter() + 1))
  2565.   {
  2566.     Word RegList = 0;
  2567.  
  2568.     if (ArgCnt >= 2)
  2569.     {
  2570.       if (!DecodeRegList(&RegList, 2, ArgCnt))
  2571.         return;
  2572.     }
  2573.     BAsmCode[CodeLen++] = Code | ((AdrVals.Mode == eAdrModeImm) ? 2 : 0) | !!RegList;
  2574.     BAsmCode[CodeLen++] = (AdrVals.Mode == eAdrModeImm) ? AdrVals.Vals[1] : (AdrVals.Vals[0] & 0x0f);
  2575.     if (RegList)
  2576.     {
  2577.       BAsmCode[CodeLen++] = Hi(RegList);
  2578.       BAsmCode[CodeLen++] = Lo(RegList);
  2579.     }
  2580.   }
  2581. }
  2582.  
  2583. /*!------------------------------------------------------------------------
  2584.  * \fn     DecodePGBN(Word Code)
  2585.  * \brief  instruction decoder for PGBN instruction
  2586.  * \param  Code specific instruction code
  2587.  * ------------------------------------------------------------------------ */
  2588.  
  2589. static void DecodePGBN(Word Code)
  2590. {
  2591.   if (ChkEmptyFormat()
  2592.    && CheckSup(&OpPart)
  2593.    && ChkOpSize(eSymbolSize8Bit, 1)
  2594.    && ChkArgCnt(0, ArgCntMax))
  2595.   {
  2596.     Word RegList = 0;
  2597.  
  2598.     if (ArgCnt >= 1)
  2599.     {
  2600.       if (!DecodeRegList(&RegList, 1, ArgCnt))
  2601.         return;
  2602.     }
  2603.     BAsmCode[CodeLen++] = Code | !!RegList;
  2604.     if (RegList)
  2605.     {
  2606.       BAsmCode[CodeLen++] = Hi(RegList);
  2607.       BAsmCode[CodeLen++] = Lo(RegList);
  2608.     }
  2609.   }
  2610. }
  2611.  
  2612. /*!------------------------------------------------------------------------
  2613.  * \fn     DecodeMOVFP(Word Code)
  2614.  * \brief  instruction decoder for MOVFP instruction
  2615.  * \param  Code specific instruction code
  2616.  * ------------------------------------------------------------------------ */
  2617.  
  2618. static void DecodeMOVFP(Word Code)
  2619. {
  2620.   tAdrVals SrcAdrVals, DestAdrVals;
  2621.  
  2622.   if (ChkEmptyFormat()
  2623.    && ChkOpSize(eSymbolSize16Bit, 6)
  2624.    && ChkArgCnt(2, 2)
  2625.    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &SrcAdrVals, EProgCounter() + 1)
  2626.    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2627.   {
  2628.     BAsmCode[CodeLen++] = Code | (OpSize - 1);
  2629.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2630.   }
  2631. }
  2632.  
  2633. /*!------------------------------------------------------------------------
  2634.  * \fn     DecodeMOVFPE(Word Code)
  2635.  * \brief  instruction decoder for MOVFPE instruction
  2636.  * \param  Code specific instruction code
  2637.  * ------------------------------------------------------------------------ */
  2638.  
  2639. static void DecodeMOVFPE(Word Code)
  2640. {
  2641.   tAdrVals SrcAdrVals, DestAdrVals;
  2642.  
  2643.   if (ChkEmptyFormat()
  2644.    && ChkOpSize(eSymbolSize16Bit, 7)
  2645.    && ChkArgCnt(2, 2)
  2646.    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &SrcAdrVals, EProgCounter() + 1)
  2647.    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2648.   {
  2649.     BAsmCode[CodeLen++] = Code | OpSize;
  2650.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2651.   }
  2652. }
  2653.  
  2654. /*!------------------------------------------------------------------------
  2655.  * \fn     DecodeMOVTP(Word Code)
  2656.  * \brief  instruction decoder for MOVTP instruction
  2657.  * \param  Code specific instruction code
  2658.  * ------------------------------------------------------------------------ */
  2659.  
  2660. static void DecodeMOVTP(Word Code)
  2661. {
  2662.   tAdrVals SrcAdrVals, DestAdrVals;
  2663.  
  2664.   if (ChkEmptyFormat()
  2665.    && ChkOpSize(eSymbolSize16Bit, 6)
  2666.    && ChkArgCnt(2, 2)
  2667.    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
  2668.    && DecodeAdr(&ArgStr[2], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2669.   {
  2670.     BAsmCode[CodeLen++] = Code | (OpSize - 1);
  2671.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2672.   }
  2673. }
  2674.  
  2675. /*!------------------------------------------------------------------------
  2676.  * \fn     DecodeMOVTPE(Word Code)
  2677.  * \brief  instruction decoder for MOVTPE instruction
  2678.  * \param  Code specific instruction code
  2679.  * ------------------------------------------------------------------------ */
  2680.  
  2681. static void DecodeMOVTPE(Word Code)
  2682. {
  2683.   tAdrVals SrcAdrVals, DestAdrVals;
  2684.  
  2685.   if (ChkEmptyFormat()
  2686.    && ChkOpSize(eSymbolSize16Bit, 7)
  2687.    && ChkArgCnt(2, 2)
  2688.    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
  2689.    && DecodeAdr(&ArgStr[2], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2690.   {
  2691.     BAsmCode[CodeLen++] = Code | OpSize;
  2692.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2693.   }
  2694. }
  2695.  
  2696. /*!------------------------------------------------------------------------
  2697.  * \fn     DecodeMOVA(Word Code)
  2698.  * \brief  instruction decoder for MOVA instruction
  2699.  * \param  Code specific instruction code
  2700.  * ------------------------------------------------------------------------ */
  2701.  
  2702. static void DecodeMOVA(Word Code)
  2703. {
  2704.   tAdrVals SrcAdrVals, DestAdrVals;
  2705.  
  2706.   if (ChkEmptyFormat()
  2707.    && ChkOpSize(eSymbolSize32Bit, 4)
  2708.    && ChkArgCnt(2, 2)
  2709.    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModeImm, &SrcAdrVals, EProgCounter() + 1)
  2710.    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
  2711.   {
  2712.     BAsmCode[CodeLen++] = Code;
  2713.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2714.   }
  2715. }
  2716.  
  2717. /*!------------------------------------------------------------------------
  2718.  * \fn     DecodeString(Word Code)
  2719.  * \brief  decode string instruction
  2720.  * \param  Code specific instruction code
  2721.  * ------------------------------------------------------------------------ */
  2722.  
  2723. static void DecodeString(Word Code)
  2724. {
  2725.   int ExpectArgCnt = (Code & 0x80) ? 4 : 3;
  2726.   unsigned SrcMask, DestMask = MModeReg | ((Code & 0x40) ? MModePre : MModePost);
  2727.   Byte SrcReg, DestReg, CntReg, FinalReg, Prefix;
  2728.  
  2729.   SrcMask = MModeReg;
  2730.   if (Code & 0x30) /* SCMP/SMOV */
  2731.     SrcMask |= (Code & 0x40) ? MModePre : MModePost;
  2732.   else if (Code & 0x80) /* SSCH */
  2733.     SrcMask |= MModeIReg;
  2734.  
  2735.   if (ChkEmptyFormat()
  2736.    && ChkOpSize(eSymbolSize16Bit, 3)
  2737.    && ChkArgCnt(ExpectArgCnt, ExpectArgCnt)
  2738.    && DecodeStringReg(&ArgStr[1], SrcMask, &SrcReg)
  2739.    && DecodeStringReg(&ArgStr[2], DestMask, &DestReg))
  2740.   {
  2741.     if (DecodeReg(&ArgStr[3], &CntReg, &Prefix, False, True))
  2742.     {
  2743.       if (4 == ExpectArgCnt)
  2744.       {
  2745.         if (!DecodeReg(&ArgStr[4], &FinalReg, &Prefix, False, True))
  2746.           return;
  2747.       }
  2748.       BAsmCode[CodeLen++] = 0x94 | OpSize;
  2749.       BAsmCode[CodeLen++] = Code | CntReg;
  2750.       BAsmCode[CodeLen++] = (SrcReg << 4) | DestReg;
  2751.       if (4 == ExpectArgCnt)
  2752.         BAsmCode[CodeLen++] = (FinalReg << 4) | Hi(Code);
  2753.     }
  2754.   }
  2755. }
  2756.  
  2757. /*!------------------------------------------------------------------------
  2758.  * \fn     DecodeBField(Word Code)
  2759.  * \brief  decode bit field instruction
  2760.  * \param  Code specific instruction code
  2761.  * ------------------------------------------------------------------------ */
  2762.  
  2763. static void DecodeBField(Word Code)
  2764. {
  2765.   tAdrVals SrcAdrVals, DestAdrVals;
  2766.   Byte PosReg, CntReg;
  2767.  
  2768.   if (OpSize != eSymbolSizeUnknown) WrError (ErrNum_InvOpSize);
  2769.   else if (ChkEmptyFormat()
  2770.         && ChkArgCnt(4, 4)
  2771.         && DecodeStringReg(&ArgStr[1], MModeReg, &PosReg)
  2772.         && DecodeStringReg(&ArgStr[2], MModeReg, &CntReg)
  2773.         && DecodeAdr(&ArgStr[3], MModeAll - MModePre - MModePost - MModeImm, &SrcAdrVals, EProgCounter() + 2)
  2774.         && DecodeAdr(&ArgStr[4], MModeAll - MModePre - MModePost - MModeImm, &DestAdrVals, EProgCounter() + 2 + SrcAdrVals.Cnt))
  2775.   {
  2776.     BAsmCode[CodeLen++] = Code;
  2777.     BAsmCode[CodeLen++] = (PosReg << 4) | CntReg;
  2778.     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
  2779.   }
  2780. }
  2781.  
  2782. /*!------------------------------------------------------------------------
  2783.  * \fn     DecodeBFMOV(Word Code)
  2784.  * \brief  decode bit field move instruction which is different from other bit field instructions
  2785.  * \param  Code specific instruction code
  2786.  * ------------------------------------------------------------------------ */
  2787.  
  2788. static void DecodeBFMOV(Word Code)
  2789. {
  2790.   Byte XReg, BReg, YReg, OReg, SReg, DReg;
  2791.  
  2792.   if (OpSize != eSymbolSizeUnknown) WrError (ErrNum_InvOpSize);
  2793.   else if (ChkEmptyFormat()
  2794.         && ChkArgCnt(6, 6)
  2795.         && DecodeStringReg(&ArgStr[1], MModeReg, &XReg)
  2796.         && DecodeStringReg(&ArgStr[2], MModeReg, &BReg)
  2797.         && DecodeStringReg(&ArgStr[3], MModeReg, &YReg)
  2798.         && DecodeStringReg(&ArgStr[4], MModeReg, &OReg)
  2799.         && DecodeStringReg(&ArgStr[5], MModeReg | MModeIReg , &SReg)
  2800.         && DecodeStringReg(&ArgStr[6], MModeReg | MModeIReg , &DReg))
  2801.   {
  2802.     BAsmCode[CodeLen++] = Code;
  2803.     BAsmCode[CodeLen++] = (XReg << 4) | BReg;
  2804.     BAsmCode[CodeLen++] = (YReg << 4) | OReg;
  2805.     BAsmCode[CodeLen++] = (SReg << 4) | DReg;
  2806.   }
  2807. }
  2808.  
  2809. /*!------------------------------------------------------------------------
  2810.  * \fn     DecodeBit(Word Code)
  2811.  * \brief  decode CPU bit handling instruction
  2812.  * \param  Code specific instruction code
  2813.  * ------------------------------------------------------------------------ */
  2814.  
  2815. static void DecodeBit(Word Code)
  2816. {
  2817.   tSymbolSize ThisOpSize;
  2818.  
  2819.   if (!ChkEmptyFormat()
  2820.    || !ChkArgCnt(1, 2))
  2821.     return;
  2822.  
  2823.   /* bit "object": */
  2824.  
  2825.   if (1 == ArgCnt)
  2826.   {
  2827.     LongWord BitArg, Address;
  2828.     Byte ImmPos;
  2829.  
  2830.     if (DecodeBitArg(&BitArg, 1, 1, OpSize)
  2831.      && DissectBitSymbol(BitArg, &Address, &ImmPos, &ThisOpSize)
  2832.      && SetOpSize(ThisOpSize))
  2833.     {
  2834.       tSymbolSize AddressSize = DeduceSize16M(Address);
  2835.  
  2836.       /* SetOpSize() has set OpSize to 0..2 or confirmed it, no need to check for invalid size */
  2837.  
  2838.       BAsmCode[CodeLen++] = 0x6c | OpSize;
  2839.       BAsmCode[CodeLen++] = Code | ImmPos;
  2840.       BAsmCode[CodeLen++] = 0x74 | (AddressSize + 1);
  2841.       CodeLen += AppendBySize(BAsmCode + CodeLen, Address, AddressSize);
  2842.     }
  2843.   }
  2844.  
  2845.   /* bit + <ea> */
  2846.  
  2847.   else
  2848.   {
  2849.     tAdrVals EAAdrVals, BitAdrVals;
  2850.     unsigned Mask = MModeAll - ((Code == 0x60) ? 0 : MModeImm);
  2851.  
  2852.     if (ChkOpSize(eSymbolSize16Bit, 7)
  2853.      && DecodeAdr(&ArgStr[2], Mask, &EAAdrVals, EProgCounter() + 2))
  2854.     {
  2855.       ThisOpSize = OpSize;
  2856.       OpSize = eSymbolSize3Bit + OpSize;
  2857.       if (DecodeAdr(&ArgStr[1], MModeImm | MModeReg, &BitAdrVals, EProgCounter() + 1))
  2858.       {
  2859.         switch (BitAdrVals.Mode)
  2860.         {
  2861.           case eAdrModeReg:
  2862.             if (!GlobalBankReg(&BitAdrVals))
  2863.             {
  2864.               WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  2865.               return;
  2866.             }
  2867.             BAsmCode[CodeLen++] = 0x64 | ThisOpSize;
  2868.             BAsmCode[CodeLen++] = Code | (BitAdrVals.Vals[0] & 15);
  2869.             break;
  2870.           case eAdrModeImm:
  2871.             BAsmCode[CodeLen++] = 0x6c | ThisOpSize;
  2872.             BAsmCode[CodeLen++] = Code | BitAdrVals.Vals[1];
  2873.             break;
  2874.           default:
  2875.             return;
  2876.         }
  2877.         AppendAdrValsToCode(&EAAdrVals);
  2878.       }
  2879.     }
  2880.   }
  2881. }
  2882.  
  2883. /*!------------------------------------------------------------------------
  2884.  * \fn     DecodeBIT(Word Code)
  2885.  * \brief  decode bit declaration instruction
  2886.  * ------------------------------------------------------------------------ */
  2887.  
  2888. static void DecodeBIT(Word Code)
  2889. {
  2890.   LongWord BitSpec;
  2891.  
  2892.   UNUSED(Code);
  2893.  
  2894.   /* if in structure definition, add special element to structure */
  2895.  
  2896.   if (ActPC == StructSeg)
  2897.   {
  2898.     Boolean OK;
  2899.     Byte BitPos;
  2900.     PStructElem pElement;
  2901.  
  2902.     if (!ChkArgCnt(2, 2))
  2903.       return;
  2904.     BitPos = EvalBitPosition(&ArgStr[1], &OK, (OpSize == eSymbolSizeUnknown) ? eSymbolSize32Bit : OpSize);
  2905.     if (!OK)
  2906.       return;
  2907.     pElement = CreateStructElem(&LabPart);
  2908.     if (!pElement)
  2909.       return;
  2910.     pElement->pRefElemName = as_strdup(ArgStr[2].str.p_str);
  2911.     /* undefined op size -> take over from ref elem */
  2912.     pElement->OpSize = OpSize;
  2913.     pElement->BitPos = BitPos;
  2914.     pElement->ExpandFnc = ExpandH16Bit;
  2915.     AddStructElem(pInnermostNamedStruct->StructRec, pElement);
  2916.   }
  2917.   else
  2918.   {
  2919.     if (!ChkOpSize(eSymbolSize16Bit, 7))
  2920.       return;
  2921.  
  2922.     if (DecodeBitArg(&BitSpec, 1, ArgCnt, OpSize))
  2923.     {
  2924.       *ListLine = '=';
  2925.       DissectBit_H16(ListLine + 1, STRINGSIZE - 3, BitSpec);
  2926.       PushLocHandle(-1);
  2927.       EnterIntSymbol(&LabPart, BitSpec, SegBData, False);
  2928.       PopLocHandle();
  2929.       /* TODO: MakeUseList? */
  2930.     }
  2931.   }
  2932. }
  2933.  
  2934. /*---------------------------------------------------------------------------*/
  2935.  
  2936. /*!------------------------------------------------------------------------
  2937.  * \fn     AddCondition(const char *pName, Word Code)
  2938.  * \brief  register condition to instruction hash table
  2939.  * \param  pName name of condition
  2940.  * \param  Code binary coding of condition
  2941.  * ------------------------------------------------------------------------ */
  2942.  
  2943. static void AddCondition(const char *pName, Word Code)
  2944. {
  2945.   char Name[20];
  2946.  
  2947.   as_snprintf(Name, sizeof(Name), "B%s", pName);
  2948.   AddInstTable(InstTable, Name, Code, DecodeBranchGen);
  2949.   as_snprintf(Name, sizeof(Name), "SET/%s", pName);
  2950.   AddInstTable(InstTable, Name, Code, DecodeSET);
  2951.   as_snprintf(Name, sizeof(Name), "TRAP/%s", pName);
  2952.   AddInstTable(InstTable, Name, Code, DecodeTRAP);
  2953.   as_snprintf(Name, sizeof(Name), "SCB/%s", pName);
  2954.   AddInstTable(InstTable, Name, Code, DecodeSCB);
  2955.   as_snprintf(Name, sizeof(Name), "SCMP/%s/F", pName);
  2956.   AddInstTable(InstTable, Name, 0x00a0 | (Code << 8), DecodeString);
  2957.   as_snprintf(Name, sizeof(Name), "SCMP/%s/B", pName);
  2958.   AddInstTable(InstTable, Name, 0x00d0 | (Code << 8), DecodeString);
  2959.   as_snprintf(Name, sizeof(Name), "SSCH/%s/F", pName);
  2960.   AddInstTable(InstTable, Name, 0x0080 | (Code << 8), DecodeString);
  2961.   as_snprintf(Name, sizeof(Name), "SSCH/%s/B", pName);
  2962.   /* per-instr. description gives 000 for both SSCH variants, taken from Figure 16-9: */
  2963.   AddInstTable(InstTable, Name, 0x00c0 | (Code << 8), DecodeString);
  2964. }
  2965.  
  2966. /*!------------------------------------------------------------------------
  2967.  * \fn     InitFields(void)
  2968.  * \brief  build up instruction hash table
  2969.  * ------------------------------------------------------------------------ */
  2970.  
  2971. static void InitFields(void)
  2972. {
  2973.   InstTable = CreateInstTable(307);
  2974.   SetDynamicInstTable(InstTable);
  2975.  
  2976.   AddInstTable(InstTable, "MOV", 0x0c, DecodeMOV_ADD_SUB_CMP);
  2977.   AddInstTable(InstTable, "ADD", 0x00, DecodeMOV_ADD_SUB_CMP);
  2978.   AddInstTable(InstTable, "SUB", 0x04, DecodeMOV_ADD_SUB_CMP);
  2979.   AddInstTable(InstTable, "CMP", 0x08, DecodeMOV_ADD_SUB_CMP);
  2980.  
  2981.   AddInstTable(InstTable, "MOVS", 0x4c, DecodeSignExt);
  2982.   AddInstTable(InstTable, "ADDS", 0x40, DecodeSignExt);
  2983.   AddInstTable(InstTable, "SUBS", 0x44, DecodeSignExt);
  2984.   AddInstTable(InstTable, "CMPS", 0x48, DecodeSignExt);
  2985.  
  2986.   AddInstTable(InstTable, "ADDX", 0x50, DecodeTwo);
  2987.   AddInstTable(InstTable, "SUBX", 0x54, DecodeTwo);
  2988.   AddInstTable(InstTable, "AND" , 0x80, DecodeTwo);
  2989.   AddInstTable(InstTable, "OR"  , 0x88, DecodeTwo);
  2990.   AddInstTable(InstTable, "XOR" , 0x84, DecodeTwo);
  2991.   AddInstTable(InstTable, "DADD", 0x83, DecodeTwo);
  2992.   AddInstTable(InstTable, "DSUB", 0x87, DecodeTwo);
  2993.  
  2994.   AddInstTable(InstTable, "MULXS" , 0x00, DecodeMUL_DIV);
  2995.   AddInstTable(InstTable, "MULXU" , 0x40, DecodeMUL_DIV);
  2996.   AddInstTable(InstTable, "DIVXS" , 0x01, DecodeMUL_DIV);
  2997.   AddInstTable(InstTable, "DIVXU" , 0x41, DecodeMUL_DIV);
  2998.  
  2999.   AddInstTable(InstTable, "NEG"  , 0x8c, DecodeOne);
  3000.   AddInstTable(InstTable, "NEGX" , 0x9c, DecodeOne);
  3001.   AddInstTable(InstTable, "NOT"  , 0x90, DecodeOne);
  3002.   AddInstTable(InstTable, "TST"  , 0x58, DecodeOne);
  3003.   AddInstTable(InstTable, "CLR"  , 0x14, DecodeOne);
  3004.   AddInstTable(InstTable, "DNEG" , 0xaf, DecodeOne);
  3005.   AddInstTable(InstTable, "TAS"  , 0xee, DecodeOne);
  3006.   AddInstTable(InstTable, "MOVF" , 0x5c, DecodeOne);
  3007.  
  3008.   AddInstTable(InstTable, "EXTS" , 0xbc, DecodeEXT);
  3009.   AddInstTable(InstTable, "EXTU" , 0xac, DecodeEXT);
  3010.  
  3011.   AddInstTable(InstTable, "ANDC" , 0xf8, DecodeCInstr);
  3012.   AddInstTable(InstTable, "ORC"  , 0xf9, DecodeCInstr);
  3013.   AddInstTable(InstTable, "XORC" , 0xfa, DecodeCInstr);
  3014.   AddInstTable(InstTable, "LDC"  , 0xfb, DecodeCInstr);
  3015.   AddInstTable(InstTable, "STC"  , 0xfc, DecodeCInstr);
  3016.  
  3017.   AddInstTable(InstTable, "BRA"  , 0x98, DecodeBranch);
  3018.   AddInstTable(InstTable, "BSR"  , 0xa8, DecodeBranch);
  3019.   AddCondition("CC" , 0x04);
  3020.   AddCondition("HS" , 0x04);
  3021.   AddCondition("CS" , 0x05);
  3022.   AddCondition("LO" , 0x05);
  3023.   AddCondition("NE" , 0x06);
  3024.   AddCondition("EQ" , 0x07);
  3025.   AddCondition("GE" , 0x0c);
  3026.   AddCondition("LT" , 0x0d);
  3027.   AddCondition("GT" , 0x0e);
  3028.   AddCondition("LE" , 0x0f);
  3029.   AddCondition("HI" , 0x02);
  3030.   AddCondition("LS" , 0x03);
  3031.   AddCondition("PL" , 0x0a);
  3032.   AddCondition("MI" , 0x0b);
  3033.   AddCondition("VC" , 0x08);
  3034.   AddCondition("VS" , 0x09);
  3035.   AddCondition("T"  , 0x00);
  3036.   AddCondition("F"  , 0x01);
  3037.  
  3038.   AddInstTable(InstTable, "RTS"  , 0x00bb, DecodeFixed);
  3039.   AddInstTable(InstTable, "RESET", 0x80f0, DecodeFixed);
  3040.   AddInstTable(InstTable, "RTE"  , 0x80f1, DecodeFixed);
  3041.   AddInstTable(InstTable, "RTR"  , 0x00f4, DecodeFixed);
  3042.   AddInstTable(InstTable, "SLEEP", 0x80f5, DecodeFixed);
  3043.   AddInstTable(InstTable, "NOP"  , 0x00ff, DecodeFixed);
  3044.   AddInstTable(InstTable, "DCBN" , 0x00fe, DecodeFixed);
  3045.   AddInstTable(InstTable, "ICBN" , 0x00fd, DecodeFixed);
  3046.  
  3047.   AddInstTable(InstTable, "SHAR"  , 0 << 5, DecodeShift);
  3048.   AddInstTable(InstTable, "SHLR"  , 1 << 5, DecodeShift);
  3049.   AddInstTable(InstTable, "ROTR"  , 2 << 5, DecodeShift);
  3050.   AddInstTable(InstTable, "ROTXR" , 3 << 5, DecodeShift);
  3051.   AddInstTable(InstTable, "SHAL"  , 4 << 5, DecodeShift);
  3052.   AddInstTable(InstTable, "SHLL"  , 5 << 5, DecodeShift);
  3053.   AddInstTable(InstTable, "ROTL"  , 6 << 5, DecodeShift);
  3054.   AddInstTable(InstTable, "ROTXL" , 7 << 5, DecodeShift);
  3055.  
  3056.   AddInstTable(InstTable, "JMP" , 0x9b, DecodeJMP_JSR);
  3057.   AddInstTable(InstTable, "JSR" , 0xab, DecodeJMP_JSR);
  3058.   AddInstTable(InstTable, "SWAP", 0xea, DecodeSWAP);
  3059.   AddInstTable(InstTable, "XCH" , 0xb3, DecodeXCH);
  3060.  
  3061.   AddInstTable(InstTable, "LINK", 0xd0, DecodeLINK);
  3062.   AddInstTable(InstTable, "UNLK", 0xd3, DecodeUNLK);
  3063.   AddInstTable(InstTable, "TRAPA",0xf2, DecodeTRAPA);
  3064.   AddInstTable(InstTable, "RTD" , 0xb8, DecodeRTD);
  3065.  
  3066.   AddInstTable(InstTable, "LDM" , 0x74, DecodeLDM_STM);
  3067.   AddInstTable(InstTable, "STM" , 0x70, DecodeLDM_STM);
  3068.   AddInstTable(InstTable, "CGBN", 0xe4, DecodeCGBN);
  3069.   AddInstTable(InstTable, "PGBN", 0xe8, DecodePGBN);
  3070.  
  3071.   AddInstTable(InstTable, "MOVFP",0xe2, DecodeMOVFP);
  3072.   AddInstTable(InstTable, "MOVFPE",0x7c, DecodeMOVFPE);
  3073.   AddInstTable(InstTable, "MOVTP",0xe0, DecodeMOVTP);
  3074.   AddInstTable(InstTable, "MOVTPE",0x78, DecodeMOVTPE);
  3075.   AddInstTable(InstTable, "MOVA", 0xbf, DecodeMOVA);
  3076.  
  3077.   AddInstTable(InstTable, "SMOV/F", 0x0020, DecodeString);
  3078.   AddInstTable(InstTable, "SMOV/B", 0x0050, DecodeString);
  3079.   AddInstTable(InstTable, "SSTR/F", 0x0000, DecodeString);
  3080.   AddInstTable(InstTable, "SSTR/B", 0x0040, DecodeString);
  3081.  
  3082.   AddInstTable(InstTable, "BFEXT", 0xd4, DecodeBField);
  3083.   AddInstTable(InstTable, "BFINS", 0xd5, DecodeBField);
  3084.   AddInstTable(InstTable, "BFSCH", 0xd6, DecodeBField);
  3085.   AddInstTable(InstTable, "BFMOV", 0xd7, DecodeBFMOV);
  3086.  
  3087.   AddInstTable(InstTable, "BCLR", 0x40, DecodeBit);
  3088.   AddInstTable(InstTable, "BNOT", 0x20, DecodeBit);
  3089.   AddInstTable(InstTable, "BSET", 0x00, DecodeBit);
  3090.   AddInstTable(InstTable, "BTST", 0x60, DecodeBit);
  3091.  
  3092.   AddInstTable(InstTable, "BIT", 0, DecodeBIT);
  3093.   AddInstTable(InstTable, "REG", 0, CodeREG);
  3094. }
  3095.  
  3096. /*!------------------------------------------------------------------------
  3097.  * \fn     DeinitFields(void)
  3098.  * \brief  tear down instruction hash table
  3099.  * ------------------------------------------------------------------------ */
  3100.  
  3101. static void DeinitFields(void)
  3102. {
  3103.   DestroyInstTable(InstTable);
  3104. }
  3105.  
  3106. /*---------------------------------------------------------------------------*/
  3107.  
  3108. /*!------------------------------------------------------------------------
  3109.  * \fn     MakeCode_H16(void)
  3110.  * \brief  general entry point to parse machine instructions
  3111.  * ------------------------------------------------------------------------ */
  3112.  
  3113. static Boolean DecodeAttrPart_H16(void)
  3114. {
  3115.   tStrComp SizePart;
  3116.   char *p;
  3117.   static char EmptyStr[] = "";
  3118.  
  3119.   /* split off format and operand size */
  3120.  
  3121.   switch (AttrSplit)
  3122.   {
  3123.     case '.':
  3124.       p = strchr(AttrPart.str.p_str, ':');
  3125.       if (p)
  3126.         StrCompSplitRef(&SizePart, &FormatPart, &AttrPart, p);
  3127.       else
  3128.       {
  3129.         StrCompRefRight(&SizePart, &AttrPart, 0);
  3130.         StrCompMkTemp(&FormatPart, EmptyStr, 0);
  3131.       }
  3132.       break;
  3133.     case ':':
  3134.       p = strchr(AttrPart.str.p_str, '.');
  3135.       if (p)
  3136.         StrCompSplitRef(&FormatPart, &SizePart, &AttrPart, p);
  3137.       else
  3138.       {
  3139.         StrCompRefRight(&FormatPart, &AttrPart, 0);
  3140.         StrCompMkTemp(&SizePart, EmptyStr, 0);
  3141.       }
  3142.       break;
  3143.     default:
  3144.       StrCompMkTemp(&FormatPart, EmptyStr, 0);
  3145.       StrCompMkTemp(&SizePart, EmptyStr, 0);
  3146.       break;
  3147.   }
  3148.  
  3149.   /* process operand size part of attribute */
  3150.  
  3151.   if (*SizePart.str.p_str)
  3152.   {
  3153.     if (!DecodeMoto16AttrSizeStr(&SizePart, &AttrPartOpSize[0], False))
  3154.       return False;
  3155.   }
  3156.   return True;
  3157. }
  3158.  
  3159. static void MakeCode_H16(void)
  3160. {
  3161.   CodeLen = 0; DontPrint = False;
  3162.  
  3163.   /* zu ignorierendes */
  3164.  
  3165.   if (Memo("")) return;
  3166.  
  3167.   OpSize = AttrPartOpSize[0];
  3168.   if (DecodeMoto16Pseudo(OpSize, True))
  3169.     return;
  3170.  
  3171.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  3172.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  3173. }
  3174.  
  3175. /*!------------------------------------------------------------------------
  3176.  * \fn     IsDef_H16(void)
  3177.  * \brief  instruction that uses up label field?
  3178.  * \return true if label field shall not be stored as label
  3179.  * ------------------------------------------------------------------------ */
  3180.  
  3181. static Boolean IsDef_H16(void)
  3182. {
  3183.   return Memo("BIT") || Memo("REG");
  3184. }
  3185.  
  3186. /*!------------------------------------------------------------------------
  3187.  * \fn     InternSymbol_H16(char *pArg, TempResult *pResult)
  3188.  * \brief  handle built-in symbols on H16
  3189.  * \param  pArg source argument
  3190.  * \param  pResult result buffer
  3191.  * ------------------------------------------------------------------------ */
  3192.  
  3193. static void InternSymbol_H16(char *pArg, TempResult *pResult)
  3194. {
  3195.   Byte Reg, Prefix;
  3196.  
  3197.   if (DecodeRegCore(pArg, &Reg, &Prefix))
  3198.   {
  3199.     pResult->Typ = TempReg;
  3200.     pResult->DataSize = eSymbolSize32Bit;
  3201.     pResult->Contents.RegDescr.Reg = ((Word)Prefix) << 8 | Reg;
  3202.     pResult->Contents.RegDescr.Dissect = DissectReg_H16;
  3203.     pResult->Contents.RegDescr.compare = compare_reg_h16;
  3204.   }
  3205. }
  3206.  
  3207. /*!------------------------------------------------------------------------
  3208.  * \fn     SwitchTo_H16(void)
  3209.  * \brief  things to do when switching to H16 as target
  3210.  * ------------------------------------------------------------------------ */
  3211.  
  3212. static void SwitchTo_H16(void)
  3213. {
  3214.   const TFamilyDescr *pDescr = FindFamilyByName("H16");
  3215.  
  3216.   TurnWords = False;
  3217.   SetIntConstMode(eIntConstModeMoto);
  3218.  
  3219.   PCSymbol = "*";
  3220.   HeaderID = pDescr->Id;
  3221.   NOPCode = 0xff;
  3222.   DivideChars = ",";
  3223.   HasAttrs = True;
  3224.   AttrChars = ".:";
  3225.  
  3226.   ValidSegs = (1 << SegCode);
  3227.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  3228.   SegLimits[SegCode] = 0xffffff;
  3229.  
  3230.   DecodeAttrPart = DecodeAttrPart_H16;
  3231.   MakeCode = MakeCode_H16;
  3232.   IsDef = IsDef_H16;
  3233.   SwitchFrom = DeinitFields;
  3234.   DissectBit = DissectBit_H16;
  3235.   DissectReg = DissectReg_H16;
  3236.   InternSymbol = InternSymbol_H16;
  3237.   InitFields();
  3238.  
  3239.   onoff_supmode_add();
  3240.  
  3241.   /* H16 code is byte-oriented, so no padding by default */
  3242.  
  3243.   AddMoto16PseudoONOFF(False);
  3244. }
  3245.  
  3246. /*!------------------------------------------------------------------------
  3247.  * \fn     codeh16_init(void)
  3248.  * \brief  register H16 to upper layers as target
  3249.  * ------------------------------------------------------------------------ */
  3250.  
  3251. void codeh16_init(void)
  3252. {
  3253.   CPU641016 = AddCPU("HD641016", SwitchTo_H16);
  3254. }
  3255.