Subversion Repositories pentevo

Rev

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

  1. /* code86.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator 8086/V-Serie                                                */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13.  
  14. #include "bpemu.h"
  15. #include "strutil.h"
  16. #include "errmsg.h"
  17. #include "asmdef.h"
  18. #include "asmsub.h"
  19. #include "asmpars.h"
  20. #include "asmallg.h"
  21. #include "onoff_common.h"
  22. #include "codepseudo.h"
  23. #include "intpseudo.h"
  24. #include "asmitree.h"
  25. #include "asmcode.h"
  26. #include "symbolsize.h"
  27. #include "codevars.h"
  28. #include "nlmessages.h"
  29. #include "as.rsc"
  30. #include "code86.h"
  31.  
  32. /*---------------------------------------------------------------------------*/
  33.  
  34. typedef struct
  35. {
  36.   const char *Name;
  37.   Byte core_mask;
  38.   Word Code;
  39. } FixedOrder;
  40.  
  41. typedef struct
  42. {
  43.   const char *Name;
  44.   Byte core_mask;
  45.   Word Code;
  46.   Boolean no_seg_check;
  47. } ModRegOrder;
  48.  
  49. typedef struct
  50. {
  51.   CPUVar MinCPU;
  52.   Word Code;
  53.   Byte Add;
  54. } AddOrder;
  55.  
  56. #define NO_FWAIT_FLAG 0x2000
  57.  
  58. #define SegRegCnt 6
  59. static const char SegRegNames[SegRegCnt][4] =
  60. {
  61.   "ES", "CS", "SS", "DS",
  62.   "DS3", "DS2" /* V55 specific */
  63. };
  64. static const Byte SegRegPrefixes[SegRegCnt] =
  65. {
  66.   0x26, 0x2e, 0x36, 0x3e,
  67.   0xd6, 0x63
  68. };
  69.  
  70. static char ArgSTStr[] = "ST";
  71. static const tStrComp ArgST = { { 0, 0 }, { 0, ArgSTStr, 0 } };
  72.  
  73. typedef enum
  74. {
  75.   TypeNone = -1,
  76.   TypeReg8 = 0,
  77.   TypeReg16 = 1,
  78.   TypeRegSeg = 2,
  79.   TypeMem = 3,
  80.   TypeImm = 4,
  81.   TypeFReg = 5
  82. } tAdrType;
  83.  
  84. #define MTypeReg8 (1 << TypeReg8)
  85. #define MTypeReg16 (1 << TypeReg16)
  86. #define MTypeRegSeg (1 << TypeRegSeg)
  87. #define MTypeMem (1 << TypeMem)
  88. #define MTypeImm (1 << TypeImm)
  89. #define MTypeFReg (1 << TypeFReg)
  90.  
  91. static tAdrType AdrType;
  92. static Byte AdrMode;
  93. static Byte AdrVals[6];
  94. static tSymbolSize OpSize;
  95. static Boolean UnknownFlag;
  96. static unsigned ImmAddrSpaceMask;
  97.  
  98. static Boolean NoSegCheck;
  99.  
  100. static Byte Prefixes[6];
  101. static Byte PrefixLen;
  102.  
  103. static Byte SegAssumes[SegRegCnt];
  104.  
  105. enum
  106. {
  107.   e_core_86    = 1 << 0, /* 8086/8088 */
  108.   e_core_186   = 1 << 1, /* 80186/80188 */
  109.   e_core_v30   = 1 << 2, /* V20/30/40/50 */
  110.   e_core_v33   = 1 << 3, /* V33/V53 */
  111.   e_core_v35   = 1 << 4, /* V25/V35 */
  112.   e_core_v55   = 1 << 5, /* V55 */
  113.   e_core_v55pi = 1 << 6, /* V55PI */
  114.   e_core_v55sc = 1 << 7, /* V55SC */
  115.  
  116.   e_core_all_v55 = e_core_v55 | e_core_v55pi | e_core_v55sc,
  117.   e_core_all_v35 = e_core_v35 | e_core_all_v55,
  118.   e_core_all_v = e_core_v30 | e_core_v33 | e_core_all_v35,
  119.   e_core_all_186 = e_core_all_v | e_core_186,
  120.   e_core_all = e_core_all_186 | e_core_86
  121. };
  122.  
  123. typedef struct
  124. {
  125.   const char name[6];
  126.   Byte core;
  127. } cpu_props_t;
  128.  
  129. static const cpu_props_t *p_curr_cpu_props;
  130.  
  131. static FixedOrder *FixedOrders, *StringOrders, *ReptOrders, *ShiftOrders,
  132.                   *RelOrders, *BrkOrders, *Imm16Orders;
  133. static AddOrder *Reg16Orders;
  134. static ModRegOrder *ModRegOrders;
  135. static unsigned StringOrderCnt;
  136.  
  137. /*------------------------------------------------------------------------------------*/
  138.  
  139. /*!------------------------------------------------------------------------
  140.  * \fn     PutCode(Word Code)
  141.  * \brief  append 1- or 2-byte machine code to instruction stream
  142.  * \param  Code machine code to append
  143.  * ------------------------------------------------------------------------ */
  144.  
  145. static void PutCode(Word Code)
  146. {
  147.   if (Hi(Code) != 0)
  148.     BAsmCode[CodeLen++] = Hi(Code);
  149.   BAsmCode[CodeLen++] = Lo(Code);
  150. }
  151.  
  152. /*!------------------------------------------------------------------------
  153.  * \fn     copy_adr_vals(int Dest)
  154.  * \brief  copy addressing mode extension bytes
  155.  * \param  Dest where to copy relative to current instruction end
  156.  * ------------------------------------------------------------------------ */
  157.  
  158. static void copy_adr_vals(int Dest)
  159. {
  160.   memcpy(BAsmCode + CodeLen + Dest, AdrVals, AdrCnt);
  161. }
  162.  
  163. /*!------------------------------------------------------------------------
  164.  * \fn     append_adr_vals(void)
  165.  * \brief  append addressing mode extension bytes
  166.  * ------------------------------------------------------------------------ */
  167.  
  168. static void append_adr_vals(void)
  169. {
  170.   copy_adr_vals(0);
  171.   CodeLen += AdrCnt;
  172. }
  173.  
  174. /*!------------------------------------------------------------------------
  175.  * \fn     Sgn(Byte inp)
  176.  * \brief  get value of upper byte after sign extension
  177.  * \param  inp value that will be extended
  178.  * \return 0 or 0xff
  179.  * ------------------------------------------------------------------------ */
  180.  
  181. static Byte Sgn(Byte inp)
  182. {
  183.   return (inp > 127) ? 0xff : 0;
  184. }
  185.  
  186. /*!------------------------------------------------------------------------
  187.  * \fn     AddPrefix(Byte Prefix)
  188.  * \brief  store new prefix
  189.  * \param  Prefix prefix byte to store
  190.  * ------------------------------------------------------------------------ */
  191.  
  192. static void AddPrefix(Byte Prefix)
  193. {
  194.   Prefixes[PrefixLen++] = Prefix;
  195. }
  196.  
  197. /*!------------------------------------------------------------------------
  198.  * \fn     AddPrefixes(void)
  199.  * \brief  prepend stored prefixes
  200.  * ------------------------------------------------------------------------ */
  201.  
  202. static void AddPrefixes(void)
  203. {
  204.   if ((CodeLen != 0) && (PrefixLen != 0))
  205.   {
  206.     memmove(BAsmCode + PrefixLen, BAsmCode, CodeLen);
  207.     memcpy(BAsmCode, Prefixes, PrefixLen);
  208.     CodeLen += PrefixLen;
  209.   }
  210. }
  211.  
  212. /*!------------------------------------------------------------------------
  213.  * \fn     AbleToSign(Word Arg)
  214.  * \brief  can argument be written as 8-bit vlaue that will be sign extended?
  215.  * \param  Arg value to check
  216.  * \return True if yes
  217.  * ------------------------------------------------------------------------ */
  218.  
  219. static Boolean AbleToSign(Word Arg)
  220. {
  221.   return ((Arg <= 0x7f) || (Arg >= 0xff80));
  222. }
  223.  
  224. /*!------------------------------------------------------------------------
  225.  * \fn     MinOneIs0(void)
  226.  * \brief  optionally set operand size to 8 bits if not yet set
  227.  * \return True if operand size was set
  228.  * ------------------------------------------------------------------------ */
  229.  
  230. static Boolean MinOneIs0(void)
  231. {
  232.   if (UnknownFlag && (OpSize == eSymbolSizeUnknown))
  233.   {
  234.     OpSize = eSymbolSize8Bit;
  235.     return True;
  236.   }
  237.   else
  238.     return False;
  239. }
  240.  
  241. /*!------------------------------------------------------------------------
  242.  * \fn     ChkOpSize(tSymbolSize NewSize)
  243.  * \brief  check, match and optionally set operand size
  244.  * \param  NewSize operand size of operand
  245.  * ------------------------------------------------------------------------ */
  246.  
  247. static void ChkOpSize(tSymbolSize NewSize)
  248. {
  249.   if (OpSize == eSymbolSizeUnknown)
  250.     OpSize = NewSize;
  251.   else if (OpSize != NewSize)
  252.   {
  253.     AdrType = TypeNone;
  254.     WrError(ErrNum_ConfOpSizes);
  255.   }
  256. }
  257.  
  258. /*!------------------------------------------------------------------------
  259.  * \fn     ChkSpaces(ShortInt SegBuffer, Byte MomSegment, const tStrComp *p_arg)
  260.  * \brief  check for matching address space of memory argument
  261.  * \param  SegBuffer index into segment assume table
  262.  * \param  MomSegment current segment being used
  263.  * \param  p_arg source argument for error reporting
  264.  * ------------------------------------------------------------------------ */
  265.  
  266. static void ChkSingleSpace(Byte Seg, Byte EffSeg, Byte MomSegment, const tStrComp *p_arg)
  267. {
  268.   Byte z;
  269.  
  270.   /* liegt Operand im zu pruefenden Segment? nein-->vergessen */
  271.  
  272.   if (!(MomSegment & (1 << Seg)))
  273.     return;
  274.  
  275.   /* zeigt bish. benutztes Segmentregister auf dieses Segment? ja-->ok */
  276.  
  277.   if (EffSeg == Seg)
  278.     return;
  279.  
  280.   /* falls schon ein Override gesetzt wurde, nur warnen */
  281.  
  282.   if (PrefixLen > 0)
  283.     WrStrErrorPos(ErrNum_WrongSegment, p_arg);
  284.  
  285.   /* ansonsten ein passendes Segment suchen und warnen, falls keines da */
  286.  
  287.   else
  288.   {
  289.     z = 0;
  290.     while ((z < SegRegCnt) && (SegAssumes[z] != Seg))
  291.       z++;
  292.     if (z > SegRegCnt)
  293.       WrXErrorPos(ErrNum_InAccSegment, SegRegNames[Seg], &p_arg->Pos);
  294.     else
  295.       AddPrefix(SegRegPrefixes[z]);
  296.   }
  297. }
  298.  
  299. static void ChkSpaces(ShortInt SegBuffer, Byte MomSegment, const tStrComp *p_arg)
  300. {
  301.   Byte EffSeg;
  302.  
  303.   if (NoSegCheck)
  304.     return;
  305.  
  306.   /* in welches Segment geht das benutzte Segmentregister ? */
  307.  
  308.   EffSeg = SegAssumes[SegBuffer];
  309.  
  310.   /* Zieloperand in Code-/Datensegment ? */
  311.  
  312.   ChkSingleSpace(SegCode, EffSeg, MomSegment, p_arg);
  313.   ChkSingleSpace(SegXData, EffSeg, MomSegment, p_arg);
  314.   ChkSingleSpace(SegData, EffSeg, MomSegment, p_arg);
  315. }
  316.  
  317. /*!------------------------------------------------------------------------
  318.  * \fn     decode_seg_reg(const char *p_arg, Byte *p_ret)
  319.  * \brief  dcheck whether argument is a segment register's name
  320.  * \param  p_arg source argument
  321.  * \param  p_ret returns register # if so
  322.  * \return True if argument is segment register
  323.  * ------------------------------------------------------------------------ */
  324.  
  325. static Boolean decode_seg_reg(const char *p_arg, Byte *p_ret)
  326. {
  327.   int reg_z, reg_cnt = SegRegCnt;
  328.  
  329.   /* DS2/DS3 only allowed on V55.  These names should be allowed as
  330.      ordinary symbol names on other targets: */
  331.  
  332.   if (!(p_curr_cpu_props->core & e_core_all_v55))
  333.     reg_cnt -= 2;
  334.   for (reg_z = 0; reg_z < reg_cnt; reg_z++)
  335.     if (!as_strcasecmp(p_arg, SegRegNames[reg_z]))
  336.     {
  337.       *p_ret = reg_z;
  338.       return True;
  339.     }
  340.   return False;
  341. }
  342.  
  343. /*!------------------------------------------------------------------------
  344.  * \fn     DecodeAdr(const tStrComp *pArg, unsigned type_mask)
  345.  * \brief  parse addressing mode argument
  346.  * \param  pArg source argument
  347.  * \param  type_mask bit mask of allowed addressing modes
  348.  * \return resulting addressing mode
  349.  * ------------------------------------------------------------------------ */
  350.  
  351. static tAdrType DecodeAdr(const tStrComp *pArg, unsigned type_mask)
  352. {
  353.   static const int RegCnt = 8;
  354.   static const char Reg16Names[8][3] =
  355.   {
  356.     "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"
  357.   };
  358.   static const char Reg8Names[8][3] =
  359.   {
  360.     "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
  361.   };
  362.   static const Byte RMCodes[8] =
  363.   {
  364.     11, 12, 21, 22, 1, 2 , 20, 10
  365.   };
  366.  
  367.   int RegZ, z;
  368.   Boolean IsImm;
  369.   ShortInt IndexBuf, BaseBuf;
  370.   Byte SumBuf;
  371.   LongInt DispAcc, DispSum;
  372.   char *pIndirStart, *pIndirEnd, *pSep;
  373.   ShortInt SegBuffer;
  374.   Byte MomSegment;
  375.   tSymbolSize FoundSize;
  376.   tStrComp Arg;
  377.   int ArgLen = strlen(pArg->str.p_str);
  378.  
  379.   AdrType = TypeNone; AdrCnt = 0;
  380.   SegBuffer = -1; MomSegment = 0;
  381.  
  382.   for (RegZ = 0; RegZ < RegCnt; RegZ++)
  383.   {
  384.     if (!as_strcasecmp(pArg->str.p_str, Reg16Names[RegZ]))
  385.     {
  386.       AdrType = TypeReg16; AdrMode = RegZ;
  387.       ChkOpSize(eSymbolSize16Bit);
  388.       goto chk_type;
  389.     }
  390.     if (!as_strcasecmp(pArg->str.p_str, Reg8Names[RegZ]))
  391.     {
  392.       AdrType = TypeReg8; AdrMode = RegZ;
  393.       ChkOpSize(eSymbolSize8Bit);
  394.       goto chk_type;
  395.     }
  396.   }
  397.  
  398.   if (decode_seg_reg(pArg->str.p_str, &AdrMode))
  399.   {
  400.     AdrType = TypeRegSeg;
  401.     ChkOpSize(eSymbolSize16Bit);
  402.     goto chk_type;
  403.   }
  404.  
  405.   if (FPUAvail)
  406.   {
  407.     if (!as_strcasecmp(pArg->str.p_str, "ST"))
  408.     {
  409.       AdrType = TypeFReg; AdrMode = 0;
  410.       ChkOpSize(eSymbolSize80Bit);
  411.       goto chk_type;
  412.     }
  413.  
  414.     if ((ArgLen > 4) && (!as_strncasecmp(pArg->str.p_str, "ST(", 3)) && (pArg->str.p_str[ArgLen - 1] == ')'))
  415.     {
  416.       tStrComp Num;
  417.       Boolean OK;
  418.  
  419.       StrCompRefRight(&Num, pArg, 3);
  420.       StrCompShorten(&Num, 1);
  421.       AdrMode = EvalStrIntExpression(&Num, UInt3, &OK);
  422.       if (OK)
  423.       {
  424.         AdrType = TypeFReg;
  425.         ChkOpSize(eSymbolSize80Bit);
  426.       }
  427.       goto chk_type;
  428.     }
  429.   }
  430.  
  431.   IsImm = True;
  432.   IndexBuf = 0; BaseBuf = 0;
  433.   DispAcc = 0; FoundSize = eSymbolSizeUnknown;
  434.   StrCompRefRight(&Arg, pArg, 0);
  435.   if (!as_strncasecmp(Arg.str.p_str, "WORD PTR", 8))
  436.   {
  437.     StrCompIncRefLeft(&Arg, 8);
  438.     FoundSize = eSymbolSize16Bit;
  439.     IsImm = False;
  440.     KillPrefBlanksStrCompRef(&Arg);
  441.   }
  442.   else if (!as_strncasecmp(Arg.str.p_str, "BYTE PTR", 8))
  443.   {
  444.     StrCompIncRefLeft(&Arg, 8);
  445.     FoundSize = eSymbolSize8Bit;
  446.     IsImm = False;
  447.     KillPrefBlanksStrCompRef(&Arg);
  448.   }
  449.   else if (!as_strncasecmp(Arg.str.p_str, "DWORD PTR", 9))
  450.   {
  451.     StrCompIncRefLeft(&Arg, 9);
  452.     FoundSize = eSymbolSize32Bit;
  453.     IsImm = False;
  454.     KillPrefBlanksStrCompRef(&Arg);
  455.   }
  456.   else if (!as_strncasecmp(Arg.str.p_str, "QWORD PTR", 9))
  457.   {
  458.     StrCompIncRefLeft(&Arg, 9);
  459.     FoundSize = eSymbolSize64Bit;
  460.     IsImm = False;
  461.     KillPrefBlanksStrCompRef(&Arg);
  462.   }
  463.   else if (!as_strncasecmp(Arg.str.p_str, "TBYTE PTR", 9))
  464.   {
  465.     StrCompIncRefLeft(&Arg, 9);
  466.     FoundSize = eSymbolSize80Bit;
  467.     IsImm = False;
  468.     KillPrefBlanksStrCompRef(&Arg);
  469.   }
  470.  
  471.   if ((strlen(Arg.str.p_str) > 2) && (Arg.str.p_str[2] == ':'))
  472.   {
  473.     tStrComp Remainder;
  474.     Byte seg_reg;
  475.  
  476.     StrCompSplitRef(&Arg, &Remainder, &Arg, Arg.str.p_str + 2);
  477.     if (decode_seg_reg(Arg.str.p_str, &seg_reg))
  478.     {
  479.       SegBuffer = seg_reg;
  480.       AddPrefix(SegRegPrefixes[SegBuffer]);
  481.     }
  482.     if (SegBuffer < 0)
  483.     {
  484.       WrStrErrorPos(ErrNum_InvReg, &Arg);
  485.       goto chk_type;
  486.     }
  487.     Arg = Remainder;
  488.   }
  489.  
  490.   do
  491.   {
  492.     pIndirStart = QuotPos(Arg.str.p_str, '[');
  493.  
  494.     /* no address expr or outer displacement: */
  495.  
  496.     if (!pIndirStart || (pIndirStart != Arg.str.p_str))
  497.     {
  498.       tStrComp Remainder;
  499.       tEvalResult EvalResult;
  500.  
  501.       if (pIndirStart)
  502.         StrCompSplitRef(&Arg, &Remainder, &Arg, pIndirStart);
  503.       DispAcc += EvalStrIntExpressionWithResult(&Arg, Int16, &EvalResult);
  504.       if (!EvalResult.OK)
  505.          goto chk_type;
  506.       UnknownFlag = UnknownFlag || mFirstPassUnknown(EvalResult.Flags);
  507.       MomSegment |= EvalResult.AddrSpaceMask;
  508.       if (FoundSize == eSymbolSizeUnknown)
  509.         FoundSize = EvalResult.DataSize;
  510.       if (pIndirStart)
  511.         Arg = Remainder;
  512.       else
  513.         break;
  514.     }
  515.     else
  516.       StrCompIncRefLeft(&Arg, 1);
  517.  
  518.     /* Arg now points right behind [ */
  519.  
  520.     if (pIndirStart)
  521.     {
  522.       tStrComp IndirArg, OutRemainder, IndirArgRemainder;
  523.       Boolean NegFlag, OldNegFlag;
  524.  
  525.       IsImm = False;
  526.  
  527.       pIndirEnd = RQuotPos(Arg.str.p_str, ']');
  528.       if (!pIndirEnd)
  529.       {
  530.         WrStrErrorPos(ErrNum_BrackErr, &Arg);
  531.         goto chk_type;
  532.       }
  533.  
  534.       StrCompSplitRef(&IndirArg, &OutRemainder, &Arg, pIndirEnd);
  535.       OldNegFlag = False;
  536.  
  537.       do
  538.       {
  539.         NegFlag = False;
  540.         KillPrefBlanksStrComp(&IndirArg);
  541.         pSep = indir_split_pos(IndirArg.str.p_str);
  542.         NegFlag = pSep && (*pSep == '-');
  543.  
  544.         if (pSep)
  545.           StrCompSplitRef(&IndirArg, &IndirArgRemainder, &IndirArg, pSep);
  546.         KillPostBlanksStrComp(&IndirArg);
  547.  
  548.         if (!as_strcasecmp(IndirArg.str.p_str, "BX"))
  549.         {
  550.           if ((OldNegFlag) || (BaseBuf != 0))
  551.             goto chk_type;
  552.           else
  553.             BaseBuf = 1;
  554.         }
  555.         else if (!as_strcasecmp(IndirArg.str.p_str, "BP"))
  556.         {
  557.           if ((OldNegFlag) || (BaseBuf != 0))
  558.             goto chk_type;
  559.           else
  560.             BaseBuf = 2;
  561.         }
  562.         else if (!as_strcasecmp(IndirArg.str.p_str, "SI"))
  563.         {
  564.           if ((OldNegFlag) || (IndexBuf != 0))
  565.             goto chk_type;
  566.           else
  567.             IndexBuf = 1;
  568.         }
  569.         else if (!as_strcasecmp(IndirArg.str.p_str, "DI"))
  570.         {
  571.           if ((OldNegFlag) || (IndexBuf !=0 ))
  572.             goto chk_type;
  573.           else
  574.             IndexBuf = 2;
  575.         }
  576.         else
  577.         {
  578.           tEvalResult EvalResult;
  579.  
  580.           DispSum = EvalStrIntExpressionWithResult(&IndirArg, Int16, &EvalResult);
  581.           if (!EvalResult.OK)
  582.             goto chk_type;
  583.           UnknownFlag = UnknownFlag || mFirstPassUnknown(EvalResult.Flags);
  584.           DispAcc = OldNegFlag ? DispAcc - DispSum : DispAcc + DispSum;
  585.           MomSegment |= EvalResult.AddrSpaceMask;
  586.           if (FoundSize == eSymbolSizeUnknown)
  587.             FoundSize = EvalResult.DataSize;
  588.         }
  589.         OldNegFlag = NegFlag;
  590.         if (pSep)
  591.           IndirArg = IndirArgRemainder;
  592.       }
  593.       while (pSep);
  594.       Arg = OutRemainder;
  595.     }
  596.   }
  597.   while (*Arg.str.p_str);
  598.  
  599.   SumBuf = BaseBuf * 10 + IndexBuf;
  600.  
  601.   /* welches Segment effektiv benutzt ? */
  602.  
  603.   if (SegBuffer == -1)
  604.     SegBuffer = (BaseBuf == 2) ? 2 : 3;
  605.  
  606.   /* nur Displacement */
  607.  
  608.   if (0 == SumBuf)
  609.   {
  610.     /* immediate */
  611.  
  612.     if (IsImm)
  613.     {
  614.       ImmAddrSpaceMask = MomSegment;
  615.       if ((UnknownFlag && (OpSize == eSymbolSize8Bit)) || (MinOneIs0()))
  616.         DispAcc &= 0xff;
  617.       switch (OpSize)
  618.       {
  619.         case eSymbolSizeUnknown:
  620.           WrStrErrorPos(ErrNum_UndefOpSizes, &Arg);
  621.           break;
  622.         case eSymbolSize8Bit:
  623.           if ((DispAcc <- 128) || (DispAcc > 255)) WrStrErrorPos(ErrNum_OverRange, &Arg);
  624.           else
  625.           {
  626.             AdrType = TypeImm;
  627.             AdrVals[0] = DispAcc & 0xff;
  628.             AdrCnt = 1;
  629.           }
  630.           break;
  631.         case eSymbolSize16Bit:
  632.           AdrType = TypeImm;
  633.           AdrVals[0] = Lo(DispAcc);
  634.           AdrVals[1] = Hi(DispAcc);
  635.           AdrCnt = 2;
  636.           break;
  637.         default:
  638.           WrStrErrorPos(ErrNum_InvOpSize, &Arg);
  639.           break;
  640.       }
  641.     }
  642.  
  643.     /* absolut */
  644.  
  645.     else
  646.     {
  647.       AdrType = TypeMem;
  648.       AdrMode = 0x06;
  649.       AdrVals[0] = Lo(DispAcc);
  650.       AdrVals[1] = Hi(DispAcc);
  651.       AdrCnt = 2;
  652.       if (FoundSize != -1)
  653.         ChkOpSize(FoundSize);
  654.       ChkSpaces(SegBuffer, MomSegment, &Arg);
  655.     }
  656.   }
  657.  
  658.   /* kombiniert */
  659.  
  660.   else
  661.   {
  662.     AdrType = TypeMem;
  663.     for (z = 0; z < 8; z++)
  664.       if (SumBuf == RMCodes[z])
  665.         AdrMode = z;
  666.     if (DispAcc == 0)
  667.     {
  668.       if (SumBuf == 20)
  669.       {
  670.         AdrMode += 0x40;
  671.         AdrVals[0] = 0;
  672.         AdrCnt = 1;
  673.       }
  674.     }
  675.     else if (AbleToSign(DispAcc))
  676.     {
  677.       AdrMode += 0x40;
  678.       AdrVals[0] = DispAcc & 0xff;
  679.       AdrCnt = 1;
  680.     }
  681.     else
  682.     {
  683.       AdrMode += 0x80;
  684.       AdrVals[0] = Lo(DispAcc);
  685.       AdrVals[1] = Hi(DispAcc);
  686.       AdrCnt = 2;
  687.     }
  688.     ChkSpaces(SegBuffer, MomSegment, &Arg);
  689.     if (FoundSize != -1)
  690.       ChkOpSize(FoundSize);
  691.   }
  692.  
  693. chk_type:
  694.   if ((AdrType != TypeNone) && !((type_mask >> AdrType) & 1))
  695.   {
  696.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  697.     AdrType = TypeNone;
  698.     AdrCnt = 0;
  699.   }
  700.   return AdrType;
  701. }
  702.  
  703. /*!------------------------------------------------------------------------
  704.  * \fn     AddFWait(Word *pCode)
  705.  * \brief  add FPU instruction entry code
  706.  * \param  pCode machine code of instruction
  707.  * ------------------------------------------------------------------------ */
  708.  
  709. static void AddFWait(Word *pCode)
  710. {
  711.   if (*pCode & NO_FWAIT_FLAG)
  712.     *pCode &= ~NO_FWAIT_FLAG;
  713.   else
  714.     AddPrefix(0x9b);
  715. }
  716.  
  717. /*!------------------------------------------------------------------------
  718.  * \fn     FPUEntry(Word *pCode)
  719.  * \brief  check for FPU availibility and add FPU instruction entry code
  720.  * \param  pCode machine code of instruction
  721.  * ------------------------------------------------------------------------ */
  722.  
  723. static Boolean FPUEntry(Word *pCode)
  724. {
  725.   if (!FPUAvail)
  726.   {
  727.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  728.     return FALSE;
  729.   }
  730.  
  731.   AddFWait(pCode);
  732.   return TRUE;
  733. }
  734.  
  735. /*!------------------------------------------------------------------------
  736.  * \fn     check_core_mask(Byte instr_core_mask)
  737.  * \brief  check whether current CPU supports core requirments
  738.  * \param  instr_core_mask mask of allowed core types
  739.  * \return True if OK
  740.  * ------------------------------------------------------------------------ */
  741.  
  742. static Boolean check_core_mask(Byte instr_core_mask)
  743. {
  744.   const char *p_cpu_name;
  745.  
  746.   if (p_curr_cpu_props->core & instr_core_mask)
  747.     return True;
  748.  
  749.   switch (instr_core_mask)
  750.   {
  751.     case e_core_all_v35:
  752.       p_cpu_name = "V25/V35";
  753.       goto write_min;
  754.     case e_core_all_v:
  755.       p_cpu_name = "V20/V30";
  756.       goto write_min;
  757.     case e_core_all_186:
  758.       p_cpu_name = "80186/80188";
  759.       goto write_min;
  760.     default:
  761.       WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
  762.       break;
  763.     write_min:
  764.     {
  765.       char str[100];
  766.  
  767.       as_snprintf(str, sizeof(str), getmessage(Num_ErrMsgMinCPUSupported), p_cpu_name);
  768.       WrXErrorPos(ErrNum_InstructionNotSupported, str, &OpPart.Pos);
  769.       break;
  770.     }
  771.   }
  772.   return False;
  773. }
  774.  
  775. /*---------------------------------------------------------------------------*/
  776.  
  777. /*!------------------------------------------------------------------------
  778.  * \fn     decode_mod_reg_core(Word code, Boolean no_seg_check, int start_index)
  779.  * \brief  decode/append mod/reg instruction
  780.  * \param  code instruction's machine code
  781.  * \param  no_seg_check
  782.  * \param  start_index position of first argument
  783.  * ------------------------------------------------------------------------ */
  784.  
  785. static void decode_mod_reg_core(Word code, Boolean no_seg_check, int start_index)
  786. {
  787.   switch (DecodeAdr(&ArgStr[start_index], MTypeReg16))
  788.   {
  789.     case TypeReg16:
  790.     {
  791.       Byte reg = (AdrMode << 3);
  792.       OpSize = no_seg_check ? eSymbolSizeUnknown : eSymbolSize32Bit;
  793.       switch (DecodeAdr(&ArgStr[start_index + 1], MTypeMem))
  794.       {
  795.         case TypeMem:
  796.           PutCode(code);
  797.           BAsmCode[CodeLen] = reg + AdrMode;
  798.           copy_adr_vals(1);
  799.           CodeLen += 1 + AdrCnt;
  800.           break;
  801.         default:
  802.           break;
  803.       }
  804.       break;
  805.     }
  806.     default:
  807.       break;
  808.   }
  809.   AddPrefixes();
  810. }
  811.  
  812. /*!------------------------------------------------------------------------
  813.  * \fn     append_rel(const tStrComp *p_arg)
  814.  * \brief  append relative displacement to instruction
  815.  * \param  p_arg source argument of branch target
  816.  * ------------------------------------------------------------------------ */
  817.  
  818. static void append_rel(const tStrComp *p_arg)
  819. {
  820.   tEvalResult eval_result;
  821.   Word adr_word = EvalStrIntExpressionWithResult(p_arg, Int16, &eval_result);
  822.  
  823.   if (eval_result.OK)
  824.   {
  825.     ChkSpace(SegCode, eval_result.AddrSpaceMask);
  826.     adr_word -= EProgCounter() + CodeLen + 1;
  827.     if ((adr_word >= 0x80) && (adr_word < 0xff80) && !mSymbolQuestionable(eval_result.Flags))
  828.     {
  829.       WrStrErrorPos(ErrNum_JmpDistTooBig, p_arg);
  830.       CodeLen = 0;
  831.     }
  832.     else
  833.       BAsmCode[CodeLen++] = Lo(adr_word);
  834.   }
  835.   else
  836.     CodeLen = 0;
  837. }
  838.  
  839. /*!------------------------------------------------------------------------
  840.  * \fn     DecodeMOV(Word Index)
  841.  * \brief  handle MOV instruction
  842.  * ------------------------------------------------------------------------ */
  843.  
  844. static void DecodeMOV(Word Index)
  845. {
  846.   Byte AdrByte;
  847.   UNUSED(Index);
  848.  
  849.   if (ChkArgCnt(2, 3))
  850.   {
  851.     switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeRegSeg))
  852.     {
  853.       case TypeReg8:
  854.       case TypeReg16:
  855.         if (!ChkArgCnt(2, 2))
  856.           return;
  857.         AdrByte = AdrMode;
  858.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeRegSeg | MTypeImm))
  859.         {
  860.           case TypeReg8:
  861.           case TypeReg16:
  862.             BAsmCode[CodeLen++] = 0x8a | OpSize;
  863.             BAsmCode[CodeLen++] = 0xc0 | (AdrByte << 3) | AdrMode;
  864.             break;
  865.           case TypeMem:
  866.             if ((AdrByte == 0) && (AdrMode == 6))
  867.             {
  868.               BAsmCode[CodeLen] = 0xa0 | OpSize;
  869.               copy_adr_vals(1);
  870.               CodeLen += 1 + AdrCnt;
  871.             }
  872.             else
  873.             {
  874.               BAsmCode[CodeLen++] = 0x8a | OpSize;
  875.               BAsmCode[CodeLen++] = AdrMode | (AdrByte << 3);
  876.               copy_adr_vals(0);
  877.               CodeLen += AdrCnt;
  878.             }
  879.             break;
  880.           case TypeRegSeg:
  881.             if (OpSize == eSymbolSize8Bit) WrError(ErrNum_ConfOpSizes);
  882.             else
  883.             {
  884.               if (AdrMode >= 4) /* V55 DS2/DS3 */
  885.                 AdrMode += 2;
  886.               BAsmCode[CodeLen++] = 0x8c;
  887.               BAsmCode[CodeLen++] = 0xc0 | (AdrMode << 3) | AdrByte;
  888.             }
  889.             break;
  890.           case TypeImm:
  891.             BAsmCode[CodeLen++] = 0xb0 | (OpSize << 3) | AdrByte;
  892.             copy_adr_vals(0);
  893.             CodeLen += AdrCnt;
  894.             break;
  895.           default:
  896.             break;
  897.         }
  898.         break;
  899.       case TypeMem:
  900.         if (!ChkArgCnt(2, 2))
  901.           return;
  902.          BAsmCode[CodeLen + 1] = AdrMode;
  903.          copy_adr_vals(2);
  904.          AdrByte = AdrCnt;
  905.          switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeRegSeg | MTypeImm))
  906.          {
  907.            case TypeReg8:
  908.            case TypeReg16:
  909.             if ((AdrMode == 0) && (BAsmCode[CodeLen + 1] == 6))
  910.             {
  911.               BAsmCode[CodeLen] = 0xa2 | OpSize;
  912.               memmove(BAsmCode + CodeLen + 1, BAsmCode + CodeLen + 2, AdrByte);
  913.               CodeLen += 1 + AdrByte;
  914.             }
  915.             else
  916.             {
  917.               BAsmCode[CodeLen] = 0x88 | OpSize;
  918.               BAsmCode[CodeLen + 1] |= AdrMode << 3;
  919.               CodeLen += 2 + AdrByte;
  920.             }
  921.             break;
  922.           case TypeRegSeg:
  923.             if (AdrMode >= 4) /* V55 DS2/DS3 */
  924.               AdrMode += 2;
  925.             BAsmCode[CodeLen] = 0x8c;
  926.             BAsmCode[CodeLen + 1] |= AdrMode << 3;
  927.             CodeLen += 2 + AdrByte;
  928.             break;
  929.           case TypeImm:
  930.             BAsmCode[CodeLen] = 0xc6 | OpSize;
  931.             copy_adr_vals(2 + AdrByte);
  932.             CodeLen += 2 + AdrByte + AdrCnt;
  933.             break;
  934.           default:
  935.             break;
  936.         }
  937.         break;
  938.       case TypeRegSeg:
  939.         if (3 == ArgCnt) /* Alias for LDS, LES... */
  940.         {
  941.           switch (AdrMode)
  942.           {
  943.             case 0: /* LES reg,ea <-> MOV ES,reg,ea */
  944.               decode_mod_reg_core(0x00c4, True, 2);
  945.               break;
  946.             case 3: /* LDS reg,ea <-> MOV DS,reg,ea */
  947.               decode_mod_reg_core(0x00c5, False, 2);
  948.               break;
  949.             case 4: /* LDS3 reg,ea <-> MOV DS3,reg,ea */
  950.               decode_mod_reg_core(0x0f36, False, 2);
  951.               break;
  952.             case 5: /* LDS2 reg,ea <-> MOV DS2,reg,ea */
  953.               decode_mod_reg_core(0x0f3e, False, 2);
  954.               break;
  955.             default:
  956.               WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  957.           }
  958.         }
  959.         else /* ordinary MOV <segreg>,r/m */
  960.         {
  961.           if (AdrMode >= 4) /* V55 DS2/DS3 */
  962.             AdrMode += 2;
  963.           BAsmCode[CodeLen + 1] = AdrMode << 3;
  964.           switch (DecodeAdr(&ArgStr[2], MTypeReg16 | MTypeMem))
  965.           {
  966.             case TypeReg16:
  967.               BAsmCode[CodeLen++] = 0x8e;
  968.               BAsmCode[CodeLen++] |= 0xc0 + AdrMode;
  969.               break;
  970.             case TypeMem:
  971.               BAsmCode[CodeLen] = 0x8e;
  972.               BAsmCode[CodeLen + 1] |= AdrMode;
  973.               copy_adr_vals(2);
  974.               CodeLen += 2 + AdrCnt;
  975.               break;
  976.             default:
  977.               break;
  978.           }
  979.         }
  980.         break;
  981.       default:
  982.         break;
  983.     }
  984.   }
  985.   AddPrefixes();
  986. }
  987.  
  988. /*!------------------------------------------------------------------------
  989.  * \fn     DecodeINCDEC(Word Index)
  990.  * \brief  handle INC/DEC instructions
  991.  * \param  Index machine code
  992.  * ------------------------------------------------------------------------ */
  993.  
  994. static void DecodeINCDEC(Word Index)
  995. {
  996.   if (ChkArgCnt(1, 1))
  997.   {
  998.     switch (DecodeAdr(&ArgStr[1], MTypeReg16 | MTypeReg8 | MTypeMem))
  999.     {
  1000.       case TypeReg16:
  1001.         BAsmCode[CodeLen] = 0x40 | AdrMode | Index;
  1002.         CodeLen++;
  1003.         break;
  1004.       case TypeReg8:
  1005.         BAsmCode[CodeLen] = 0xfe;
  1006.         BAsmCode[CodeLen + 1] = 0xc0 | AdrMode | Index;
  1007.         CodeLen += 2;
  1008.         break;
  1009.       case TypeMem:
  1010.         MinOneIs0();
  1011.         if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  1012.         else
  1013.         {
  1014.           BAsmCode[CodeLen] = 0xfe | OpSize; /* ANSI :-0 */
  1015.           BAsmCode[CodeLen + 1] = AdrMode | Index;
  1016.           copy_adr_vals(2);
  1017.           CodeLen += 2 + AdrCnt;
  1018.         }
  1019.         break;
  1020.       default:
  1021.         break;
  1022.     }
  1023.   }
  1024.   AddPrefixes();
  1025. }
  1026.  
  1027. /*!------------------------------------------------------------------------
  1028.  * \fn     DecodeINOUT(Word Index)
  1029.  * \brief  handle IN/OUT instructions
  1030.  * \param  Index machine code
  1031.  * ------------------------------------------------------------------------ */
  1032.  
  1033. static void DecodeINT(Word Index)
  1034. {
  1035.   Boolean OK;
  1036.   UNUSED(Index);
  1037.  
  1038.   if (ChkArgCnt(1, 1))
  1039.   {
  1040.     BAsmCode[CodeLen + 1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
  1041.     if (OK)
  1042.     {
  1043.       if (BAsmCode[1] == 3)
  1044.         BAsmCode[CodeLen++] = 0xcc;
  1045.       else
  1046.       {
  1047.         BAsmCode[CodeLen] = 0xcd;
  1048.         CodeLen += 2;
  1049.       }
  1050.     }
  1051.   }
  1052.   AddPrefixes();
  1053. }
  1054.  
  1055. /*!------------------------------------------------------------------------
  1056.  * \fn     DecodeBrk(Word Index)
  1057.  * \brief  Decode BRKxx instructions
  1058.  * \param  Index instruction table index
  1059.  * ------------------------------------------------------------------------ */
  1060.  
  1061. static void DecodeBrk(Word Index)
  1062. {
  1063.   Boolean OK;
  1064.   const FixedOrder *p_order = &BrkOrders[Index];
  1065.  
  1066.   if (ChkArgCnt(1, 1) && check_core_mask(p_order->core_mask))
  1067.   {
  1068.     PutCode(p_order->Code);
  1069.     BAsmCode[CodeLen] = EvalStrIntExpression(&ArgStr[1], UInt8, &OK);
  1070.     if (OK)
  1071.     {
  1072.       CodeLen++;
  1073.       AddPrefixes();
  1074.     }
  1075.     else
  1076.       CodeLen = 0;
  1077.   }
  1078.   AddPrefixes();
  1079. }
  1080.  
  1081. /*!------------------------------------------------------------------------
  1082.  * \fn     DecodeINOUT(Word Index)
  1083.  * \brief  handle IN/OUT (intra-segment) instructions
  1084.  * \param  Index machine code
  1085.  * ------------------------------------------------------------------------ */
  1086.  
  1087. static void DecodeINOUT(Word Index)
  1088. {
  1089.   if (ChkArgCnt(2, 2))
  1090.   {
  1091.     tStrComp *pPortArg = Index ? &ArgStr[1] : &ArgStr[2],
  1092.              *pRegArg = Index ? &ArgStr[2] : &ArgStr[1];
  1093.  
  1094.     switch (DecodeAdr(pRegArg, MTypeReg8 | MTypeReg16))
  1095.     {
  1096.       case TypeReg8:
  1097.       case TypeReg16:
  1098.         if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pRegArg);
  1099.         else if (!as_strcasecmp(pPortArg->str.p_str, "DX"))
  1100.           BAsmCode[CodeLen++] = 0xec | OpSize | Index;
  1101.         else
  1102.         {
  1103.           tEvalResult EvalResult;
  1104.  
  1105.           BAsmCode[CodeLen + 1] = EvalStrIntExpressionWithResult(pPortArg, UInt8, &EvalResult);
  1106.           if (EvalResult.OK)
  1107.           {
  1108.             ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  1109.             BAsmCode[CodeLen] = 0xe4 | OpSize | Index;
  1110.             CodeLen += 2;
  1111.           }
  1112.         }
  1113.         break;
  1114.       default:
  1115.         break;
  1116.     }
  1117.   }
  1118.   AddPrefixes();
  1119. }
  1120.  
  1121. /*!------------------------------------------------------------------------
  1122.  * \fn     DecodeCALLJMP(Word Index)
  1123.  * \brief  handle CALL/JMP (intra-segment) instructions
  1124.  * \param  Index machine code
  1125.  * ------------------------------------------------------------------------ */
  1126.  
  1127. static void DecodeCALLJMP(Word Index)
  1128. {
  1129.   Byte AdrByte;
  1130.   Word AdrWord;
  1131.   Boolean OK;
  1132.  
  1133.   if (ChkArgCnt(1, 1))
  1134.   {
  1135.     char *pAdr = ArgStr[1].str.p_str;
  1136.  
  1137.     if (!strncmp(pAdr, "SHORT ", 6))
  1138.     {
  1139.       AdrByte = 2;
  1140.       pAdr += 6;
  1141.       KillPrefBlanks(pAdr);
  1142.     }
  1143.     else if ((!strncmp(pAdr, "LONG ", 5)) || (!strncmp(pAdr, "NEAR ", 5)))
  1144.     {
  1145.       AdrByte = 1;
  1146.       pAdr +=  5;
  1147.       KillPrefBlanks(pAdr);
  1148.     }
  1149.     else
  1150.       AdrByte = 0;
  1151.     OK = True;
  1152.     if (Index == 0)
  1153.     {
  1154.       if (AdrByte == 2)
  1155.       {
  1156.         WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1157.         OK = False;
  1158.       }
  1159.       else
  1160.         AdrByte = 1;
  1161.     }
  1162.  
  1163.     if (OK)
  1164.     {
  1165.       OpSize = eSymbolSize16Bit;
  1166.       switch (DecodeAdr(&ArgStr[1], MTypeReg16 | MTypeMem | MTypeImm))
  1167.       {
  1168.         case TypeReg16:
  1169.           BAsmCode[0] = 0xff;
  1170.           BAsmCode[1] = AdrMode | (0xd0 + (Index << 4));
  1171.           CodeLen = 2;
  1172.           break;
  1173.         case TypeMem:
  1174.           BAsmCode[0] = 0xff;
  1175.           BAsmCode[1] = AdrMode | (0x10 + (Index << 4));
  1176.           copy_adr_vals(2);
  1177.           CodeLen = 2 + AdrCnt;
  1178.           break;
  1179.         case TypeImm:
  1180.           ChkSpace(SegCode, ImmAddrSpaceMask);
  1181.           AdrWord = (((Word) AdrVals[1]) << 8) | AdrVals[0];
  1182.           if ((AdrByte == 2) || ((AdrByte == 0) && (AbleToSign(AdrWord - EProgCounter() - 2))))
  1183.           {
  1184.             AdrWord -= EProgCounter() + 2;
  1185.             if (!AbleToSign(AdrWord)) WrStrErrorPos(ErrNum_DistTooBig, &ArgStr[1]);
  1186.             else
  1187.             {
  1188.               BAsmCode[0] = 0xeb;
  1189.               BAsmCode[1] = Lo(AdrWord);
  1190.               CodeLen = 2;
  1191.             }
  1192.           }
  1193.           else
  1194.           {
  1195.             AdrWord -= EProgCounter() + 3;
  1196.             BAsmCode[0] = 0xe8 | Index;
  1197.             BAsmCode[1] = Lo(AdrWord);
  1198.             BAsmCode[2] = Hi(AdrWord);
  1199.             CodeLen = 3;
  1200.             AdrWord++;
  1201.           }
  1202.           break;
  1203.         default:
  1204.           break;
  1205.       }
  1206.     }
  1207.   }
  1208.   AddPrefixes();
  1209. }
  1210.  
  1211. /*!------------------------------------------------------------------------
  1212.  * \fn     DecodePUSHPOP(Word Index)
  1213.  * \brief  handle PUSH/POP instructions
  1214.  * \param  Index machine code
  1215.  * ------------------------------------------------------------------------ */
  1216.  
  1217. static void DecodePUSHPOP(Word Index)
  1218. {
  1219.   if (ChkArgCnt(1, 1))
  1220.   {
  1221.     OpSize = eSymbolSize16Bit;
  1222.     switch (DecodeAdr(&ArgStr[1], MTypeReg16 | MTypeMem | MTypeRegSeg | ((Index == 1) ? 0 : MTypeImm)))
  1223.     {
  1224.       case TypeReg16:
  1225.         BAsmCode[CodeLen] = 0x50 |  AdrMode | (Index << 3);
  1226.         CodeLen++;
  1227.         break;
  1228.       case TypeRegSeg:
  1229.         if (AdrMode >= 4) /* V55 DS2/DS3 */
  1230.         {
  1231.           BAsmCode[CodeLen++] = 0x0f;
  1232.           BAsmCode[CodeLen++] = 0x76 | ((AdrMode & 1) << 3) | Index;
  1233.         }
  1234.         else
  1235.         {
  1236.           BAsmCode[CodeLen] = 0x06 | (AdrMode << 3) | Index;
  1237.           CodeLen++;
  1238.         }
  1239.         break;
  1240.       case TypeMem:
  1241.         BAsmCode[CodeLen] = 0x8f;
  1242.         BAsmCode[CodeLen + 1] = AdrMode;
  1243.         if (Index == 0)
  1244.         {
  1245.           BAsmCode[CodeLen] += 0x70;
  1246.           BAsmCode[CodeLen + 1] += 0x30;
  1247.         }
  1248.         copy_adr_vals(2);
  1249.         CodeLen += 2 + AdrCnt;
  1250.         break;
  1251.       case TypeImm:
  1252.         if (check_core_mask(e_core_all_186))
  1253.         {
  1254.           BAsmCode[CodeLen] = 0x68;
  1255.           BAsmCode[CodeLen + 1] = AdrVals[0];
  1256.           if (Sgn(AdrVals[0]) == AdrVals[1])
  1257.           {
  1258.             BAsmCode[CodeLen] += 2;
  1259.             CodeLen += 2;
  1260.           }
  1261.           else
  1262.           {
  1263.             BAsmCode[CodeLen + 2] = AdrVals[1];
  1264.             CodeLen += 3;
  1265.           }
  1266.         }
  1267.         break;
  1268.       default:
  1269.         break;
  1270.     }
  1271.   }
  1272.   AddPrefixes();
  1273. }
  1274.  
  1275. /*!------------------------------------------------------------------------
  1276.  * \fn     DecodeNOTNEG(Word Index)
  1277.  * \brief  handle NOT/NEG instructions
  1278.  * \param  Index machine code
  1279.  * ------------------------------------------------------------------------ */
  1280.  
  1281. static void DecodeNOTNEG(Word Index)
  1282. {
  1283.   if (ChkArgCnt(1, 1))
  1284.   {
  1285.     DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem);
  1286.     MinOneIs0();
  1287.     BAsmCode[CodeLen] = 0xf6 | OpSize;
  1288.     BAsmCode[CodeLen + 1] = 0x10 | Index;
  1289.     switch (AdrType)
  1290.     {
  1291.       case TypeReg8:
  1292.       case TypeReg16:
  1293.         BAsmCode[CodeLen + 1] |= 0xc0 | AdrMode;
  1294.         CodeLen += 2;
  1295.         break;
  1296.       case TypeMem:
  1297.         if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  1298.         else
  1299.         {
  1300.           BAsmCode[CodeLen + 1] |= AdrMode;
  1301.           copy_adr_vals(2);
  1302.           CodeLen += 2 + AdrCnt;
  1303.         }
  1304.         break;
  1305.       default:
  1306.         break;
  1307.     }
  1308.   }
  1309.   AddPrefixes();
  1310. }
  1311.  
  1312. /*!------------------------------------------------------------------------
  1313.  * \fn     DecodeRET(Word Index)
  1314.  * \brief  handle RET instruction
  1315.  * ------------------------------------------------------------------------ */
  1316.  
  1317. static void DecodeRET(Word Index)
  1318. {
  1319.   Word AdrWord;
  1320.   Boolean OK;
  1321.  
  1322.   if (!ChkArgCnt(0, 1));
  1323.   else if (ArgCnt == 0)
  1324.     BAsmCode[CodeLen++] = 0xc3 | Index;
  1325.   else
  1326.   {
  1327.     AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
  1328.     if (OK)
  1329.     {
  1330.       BAsmCode[CodeLen++] = 0xc2 | Index;
  1331.       BAsmCode[CodeLen++] = Lo(AdrWord);
  1332.       BAsmCode[CodeLen++] = Hi(AdrWord);
  1333.     }
  1334.   }
  1335. }
  1336.  
  1337. /*!------------------------------------------------------------------------
  1338.  * \fn     DecodeTEST(Word Index)
  1339.  * \brief  handle TEST instruction
  1340.  * ------------------------------------------------------------------------ */
  1341.  
  1342. static void DecodeTEST(Word Index)
  1343. {
  1344.   Byte AdrByte;
  1345.   UNUSED(Index);
  1346.  
  1347.   if (ChkArgCnt(2, 2))
  1348.   {
  1349.     switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
  1350.     {
  1351.       case TypeReg8:
  1352.       case TypeReg16:
  1353.         BAsmCode[CodeLen + 1] = (AdrMode << 3);
  1354.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeImm))
  1355.         {
  1356.           case TypeReg8:
  1357.           case TypeReg16:
  1358.             BAsmCode[CodeLen + 1] += 0xc0 | AdrMode;
  1359.             BAsmCode[CodeLen] = 0x84 | OpSize;
  1360.             CodeLen += 2;
  1361.             break;
  1362.           case TypeMem:
  1363.             BAsmCode[CodeLen + 1] |= AdrMode;
  1364.             BAsmCode[CodeLen] = 0x84 | OpSize;
  1365.             copy_adr_vals(2);
  1366.             CodeLen += 2 + AdrCnt;
  1367.             break;
  1368.           case TypeImm:
  1369.             if (((BAsmCode[CodeLen+1] >> 3) & 7) == 0)
  1370.             {
  1371.               BAsmCode[CodeLen] = 0xa8 | OpSize;
  1372.               copy_adr_vals(1);
  1373.               CodeLen += 1 + AdrCnt;
  1374.             }
  1375.             else
  1376.             {
  1377.               BAsmCode[CodeLen] = OpSize | 0xf6;
  1378.               BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] >> 3) | 0xc0;
  1379.               copy_adr_vals(2);
  1380.               CodeLen += 2 + AdrCnt;
  1381.             }
  1382.             break;
  1383.           default:
  1384.             break;;
  1385.         }
  1386.         break;
  1387.       case TypeMem:
  1388.         BAsmCode[CodeLen + 1] = AdrMode;
  1389.         AdrByte = AdrCnt;
  1390.         copy_adr_vals(2);
  1391.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeImm))
  1392.         {
  1393.           case TypeReg8:
  1394.           case TypeReg16:
  1395.             BAsmCode[CodeLen] = 0x84 | OpSize;
  1396.             BAsmCode[CodeLen + 1] += (AdrMode << 3);
  1397.             CodeLen += 2 + AdrByte;
  1398.             break;
  1399.           case TypeImm:
  1400.             BAsmCode[CodeLen] = OpSize | 0xf6;
  1401.             copy_adr_vals(2 + AdrByte);
  1402.             CodeLen += 2 + AdrCnt + AdrByte;
  1403.             break;
  1404.           default:
  1405.             break;
  1406.         }
  1407.         break;
  1408.       default:
  1409.         break;
  1410.     }
  1411.   }
  1412.   AddPrefixes();
  1413. }
  1414.  
  1415. /*!------------------------------------------------------------------------
  1416.  * \fn     DecodeXCHG(Word Index)
  1417.  * \brief  handle XCHG instruction
  1418.  * ------------------------------------------------------------------------ */
  1419.  
  1420. static void DecodeXCHG(Word Index)
  1421. {
  1422.   Byte AdrByte;
  1423.   UNUSED(Index);
  1424.  
  1425.   if (ChkArgCnt(2, 2))
  1426.   {
  1427.     switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
  1428.     {
  1429.       case TypeReg8:
  1430.       case TypeReg16:
  1431.         AdrByte = AdrMode;
  1432.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem))
  1433.         {
  1434.           case TypeReg8:
  1435.           case TypeReg16:
  1436.             if ((OpSize == eSymbolSize16Bit) && ((AdrMode == 0) || (AdrByte == 0)))
  1437.             {
  1438.               BAsmCode[CodeLen] = 0x90 | AdrMode | AdrByte;
  1439.               CodeLen++;
  1440.             }
  1441.             else
  1442.             {
  1443.               BAsmCode[CodeLen] = 0x86 | OpSize;
  1444.               BAsmCode[CodeLen+1] = AdrMode | 0xc0 | (AdrByte << 3);
  1445.               CodeLen += 2;
  1446.             }
  1447.             break;
  1448.           case TypeMem:
  1449.             BAsmCode[CodeLen] = 0x86 | OpSize;
  1450.             BAsmCode[CodeLen+1] = AdrMode | (AdrByte << 3);
  1451.             copy_adr_vals(2);
  1452.             CodeLen += AdrCnt + 2;
  1453.             break;
  1454.           default:
  1455.             break;
  1456.         }
  1457.         break;
  1458.       case TypeMem:
  1459.         BAsmCode[CodeLen + 1] = AdrMode;
  1460.         copy_adr_vals(2);
  1461.         AdrByte = AdrCnt;
  1462.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16))
  1463.         {
  1464.           case TypeReg8:
  1465.           case TypeReg16:
  1466.             BAsmCode[CodeLen] = 0x86 | OpSize;
  1467.             BAsmCode[CodeLen+1] |= (AdrMode << 3);
  1468.             CodeLen += AdrByte + 2;
  1469.             break;
  1470.           default:
  1471.             break;
  1472.         }
  1473.         break;
  1474.       default:
  1475.         break;
  1476.     }
  1477.   }
  1478.   AddPrefixes();
  1479. }
  1480.  
  1481. /*!------------------------------------------------------------------------
  1482.  * \fn     DecodeCALLJMPF(Word Index)
  1483.  * \brief  handle CALLF/JMPF (inter-segment) instructions
  1484.  * \param  Index machine code
  1485.  * ------------------------------------------------------------------------ */
  1486.  
  1487. static void DecodeCALLJMPF(Word Index)
  1488. {
  1489.   char *p;
  1490.   Word AdrWord;
  1491.   Boolean OK;
  1492.  
  1493.   if (ChkArgCnt(1, 1))
  1494.   {
  1495.     p = QuotPos(ArgStr[1].str.p_str, ':');
  1496.     if (!p)
  1497.     {
  1498.       switch (DecodeAdr(&ArgStr[1], MTypeMem))
  1499.       {
  1500.         case TypeMem:
  1501.           BAsmCode[CodeLen] = 0xff;
  1502.           BAsmCode[CodeLen + 1] = AdrMode | Hi(Index);
  1503.           copy_adr_vals(2);
  1504.           CodeLen += 2 + AdrCnt;
  1505.           break;
  1506.         default:
  1507.           break;
  1508.       }
  1509.     }
  1510.     else
  1511.     {
  1512.       tStrComp SegArg, OffsArg;
  1513.  
  1514.       StrCompSplitRef(&SegArg, &OffsArg, &ArgStr[1], p);
  1515.       AdrWord = EvalStrIntExpression(&SegArg, UInt16, &OK);
  1516.       if (OK)
  1517.       {
  1518.         BAsmCode[CodeLen + 3] = Lo(AdrWord);
  1519.         BAsmCode[CodeLen + 4] = Hi(AdrWord);
  1520.         AdrWord = EvalStrIntExpression(&OffsArg, UInt16, &OK);
  1521.         if (OK)
  1522.         {
  1523.           BAsmCode[CodeLen + 1] = Lo(AdrWord);
  1524.           BAsmCode[CodeLen + 2] = Hi(AdrWord);
  1525.           BAsmCode[CodeLen] = Lo(Index);
  1526.           CodeLen += 5;
  1527.         }
  1528.       }
  1529.     }
  1530.   }
  1531.   AddPrefixes();
  1532. }
  1533.  
  1534. /*!------------------------------------------------------------------------
  1535.  * \fn     DecodeENTER(Word Index)
  1536.  * \brief  handle ENTER instruction
  1537.  * ------------------------------------------------------------------------ */
  1538.  
  1539. static void DecodeENTER(Word Index)
  1540. {
  1541.   Word AdrWord;
  1542.   Boolean OK;
  1543.   UNUSED(Index);
  1544.  
  1545.   if (!ChkArgCnt(2, 2));
  1546.   else if (check_core_mask(e_core_all_186))
  1547.   {
  1548.     AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
  1549.     if (OK)
  1550.     {
  1551.       BAsmCode[CodeLen + 1] = Lo(AdrWord);
  1552.       BAsmCode[CodeLen + 2] = Hi(AdrWord);
  1553.       BAsmCode[CodeLen + 3] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  1554.       if (OK)
  1555.       {
  1556.         BAsmCode[CodeLen] = 0xc8;
  1557.         CodeLen += 4;
  1558.       }
  1559.     }
  1560.   }
  1561.   AddPrefixes();
  1562. }
  1563.  
  1564. /*!------------------------------------------------------------------------
  1565.  * \fn     DecodeFixed(Word Index)
  1566.  * \brief  handle instructions without argument
  1567.  * \param  Index index into instruction table
  1568.  * ------------------------------------------------------------------------ */
  1569.  
  1570. static void DecodeFixed(Word Index)
  1571. {
  1572.   const FixedOrder *pOrder = FixedOrders + Index;
  1573.  
  1574.   if (ChkArgCnt(0, 0)
  1575.    && check_core_mask(pOrder->core_mask))
  1576.     PutCode(pOrder->Code);
  1577.   AddPrefixes();
  1578. }
  1579.  
  1580. /*!------------------------------------------------------------------------
  1581.  * \fn     DecodeALU2(Word Index)
  1582.  * \brief  handle ALU instructions with two arguments
  1583.  * \param  Index index into instruction table
  1584.  * ------------------------------------------------------------------------ */
  1585.  
  1586. static void DecodeALU2(Word Index)
  1587. {
  1588.   Byte AdrByte;
  1589.  
  1590.   if (ChkArgCnt(2, 2))
  1591.   {
  1592.     switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
  1593.     {
  1594.       case TypeReg8:
  1595.       case TypeReg16:
  1596.         BAsmCode[CodeLen + 1] = AdrMode << 3;
  1597.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeImm))
  1598.         {
  1599.           case TypeReg8:
  1600.           case TypeReg16:
  1601.             BAsmCode[CodeLen + 1] |= 0xc0 | AdrMode;
  1602.             BAsmCode[CodeLen] = (Index << 3) | 2 | OpSize;
  1603.             CodeLen += 2;
  1604.             break;
  1605.           case TypeMem:
  1606.             BAsmCode[CodeLen + 1] |= AdrMode;
  1607.             BAsmCode[CodeLen] = (Index << 3) | 2 | OpSize;
  1608.             copy_adr_vals(2);
  1609.             CodeLen += 2 + AdrCnt;
  1610.             break;
  1611.           case TypeImm:
  1612.             if (((BAsmCode[CodeLen+1] >> 3) & 7) == 0)
  1613.             {
  1614.               BAsmCode[CodeLen] = (Index << 3) | 4 | OpSize;
  1615.               copy_adr_vals(1);
  1616.               CodeLen += 1 + AdrCnt;
  1617.             }
  1618.             else
  1619.             {
  1620.               BAsmCode[CodeLen] = OpSize | 0x80;
  1621.               if ((OpSize == eSymbolSize16Bit) && (Sgn(AdrVals[0]) == AdrVals[1]))
  1622.               {
  1623.                 AdrCnt = 1;
  1624.                 BAsmCode[CodeLen] |= 2;
  1625.               }
  1626.               BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] >> 3) + 0xc0 + (Index << 3);
  1627.               copy_adr_vals(2);
  1628.               CodeLen += 2 + AdrCnt;
  1629.             }
  1630.             break;
  1631.           default:
  1632.             break;
  1633.         }
  1634.         break;
  1635.       case TypeMem:
  1636.         BAsmCode[CodeLen + 1] = AdrMode;
  1637.         AdrByte = AdrCnt;
  1638.         copy_adr_vals(2);
  1639.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeImm))
  1640.         {
  1641.           case TypeReg8:
  1642.           case TypeReg16:
  1643.             BAsmCode[CodeLen] = (Index << 3) | OpSize;
  1644.             BAsmCode[CodeLen + 1] |= (AdrMode << 3);
  1645.             CodeLen += 2 + AdrByte;
  1646.             break;
  1647.           case TypeImm:
  1648.             BAsmCode[CodeLen] = OpSize | 0x80;
  1649.             if ((OpSize == eSymbolSize16Bit) && (Sgn(AdrVals[0]) == AdrVals[1]))
  1650.             {
  1651.               AdrCnt = 1;
  1652.               BAsmCode[CodeLen] += 2;
  1653.             }
  1654.             BAsmCode[CodeLen + 1] += (Index << 3);
  1655.             copy_adr_vals(2 + AdrByte);
  1656.             CodeLen += 2 + AdrCnt + AdrByte;
  1657.             break;
  1658.           default:
  1659.             break;
  1660.         }
  1661.         break;
  1662.       default:
  1663.         break;
  1664.     }
  1665.   }
  1666.   AddPrefixes();
  1667. }
  1668.  
  1669. /*!------------------------------------------------------------------------
  1670.  * \fn     DecodeRel(Word Index)
  1671.  * \brief  handle relative branches
  1672.  * \param  Index index into instruction table
  1673.  * ------------------------------------------------------------------------ */
  1674.  
  1675. static void DecodeRel(Word Index)
  1676. {
  1677.   const FixedOrder *pOrder = RelOrders + Index;
  1678.  
  1679.   if (ChkArgCnt(1, 1)
  1680.    && check_core_mask(pOrder->core_mask))
  1681.   {
  1682.     PutCode(pOrder->Code);
  1683.     append_rel(&ArgStr[1]);
  1684.   }
  1685. }
  1686.  
  1687. /*!------------------------------------------------------------------------
  1688.  * \fn     DecodeASSUME(void)
  1689.  * \brief  handle ASSUME instruction
  1690.  * ------------------------------------------------------------------------ */
  1691.  
  1692. static void DecodeASSUME(void)
  1693. {
  1694.   Boolean OK;
  1695.   int z, z3;
  1696.   char *p, empty_str[1] = "";
  1697.  
  1698.   if (ChkArgCnt(1, ArgCntMax))
  1699.   {
  1700.     z = 1 ; OK = True;
  1701.     while ((z <= ArgCnt) && (OK))
  1702.     {
  1703.       Byte seg_reg;
  1704.       tStrComp seg_arg, val_arg;
  1705.  
  1706.       OK = False;
  1707.       p = QuotPos(ArgStr[z].str.p_str, ':');
  1708.       if (p)
  1709.         StrCompSplitRef(&seg_arg, &val_arg, &ArgStr[z], p);
  1710.       else
  1711.       {
  1712.         StrCompRefRight(&seg_arg, &ArgStr[z], 0);
  1713.         StrCompMkTemp(&val_arg, empty_str, sizeof(empty_str));
  1714.       }
  1715.       if (!decode_seg_reg(seg_arg.str.p_str, &seg_reg)) WrStrErrorPos(ErrNum_UnknownSegReg, &seg_arg);
  1716.       else
  1717.       {
  1718.         z3 = addrspace_lookup(val_arg.str.p_str);
  1719.         if (z3 >= SegCount) WrStrErrorPos(ErrNum_UnknownSegment, &val_arg);
  1720.         else if ((z3 != SegCode) && (z3 != SegData) && (z3 != SegXData) && (z3 != SegNone)) WrStrErrorPos(ErrNum_InvSegment, &val_arg);
  1721.         else
  1722.         {
  1723.           SegAssumes[seg_reg] = z3;
  1724.           OK = True;
  1725.         }
  1726.       }
  1727.       z++;
  1728.     }
  1729.   }
  1730. }
  1731.  
  1732. /*!------------------------------------------------------------------------
  1733.  * \fn     DecodePORT(Word Code)
  1734.  * \brief  handle PORT instruction
  1735.  * ------------------------------------------------------------------------ */
  1736.  
  1737. static void DecodePORT(Word Code)
  1738. {
  1739.   UNUSED(Code);
  1740.  
  1741.   CodeEquate(SegIO, 0, 0xffff);
  1742. }
  1743.  
  1744. /*!------------------------------------------------------------------------
  1745.  * \fn     DecodeFPUFixed(Word Code)
  1746.  * \brief  handle FPU instructions with no arguments
  1747.  * \param  Code machine code
  1748.  * ------------------------------------------------------------------------ */
  1749.  
  1750. static void DecodeFPUFixed(Word Code)
  1751. {
  1752.   if (!FPUEntry(&Code))
  1753.     return;
  1754.  
  1755.   if (ChkArgCnt(0, 0))
  1756.   {
  1757.     PutCode(Code);
  1758.     AddPrefixes();
  1759.   }
  1760. }
  1761.  
  1762. /*!------------------------------------------------------------------------
  1763.  * \fn     DecodeFPUSt(Word Code)
  1764.  * \brief  handle FPU instructions with one register argument
  1765.  * \param  Code machine code
  1766.  * ------------------------------------------------------------------------ */
  1767.  
  1768. static void DecodeFPUSt(Word Code)
  1769. {
  1770.   if (!FPUEntry(&Code))
  1771.     return;
  1772.  
  1773.   if (ChkArgCnt(1, 1))
  1774.   {
  1775.     if (DecodeAdr(&ArgStr[1], MTypeFReg) == TypeFReg)
  1776.     {
  1777.       PutCode(Code);
  1778.       BAsmCode[CodeLen-1] |= AdrMode;
  1779.       AddPrefixes();
  1780.     }
  1781.   }
  1782. }
  1783.  
  1784. /*!------------------------------------------------------------------------
  1785.  * \fn     DecodeFLD(Word Code)
  1786.  * \brief  handle FLD instruction
  1787.  * \param  Code machine code
  1788.  * ------------------------------------------------------------------------ */
  1789.  
  1790. static void DecodeFLD(Word Code)
  1791. {
  1792.   if (!FPUEntry(&Code))
  1793.     return;
  1794.  
  1795.   if (ChkArgCnt(1, 1))
  1796.   {
  1797.     switch (DecodeAdr(&ArgStr[1], MTypeFReg | MTypeMem))
  1798.     {
  1799.       case TypeFReg:
  1800.         BAsmCode[CodeLen++] = 0xd9;
  1801.         BAsmCode[CodeLen++] = 0xc0 | AdrMode;
  1802.         break;
  1803.       case TypeMem:
  1804.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  1805.           OpSize = eSymbolSize32Bit;
  1806.         switch (OpSize)
  1807.         {
  1808.           case eSymbolSize32Bit:
  1809.             BAsmCode[CodeLen++] = 0xd9;
  1810.             BAsmCode[CodeLen++] = AdrMode;
  1811.             break;
  1812.           case eSymbolSize64Bit:
  1813.             BAsmCode[CodeLen++] = 0xdd;
  1814.             BAsmCode[CodeLen++] = AdrMode;
  1815.             break;
  1816.           case eSymbolSize80Bit:
  1817.             BAsmCode[CodeLen++] = 0xdb;
  1818.             BAsmCode[CodeLen++] = AdrMode | 0x28;
  1819.             break;
  1820.           case eSymbolSizeUnknown:
  1821.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  1822.             CodeLen = 0;
  1823.             break;
  1824.           default:
  1825.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  1826.             CodeLen = 0;
  1827.             break;
  1828.         }
  1829.         if (CodeLen)
  1830.           append_adr_vals();
  1831.         break;
  1832.       default:
  1833.         break;
  1834.     }
  1835.   }
  1836.   AddPrefixes();
  1837. }
  1838.  
  1839. /*!------------------------------------------------------------------------
  1840.  * \fn     DecodeFILD(Word Code)
  1841.  * \brief  handle FILD instruction
  1842.  * \param  Code machine code
  1843.  * ------------------------------------------------------------------------ */
  1844.  
  1845. static void DecodeFILD(Word Code)
  1846. {
  1847.   if (!FPUEntry(&Code))
  1848.     return;
  1849.  
  1850.   if (ChkArgCnt(1, 1))
  1851.   {
  1852.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  1853.     {
  1854.       case TypeMem:
  1855.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  1856.           OpSize = eSymbolSize16Bit;
  1857.         switch (OpSize)
  1858.         {
  1859.           case eSymbolSize16Bit:
  1860.             BAsmCode[CodeLen++] = 0xdf;
  1861.             BAsmCode[CodeLen++] = AdrMode;
  1862.             break;
  1863.           case eSymbolSize32Bit:
  1864.             BAsmCode[CodeLen++] = 0xdb;
  1865.             BAsmCode[CodeLen++] = AdrMode;
  1866.             break;
  1867.           case eSymbolSize64Bit:
  1868.             BAsmCode[CodeLen++] = 0xdf;
  1869.             BAsmCode[CodeLen++] = AdrMode | 0x28;
  1870.             break;
  1871.           case eSymbolSizeUnknown:
  1872.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  1873.             CodeLen = 0;
  1874.             break;
  1875.           default:
  1876.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  1877.             CodeLen = 0;
  1878.             break;
  1879.         }
  1880.         if (CodeLen)
  1881.           append_adr_vals();
  1882.         break;
  1883.       default:
  1884.         break;
  1885.     }
  1886.   }
  1887.   AddPrefixes();
  1888. }
  1889.  
  1890. /*!------------------------------------------------------------------------
  1891.  * \fn     DecodeFBLD(Word Code)
  1892.  * \brief  handle FBLD instruction
  1893.  * \param  Code machine code
  1894.  * ------------------------------------------------------------------------ */
  1895.  
  1896. static void DecodeFBLD(Word Code)
  1897. {
  1898.   if (!FPUEntry(&Code))
  1899.     return;
  1900.  
  1901.   if (ChkArgCnt(1, 1))
  1902.   {
  1903.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  1904.     {
  1905.       case TypeMem:
  1906.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  1907.           OpSize = eSymbolSize80Bit;
  1908.         switch (OpSize)
  1909.         {
  1910.           case eSymbolSizeUnknown:
  1911.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  1912.             CodeLen = 0;
  1913.             break;
  1914.           case eSymbolSize80Bit:
  1915.             BAsmCode[CodeLen++] = 0xdf;
  1916.             BAsmCode[CodeLen++] = AdrMode + 0x20;
  1917.             break;
  1918.           default:
  1919.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  1920.             CodeLen = 0;
  1921.             break;
  1922.         }
  1923.         if (CodeLen > 0)
  1924.           append_adr_vals();
  1925.         break;
  1926.       default:
  1927.         break;
  1928.     }
  1929.   }
  1930.   AddPrefixes();
  1931. }
  1932.  
  1933. /*!------------------------------------------------------------------------
  1934.  * \fn     DecodeFST_FSTP(Word Code)
  1935.  * \brief  handle FST(P) instructions
  1936.  * \param  Code machine code
  1937.  * ------------------------------------------------------------------------ */
  1938.  
  1939. static void DecodeFST_FSTP(Word Code)
  1940. {
  1941.   if (!FPUEntry(&Code))
  1942.     return;
  1943.  
  1944.   if (ChkArgCnt(1, 1))
  1945.   {
  1946.     switch (DecodeAdr(&ArgStr[1], MTypeFReg | MTypeMem))
  1947.     {
  1948.       case TypeFReg:
  1949.         BAsmCode[CodeLen++] = 0xdd;
  1950.         BAsmCode[CodeLen++] = Code | AdrMode;
  1951.         break;
  1952.       case TypeMem:
  1953.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  1954.           OpSize = eSymbolSize32Bit;
  1955.         switch (OpSize)
  1956.         {
  1957.           case eSymbolSize32Bit:
  1958.             BAsmCode[CodeLen++] = 0xd9;
  1959.             BAsmCode[CodeLen++] = 0x00;
  1960.             break;
  1961.           case eSymbolSize64Bit:
  1962.             BAsmCode[CodeLen++] = 0xdd;
  1963.             BAsmCode[CodeLen++] = 0x00;
  1964.             break;
  1965.           case eSymbolSize80Bit:
  1966.             if (Code == 0xd0)
  1967.               goto invalid;
  1968.             BAsmCode[CodeLen++] = 0xdb;
  1969.             BAsmCode[CodeLen++] = 0x20;
  1970.             break;
  1971.           case eSymbolSizeUnknown:
  1972.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  1973.             CodeLen = 0;
  1974.             break;
  1975.           invalid:
  1976.           default:
  1977.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  1978.             CodeLen = 0;
  1979.             break;
  1980.         }
  1981.         if (CodeLen > 0)
  1982.         {
  1983.           BAsmCode[CodeLen - 1] |= AdrMode | 0x10 | (Code & 8);
  1984.           append_adr_vals();
  1985.         }
  1986.         break;
  1987.       default:
  1988.         break;
  1989.     }
  1990.   }
  1991.   AddPrefixes();
  1992. }
  1993.  
  1994. /*!------------------------------------------------------------------------
  1995.  * \fn     DecodeFIST_FISTP(Word Code)
  1996.  * \brief  handle FIST(P) instructions
  1997.  * \param  Code machine code
  1998.  * ------------------------------------------------------------------------ */
  1999.  
  2000. static void DecodeFIST_FISTP(Word Code)
  2001. {
  2002.   if (!FPUEntry(&Code))
  2003.     return;
  2004.  
  2005.   if (ChkArgCnt(1, 1))
  2006.   {
  2007.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  2008.     {
  2009.       case TypeMem:
  2010.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2011.           OpSize = eSymbolSize16Bit;
  2012.         switch (OpSize)
  2013.         {
  2014.           case eSymbolSize16Bit:
  2015.             BAsmCode[CodeLen++] = 0xdf;
  2016.             BAsmCode[CodeLen++] = 0x00;
  2017.             break;
  2018.           case eSymbolSize32Bit:
  2019.             BAsmCode[CodeLen++] = 0xdb;
  2020.             BAsmCode[CodeLen++] = 0x00;
  2021.             break;
  2022.           case eSymbolSize64Bit:
  2023.             if (Code == 0x10)
  2024.               goto invalid;
  2025.             BAsmCode[CodeLen++] = 0xdf;
  2026.             BAsmCode[CodeLen++] = 0x20;
  2027.             break;
  2028.           case eSymbolSizeUnknown:
  2029.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2030.             break;
  2031.           invalid:
  2032.           default:
  2033.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  2034.             CodeLen = 0;
  2035.             break;
  2036.         }
  2037.         if (CodeLen > 0)
  2038.         {
  2039.           BAsmCode[CodeLen - 1] |= AdrMode | Code;
  2040.           append_adr_vals();
  2041.         }
  2042.         break;
  2043.       default:
  2044.         break;
  2045.     }
  2046.   }
  2047.   AddPrefixes();
  2048. }
  2049.  
  2050. /*!------------------------------------------------------------------------
  2051.  * \fn     DecodeFBSTP(Word Code)
  2052.  * \brief  handle FBSTP instruction
  2053.  * \param  Code machine code
  2054.  * ------------------------------------------------------------------------ */
  2055.  
  2056. static void DecodeFBSTP(Word Code)
  2057. {
  2058.   if (!FPUEntry(&Code))
  2059.     return;
  2060.  
  2061.   if (ChkArgCnt(1, 1))
  2062.   {
  2063.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  2064.     {
  2065.       case TypeMem:
  2066.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2067.           OpSize = eSymbolSize16Bit;
  2068.         switch (OpSize)
  2069.         {
  2070.           case eSymbolSizeUnknown:
  2071.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2072.             break;
  2073.           case eSymbolSize80Bit:
  2074.             BAsmCode[CodeLen] = 0xdf;
  2075.             BAsmCode[CodeLen + 1] = AdrMode | 0x30;
  2076.             copy_adr_vals(2);
  2077.             CodeLen += 2 + AdrCnt;
  2078.             break;
  2079.           default:
  2080.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  2081.         }
  2082.         break;
  2083.       default:
  2084.         break;
  2085.     }
  2086.   }
  2087.   AddPrefixes();
  2088. }
  2089.  
  2090. /*!------------------------------------------------------------------------
  2091.  * \fn     DecodeFCOM_FCOMP(Word Code)
  2092.  * \brief  handle FCOM(P) instructions
  2093.  * \param  Code machine code
  2094.  * ------------------------------------------------------------------------ */
  2095.  
  2096. static void DecodeFCOM_FCOMP(Word Code)
  2097. {
  2098.   if (!FPUEntry(&Code))
  2099.     return;
  2100.  
  2101.   if (ChkArgCnt(1, 1))
  2102.   {
  2103.     switch (DecodeAdr(&ArgStr[1], MTypeFReg | MTypeMem))
  2104.     {
  2105.       case TypeFReg:
  2106.         BAsmCode[CodeLen] = 0xd8;
  2107.         BAsmCode[CodeLen+1] = Code | AdrMode;
  2108.         CodeLen += 2;
  2109.         break;
  2110.       case TypeMem:
  2111.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2112.           OpSize = eSymbolSize16Bit;
  2113.         switch (OpSize)
  2114.         {
  2115.           case eSymbolSize32Bit:
  2116.             BAsmCode[CodeLen++] = 0xd8;
  2117.             break;
  2118.           case eSymbolSize64Bit:
  2119.             BAsmCode[CodeLen++] = 0xdc;
  2120.             break;
  2121.           case eSymbolSizeUnknown:
  2122.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2123.             CodeLen = 0;
  2124.             break;
  2125.           default:
  2126.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  2127.             CodeLen = 0;
  2128.             break;
  2129.         }
  2130.         if (CodeLen > 0)
  2131.         {
  2132.           BAsmCode[CodeLen++] = AdrMode | 0x10 | (Code & 8);
  2133.           append_adr_vals();
  2134.         }
  2135.         break;
  2136.       default:
  2137.         break;
  2138.     }
  2139.   }
  2140.   AddPrefixes();
  2141. }
  2142.  
  2143. /*!------------------------------------------------------------------------
  2144.  * \fn     DecodeFICOM_FICOMP(Word Code)
  2145.  * \brief  handle FICOM(P) instructions
  2146.  * \param  Code machine code
  2147.  * ------------------------------------------------------------------------ */
  2148.  
  2149. static void DecodeFICOM_FICOMP(Word Code)
  2150. {
  2151.   if (!FPUEntry(&Code))
  2152.     return;
  2153.  
  2154.   if (ChkArgCnt(1, 1))
  2155.   {
  2156.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  2157.     {
  2158.       case TypeMem:
  2159.         if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2160.           OpSize = eSymbolSize16Bit;
  2161.         switch (OpSize)
  2162.         {
  2163.           case eSymbolSize16Bit:
  2164.             BAsmCode[CodeLen++] = 0xde;
  2165.             break;
  2166.           case eSymbolSize32Bit:
  2167.             BAsmCode[CodeLen++] = 0xda;
  2168.             break;
  2169.           case eSymbolSizeUnknown:
  2170.             WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2171.             CodeLen = 0;
  2172.             break;
  2173.           default:
  2174.             WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  2175.             CodeLen = 0;
  2176.             break;
  2177.         }
  2178.         if (CodeLen > 0)
  2179.         {
  2180.           BAsmCode[CodeLen++] = AdrMode | Code;
  2181.           append_adr_vals();
  2182.         }
  2183.         break;
  2184.       default:
  2185.         break;
  2186.     }
  2187.   }
  2188.   AddPrefixes();
  2189. }
  2190.  
  2191. /*!------------------------------------------------------------------------
  2192.  * \fn     DecodeFADD_FMUL(Word Code)
  2193.  * \brief  handle FADD/FMUL instructions
  2194.  * \param  Code machine code
  2195.  * ------------------------------------------------------------------------ */
  2196.  
  2197. static void DecodeFADD_FMUL(Word Code)
  2198. {
  2199.   if (!FPUEntry(&Code))
  2200.     return;
  2201.  
  2202.   if (ArgCnt == 0)
  2203.   {
  2204.     BAsmCode[CodeLen] = 0xde;
  2205.     BAsmCode[CodeLen + 1] = 0xc1 + Code;
  2206.     CodeLen += 2;
  2207.   }
  2208.   else if (ChkArgCnt(0, 2))
  2209.   {
  2210.     const tStrComp *pArg1 = &ArgStr[1],
  2211.                    *pArg2 = &ArgStr[2];
  2212.  
  2213.     if (ArgCnt == 1)
  2214.     {
  2215.       pArg2 = &ArgStr[1];
  2216.       pArg1 = &ArgST;
  2217.     }
  2218.  
  2219.     switch (DecodeAdr(pArg1, MTypeFReg))
  2220.     {
  2221.       case TypeFReg:
  2222.         OpSize = eSymbolSizeUnknown;
  2223.         if (AdrMode != 0)   /* ST(i) ist Ziel */
  2224.         {
  2225.           BAsmCode[CodeLen + 1] = AdrMode;
  2226.           switch (DecodeAdr(pArg2, MTypeFReg))
  2227.           {
  2228.             case TypeFReg:
  2229.               BAsmCode[CodeLen] = 0xdc;
  2230.               BAsmCode[CodeLen + 1] += 0xc0 + Code;
  2231.               CodeLen += 2;
  2232.               break;
  2233.             default:
  2234.               break;
  2235.           }
  2236.         }
  2237.         else                      /* ST ist Ziel */
  2238.         {
  2239.           switch (DecodeAdr(pArg2, MTypeFReg | MTypeMem))
  2240.           {
  2241.             case TypeFReg:
  2242.               BAsmCode[CodeLen] = 0xd8;
  2243.               BAsmCode[CodeLen + 1] = 0xc0 + AdrMode + Code;
  2244.               CodeLen += 2;
  2245.               break;
  2246.             case TypeMem:
  2247.               if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2248.                 OpSize = eSymbolSize32Bit;
  2249.               switch (OpSize)
  2250.               {
  2251.                 case eSymbolSize32Bit:
  2252.                   BAsmCode[CodeLen++] = 0xd8;
  2253.                   break;
  2254.                 case eSymbolSize64Bit:
  2255.                   BAsmCode[CodeLen++] = 0xdc;
  2256.                   break;
  2257.                 case eSymbolSizeUnknown:
  2258.                   WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2259.                   CodeLen = 0;
  2260.                   break;
  2261.                 default:
  2262.                   WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
  2263.                   CodeLen = 0;
  2264.                   break;
  2265.               }
  2266.               if (CodeLen > 0)
  2267.               {
  2268.                 BAsmCode[CodeLen++] = AdrMode + Code;
  2269.                 append_adr_vals();
  2270.               }
  2271.               break;
  2272.             default:
  2273.               break;
  2274.           }
  2275.         }
  2276.         break;
  2277.       default:
  2278.         break;
  2279.     }
  2280.   }
  2281.   AddPrefixes();
  2282. }
  2283.  
  2284. /*!------------------------------------------------------------------------
  2285.  * \fn     DecodeFIADD_FIMUL(Word Code)
  2286.  * \brief  decode FIADD/FIMUL instructions
  2287.  * \param  Code machine code
  2288.  * ------------------------------------------------------------------------ */
  2289.  
  2290. static void DecodeFIADD_FIMUL(Word Code)
  2291. {
  2292.   const tStrComp *pArg1 = &ArgStr[1],
  2293.                  *pArg2 = &ArgStr[2];
  2294.  
  2295.   if (!FPUEntry(&Code))
  2296.     return;
  2297.  
  2298.   if (ArgCnt == 1)
  2299.   {
  2300.     pArg2 = &ArgStr[1];
  2301.     pArg1 = &ArgST;
  2302.   }
  2303.   if (ChkArgCnt(1, 2))
  2304.   {
  2305.     switch (DecodeAdr(pArg1, MTypeFReg))
  2306.     {
  2307.       case TypeFReg:
  2308.         if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  2309.         else
  2310.         {
  2311.           OpSize = eSymbolSizeUnknown;
  2312.           switch (DecodeAdr(pArg2, MTypeMem))
  2313.           {
  2314.             case TypeMem:
  2315.               if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2316.                 OpSize = eSymbolSize16Bit;
  2317.               switch (OpSize)
  2318.               {
  2319.                 case eSymbolSize16Bit:
  2320.                   BAsmCode[CodeLen++] = 0xde;
  2321.                   break;
  2322.                 case eSymbolSize32Bit:
  2323.                   BAsmCode[CodeLen++] = 0xda;
  2324.                   break;
  2325.                 case eSymbolSizeUnknown:
  2326.                   WrStrErrorPos(ErrNum_UndefOpSizes, pArg1);
  2327.                   CodeLen = 0;
  2328.                   break;
  2329.                 default:
  2330.                   WrStrErrorPos(ErrNum_InvOpSize, pArg1);
  2331.                   CodeLen = 0;
  2332.                   break;
  2333.               }
  2334.               if (CodeLen > 0)
  2335.               {
  2336.                 BAsmCode[CodeLen++] = AdrMode + Code;
  2337.                 append_adr_vals();
  2338.               }
  2339.               break;
  2340.             default:
  2341.               break;
  2342.           }
  2343.         }
  2344.         break;
  2345.       default:
  2346.         break;
  2347.     }
  2348.   }
  2349.   AddPrefixes();
  2350. }
  2351.  
  2352. /*!------------------------------------------------------------------------
  2353.  * \fn     DecodeFADDP_FMULP(Word Code)
  2354.  * \brief  handle FADDP/FMULP instructions
  2355.  * \param  Code machine code
  2356.  * ------------------------------------------------------------------------ */
  2357.  
  2358. static void DecodeFADDP_FMULP(Word Code)
  2359. {
  2360.   if (!FPUEntry(&Code))
  2361.     return;
  2362.  
  2363.   if (ChkArgCnt(2, 2))
  2364.   {
  2365.     switch (DecodeAdr(&ArgStr[2], MTypeFReg))
  2366.     {
  2367.       case TypeFReg:
  2368.         if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2369.         else
  2370.         {
  2371.           switch (DecodeAdr(&ArgStr[1], MTypeFReg))
  2372.           {
  2373.             case TypeFReg:
  2374.               BAsmCode[CodeLen] = 0xde;
  2375.               BAsmCode[CodeLen + 1] = 0xc0 + AdrMode + Code;
  2376.               CodeLen += 2;
  2377.             default:
  2378.               break;
  2379.           }
  2380.         }
  2381.         break;
  2382.       default:
  2383.         break;
  2384.     }
  2385.   }
  2386.   AddPrefixes();
  2387. }
  2388.  
  2389. /*!------------------------------------------------------------------------
  2390.  * \fn     DecodeFSUB_FSUBR_FDIV_FDIVR(Word Code)
  2391.  * \brief  handle FSUB(R)/FDIV(R) instructions
  2392.  * \param  Code machine code
  2393.  * ------------------------------------------------------------------------ */
  2394.  
  2395. static void DecodeFSUB_FSUBR_FDIV_FDIVR(Word Code)
  2396. {
  2397.   if (!FPUEntry(&Code))
  2398.     return;
  2399.  
  2400.   if (ArgCnt == 0)
  2401.   {
  2402.     BAsmCode[CodeLen] = 0xde;
  2403.     BAsmCode[CodeLen + 1] = 0xe1 + (Code ^ 8);
  2404.     CodeLen += 2;
  2405.   }
  2406.   else if (ChkArgCnt(0, 2))
  2407.   {
  2408.     const tStrComp *pArg1 = &ArgStr[1],
  2409.                    *pArg2 = &ArgStr[2];
  2410.  
  2411.     if (ArgCnt == 1)
  2412.     {
  2413.       pArg1 = &ArgST;
  2414.       pArg2 = &ArgStr[1];
  2415.     }
  2416.  
  2417.     switch (DecodeAdr(pArg1, MTypeFReg))
  2418.     {
  2419.       case TypeFReg:
  2420.         OpSize = eSymbolSizeUnknown;
  2421.         if (AdrMode != 0)   /* ST(i) ist Ziel */
  2422.         {
  2423.           BAsmCode[CodeLen + 1] = AdrMode;
  2424.           switch (DecodeAdr(pArg2, MTypeFReg))
  2425.           {
  2426.             case TypeFReg:
  2427.               if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
  2428.               else
  2429.               {
  2430.                 BAsmCode[CodeLen] = 0xdc;
  2431.                 BAsmCode[CodeLen + 1] += 0xe0 + (Code ^ 8);
  2432.                 CodeLen += 2;
  2433.               }
  2434.               break;
  2435.             default:
  2436.               break;
  2437.           }
  2438.         }
  2439.         else  /* ST ist Ziel */
  2440.         {
  2441.           switch (DecodeAdr(pArg2, MTypeFReg | MTypeMem))
  2442.           {
  2443.             case TypeFReg:
  2444.               BAsmCode[CodeLen] = 0xd8;
  2445.               BAsmCode[CodeLen + 1] = 0xe0 + AdrMode + Code;
  2446.               CodeLen += 2;
  2447.               break;
  2448.             case TypeMem:
  2449.               if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2450.                 OpSize = eSymbolSize32Bit;
  2451.               switch (OpSize)
  2452.               {
  2453.                 case eSymbolSize32Bit:
  2454.                   BAsmCode[CodeLen++] = 0xd8;
  2455.                   break;
  2456.                 case eSymbolSize64Bit:
  2457.                   BAsmCode[CodeLen++] = 0xdc;
  2458.                   break;
  2459.                 case eSymbolSizeUnknown:
  2460.                   WrStrErrorPos(ErrNum_UndefOpSizes, pArg2);
  2461.                   CodeLen = 0;
  2462.                   break;
  2463.                 default:
  2464.                   WrStrErrorPos(ErrNum_InvOpSize, pArg2);
  2465.                   CodeLen = 0;
  2466.                   break;
  2467.               }
  2468.               if (CodeLen > 0)
  2469.               {
  2470.                 BAsmCode[CodeLen++] = AdrMode + 0x20 + Code;
  2471.                 append_adr_vals();
  2472.               }
  2473.               break;
  2474.             default:
  2475.               break;
  2476.           }
  2477.         }
  2478.         break;
  2479.       default:
  2480.         break;
  2481.     }
  2482.   }
  2483.   AddPrefixes();
  2484. }
  2485.  
  2486. /*!------------------------------------------------------------------------
  2487.  * \fn     DecodeFISUB_FISUBR_FIDIV_FIDIVR(Word Code)
  2488.  * \brief  handle FISUB(R)/FIDIV(R) instructions
  2489.  * \param  Code machine code
  2490.  * ------------------------------------------------------------------------ */
  2491.  
  2492. static void DecodeFISUB_FISUBR_FIDIV_FIDIVR(Word Code)
  2493. {
  2494.   if (!FPUEntry(&Code))
  2495.     return;
  2496.  
  2497.   if (ChkArgCnt(1, 2))
  2498.   {
  2499.     const tStrComp *pArg1 = &ArgStr[1],
  2500.                    *pArg2 = &ArgStr[2];
  2501.  
  2502.     if (ArgCnt == 1)
  2503.     {
  2504.       pArg1 = &ArgST;
  2505.       pArg2 = &ArgStr[1];
  2506.     }
  2507.  
  2508.     switch (DecodeAdr(pArg1, MTypeFReg))
  2509.     {
  2510.       case TypeFReg:
  2511.         if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  2512.         else
  2513.         {
  2514.           OpSize = eSymbolSizeUnknown;
  2515.           switch (DecodeAdr(pArg2, MTypeMem))
  2516.           {
  2517.             case TypeMem:
  2518.               if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
  2519.                 OpSize = eSymbolSize16Bit;
  2520.               switch (OpSize)
  2521.               {
  2522.                 case eSymbolSize16Bit:
  2523.                   BAsmCode[CodeLen++] = 0xde;
  2524.                   break;
  2525.                 case eSymbolSize32Bit:
  2526.                   BAsmCode[CodeLen++] = 0xda;
  2527.                   break;
  2528.                 case eSymbolSizeUnknown:
  2529.                   WrStrErrorPos(ErrNum_UndefOpSizes, pArg2);
  2530.                   CodeLen = 0;
  2531.                   break;
  2532.                 default:
  2533.                   WrStrErrorPos(ErrNum_InvOpSize, pArg2);
  2534.                   CodeLen = 0;
  2535.                   break;
  2536.               }
  2537.               if (CodeLen > 0)
  2538.               {
  2539.                 BAsmCode[CodeLen++] = AdrMode + 0x20 + Code;
  2540.                 append_adr_vals();
  2541.               }
  2542.               break;
  2543.             default:
  2544.               break;
  2545.           }
  2546.         }
  2547.         break;
  2548.       default:
  2549.         break;
  2550.     }
  2551.   }
  2552.   AddPrefixes();
  2553. }
  2554.  
  2555. /*!------------------------------------------------------------------------
  2556.  * \fn     DecodeFSUBP_FSUBRP_FDIVP_FDIVRP(Word Code)
  2557.  * \brief  handle FSUB(R)P/FDIV(R)P instructions
  2558.  * \param  Code machine code
  2559.  * ------------------------------------------------------------------------ */
  2560.  
  2561. static void DecodeFSUBP_FSUBRP_FDIVP_FDIVRP(Word Code)
  2562. {
  2563.   if (!FPUEntry(&Code))
  2564.     return;
  2565.  
  2566.   if (ChkArgCnt(2, 2))
  2567.   {
  2568.     switch (DecodeAdr(&ArgStr[2], MTypeFReg))
  2569.     {
  2570.       case TypeFReg:
  2571.         if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2572.         else
  2573.         {
  2574.           switch (DecodeAdr(&ArgStr[1], MTypeFReg))
  2575.           {
  2576.             case TypeFReg:
  2577.               BAsmCode[CodeLen] = 0xde;
  2578.               BAsmCode[CodeLen+1] = 0xe0 + AdrMode + (Code ^ 8);
  2579.               CodeLen += 2;
  2580.               break;
  2581.             default:
  2582.               break;
  2583.           }
  2584.         }
  2585.         break;
  2586.       default:
  2587.         break;
  2588.     }
  2589.   }
  2590.   AddPrefixes();
  2591. }
  2592.  
  2593. /*!------------------------------------------------------------------------
  2594.  * \fn     DecodeFPU16(Word Code)
  2595.  * \brief  handle FPU instructions with one 16 bit memory argument
  2596.  * \param  Code machine code
  2597.  * ------------------------------------------------------------------------ */
  2598.  
  2599. static void DecodeFPU16(Word Code)
  2600. {
  2601.   if (!FPUEntry(&Code))
  2602.     return;
  2603.  
  2604.   if (ChkArgCnt(1, 1))
  2605.   {
  2606.     OpSize = eSymbolSize16Bit;
  2607.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  2608.     {
  2609.       case TypeMem:
  2610.         PutCode(Code);
  2611.         BAsmCode[CodeLen - 1] += AdrMode;
  2612.         copy_adr_vals(0);
  2613.         CodeLen += AdrCnt;
  2614.         break;
  2615.       default:
  2616.         break;
  2617.     }
  2618.   }
  2619.   AddPrefixes();
  2620. }
  2621.  
  2622. /*!------------------------------------------------------------------------
  2623.  * \fn     DecodeFSAVE_FRSTOR(Word Code)
  2624.  * \brief  handle FSAVE/FRSTOR instructions
  2625.  * \param  Code machine code
  2626.  * ------------------------------------------------------------------------ */
  2627.  
  2628. static void DecodeFSAVE_FRSTOR(Word Code)
  2629. {
  2630.   if (!FPUEntry(&Code))
  2631.     return;
  2632.  
  2633.   if (ChkArgCnt(1, 1))
  2634.   {
  2635.     switch (DecodeAdr(&ArgStr[1], MTypeMem))
  2636.     {
  2637.       case TypeMem:
  2638.         BAsmCode[CodeLen] = 0xdd;
  2639.         BAsmCode[CodeLen + 1] = AdrMode + Code;
  2640.         copy_adr_vals(2);
  2641.         CodeLen += 2 + AdrCnt;
  2642.         break;
  2643.       default:
  2644.         break;
  2645.     }
  2646.   }
  2647.   AddPrefixes();
  2648. }
  2649.  
  2650. /*!------------------------------------------------------------------------
  2651.  * \fn     DecodeRept(Word Index)
  2652.  * \brief  handle repetition instructions
  2653.  * \param  Index index into instruction table
  2654.  * ------------------------------------------------------------------------ */
  2655.  
  2656. static void DecodeRept(Word Index)
  2657. {
  2658.   const FixedOrder *pOrder = ReptOrders + Index;
  2659.  
  2660.   if (ChkArgCnt(1, 1)
  2661.    && check_core_mask(pOrder->core_mask))
  2662.   {
  2663.     unsigned z2;
  2664.  
  2665.     for (z2 = 0; z2 < StringOrderCnt; z2++)
  2666.       if (!as_strcasecmp(StringOrders[z2].Name, ArgStr[1].str.p_str))
  2667.         break;
  2668.     if (z2 >= StringOrderCnt) WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
  2669.     else if (check_core_mask(StringOrders[z2].core_mask))
  2670.     {
  2671.       PutCode(pOrder->Code);
  2672.       PutCode(StringOrders[z2].Code);
  2673.     }
  2674.   }
  2675.   AddPrefixes();
  2676. }
  2677.  
  2678. /*!------------------------------------------------------------------------
  2679.  * \fn     DecodeMul(Word Index)
  2680.  * \brief  handle multiplication instructions
  2681.  * \param  Index machine code
  2682.  * ------------------------------------------------------------------------ */
  2683.  
  2684. static void DecodeMul(Word Index)
  2685. {
  2686.   Boolean OK;
  2687.   Word AdrWord;
  2688.  
  2689.   if (!ChkArgCnt(1, (1 == Index) ? 3 : 1)) /* IMUL only 2/3 ops */
  2690.     return;
  2691.  
  2692.   switch (ArgCnt)
  2693.   {
  2694.     case 1:
  2695.       switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
  2696.       {
  2697.         case TypeReg8:
  2698.         case TypeReg16:
  2699.           BAsmCode[CodeLen] = 0xf6 + OpSize;
  2700.           BAsmCode[CodeLen + 1] = 0xe0 + (Index << 3) + AdrMode;
  2701.           CodeLen += 2;
  2702.           break;
  2703.         case TypeMem:
  2704.           MinOneIs0();
  2705.           if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2706.           else
  2707.           {
  2708.             BAsmCode[CodeLen] = 0xf6 + OpSize;
  2709.             BAsmCode[CodeLen+1] = 0x20 + (Index << 3) + AdrMode;
  2710.             copy_adr_vals(2);
  2711.             CodeLen += 2 + AdrCnt;
  2712.           }
  2713.           break;
  2714.         default:
  2715.           break;
  2716.       }
  2717.       break;
  2718.     case 2:
  2719.     case 3:
  2720.       if (check_core_mask(e_core_all_186))
  2721.       {
  2722.         tStrComp *pArg1 = &ArgStr[1],
  2723.                  *pArg2 = (ArgCnt == 2) ? &ArgStr[1] : &ArgStr[2],
  2724.                  *pArg3 = (ArgCnt == 2) ? &ArgStr[2] : &ArgStr[3];
  2725.  
  2726.         BAsmCode[CodeLen] = 0x69;
  2727.         switch (DecodeAdr(pArg1, MTypeReg16))
  2728.         {
  2729.           case TypeReg16:
  2730.             BAsmCode[CodeLen + 1] = (AdrMode << 3);
  2731.             switch (DecodeAdr(pArg2, MTypeReg16 | MTypeMem))
  2732.             {
  2733.               case TypeReg16:
  2734.                 AdrMode += 0xc0;
  2735.                 /* FALL-THRU */
  2736.               case TypeMem:
  2737.                 BAsmCode[CodeLen + 1] += AdrMode;
  2738.                 copy_adr_vals(2);
  2739.                 AdrWord = EvalStrIntExpression(pArg3, Int16, &OK);
  2740.                 if (OK)
  2741.                 {
  2742.                   BAsmCode[CodeLen + 2 + AdrCnt] = Lo(AdrWord);
  2743.                   BAsmCode[CodeLen + 3 + AdrCnt] = Hi(AdrWord);
  2744.                   CodeLen += 2 + AdrCnt + 2;
  2745.                   if ((AdrWord >= 0xff80) || (AdrWord < 0x80))
  2746.                   {
  2747.                     CodeLen--;
  2748.                     BAsmCode[CodeLen-AdrCnt - 2 - 1] += 2;
  2749.                   }
  2750.                 }
  2751.                 break;
  2752.               default:
  2753.                 break;
  2754.             }
  2755.             break;
  2756.           default:
  2757.             break;
  2758.         }
  2759.       }
  2760.       break;
  2761.   }
  2762.   AddPrefixes();
  2763. }
  2764.  
  2765. /*!------------------------------------------------------------------------
  2766.  * \fn     DecodeModReg(Word Index)
  2767.  * \brief  handle instructions with one mod/reg argument
  2768.  * \param  Index index into instruction table
  2769.  * ------------------------------------------------------------------------ */
  2770.  
  2771. static void DecodeModReg(Word Index)
  2772. {
  2773.   const ModRegOrder *pOrder = ModRegOrders + Index;
  2774.  
  2775.   NoSegCheck = pOrder->no_seg_check;
  2776.   if (ChkArgCnt(2, 2)
  2777.    && check_core_mask(pOrder->core_mask))
  2778.     decode_mod_reg_core(pOrder->Code, pOrder->no_seg_check, 1);
  2779. }
  2780.  
  2781. /*!------------------------------------------------------------------------
  2782.  * \fn     DecodeShift(Word Index)
  2783.  * \brief  handle shift instructions
  2784.  * \param  Index index into instruction table
  2785.  * ------------------------------------------------------------------------ */
  2786.  
  2787. static void DecodeShift(Word Index)
  2788. {
  2789.   const FixedOrder *pOrder = ShiftOrders + Index;
  2790.  
  2791.   if (ChkArgCnt(2, 2)
  2792.    && check_core_mask(pOrder->core_mask))
  2793.   {
  2794.     DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem);
  2795.     MinOneIs0();
  2796.     if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2797.     else switch (AdrType)
  2798.     {
  2799.       case TypeReg8:
  2800.       case TypeReg16:
  2801.       case TypeMem:
  2802.         BAsmCode[CodeLen] = OpSize;
  2803.         BAsmCode[CodeLen + 1] = AdrMode + (pOrder->Code << 3);
  2804.         if (AdrType != TypeMem)
  2805.           BAsmCode[CodeLen + 1] += 0xc0;
  2806.         copy_adr_vals(2);
  2807.         if (!as_strcasecmp(ArgStr[2].str.p_str, "CL"))
  2808.         {
  2809.           BAsmCode[CodeLen] += 0xd2;
  2810.           CodeLen += 2 + AdrCnt;
  2811.         }
  2812.         else
  2813.         {
  2814.           Boolean OK;
  2815.  
  2816.           BAsmCode[CodeLen + 2 + AdrCnt] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  2817.           if (OK)
  2818.           {
  2819.             if (BAsmCode[CodeLen + 2 + AdrCnt] == 1)
  2820.             {
  2821.               BAsmCode[CodeLen] += 0xd0;
  2822.               CodeLen += 2 + AdrCnt;
  2823.             }
  2824.             else if (check_core_mask(e_core_all_186))
  2825.             {
  2826.               BAsmCode[CodeLen] += 0xc0;
  2827.               CodeLen += 3 + AdrCnt;
  2828.             }
  2829.           }
  2830.         }
  2831.         break;
  2832.       default:
  2833.         break;
  2834.     }
  2835.   }
  2836.   AddPrefixes();
  2837. }
  2838.  
  2839. /*!------------------------------------------------------------------------
  2840.  * \fn     DecodeROL4_ROR4(Word Code)
  2841.  * \brief  handle V20 ROL4/ROR4 instructions
  2842.  * \param  Code machine code
  2843.  * ------------------------------------------------------------------------ */
  2844.  
  2845. static void DecodeROL4_ROR4(Word Code)
  2846. {
  2847.   if (ChkArgCnt(1, 1)
  2848.    && check_core_mask(e_core_all_v))
  2849.   {
  2850.     BAsmCode[CodeLen    ] = 0x0f;
  2851.     BAsmCode[CodeLen + 1] = Code;
  2852.     switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeMem))
  2853.     {
  2854.       case TypeReg8:
  2855.         /* TODO: convert mode */
  2856.         BAsmCode[CodeLen + 2] = 0xc0 + AdrMode;
  2857.         CodeLen += 3;
  2858.         break;
  2859.       case TypeMem:
  2860.         BAsmCode[CodeLen + 2] = AdrMode;
  2861.         copy_adr_vals(3);
  2862.         CodeLen += 3 + AdrCnt;
  2863.         break;
  2864.       default:
  2865.         break;
  2866.     }
  2867.   }
  2868.   AddPrefixes();
  2869. }
  2870.  
  2871. /*!------------------------------------------------------------------------
  2872.  * \fn     DecodeBit1(Word Index)
  2873.  * \brief  Handle V30-specific bit instructions (NOT1, CLR1, SET1, TEST1)
  2874.  * \param  Index machine code index
  2875.  * ------------------------------------------------------------------------ */
  2876.  
  2877. static void DecodeBit1(Word Index)
  2878. {
  2879.   int min_arg_cnt = (Index == 0) ? 2 : 1;
  2880.   if (!check_core_mask(e_core_all_v))
  2881.     return;
  2882.  
  2883.   switch (ArgCnt)
  2884.   {
  2885.     case 2:
  2886.       switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
  2887.       {
  2888.         case TypeReg8:
  2889.         case TypeReg16:
  2890.           AdrMode += 0xc0;
  2891.           /* FALL-THRU */
  2892.         case TypeMem:
  2893.           MinOneIs0();
  2894.           if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2895.           else
  2896.           {
  2897.             BAsmCode[CodeLen    ] = 0x0f;
  2898.             BAsmCode[CodeLen + 1] = 0x10 + (Index << 1) + OpSize;
  2899.             BAsmCode[CodeLen + 2] = AdrMode;
  2900.             copy_adr_vals(3);
  2901.             if (!as_strcasecmp(ArgStr[2].str.p_str, "CL"))
  2902.               CodeLen += 3 + AdrCnt;
  2903.             else
  2904.             {
  2905.               Boolean OK;
  2906.  
  2907.               BAsmCode[CodeLen + 1] += 8;
  2908.               BAsmCode[CodeLen + 3 + AdrCnt] = EvalStrIntExpression(&ArgStr[2], Int4, &OK);
  2909.               if (OK)
  2910.                 CodeLen += 4 + AdrCnt;
  2911.             }
  2912.           }
  2913.           break;
  2914.         default:
  2915.           break;
  2916.       }
  2917.       break;
  2918.  
  2919.     case 1:
  2920.       if (min_arg_cnt > 1)
  2921.         goto bad_arg_cnt;
  2922.       if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2923.       BAsmCode[CodeLen++] = Index == 3 ? 0xf5 : (Index + 0xf7);
  2924.       break;
  2925.  
  2926.     bad_arg_cnt:
  2927.     default:
  2928.       (void)ChkArgCnt(min_arg_cnt, 2);
  2929.   }
  2930.   AddPrefixes();
  2931. }
  2932.  
  2933. /*!------------------------------------------------------------------------
  2934.  * \fn     DecodeBSCH(Word Index)
  2935.  * \brief  Handle V55-specific BSCH instruction
  2936.  * \param  code machine code
  2937.  * ------------------------------------------------------------------------ */
  2938.  
  2939. static void DecodeBSCH(Word code)
  2940. {
  2941.   if (check_core_mask(e_core_all_v55) && ChkArgCnt(1, 1))
  2942.     switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
  2943.     {
  2944.       case TypeReg8:
  2945.       case TypeReg16:
  2946.         AdrMode += 0xc0;
  2947.         /* FALL-THRU */
  2948.       case TypeMem:
  2949.         MinOneIs0();
  2950.         if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
  2951.         PutCode(code + OpSize);
  2952.         BAsmCode[CodeLen++] = AdrMode;
  2953.         copy_adr_vals(3);
  2954.         break;
  2955.       default:
  2956.         break;
  2957.     }
  2958.   AddPrefixes();
  2959. }
  2960.  
  2961. /*!------------------------------------------------------------------------
  2962.  * \fn     DecodeRSTWDT(Word code)
  2963.  * \brief  handle RSTWDT instruction
  2964.  * \param  code machine code
  2965.  * ------------------------------------------------------------------------ */
  2966.  
  2967. static void DecodeRSTWDT(Word code)
  2968. {
  2969.   if (check_core_mask(e_core_all_v55)
  2970.    && ChkArgCnt(2, 2))
  2971.   {
  2972.     Boolean ok;
  2973.  
  2974.     BAsmCode[2] = EvalStrIntExpression(&ArgStr[1], Int8, &ok);
  2975.     if (ok)
  2976.       BAsmCode[3] = EvalStrIntExpression(&ArgStr[2], Int8, &ok);
  2977.     if (ok)
  2978.     {
  2979.       PutCode(code);
  2980.       CodeLen += 2;
  2981.     }
  2982.   }
  2983. }
  2984.  
  2985. /*!------------------------------------------------------------------------
  2986.  * \fn     DecodeBTCLRL(Word code)
  2987.  * \brief  handle BTCLRL instruction
  2988.  * \param  code machine code
  2989.  * ------------------------------------------------------------------------ */
  2990.  
  2991. static void DecodeBTCLRL(Word code)
  2992. {
  2993.   if (check_core_mask(e_core_all_v55)
  2994.    && ChkArgCnt(3, 3))
  2995.   {
  2996.     Boolean ok;
  2997.  
  2998.     PutCode(code);
  2999.     BAsmCode[CodeLen++] = EvalStrIntExpression(&ArgStr[1], Int8, &ok);
  3000.     if (ok)
  3001.       BAsmCode[CodeLen++] = EvalStrIntExpression(&ArgStr[2], Int8, &ok);
  3002.     if (ok)
  3003.       append_rel(&ArgStr[3]);
  3004.   }
  3005. }
  3006.  
  3007. /*!------------------------------------------------------------------------
  3008.  * \fn     DecodeINS_EXT(Word Code)
  3009.  * \brief  Handle V30-specific bit field instructions (INS, EXT)
  3010.  * ------------------------------------------------------------------------ */
  3011.  
  3012. static void DecodeINS_EXT(Word Code)
  3013. {
  3014.   if (ChkArgCnt(2, 2)
  3015.    && check_core_mask(e_core_all_v))
  3016.   {
  3017.     if (DecodeAdr(&ArgStr[1], MTypeReg8) == TypeReg8)
  3018.     {
  3019.       BAsmCode[CodeLen    ] = 0x0f;
  3020.       BAsmCode[CodeLen + 1] = Code;
  3021.       BAsmCode[CodeLen + 2] = 0xc0 + AdrMode;
  3022.       switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeImm))
  3023.       {
  3024.         case TypeReg8:
  3025.           BAsmCode[CodeLen + 2] += (AdrMode << 3);
  3026.           CodeLen += 3;
  3027.           break;
  3028.         case TypeImm:
  3029.           if (AdrVals[0] > 15) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
  3030.           else
  3031.           {
  3032.             BAsmCode[CodeLen + 1] += 8;
  3033.             BAsmCode[CodeLen + 3] = AdrVals[0];
  3034.             CodeLen += 4;
  3035.           }
  3036.           break;
  3037.         default:
  3038.           break;
  3039.       }
  3040.     }
  3041.   }
  3042.   AddPrefixes();
  3043. }
  3044.  
  3045. /*!------------------------------------------------------------------------
  3046.  * \fn     DecodeFPO2(Word Code)
  3047.  * \brief  handle FPO2 instruction
  3048.  * ------------------------------------------------------------------------ */
  3049.  
  3050. static void DecodeFPO2(Word Code)
  3051. {
  3052.   UNUSED(Code);
  3053.  
  3054.   if (ChkArgCnt(1, 2)
  3055.    && check_core_mask(e_core_all_v))
  3056.   {
  3057.     Byte AdrByte;
  3058.     Boolean OK;
  3059.  
  3060.     AdrByte = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
  3061.     if (OK)
  3062.     {
  3063.       BAsmCode[CodeLen    ] = 0x66 + (AdrByte >> 3);
  3064.       BAsmCode[CodeLen + 1] = (AdrByte & 7) << 3;
  3065.       if (ArgCnt == 1)
  3066.       {
  3067.         BAsmCode[CodeLen + 1] += 0xc0;
  3068.         CodeLen += 2;
  3069.       }
  3070.       else
  3071.       {
  3072.         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeMem))
  3073.         {
  3074.           case TypeReg8:
  3075.             BAsmCode[CodeLen + 1] += 0xc0 + AdrMode;
  3076.             CodeLen += 2;
  3077.             break;
  3078.           case TypeMem:
  3079.             BAsmCode[CodeLen + 1] += AdrMode;
  3080.             copy_adr_vals(2);
  3081.             CodeLen += 2 + AdrCnt;
  3082.             break;
  3083.           default:
  3084.             break;
  3085.         }
  3086.       }
  3087.     }
  3088.   }
  3089.   AddPrefixes();
  3090. }
  3091.  
  3092. /*!------------------------------------------------------------------------
  3093.  * \fn     DecodeBTCLR(Word Code)
  3094.  * \brief  handle BTCLR instruction
  3095.  * ------------------------------------------------------------------------ */
  3096.  
  3097. static void DecodeBTCLR(Word Code)
  3098. {
  3099.   UNUSED(Code);
  3100.  
  3101.   if (ChkArgCnt(3, 3)
  3102.    && check_core_mask(e_core_all_v35))
  3103.   {
  3104.     Boolean OK;
  3105.  
  3106.     BAsmCode[CodeLen  ] = 0x0f;
  3107.     BAsmCode[CodeLen + 1] = 0x9c;
  3108.     BAsmCode[CodeLen + 2] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
  3109.     if (OK)
  3110.     {
  3111.       BAsmCode[CodeLen + 3] = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
  3112.       if (OK)
  3113.       {
  3114.         Word AdrWord;
  3115.         tSymbolFlags Flags;
  3116.  
  3117.         AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[3], Int16, &OK, & Flags) - (EProgCounter() + 5);
  3118.         if (OK)
  3119.         {
  3120.           if (!mSymbolQuestionable(Flags) && ((AdrWord > 0x7f) && (AdrWord < 0xff80))) WrStrErrorPos(ErrNum_DistTooBig, &ArgStr[3]);
  3121.           else
  3122.           {
  3123.             BAsmCode[CodeLen + 4] = Lo(AdrWord);
  3124.             CodeLen += 5;
  3125.           }
  3126.         }
  3127.       }
  3128.     }
  3129.   }
  3130.   AddPrefixes();
  3131. }
  3132.  
  3133. /*!------------------------------------------------------------------------
  3134.  * \fn     DecodeReg16(Word Index)
  3135.  * \brief  handle instructions with one 16 bit register argument
  3136.  * \param  Index index into list of instructions
  3137.  * ------------------------------------------------------------------------ */
  3138.  
  3139. static void DecodeReg16(Word Index)
  3140. {
  3141.   const AddOrder *pOrder = Reg16Orders + Index;
  3142.  
  3143.   if (ChkArgCnt(1, 1))
  3144.   {
  3145.     switch (DecodeAdr(&ArgStr[1], MTypeReg16))
  3146.     {
  3147.       case TypeReg16:
  3148.         PutCode(pOrder->Code);
  3149.         BAsmCode[CodeLen++] = pOrder->Add + AdrMode;
  3150.         break;
  3151.       default:
  3152.         break;
  3153.     }
  3154.   }
  3155.   AddPrefixes();
  3156. }
  3157.  
  3158. /*!------------------------------------------------------------------------
  3159.  * \fn     DecodeImm16(Word index)
  3160.  * \brief  handle instructions with one immediate 16 bit argument
  3161.  * \param  index index into instruction table
  3162.  * ------------------------------------------------------------------------ */
  3163.  
  3164. static void DecodeImm16(Word index)
  3165. {
  3166.   const FixedOrder *p_order = &Imm16Orders[index];
  3167.  
  3168.   if (ChkArgCnt(1, 1)
  3169.    && check_core_mask(p_order->core_mask))
  3170.   {
  3171.     Word arg;
  3172.     Boolean ok;
  3173.  
  3174.     PutCode(p_order->Code);
  3175.     arg = EvalStrIntExpression(&ArgStr[1], Int16, &ok);
  3176.     if (ok)
  3177.     {
  3178.       BAsmCode[CodeLen++] = Lo(arg);
  3179.       BAsmCode[CodeLen++] = Hi(arg);
  3180.     }
  3181.     else
  3182.       CodeLen = 0;
  3183.   }
  3184. }
  3185.  
  3186. /*!------------------------------------------------------------------------
  3187.  * \fn     DecodeString(Word Index)
  3188.  * \brief  handle string instructions
  3189.  * \param  Index index into instruction table
  3190.  * ------------------------------------------------------------------------ */
  3191.  
  3192. static void DecodeString(Word Index)
  3193. {
  3194.   const FixedOrder *pOrder = StringOrders + Index;
  3195.  
  3196.   if (ChkArgCnt(0, 0)
  3197.    && check_core_mask(pOrder->core_mask))
  3198.     PutCode(pOrder->Code);
  3199.   AddPrefixes();
  3200. }
  3201.  
  3202. /*---------------------------------------------------------------------------*/
  3203.  
  3204. /*!------------------------------------------------------------------------
  3205.  * \fn     InitFields(void)
  3206.  * \brief  create/initialize dynamic instruction and hash tables
  3207.  * ------------------------------------------------------------------------ */
  3208.  
  3209. static void AddFPU(const char *NName, Word NCode, InstProc NProc)
  3210. {
  3211.   char Instr[30];
  3212.  
  3213.   AddInstTable(InstTable, NName, NCode, NProc);
  3214.   as_snprintf(Instr, sizeof(Instr), "%cN%s", *NName, NName + 1);
  3215.   AddInstTable(InstTable, Instr, NCode | NO_FWAIT_FLAG, NProc);
  3216. }
  3217.  
  3218. static void AddFixed(const char *NName, Byte core_mask, Word NCode)
  3219. {
  3220.   order_array_rsv_end(FixedOrders, FixedOrder);
  3221.   FixedOrders[InstrZ].core_mask = core_mask;
  3222.   FixedOrders[InstrZ].Code = NCode;
  3223.   AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
  3224. }
  3225.  
  3226. static void AddBrk(const char *NName, Byte core_mask, Word NCode)
  3227. {
  3228.   order_array_rsv_end(BrkOrders, FixedOrder);
  3229.   BrkOrders[InstrZ].core_mask = core_mask;
  3230.   BrkOrders[InstrZ].Code = NCode;
  3231.   AddInstTable(InstTable, NName, InstrZ++, DecodeBrk);
  3232. }
  3233.  
  3234. static void AddFPUFixed(const char *NName, Word NCode)
  3235. {
  3236.   AddFPU(NName, NCode, DecodeFPUFixed);
  3237. }
  3238.  
  3239. static void AddFPUSt(const char *NName, Word NCode)
  3240. {
  3241.   AddFPU(NName, NCode, DecodeFPUSt);
  3242. }
  3243.  
  3244. static void AddFPU16(const char *NName, Word NCode)
  3245. {
  3246.   AddFPU(NName, NCode, DecodeFPU16);
  3247. }
  3248.  
  3249. static void AddString(const char *NName, Byte core_mask, Word NCode)
  3250. {
  3251.   order_array_rsv_end(StringOrders, FixedOrder);
  3252.   StringOrders[InstrZ].Name = NName;
  3253.   StringOrders[InstrZ].core_mask = core_mask;
  3254.   StringOrders[InstrZ].Code = NCode;
  3255.   AddInstTable(InstTable, NName, InstrZ++, DecodeString);
  3256. }
  3257.  
  3258. static void AddRept(const char *NName, Byte core_mask, Word NCode)
  3259. {
  3260.   order_array_rsv_end(ReptOrders, FixedOrder);
  3261.   ReptOrders[InstrZ].Code = NCode;
  3262.   ReptOrders[InstrZ].core_mask = core_mask;
  3263.   AddInstTable(InstTable, NName, InstrZ++, DecodeRept);
  3264. }
  3265.  
  3266. static void AddRel(const char *NName, Byte core_mask, Word NCode)
  3267. {
  3268.   order_array_rsv_end(RelOrders, FixedOrder);
  3269.   RelOrders[InstrZ].core_mask = core_mask;
  3270.   RelOrders[InstrZ].Code = NCode;
  3271.   AddInstTable(InstTable, NName, InstrZ++, DecodeRel);
  3272. }
  3273.  
  3274. static void AddModReg(const char *NName, Byte core_mask, Word NCode, Boolean no_seg_check)
  3275. {
  3276.   order_array_rsv_end(ModRegOrders, ModRegOrder);
  3277.   ModRegOrders[InstrZ].core_mask = core_mask;
  3278.   ModRegOrders[InstrZ].Code = NCode;
  3279.   ModRegOrders[InstrZ].no_seg_check = no_seg_check;
  3280.   AddInstTable(InstTable, NName, InstrZ++, DecodeModReg);
  3281. }
  3282.  
  3283. static void AddShift(const char *NName, Byte core_mask, Word NCode)
  3284. {
  3285.   order_array_rsv_end(ShiftOrders, FixedOrder);
  3286.   ShiftOrders[InstrZ].core_mask = core_mask;
  3287.   ShiftOrders[InstrZ].Code = NCode;
  3288.   AddInstTable(InstTable, NName, InstrZ++, DecodeShift);
  3289. }
  3290.  
  3291. static void AddReg16(const char *NName, CPUVar NMin, Word NCode, Byte NAdd)
  3292. {
  3293.   order_array_rsv_end(Reg16Orders, AddOrder);
  3294.   Reg16Orders[InstrZ].MinCPU = NMin;
  3295.   Reg16Orders[InstrZ].Code = NCode;
  3296.   Reg16Orders[InstrZ].Add = NAdd;
  3297.   AddInstTable(InstTable, NName, InstrZ++, DecodeReg16);
  3298. }
  3299.  
  3300. static void AddImm16(const char *NName, Byte core_mask, Word code)
  3301. {
  3302.   order_array_rsv_end(Imm16Orders, FixedOrder);
  3303.   Imm16Orders[InstrZ].core_mask = core_mask;
  3304.   Imm16Orders[InstrZ].Code = code;
  3305.   AddInstTable(InstTable, NName, InstrZ++, DecodeImm16);
  3306. }
  3307.  
  3308. static void InitFields(void)
  3309. {
  3310.   InstTable = CreateInstTable(403);
  3311.   SetDynamicInstTable(InstTable);
  3312.  
  3313.   AddInstTable(InstTable, "MOV"  , 0, DecodeMOV);
  3314.   AddInstTable(InstTable, "INC"  , 0, DecodeINCDEC);
  3315.   AddInstTable(InstTable, "DEC"  , 8, DecodeINCDEC);
  3316.   AddInstTable(InstTable, "INT"  , 0, DecodeINT);
  3317.   AddInstTable(InstTable, "IN"   , 0, DecodeINOUT);
  3318.   AddInstTable(InstTable, "OUT"  , 2, DecodeINOUT);
  3319.   AddInstTable(InstTable, "CALL" , 0, DecodeCALLJMP);
  3320.   AddInstTable(InstTable, "JMP"  , 1, DecodeCALLJMP);
  3321.   AddInstTable(InstTable, "PUSH" , 0, DecodePUSHPOP);
  3322.   AddInstTable(InstTable, "POP"  , 1, DecodePUSHPOP);
  3323.   AddInstTable(InstTable, "NOT"  , 0, DecodeNOTNEG);
  3324.   AddInstTable(InstTable, "NEG"  , 8, DecodeNOTNEG);
  3325.   AddInstTable(InstTable, "RET"  , 0, DecodeRET);
  3326.   AddInstTable(InstTable, "RETF" , 8, DecodeRET);
  3327.   AddInstTable(InstTable, "TEST" , 0, DecodeTEST);
  3328.   AddInstTable(InstTable, "XCHG" , 0, DecodeXCHG);
  3329.   AddInstTable(InstTable, "CALLF", 0x189a, DecodeCALLJMPF);
  3330.   AddInstTable(InstTable, "JMPF" , 0x28ea, DecodeCALLJMPF);
  3331.   AddInstTable(InstTable, "ENTER", 0, DecodeENTER);
  3332.   AddInstTable(InstTable, "PORT", 0, DecodePORT);
  3333.   AddInstTable(InstTable, "ROL4", 0x28, DecodeROL4_ROR4);
  3334.   AddInstTable(InstTable, "ROR4", 0x2a, DecodeROL4_ROR4);
  3335.   AddInstTable(InstTable, "INS", 0x31, DecodeINS_EXT);
  3336.   AddInstTable(InstTable, "EXT", 0x33, DecodeINS_EXT);
  3337.   AddInstTable(InstTable, "FPO2", 0, DecodeFPO2);
  3338.   AddInstTable(InstTable, "BTCLR", 0, DecodeBTCLR);
  3339.   AddFPU("FLD", 0, DecodeFLD);
  3340.   AddFPU("FILD", 0, DecodeFILD);
  3341.   AddFPU("FBLD", 0, DecodeFBLD);
  3342.   AddFPU("FST", 0xd0, DecodeFST_FSTP);
  3343.   AddFPU("FSTP", 0xd8, DecodeFST_FSTP);
  3344.   AddFPU("FIST", 0x10, DecodeFIST_FISTP);
  3345.   AddFPU("FISTP", 0x18, DecodeFIST_FISTP);
  3346.   AddFPU("FBSTP", 0, DecodeFBSTP);
  3347.   AddFPU("FCOM", 0xd0, DecodeFCOM_FCOMP);
  3348.   AddFPU("FCOMP", 0xd8, DecodeFCOM_FCOMP);
  3349.   AddFPU("FICOM", 0x10, DecodeFICOM_FICOMP);
  3350.   AddFPU("FICOMP", 0x18, DecodeFICOM_FICOMP);
  3351.   AddFPU("FADD", 0, DecodeFADD_FMUL);
  3352.   AddFPU("FMUL", 8, DecodeFADD_FMUL);
  3353.   AddFPU("FIADD", 0, DecodeFIADD_FIMUL);
  3354.   AddFPU("FIMUL", 8, DecodeFIADD_FIMUL);
  3355.   AddFPU("FADDP", 0, DecodeFADDP_FMULP);
  3356.   AddFPU("FMULP", 8, DecodeFADDP_FMULP);
  3357.   AddFPU("FDIV" , 16, DecodeFSUB_FSUBR_FDIV_FDIVR);
  3358.   AddFPU("FDIVR", 24, DecodeFSUB_FSUBR_FDIV_FDIVR);
  3359.   AddFPU("FSUB" ,  0, DecodeFSUB_FSUBR_FDIV_FDIVR);
  3360.   AddFPU("FSUBR",  8, DecodeFSUB_FSUBR_FDIV_FDIVR);
  3361.   AddFPU("FIDIV" , 16, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
  3362.   AddFPU("FIDIVR", 24, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
  3363.   AddFPU("FISUB" ,  0, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
  3364.   AddFPU("FISUBR",  8, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
  3365.   AddFPU("FDIVP" , 16, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
  3366.   AddFPU("FDIVRP", 24, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
  3367.   AddFPU("FSUBP" ,  0, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
  3368.   AddFPU("FSUBRP",  8, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
  3369.   AddFPU("FSAVE" , 0x30, DecodeFSAVE_FRSTOR);
  3370.   AddFPU("FRSTOR" , 0x20, DecodeFSAVE_FRSTOR);
  3371.  
  3372.   InstrZ = 0;
  3373.   AddFixed("AAA",   e_core_all,     0x0037);  AddFixed("AAS",   e_core_all,     0x003f);
  3374.   AddFixed("AAM",   e_core_all,     0xd40a);  AddFixed("AAD",   e_core_all,     0xd50a);
  3375.   AddFixed("CBW",   e_core_all,     0x0098);  AddFixed("CLC",   e_core_all,     0x00f8);
  3376.   AddFixed("CLD",   e_core_all,     0x00fc);  AddFixed("CLI",   e_core_all,     0x00fa);
  3377.   AddFixed("CMC",   e_core_all,     0x00f5);  AddFixed("CWD",   e_core_all,     0x0099);
  3378.   AddFixed("DAA",   e_core_all,     0x0027);  AddFixed("DAS",   e_core_all,     0x002f);
  3379.   AddFixed("HLT",   e_core_all,     0x00f4);  AddFixed("INTO",  e_core_all,     0x00ce);
  3380.   AddFixed("IRET",  e_core_all,     0x00cf);  AddFixed("LAHF",  e_core_all,     0x009f);
  3381.   AddFixed("LOCK",  e_core_all,     0x00f0);  AddFixed("NOP",   e_core_all,     0x0090);
  3382.   AddFixed("POPF",  e_core_all,     0x009d);  AddFixed("PUSHF", e_core_all,     0x009c);
  3383.   AddFixed("SAHF",  e_core_all,     0x009e);  AddFixed("STC",   e_core_all,     0x00f9);
  3384.   AddFixed("STD",   e_core_all,     0x00fd);  AddFixed("STI",   e_core_all,     0x00fb);
  3385.   AddFixed("WAIT",  e_core_all,     0x009b);  AddFixed("XLAT",  e_core_all,     0x00d7);
  3386.   AddFixed("LEAVE", e_core_all_186, 0x00c9);  AddFixed("PUSHA", e_core_all_186, 0x0060);
  3387.   AddFixed("POPA",  e_core_all_186, 0x0061);  AddFixed("ADD4S", e_core_all_v,   0x0f20);
  3388.   AddFixed("SUB4S", e_core_all_v,   0x0f22);  AddFixed("CMP4S", e_core_all_v,   0x0f26);
  3389.   AddFixed("STOP",  e_core_all_v35, 0x0f9e);  AddFixed("RETRBI",e_core_all_v35, 0x0f91);
  3390.   AddFixed("FINT",  e_core_all_v35, 0x0f92);  AddFixed("MOVSPA",e_core_all_v35, 0x0f25);
  3391.   AddFixed("SEGES", e_core_all,     0x0026);  AddFixed("SEGCS", e_core_all,     0x002e);
  3392.   AddFixed("SEGSS", e_core_all,     0x0036);  AddFixed("SEGDS", e_core_all,     0x003e);
  3393.   AddFixed("SEGDS2",e_core_all_v55, 0x0063);  AddFixed("SEGDS3",e_core_all_v55, 0x00d6);
  3394.   AddFixed("FWAIT", e_core_all,     0x009b);  AddFixed("IDLE",  e_core_v55sc,   0x0f9f);
  3395.   AddFixed("ALBIT", e_core_v55pi,   0x0f9a);  AddFixed("COLTRP",e_core_v55pi,   0x0f9b);
  3396.   AddFixed("MHENC", e_core_v55pi,   0x0f93);  AddFixed("MRENC", e_core_v55pi,   0x0f97);
  3397.   AddFixed("SCHEOL",e_core_v55pi,   0x0f78);  AddFixed("GETBIT",e_core_v55pi,   0x0f79);
  3398.   AddFixed("MHDEC", e_core_v55pi,   0x0f7c);  AddFixed("MRDEC", e_core_v55pi,   0x0f7d);
  3399.   AddFixed("CNVTRP",e_core_v55pi,   0x0f7a);  AddFixed("IRAM",  e_core_all_v55, 0x00f1);
  3400.  
  3401.   InstrZ = 0;
  3402.   AddBrk("BRKEM", e_core_v30, 0x0fff);
  3403.   AddBrk("BRKXA", e_core_v33, 0x0fe0);
  3404.   AddBrk("RETXA", e_core_v33, 0x0ff0);
  3405.   AddBrk("BRKS",  e_core_v35, 0x00f1);
  3406.   AddBrk("BRKN",  e_core_v35, 0x0063);
  3407.  
  3408.   AddFPUFixed("FCOMPP", 0xded9); AddFPUFixed("FTST",   0xd9e4);
  3409.   AddFPUFixed("FXAM",   0xd9e5); AddFPUFixed("FLDZ",   0xd9ee);
  3410.   AddFPUFixed("FLD1",   0xd9e8); AddFPUFixed("FLDPI",  0xd9eb);
  3411.   AddFPUFixed("FLDL2T", 0xd9e9); AddFPUFixed("FLDL2E", 0xd9ea);
  3412.   AddFPUFixed("FLDLG2", 0xd9ec); AddFPUFixed("FLDLN2", 0xd9ed);
  3413.   AddFPUFixed("FSQRT",  0xd9fa); AddFPUFixed("FSCALE", 0xd9fd);
  3414.   AddFPUFixed("FPREM",  0xd9f8); AddFPUFixed("FRNDINT",0xd9fc);
  3415.   AddFPUFixed("FXTRACT",0xd9f4); AddFPUFixed("FABS",   0xd9e1);
  3416.   AddFPUFixed("FCHS",   0xd9e0); AddFPUFixed("FPTAN",  0xd9f2);
  3417.   AddFPUFixed("FPATAN", 0xd9f3); AddFPUFixed("F2XM1",  0xd9f0);
  3418.   AddFPUFixed("FYL2X",  0xd9f1); AddFPUFixed("FYL2XP1",0xd9f9);
  3419.   AddFPUFixed("FINIT",  0xdbe3); AddFPUFixed("FENI",   0xdbe0);
  3420.   AddFPUFixed("FDISI",  0xdbe1); AddFPUFixed("FCLEX",  0xdbe2);
  3421.   AddFPUFixed("FINCSTP",0xd9f7); AddFPUFixed("FDECSTP",0xd9f6);
  3422.   AddFPUFixed("FNOP",   0xd9d0);
  3423.  
  3424.   AddFPUSt("FXCH",  0xd9c8);
  3425.   AddFPUSt("FFREE", 0xddc0);
  3426.  
  3427.   AddFPU16("FLDCW",  0xd928);
  3428.   AddFPU16("FSTCW",  0xd938);
  3429.   AddFPU16("FSTSW",  0xdd38);
  3430.   AddFPU16("FSTENV", 0xd930);
  3431.   AddFPU16("FLDENV", 0xd920);
  3432.  
  3433.   InstrZ = 0;
  3434.   AddString("CMPSB", e_core_all,     0x00a6);
  3435.   AddString("CMPSW", e_core_all,     0x00a7);
  3436.   AddString("LODSB", e_core_all,     0x00ac);
  3437.   AddString("LODSW", e_core_all,     0x00ad);
  3438.   AddString("MOVSB", e_core_all,     0x00a4);
  3439.   AddString("MOVSW", e_core_all,     0x00a5);
  3440.   AddString("SCASB", e_core_all,     0x00ae);
  3441.   AddString("SCASW", e_core_all,     0x00af);
  3442.   AddString("STOSB", e_core_all,     0x00aa);
  3443.   AddString("STOSW", e_core_all,     0x00ab);
  3444.   AddString("INSB",  e_core_all_186, 0x006c);
  3445.   AddString("INSW",  e_core_all_186, 0x006d);
  3446.   AddString("OUTSB", e_core_all_186, 0x006e);
  3447.   AddString("OUTSW", e_core_all_186, 0x006f);
  3448.   StringOrderCnt = InstrZ;
  3449.  
  3450.   InstrZ = 0;
  3451.   AddRept("REP",   e_core_all,   0x00f3);
  3452.   AddRept("REPE",  e_core_all,   0x00f3);
  3453.   AddRept("REPZ",  e_core_all,   0x00f3);
  3454.   AddRept("REPNE", e_core_all,   0x00f2);
  3455.   AddRept("REPNZ", e_core_all,   0x00f2);
  3456.   AddRept("REPC",  e_core_all_v, 0x0065);
  3457.   AddRept("REPNC", e_core_all_v, 0x0064);
  3458.  
  3459.   InstrZ = 0;
  3460.   AddRel("JA",    e_core_all, 0x0077); AddRel("JNBE",  e_core_all, 0x0077);
  3461.   AddRel("JAE",   e_core_all, 0x0073); AddRel("JNB",   e_core_all, 0x0073);
  3462.   AddRel("JB",    e_core_all, 0x0072); AddRel("JNAE",  e_core_all, 0x0072);
  3463.   AddRel("JBE",   e_core_all, 0x0076); AddRel("JNA",   e_core_all, 0x0076);
  3464.   AddRel("JC",    e_core_all, 0x0072); AddRel("JCXZ",  e_core_all, 0x00e3);
  3465.   AddRel("JE",    e_core_all, 0x0074); AddRel("JZ",    e_core_all, 0x0074);
  3466.   AddRel("JG",    e_core_all, 0x007f); AddRel("JNLE",  e_core_all, 0x007f);
  3467.   AddRel("JGE",   e_core_all, 0x007d); AddRel("JNL",   e_core_all, 0x007d);
  3468.   AddRel("JL",    e_core_all, 0x007c); AddRel("JNGE",  e_core_all, 0x007c);
  3469.   AddRel("JLE",   e_core_all, 0x007e); AddRel("JNG",   e_core_all, 0x007e);
  3470.   AddRel("JNC",   e_core_all, 0x0073); AddRel("JNE",   e_core_all, 0x0075);
  3471.   AddRel("JNZ",   e_core_all, 0x0075); AddRel("JNO",   e_core_all, 0x0071);
  3472.   AddRel("JNS",   e_core_all, 0x0079); AddRel("JNP",   e_core_all, 0x007b);
  3473.   AddRel("JPO",   e_core_all, 0x007b); AddRel("JO",    e_core_all, 0x0070);
  3474.   AddRel("JP",    e_core_all, 0x007a); AddRel("JPE",   e_core_all, 0x007a);
  3475.   AddRel("JS",    e_core_all, 0x0078); AddRel("LOOP",  e_core_all, 0x00e2);
  3476.   AddRel("LOOPE", e_core_all, 0x00e1); AddRel("LOOPZ", e_core_all, 0x00e1);
  3477.   AddRel("LOOPNE",e_core_all, 0x00e0); AddRel("LOOPNZ",e_core_all, 0x00e0);
  3478.  
  3479.   InstrZ = 0;
  3480.   AddModReg("LDS",   e_core_all,     0x00c5, False);
  3481.   AddModReg("LEA",   e_core_all,     0x008d, True );
  3482.   AddModReg("LES",   e_core_all,     0x00c4, False);
  3483.   AddModReg("BOUND", e_core_all_186, 0x0062, False);
  3484.   AddModReg("LDS3",  e_core_all,     0x0f36, False);
  3485.   AddModReg("LDS2",  e_core_all,     0x0f3e, False);
  3486.  
  3487.   InstrZ = 0;
  3488.   AddShift("SHL",   e_core_all, 4); AddShift("SAL",   e_core_all, 4);
  3489.   AddShift("SHR",   e_core_all, 5); AddShift("SAR",   e_core_all, 7);
  3490.   AddShift("ROL",   e_core_all, 0); AddShift("ROR",   e_core_all, 1);
  3491.   AddShift("RCL",   e_core_all, 2); AddShift("RCR",   e_core_all, 3);
  3492.  
  3493.   InstrZ = 0;
  3494.   AddReg16("BRKCS" , e_core_all_v35, 0x0f2d, 0xc0);
  3495.   AddReg16("TSKSW" , e_core_all_v35, 0x0f94, 0xf8);
  3496.   AddReg16("MOVSPB", e_core_all_v35, 0x0f95, 0xf8);
  3497.  
  3498.   InstrZ = 0;
  3499.   AddInstTable(InstTable, "ADD", InstrZ++, DecodeALU2);
  3500.   AddInstTable(InstTable, "OR" , InstrZ++, DecodeALU2);
  3501.   AddInstTable(InstTable, "ADC", InstrZ++, DecodeALU2);
  3502.   AddInstTable(InstTable, "SBB", InstrZ++, DecodeALU2);
  3503.   AddInstTable(InstTable, "AND", InstrZ++, DecodeALU2);
  3504.   AddInstTable(InstTable, "SUB", InstrZ++, DecodeALU2);
  3505.   AddInstTable(InstTable, "XOR", InstrZ++, DecodeALU2);
  3506.   AddInstTable(InstTable, "CMP", InstrZ++, DecodeALU2);
  3507.  
  3508.   InstrZ = 0;
  3509.   AddInstTable(InstTable, "MUL" , InstrZ++, DecodeMul);
  3510.   AddInstTable(InstTable, "IMUL", InstrZ++, DecodeMul);
  3511.   AddInstTable(InstTable, "DIV" , InstrZ++, DecodeMul);
  3512.   AddInstTable(InstTable, "IDIV", InstrZ++, DecodeMul);
  3513.  
  3514.   InstrZ = 0;
  3515.   AddInstTable(InstTable, "TEST1", InstrZ++, DecodeBit1);
  3516.   AddInstTable(InstTable, "CLR1" , InstrZ++, DecodeBit1);
  3517.   AddInstTable(InstTable, "SET1" , InstrZ++, DecodeBit1);
  3518.   AddInstTable(InstTable, "NOT1" , InstrZ++, DecodeBit1);
  3519.  
  3520.   AddInstTable(InstTable, "BSCH" , 0x0f3c, DecodeBSCH);
  3521.   AddInstTable(InstTable, "RSTWDT", 0x0f96, DecodeRSTWDT);
  3522.   AddInstTable(InstTable, "BTCLRL", 0x0f9d, DecodeBTCLRL);
  3523.  
  3524.   InstrZ = 0;
  3525.   AddImm16("QHOUT",  e_core_all_v55, 0x0fe0);
  3526.   AddImm16("QOUT",   e_core_all_v55, 0x0fe1);
  3527.   AddImm16("QTIN",   e_core_all_v55, 0x0fe2);
  3528. }
  3529.  
  3530. /*!------------------------------------------------------------------------
  3531.  * \fn     DeinitFields(void)
  3532.  * \brief  dispose instructions fields after switch from target
  3533.  * ------------------------------------------------------------------------ */
  3534.  
  3535. static void DeinitFields(void)
  3536. {
  3537.   DestroyInstTable(InstTable);
  3538.   order_array_free(FixedOrders);
  3539.   order_array_free(BrkOrders);
  3540.   order_array_free(ReptOrders);
  3541.   order_array_free(ShiftOrders);
  3542.   order_array_free(StringOrders);
  3543.   order_array_free(ModRegOrders);
  3544.   order_array_free(Reg16Orders);
  3545.   order_array_free(RelOrders);
  3546.   order_array_free(Imm16Orders);
  3547. }
  3548.  
  3549. /*!------------------------------------------------------------------------
  3550.  * \fn     MakeCode_86(void)
  3551.  * \brief  parse/encode one instruction
  3552.  * ------------------------------------------------------------------------ */
  3553.  
  3554. static void MakeCode_86(void)
  3555. {
  3556.   CodeLen = 0;
  3557.   DontPrint = False;
  3558.   OpSize = eSymbolSizeUnknown;
  3559.   PrefixLen = 0;
  3560.   NoSegCheck = False;
  3561.   UnknownFlag = False;
  3562.  
  3563.   /* zu ignorierendes */
  3564.  
  3565.   if (Memo(""))
  3566.     return;
  3567.  
  3568.   /* Pseudoanweisungen */
  3569.  
  3570.   if (DecodeIntelPseudo(False))
  3571.     return;
  3572.  
  3573.   /* vermischtes */
  3574.  
  3575.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  3576.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  3577. }
  3578.  
  3579. /*!------------------------------------------------------------------------
  3580.  * \fn     InitCode_86(void)
  3581.  * \brief  y86-specific initializations prior to pass
  3582.  * ------------------------------------------------------------------------ */
  3583.  
  3584. static void InitCode_86(void)
  3585. {
  3586.   SegAssumes[0] = SegNone; /* ASSUME ES:NOTHING */
  3587.   SegAssumes[1] = SegCode; /* ASSUME CS:CODE */
  3588.   SegAssumes[2] = SegNone; /* ASSUME SS:NOTHING */
  3589.   SegAssumes[3] = SegData; /* ASSUME DS:DATA */
  3590. }
  3591.  
  3592. /*!------------------------------------------------------------------------
  3593.  * \fn     IsDef_86(void)
  3594.  * \brief  does instruction consume label field?
  3595.  * \return True if yes
  3596.  * ------------------------------------------------------------------------ */
  3597.  
  3598. static Boolean IsDef_86(void)
  3599. {
  3600.   return (Memo("PORT"));
  3601. }
  3602.  
  3603. /*!------------------------------------------------------------------------
  3604.  * \fn     SwitchTo_86(void *p_user)
  3605.  * \brief  switch to x86 target
  3606.  * \param  p_user * to properties of specific variant
  3607.  * ------------------------------------------------------------------------ */
  3608.  
  3609. static void SwitchTo_86(void *p_user)
  3610. {
  3611.   p_curr_cpu_props = (const cpu_props_t*)p_user;
  3612.  
  3613.   TurnWords = False; SetIntConstMode(eIntConstModeIntel);
  3614.  
  3615.   PCSymbol = "$"; HeaderID = 0x42; NOPCode = 0x90;
  3616.   DivideChars = ","; HasAttrs = False;
  3617.  
  3618.   ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegXData) | (1 << SegIO);
  3619.   Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
  3620.   SegLimits[SegCode ] = 0xffff;
  3621.   Grans[SegData ] = 1; ListGrans[SegData ] = 1; SegInits[SegData ] = 0;
  3622.   SegLimits[SegData ] = 0xffff;
  3623.   Grans[SegXData] = 1; ListGrans[SegXData] = 1; SegInits[SegXData] = 0;
  3624.   SegLimits[SegXData] = 0xffff;
  3625.   Grans[SegIO   ] = 1; ListGrans[SegIO   ] = 1; SegInits[SegIO   ] = 0;
  3626.   SegLimits[SegIO   ] = 0xffff;
  3627.  
  3628.   pASSUMEOverride = DecodeASSUME;
  3629.  
  3630.   MakeCode = MakeCode_86; IsDef = IsDef_86;
  3631.   SwitchFrom = DeinitFields; InitFields();
  3632.   onoff_fpu_add();
  3633. }
  3634.  
  3635. /*!------------------------------------------------------------------------
  3636.  * \fn     code86_init(void)
  3637.  * \brief  register x86 target
  3638.  * ------------------------------------------------------------------------ */
  3639.  
  3640. static const cpu_props_t cpu_props[] =
  3641. {
  3642.   { "8088"   , e_core_86    },
  3643.   { "8086"   , e_core_86    },
  3644.   { "80188"  , e_core_186   },
  3645.   { "80186"  , e_core_186   },
  3646.   { "V20"    , e_core_v30   },
  3647.   { "V25"    , e_core_v35   },
  3648.   { "V30"    , e_core_v30   },
  3649.   { "V33"    , e_core_v33   },
  3650.   { "V35"    , e_core_v35   },
  3651.   { "V40"    , e_core_v30   },
  3652.   { "V50"    , e_core_v30   },
  3653.   { "V53"    , e_core_v33   },
  3654.   { "V55"    , e_core_v55   },
  3655.   { "V55SC"  , e_core_v55sc },
  3656.   { "V55PI"  , e_core_v55pi },
  3657.   { ""       , e_core_86    }
  3658. };
  3659.  
  3660. void code86_init(void)
  3661. {
  3662.   const cpu_props_t *p_prop;
  3663.   for (p_prop = cpu_props; p_prop->name[0]; p_prop++)
  3664.     (void)AddCPUUser(p_prop->name, SwitchTo_86, (void*)p_prop, NULL);
  3665.  
  3666.   AddInitPassProc(InitCode_86);
  3667. }
  3668.