Subversion Repositories pentevo

Rev

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

  1. /* codez80.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator Zilog Z80/180/380                                           */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <ctype.h>
  13. #include <string.h>
  14.  
  15. #include "nls.h"
  16. #include "strutil.h"
  17. #include "bpemu.h"
  18. #include "asmdef.h"
  19. #include "asmsub.h"
  20. #include "asmpars.h"
  21. #include "asmcode.h"
  22. #include "asmallg.h"
  23. #include "onoff_common.h"
  24. #include "asmitree.h"
  25. #include "codepseudo.h"
  26. #include "intpseudo.h"
  27. #include "codevars.h"
  28. #include "cpu2phys.h"
  29. #include "function.h"
  30. #include "errmsg.h"
  31.  
  32. #include "codez80.h"
  33.  
  34. /*-------------------------------------------------------------------------*/
  35. /* Instruktionsgruppendefinitionen */
  36.  
  37. typedef struct
  38. {
  39.   CPUVar MinCPU;
  40.   Byte Len;
  41.   Word Code;
  42. } BaseOrder;
  43.  
  44. typedef struct
  45. {
  46.   const char *Name;
  47.   Byte Code;
  48. } Condition;
  49.  
  50. /*-------------------------------------------------------------------------*/
  51. /* Praefixtyp */
  52.  
  53. typedef enum
  54. {
  55.   Pref_IN_N,Pref_IN_W ,Pref_IB_W ,Pref_IW_W ,Pref_IB_N ,
  56.   Pref_IN_LW,Pref_IB_LW,Pref_IW_LW,Pref_IW_N
  57. } PrefType;
  58.  
  59. typedef enum
  60. {
  61.   ePrefixNone,
  62.   ePrefixW,   /* word processing */
  63.   ePrefixLW,  /* long word processing */
  64.   ePrefixIB,  /* one byte more in argument */
  65.   ePrefixIW   /* one word more in argument */
  66. } tOpPrefix;
  67.  
  68. #ifdef __cplusplus
  69. # include "codez80.hpp"
  70. #endif
  71.  
  72. #define LWordFlagName  "INLWORDMODE"
  73.  
  74. #define ModNone (-1)
  75. #define ModReg8 1
  76. #define ModReg16 2
  77. #define ModIndReg16 3
  78. #define ModImm 4
  79. #define ModAbs 5
  80. #define ModRef 6
  81. #define ModInt 7
  82. #define ModSPRel 8
  83. #define ModIndReg8 9
  84. #define ModSPAdd 10
  85. #define ModHLInc 11
  86. #define ModHLDec 12
  87. #define ModIOAbs 13
  88. #define ModImmIsAbs 14
  89.  
  90. #define MModReg8 (1 << ModReg8)
  91. #define MModReg16 (1 << ModReg16)
  92. #define MModIndReg16 (1 << ModIndReg16)
  93. #define MModImm (1 << ModImm)
  94. #define MModAbs (1 << ModAbs)
  95. #define MModRef (1 << ModRef)
  96. #define MModInt (1 << ModInt)
  97. #define MModSPRel (1 << ModSPRel)
  98. #define MModIndReg8 (1 << ModIndReg8)
  99. #define MModSPAdd (1 << ModSPAdd)
  100. #define MModHLInc (1 << ModHLInc)
  101. #define MModHLDec (1 << ModHLDec)
  102. #define MModIOAbs (1 << ModIOAbs)
  103. #define MModImmIsAbs (1 << ModImmIsAbs)
  104.  
  105. /* These masks deliberately omit the (special)
  106.    Sharp/Gameboy addressing modes: */
  107.  
  108. #define MModNoImm (MModReg8 | MModReg16 | MModIndReg16 | MModAbs | MModRef | MModInt | MModSPRel)
  109. #define MModAll (MModReg8 | MModReg16 | MModIndReg16 | MModImm | MModAbs | MModRef | MModInt | MModSPRel)
  110.  
  111. #define IXPrefix 0xdd
  112. #define IYPrefix 0xfd
  113.  
  114. #define AccReg 7
  115. #define DEReg 1
  116. #define HLReg 2
  117. #define SPReg 3
  118.  
  119. /*-------------------------------------------------------------------------*/
  120.  
  121. static Byte PrefixCnt;
  122. static Byte AdrPart,OpSize;
  123. static Byte AdrVals[4];
  124. static ShortInt AdrMode;
  125.  
  126. static BaseOrder *FixedOrders;
  127. static BaseOrder *AccOrders;
  128. static BaseOrder *HLOrders;
  129. static Condition *Conditions;
  130.  
  131. static CPUVar CPULR35902, CPUGBZ80,
  132.               CPUZ80, CPUZ80U, CPUZ180,
  133.               CPUR2000, CPUZ380;
  134.  
  135. static Boolean MayLW,             /* Instruktion erlaubt 32 Bit */
  136.                ExtFlag,           /* Prozessor im 4GByte-Modus ? */
  137.                LWordFlag;         /* 32-Bit-Verarbeitung ? */
  138.  
  139. static PrefType CurrPrefix,       /* mom. explizit erzeugter Praefix */
  140.                 LastPrefix;       /* von der letzten Anweisung generierter Praefix */
  141.  
  142. static LongInt Reg_CBAR,
  143.                Reg_BBR,
  144.                Reg_CBR;
  145. static const char Reg8Names[] = "BCDEHL*A";
  146. static int Reg16Cnt;
  147. static const char Reg16Names[][3] = { "BC", "DE", "HL", "SP", "IX", "IY" };
  148.  
  149. /*==========================================================================*/
  150. /* Aux Functions */
  151.  
  152. static Boolean is_sharp(void)
  153. {
  154.   return (MomCPU == CPULR35902) || (MomCPU == CPUGBZ80);
  155. }
  156.  
  157. /*--------------------------------------------------------------------------*/
  158. /* Praefix dazuaddieren */
  159.  
  160. static tOpPrefix DecodePrefix(const char *pArg)
  161. {
  162.   const char *pPrefNames[] = { "W", "LW", "IB", "IW", NULL };
  163.   tOpPrefix Result;
  164.  
  165.   for (Result = ePrefixW; pPrefNames[Result - 1]; Result++)
  166.     if (!as_strcasecmp(pArg, pPrefNames[Result - 1]))
  167.       return Result;
  168.   return ePrefixNone;
  169. }
  170.  
  171. static Boolean ExtendPrefix(PrefType *Dest, tOpPrefix AddPrefix)
  172. {
  173.   Byte SPart,IPart;
  174.  
  175.   switch (*Dest)
  176.   {
  177.     case Pref_IB_N:
  178.     case Pref_IB_W:
  179.     case Pref_IB_LW:
  180.       IPart = 1;
  181.       break;
  182.     case Pref_IW_N:
  183.     case Pref_IW_W:
  184.     case Pref_IW_LW:
  185.       IPart = 2;
  186.       break;
  187.     default:
  188.       IPart = 0;
  189.   }
  190.  
  191.   switch (*Dest)
  192.   {
  193.     case Pref_IN_W:
  194.     case Pref_IB_W:
  195.     case Pref_IW_W:
  196.       SPart = 1;
  197.       break;
  198.     case Pref_IN_LW:
  199.     case Pref_IB_LW:
  200.     case Pref_IW_LW:
  201.       SPart = 2;
  202.       break;
  203.     default:
  204.       SPart = 0;
  205.   }
  206.  
  207.   switch (AddPrefix)
  208.   {
  209.     case ePrefixW:
  210.       SPart = 1; break;
  211.     case ePrefixLW:
  212.       SPart = 2; break;
  213.     case ePrefixIB:
  214.       IPart = 1; break;
  215.     case ePrefixIW:
  216.       IPart = 2; break;
  217.     default:
  218.       return False;
  219.   }
  220.  
  221.   switch ((IPart << 4) | SPart)
  222.   {
  223.     case 0x00:
  224.       *Dest = Pref_IN_N;
  225.       break;
  226.     case 0x01:
  227.       *Dest = Pref_IN_W;
  228.       break;
  229.     case 0x02:
  230.       *Dest = Pref_IN_LW;
  231.       break;
  232.     case 0x10:
  233.       *Dest = Pref_IB_N;
  234.       break;
  235.     case 0x11:
  236.       *Dest = Pref_IB_W;
  237.       break;
  238.     case 0x12:
  239.       *Dest = Pref_IB_LW;
  240.       break;
  241.     case 0x20:
  242.       *Dest = Pref_IW_N;
  243.       break;
  244.     case 0x21:
  245.       *Dest = Pref_IW_W;
  246.       break;
  247.     case 0x22:
  248.       *Dest = Pref_IW_LW;
  249.       break;
  250.   }
  251.  
  252.   return True;
  253. }
  254.  
  255. /*--------------------------------------------------------------------------*/
  256. /* Code fuer Praefix bilden */
  257.  
  258. static void GetPrefixCode(PrefType inp, Byte *b1 ,Byte *b2)
  259. {
  260.   int z;
  261.  
  262.   z = ((int)inp) - 1;
  263.   *b1 = 0xdd + ((z & 4) << 3);
  264.   *b2 = 0xc0 + (z & 3);
  265. }
  266.  
  267. /*--------------------------------------------------------------------------*/
  268. /* DD-Praefix addieren, nur EINMAL pro Instruktion benutzen! */
  269.  
  270. static void ChangeDDPrefix(tOpPrefix Prefix)
  271. {
  272.   PrefType ActPrefix;
  273.   int z;
  274.  
  275.   ActPrefix = LastPrefix;
  276.   if (ExtendPrefix(&ActPrefix, Prefix))
  277.     if (LastPrefix != ActPrefix)
  278.     {
  279.       if (LastPrefix != Pref_IN_N) RetractWords(2);
  280.       for (z = PrefixCnt - 1; z >= 0; z--) BAsmCode[2 + z] = BAsmCode[z];
  281.       PrefixCnt += 2;
  282.       GetPrefixCode(ActPrefix, BAsmCode + 0, BAsmCode + 1);
  283.     }
  284. }
  285.  
  286. /*--------------------------------------------------------------------------*/
  287. /* IX/IY used ? */
  288.  
  289. static Boolean IndexPrefix(void)
  290. {
  291.   return   ((PrefixCnt > 0)
  292.          && ((BAsmCode[PrefixCnt - 1] == IXPrefix)
  293.           || (BAsmCode[PrefixCnt - 1] == IYPrefix)));
  294. }
  295.  
  296. /*--------------------------------------------------------------------------*/
  297. /* Wortgroesse ? */
  298.  
  299. static Boolean InLongMode(void)
  300. {
  301.   switch (LastPrefix)
  302.   {
  303.     case Pref_IN_W:
  304.     case Pref_IB_W:
  305.     case Pref_IW_W:
  306.       return False;
  307.     case Pref_IN_LW:
  308.     case Pref_IB_LW:
  309.     case Pref_IW_LW:
  310.       return MayLW;
  311.     default:
  312.       return LWordFlag && MayLW;
  313.   }
  314. }
  315.  
  316. /*--------------------------------------------------------------------------*/
  317. /* absolute Adresse */
  318.  
  319. static LongWord EvalAbsAdrExpression(const tStrComp *pArg, tEvalResult *pEvalResult)
  320. {
  321.   return EvalStrIntExpressionWithResult(pArg, ExtFlag ? Int32 : UInt16, pEvalResult);
  322. }
  323.  
  324. /*==========================================================================*/
  325. /* Adressparser */
  326.  
  327. /*!------------------------------------------------------------------------
  328.  * \fn     DecodeReg8Core(const char *p_asc, Byte *p_ret)
  329.  * \brief  parse 8 bit register
  330.  * \param  p_asc source argument
  331.  * \param  p_ret return buffer
  332.  * \return true if valid register name
  333.  * ------------------------------------------------------------------------ */
  334.  
  335. static Boolean DecodeReg8Core(const char *p_asc, Byte *p_ret)
  336. {
  337.   const char *p_pos;
  338.  
  339.   switch (strlen(p_asc))
  340.   {
  341.     case 1:
  342.       p_pos = strchr(Reg8Names, as_toupper(p_asc[0]));
  343.       if (!p_pos)
  344.         return False;
  345.       *p_ret = p_pos - Reg8Names;
  346.       return (*p_ret != 6);
  347.     case 3:
  348.     {
  349.       char ix = toupper(p_asc[1]);
  350.  
  351.       if ((toupper(p_asc[0]) != 'I')
  352.        || ((ix != 'X') && (ix != 'Y')))
  353.         return False;
  354.       switch (toupper(p_asc[2]))
  355.       {
  356.         case 'L':
  357.           *p_ret = 5 | (((ix == 'X') ? IXPrefix : IYPrefix) & 0xf0);
  358.           return True;
  359.         case 'H':
  360.           if (MomCPU != CPUZ80U) /* do not allow IXH/IYH on Z380 */
  361.             return False;
  362.           /* else fall-through */
  363.         case 'U':
  364.           *p_ret = 4 | (((ix == 'X') ? IXPrefix : IYPrefix) & 0xf0);
  365.           return True;
  366.         default:
  367.           return False;
  368.       }
  369.     }  
  370.     default:
  371.       return False;
  372.   }
  373. }
  374.  
  375. /*!------------------------------------------------------------------------
  376.  * \fn     DecodeReg16Core(const char *p_asc, Byte *p_ret)
  377.  * \brief  parse 16 bit register
  378.  * \param  p_asc source argument
  379.  * \param  p_ret return buffer
  380.  * \return true if valid register name
  381.  * ------------------------------------------------------------------------ */
  382.  
  383. static Boolean DecodeReg16Core(const char *p_asc, Byte *p_ret)
  384. {
  385.   int z;
  386.  
  387.   for (z = 0; z < Reg16Cnt; z++)
  388.     if (!as_strcasecmp(p_asc, Reg16Names[z]))
  389.     {
  390.       if (z <= 3)
  391.         *p_ret = z;
  392.       else
  393.         *p_ret = 2 /* = HL */ | (((z == 4) ? IXPrefix : IYPrefix) & 0xf0);
  394.       return True;
  395.     }
  396.   return False;
  397. }
  398.  
  399. /*!------------------------------------------------------------------------
  400.  * \fn     DecodeReg(const tStrComp *p_arg, Byte *p_ret, tSymbolSize *p_size, tSymbolSize req_size, Boolean must_be_reg)
  401.  * \brief  check whether argument is a CPU register or user-defined register alias
  402.  * \param  p_arg argument
  403.  * \param  p_value resulting register # if yes
  404.  * \param  p_size resulting register size if yes
  405.  * \param  req_size requested register size
  406.  * \param  must_be_reg expecting register or maybe not?
  407.  * \return reg eval result
  408.  * ------------------------------------------------------------------------ */
  409.  
  410. static Boolean chk_reg_size(tSymbolSize req_size, tSymbolSize act_size)
  411. {
  412.   return (req_size == eSymbolSizeUnknown)
  413.       || (req_size == act_size);
  414. }
  415.  
  416. static tRegEvalResult DecodeReg(const tStrComp *p_arg, Byte *p_ret, tSymbolSize *p_size, tSymbolSize req_size, Boolean must_be_reg)
  417. {
  418.   tRegEvalResult reg_eval_result;
  419.   tEvalResult eval_result;
  420.   tRegDescr reg_descr;
  421.  
  422.   if (DecodeReg8Core(p_arg->str.p_str, p_ret))
  423.   {
  424.     eval_result.DataSize = eSymbolSize8Bit;
  425.     reg_eval_result = eIsReg;
  426.   }
  427.   else if (DecodeReg16Core(p_arg->str.p_str, p_ret))
  428.   {
  429.     eval_result.DataSize = eSymbolSize16Bit;
  430.     reg_eval_result = eIsReg;
  431.   }
  432.   else
  433.   {
  434.     reg_eval_result = EvalStrRegExpressionAsOperand(p_arg, &reg_descr, &eval_result, eSymbolSizeUnknown, must_be_reg);
  435.     if (reg_eval_result == eIsReg)
  436.       *p_ret = reg_descr.Reg;
  437.   }
  438.  
  439.   if (reg_eval_result == eIsReg)
  440.   {
  441.     if (!chk_reg_size(req_size, eval_result.DataSize))
  442.     {
  443.       WrStrErrorPos(ErrNum_InvOpSize, p_arg);
  444.       reg_eval_result = must_be_reg ? eIsNoReg : eRegAbort;
  445.     }
  446.   }
  447.  
  448.   if (p_size) *p_size = eval_result.DataSize;
  449.   return reg_eval_result;
  450. }
  451.  
  452. static Boolean IsSym(char ch)
  453. {
  454.   return ((ch == '_')
  455.        || ((ch >= '0') && (ch <= '9'))
  456.        || ((ch >= 'A') && (ch <= 'Z'))
  457.        || ((ch >= 'a') && (ch <= 'z')));
  458. }
  459.  
  460. static ShortInt DecodeAdr(const tStrComp *pArg, unsigned ModeMask)
  461. {
  462.   Integer AdrInt;
  463. #if 0
  464.   int z, l;
  465.   LongInt AdrLong;
  466. #endif
  467.   Boolean OK, is_indirect;
  468.   tEvalResult EvalResult;
  469.  
  470.   AdrMode = ModNone;
  471.   AdrCnt = 0;
  472.   AdrPart = 0;
  473.  
  474.   /* 0. Sonderregister */
  475.  
  476.   if (!as_strcasecmp(pArg->str.p_str, "R"))
  477.   {
  478.     AdrMode = ModRef;
  479.     goto found;
  480.   }
  481.  
  482.   if (!as_strcasecmp(pArg->str.p_str, "I"))
  483.   {
  484.     AdrMode = ModInt;
  485.     goto found;
  486.   }
  487.  
  488.   /* 1. 8/16 bit registers ? */
  489.  
  490.   switch (DecodeReg(pArg, &AdrPart, &EvalResult.DataSize, eSymbolSizeUnknown, False))
  491.   {
  492.     case eRegAbort:
  493.       goto found;
  494.     case eIsReg:
  495.       if (AdrPart & 0xf0)
  496.         BAsmCode[PrefixCnt++] = (AdrPart & 0xf0) | 0x0d;
  497.       AdrPart &= (EvalResult.DataSize == eSymbolSize8Bit) ? 7 : 3;
  498.       AdrMode = (EvalResult.DataSize == eSymbolSize8Bit) ? ModReg8 : ModReg16;
  499.       goto found;
  500.     default:
  501.       break;
  502.   }
  503.  
  504.   /* 2. SP+d8 (Gameboy specific) */
  505.  
  506.   if ((ModeMask & MModSPAdd)
  507.    && (strlen(pArg->str.p_str) >= 4)
  508.    && !as_strncasecmp(pArg->str.p_str, "SP", 2)
  509.    && !IsSym(pArg->str.p_str[2]))
  510.   {
  511.     AdrVals[0] = EvalStrIntExpressionOffs(pArg, 2, SInt8, &OK);
  512.     if (OK)
  513.     {
  514.       AdrCnt = 1;
  515.       AdrMode = ModSPAdd;
  516.     }
  517.     goto found;
  518.   }
  519.  
  520.   /* all types of indirect expressions (...): */
  521.  
  522.   is_indirect = IsIndirect(pArg->str.p_str);
  523.   if (is_indirect || (ModeMask & MModImmIsAbs))
  524.   {
  525.     tStrComp arg, remainder;
  526.     char *p_split_pos;
  527.     Boolean neg_flag, next_neg_flag;
  528.     tEvalResult disp_eval_result;
  529.     LongInt disp_acc;
  530.     Byte addr_reg, this_reg;
  531.     tSymbolSize addr_reg_size, this_reg_size;
  532.  
  533.     /* strip outer braces and spaces */
  534.  
  535.     StrCompRefRight(&arg, pArg, !!is_indirect);
  536.     StrCompShorten(&arg, !!is_indirect);
  537.     KillPrefBlanksStrCompRef(&arg);
  538.     KillPostBlanksStrComp(&arg);
  539.  
  540.     /* special cases: */
  541.  
  542.     if ((ModeMask & MModHLInc) && (!as_strcasecmp(arg.str.p_str, "HL+") || !as_strcasecmp(arg.str.p_str, "HLI")))
  543.     {
  544.       AdrMode = ModHLInc;
  545.       goto found;
  546.     }
  547.     if ((ModeMask & MModHLDec) && (!as_strcasecmp(arg.str.p_str, "HL-") || !as_strcasecmp(arg.str.p_str, "HLD")))
  548.     {
  549.       AdrMode = ModHLDec;
  550.       goto found;
  551.     }
  552.  
  553.     /* otherwise, walk through the components : */
  554.  
  555.     disp_eval_result.Flags = eSymbolFlag_None;
  556.     disp_eval_result.AddrSpaceMask = 0;
  557.     disp_acc = 0;
  558.     neg_flag = False;
  559.     addr_reg = 0xff;
  560.     addr_reg_size = eSymbolSizeUnknown;
  561.     do
  562.     {
  563.       /* Split off one component: */
  564.  
  565.       p_split_pos = indir_split_pos(arg.str.p_str);
  566.       next_neg_flag = p_split_pos && (*p_split_pos == '-');
  567.       if ((p_split_pos == arg.str.p_str) || (p_split_pos == arg.str.p_str + strlen(arg.str.p_str) - 1))
  568.       {
  569.         WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  570.         return AdrMode;
  571.       }
  572.       if (p_split_pos)
  573.         StrCompSplitRef(&arg, &remainder, &arg, p_split_pos);
  574.       KillPrefBlanksStrCompRef(&arg);
  575.       KillPostBlanksStrComp(&arg);
  576.  
  577.       /* register or displacement? */
  578.  
  579.       switch (DecodeReg(&arg, &this_reg, &this_reg_size, eSymbolSizeUnknown, False))
  580.       {
  581.         case eIsReg:
  582.           if (addr_reg != 0xff)
  583.           {
  584.             WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  585.             return AdrMode;
  586.           }
  587.           addr_reg = this_reg;
  588.           addr_reg_size = this_reg_size;
  589.           break;
  590.         case eRegAbort:
  591.           return AdrMode;
  592.         default:
  593.         {
  594.           tEvalResult eval_result;
  595.           LongInt this_disp;
  596.  
  597.           /* special case for GameBoy/Sharp: FF00 always allowed, independent of radix: */
  598.  
  599.           if (!as_strcasecmp(arg.str.p_str, "FF00"))
  600.           {
  601.             this_disp = 0xff00;
  602.             eval_result.OK = True;
  603.             eval_result.Flags = eSymbolFlag_None;
  604.             eval_result.AddrSpaceMask = 0;
  605.           }
  606.           else
  607.             this_disp = EvalStrIntExpressionWithResult(&arg, Int32, &eval_result);
  608.           if (!eval_result.OK)
  609.             return AdrMode;
  610.           disp_eval_result.Flags |= eval_result.Flags;
  611.           disp_eval_result.AddrSpaceMask |= eval_result.AddrSpaceMask;
  612.           if (neg_flag)
  613.             disp_acc -= this_disp;
  614.           else
  615.             disp_acc += this_disp;
  616.         }
  617.       }
  618.  
  619.       /* sign of next component */
  620.  
  621.       neg_flag = next_neg_flag;
  622.       if (p_split_pos)
  623.         arg = remainder;
  624.     }
  625.     while (p_split_pos);
  626.  
  627.     /* now we have parsed the expression, see what we can do with it: */
  628.  
  629.     switch (addr_reg)
  630.     {
  631.       /* no register: absolute */
  632.       case 0xff:
  633.       {
  634.         LongWord address = disp_acc;
  635.  
  636.         if (ModeMask & MModAbs)
  637.         {
  638.           /* no range checking if address range is 32 bits - disp_acc is only a 32 bit value */
  639.  
  640.           if (!mFirstPassUnknownOrQuestionable(disp_eval_result.Flags)
  641.            && !ExtFlag
  642.            && !ChkRangeByType(disp_acc, UInt16, pArg))
  643.             return AdrMode;
  644.           ChkSpace(SegCode, disp_eval_result.AddrSpaceMask);
  645.           AdrVals[0] = address & 0xff;
  646.           AdrVals[1] = (address >> 8) & 0xff;
  647.           AdrCnt = 2;
  648.           if (address > 0xfffful)
  649.           {
  650.             AdrVals[AdrCnt++] = (address >> 16) & 0xff;
  651.             if (address <= 0xfffffful)
  652.               ChangeDDPrefix(ePrefixIB);
  653.             else
  654.             {
  655.               AdrVals[AdrCnt++] = ((address >> 24) & 0xff);
  656.               ChangeDDPrefix(ePrefixIW);
  657.             }
  658.           }
  659.           AdrMode = ModAbs;
  660.           goto found;
  661.         }
  662.         else if (ModeMask & MModIOAbs)
  663.         {
  664.           if (!mFirstPassUnknownOrQuestionable(disp_eval_result.Flags) && !ChkRangeByType(disp_acc, UInt8, pArg))
  665.             return AdrMode;
  666.           ChkSpace(SegIO, disp_eval_result.AddrSpaceMask);
  667.           AdrVals[0] = address & 0xff;
  668.           AdrCnt = 1;
  669.           AdrMode = ModIOAbs;
  670.           goto found;
  671.         }
  672.         else
  673.           goto inv_mode;
  674.       }
  675.  
  676.       case 0:
  677.         if ((addr_reg_size != eSymbolSize16Bit) || disp_acc) /* no (B), (BC+d) */
  678.           goto wrong;
  679.         else /* (BC) */
  680.         {
  681.           AdrMode = ModIndReg16;
  682.           AdrPart = 0;
  683.           goto found;
  684.         }
  685.  
  686.       case 1:
  687.         if (addr_reg_size  == eSymbolSize16Bit) /* (DE) */
  688.         {
  689.           if (disp_acc)
  690.             goto wrong;
  691.           AdrMode = ModIndReg16;
  692.           AdrPart = 1;
  693.           goto found;
  694.         }
  695.         else /* (C), (FF00+C) on Sharp/GB */
  696.         {
  697.           if (!disp_acc || (is_sharp() && (disp_acc == 0xff00)))
  698.           {
  699.             AdrMode = ModIndReg8;
  700.             goto found;
  701.           }
  702.           else
  703.             goto wrong;
  704.         }
  705.  
  706.       case 2:
  707.         if ((addr_reg_size != eSymbolSize16Bit) || disp_acc) /* no (D), (HL+d) */
  708.           goto wrong;
  709.         else /* (HL) */
  710.         {
  711.           AdrMode = ModReg8; /* (HL) is M-Reg */
  712.           AdrPart = 6;
  713.           goto found;
  714.         }
  715.  
  716.       case (IXPrefix & 0xf0) | 2: /* (IX+d) */
  717.       case (IYPrefix & 0xf0) | 2: /* (IY+d) */
  718.       case 3: /* (SP+d) */
  719.         if (!mFirstPassUnknownOrQuestionable(disp_eval_result.Flags) && !ChkRangeByType(disp_acc, (MomCPU >= CPUZ380) ? SInt24 : SInt8, pArg))
  720.           return AdrMode;
  721.         if (addr_reg == 3)
  722.           AdrMode = ModSPRel;
  723.         else
  724.         {
  725.           AdrMode = ModReg8;
  726.           AdrPart = 6;
  727.           BAsmCode[PrefixCnt++] = 0x0d | (addr_reg & 0xf0);
  728.         }
  729.         AdrVals[0] = disp_acc & 0xff;
  730.         AdrCnt = 1;
  731.         if (((disp_acc < -0x80l) || (disp_acc > 0x7fl)) && (MomCPU >= CPUZ380))
  732.         {
  733.           AdrVals[AdrCnt++] = (disp_acc >> 8) & 0xff;
  734.           if ((disp_acc >= -0x8000l) && (disp_acc <= 0x7fffl))
  735.             ChangeDDPrefix(ePrefixIB);
  736.           else
  737.           {
  738.             AdrVals[AdrCnt++] = (disp_acc >> 16) & 0xff;
  739.             ChangeDDPrefix(ePrefixIW);
  740.           }
  741.         }
  742.         goto found;
  743.  
  744.       wrong:
  745.       default:
  746.         WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  747.         return AdrMode;
  748.     }
  749.   }
  750.  
  751.   /* ...immediate */
  752.  
  753.   if (!(ModeMask & MModImm))
  754.     goto inv_mode;
  755.   switch (OpSize)
  756.   {
  757.     case 0xff:
  758.       if (ModeMask & MModImm)
  759.         WrError(ErrNum_UndefOpSizes);
  760.       else
  761.         AdrMode = ModImm;  /* will fail on test @ label found */
  762.       break;
  763.     case 0:
  764.       AdrVals[0] = EvalStrIntExpression(pArg, Int8, &OK);
  765.       if (OK)
  766.       {
  767.         AdrMode = ModImm;
  768.         AdrCnt = 1;
  769.       }
  770.       break;
  771.     case 1:
  772.       if (InLongMode())
  773.       {
  774.         LongWord ImmVal = EvalStrIntExpression(pArg, Int32, &OK);
  775.         if (OK)
  776.         {
  777.           AdrVals[0] = Lo(ImmVal);
  778.           AdrVals[1] = Hi(ImmVal);
  779.           AdrMode = ModImm;
  780.           AdrCnt = 2;
  781.           if (ImmVal <= 0xfffful);
  782.           else
  783.           {
  784.             AdrVals[AdrCnt++] = (ImmVal >> 16) & 0xff;
  785.             if (ImmVal <= 0xfffffful)
  786.               ChangeDDPrefix(ePrefixIB);
  787.             else
  788.             {
  789.               AdrVals[AdrCnt++] = (ImmVal >> 24) & 0xff;
  790.               ChangeDDPrefix(ePrefixIW);
  791.             }
  792.           }
  793.         }
  794.       }
  795.      else
  796.      {
  797.        AdrInt = EvalStrIntExpression(pArg, Int16, &OK);
  798.        if (OK)
  799.        {
  800.          AdrVals[0] = Lo(AdrInt);
  801.          AdrVals[1] = Hi(AdrInt);
  802.          AdrMode = ModImm;
  803.          AdrCnt = 2;
  804.        }
  805.      }
  806.      break;
  807.   }
  808.  
  809. found:
  810.   if ((AdrMode != ModNone) && !(ModeMask & (1 << AdrMode)))
  811.     goto inv_mode;
  812.   return AdrMode;
  813.  
  814. inv_mode:
  815.   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  816.   AdrMode = ModNone;
  817.   return AdrMode;
  818. }
  819.  
  820. /*!------------------------------------------------------------------------
  821.  * \fn     DecodeAdr_A(const tStrComp *p_arg)
  822.  * \brief  check whether argument is accumulator (including possible register aliases)
  823.  * \param  p_arg source argument
  824.  * \return True if it is
  825.  * ------------------------------------------------------------------------ */
  826.  
  827. static Boolean DecodeAdr_A(const tStrComp *p_arg)
  828. {
  829.   if (DecodeAdr(p_arg, MModReg8) != ModReg8)
  830.     return False;
  831.   if (AdrPart != AccReg)
  832.   {
  833.     WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  834.     return False;
  835.   }
  836.   else
  837.     return True;
  838. }
  839.  
  840. /*!------------------------------------------------------------------------
  841.  * \fn     DecodeAdr_HL(const tStrComp *p_arg)
  842.  * \brief  check whether argument is HL (including possible register aliases)
  843.  * \param  p_arg source argument
  844.  * \return True if it is
  845.  * ------------------------------------------------------------------------ */
  846.  
  847. static Boolean DecodeAdr_HL(const tStrComp *p_arg)
  848. {
  849.   if (DecodeAdr(p_arg, MModReg16) != ModReg16)
  850.     return False;
  851.   if ((AdrPart != HLReg) || (PrefixCnt > 0))
  852.   {
  853.     WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  854.     return False;
  855.   }
  856.   else
  857.     return True;
  858. }
  859.  
  860. /*!------------------------------------------------------------------------
  861.  * \fn     DecodeAdrWithF(const tStrComp *pArg, Boolean AllowF)
  862.  * \brief  Handle address expression, treating F as 8th register
  863.  * \param  pArg source argument
  864.  * \param  allow 'F' at all?
  865.  * ------------------------------------------------------------------------ */
  866.  
  867. static void DecodeAdrWithF(const tStrComp *pArg, Boolean AllowF)
  868. {
  869.   Boolean applies_to_cpu = (MomCPU == CPUZ80U) || (MomCPU == CPUZ180) || (MomCPU == CPUZ380);
  870.  
  871.   if (applies_to_cpu
  872.    && AllowF
  873.    && !as_strcasecmp(pArg->str.p_str, "F"))
  874.   {
  875.     AdrMode = ModReg8;
  876.     AdrPart = 6;
  877.     return;
  878.   }
  879.  
  880.   DecodeAdr(pArg, MModAll);
  881.  
  882.   /* if 110 denotes F, it cannot denote (HL) */
  883.  
  884.   if (applies_to_cpu
  885.    && (AdrMode == ModReg8)
  886.    && (AdrPart == 6))
  887.   {
  888.     AdrMode = ModNone;
  889.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  890.   }
  891. }
  892.  
  893. static Boolean ImmIs8(void)
  894. {
  895.   Word tmp;
  896.  
  897.   if (AdrCnt < 2)
  898.     return True;
  899.  
  900.   tmp = (Word) AdrVals[AdrCnt - 2];
  901.  
  902.   return ((tmp <= 255) || (tmp >= 0xff80));
  903. }
  904.  
  905. static Boolean ImmIsS8(void)
  906. {
  907.   Word tmp;
  908.  
  909.   if (AdrCnt < 2)
  910.     return True;
  911.  
  912.   tmp = AdrVals[1];
  913.   tmp = (tmp << 8) | AdrVals[0];
  914.  
  915.   return ((tmp <= 127) || (tmp >= 0xff80));
  916. }
  917.  
  918. static void AppendVals(const Byte *pVals, unsigned ValLen)
  919. {
  920.   memcpy(BAsmCode + CodeLen, pVals, ValLen);
  921.   CodeLen += ValLen;
  922. }
  923.  
  924. static void AppendAdrVals(void)
  925. {
  926.   AppendVals(AdrVals, AdrCnt);
  927. }
  928.  
  929. static Boolean ParPair(const char *Name1, const char *Name2)
  930. {
  931.   return (((!as_strcasecmp(ArgStr[1].str.p_str, Name1)) && (!as_strcasecmp(ArgStr[2].str.p_str, Name2))) ||
  932.           ((!as_strcasecmp(ArgStr[1].str.p_str, Name2)) && (!as_strcasecmp(ArgStr[2].str.p_str, Name1))));
  933. }
  934.  
  935. /*-------------------------------------------------------------------------*/
  936. /* Bedingung entschluesseln */
  937.  
  938. static Boolean DecodeCondition(const char *Name, int *Erg)
  939. {
  940.   int z;
  941.  
  942.   for (z = 0; Conditions[z].Name; z++)
  943.     if (!as_strcasecmp(Conditions[z].Name, Name))
  944.     {
  945.       *Erg = Conditions[z].Code;
  946.       return True;
  947.     }
  948.   *Erg = 0;
  949.   return False;
  950. }
  951.  
  952. /*-------------------------------------------------------------------------*/
  953. /* Sonderregister dekodieren */
  954.  
  955. static Boolean DecodeSFR(char *Inp, Byte *Erg)
  956. {
  957.   if (!as_strcasecmp(Inp, "SR"))
  958.     *Erg = 1;
  959.   else if (!as_strcasecmp(Inp, "XSR"))
  960.     *Erg = 5;
  961.   else if (!as_strcasecmp(Inp, "DSR"))
  962.     *Erg = 6;
  963.   else if (!as_strcasecmp(Inp, "YSR"))
  964.     *Erg = 7;
  965.   else
  966.     return False;
  967.   return True;
  968. }
  969.  
  970. /*==========================================================================*/
  971. /* Adressbereiche */
  972.  
  973. static LargeWord PortEnd(void)
  974. {
  975.   return (LargeWord)IntTypeDefs[ExtFlag ? UInt32 : UInt16].Max;
  976. }
  977.  
  978. /*==========================================================================*/
  979. /* instruction decoders */
  980.  
  981. static void DecodeFixed(Word Index)
  982. {
  983.   BaseOrder *POrder = FixedOrders + Index;
  984.  
  985.   if (ChkArgCnt(0, 0)
  986.    && ChkMinCPU(POrder->MinCPU))
  987.   {
  988.     if (POrder->Len == 2)
  989.     {
  990.       BAsmCode[PrefixCnt++] = Hi(POrder->Code);
  991.       BAsmCode[PrefixCnt++] = Lo(POrder->Code);
  992.     }
  993.     else
  994.       BAsmCode[PrefixCnt++] = Lo(POrder->Code);
  995.     CodeLen = PrefixCnt;
  996.   }
  997. }
  998.  
  999. /*!------------------------------------------------------------------------
  1000.  * \fn     DecodeSTOP(Word Code)
  1001.  * \brief  handle STOP machine instruction
  1002.  * \param  Code machine code
  1003.  * ------------------------------------------------------------------------ */
  1004.  
  1005. static void DecodeSTOP(Word Code)
  1006. {
  1007.   if (ChkArgCnt(0, 0) && (ChkExactCPUList(ErrNum_InstructionNotSupported, CPUGBZ80, CPULR35902, CPUNone) >= 0))
  1008.   {
  1009.     BAsmCode[PrefixCnt++] = Lo(Code);
  1010.     CodeLen = PrefixCnt;
  1011.   }
  1012. }
  1013.  
  1014. static void DecodeAcc(Word Index)
  1015. {
  1016.   BaseOrder *POrder = AccOrders + Index;
  1017.  
  1018.   if (!ChkArgCnt(0, 1)
  1019.    || !ChkMinCPU(POrder->MinCPU))
  1020.     return;
  1021.  
  1022.   if (ArgCnt && !DecodeAdr_A(&ArgStr[1]))
  1023.     return;
  1024.  
  1025.   if (POrder->Len == 2)
  1026.   {
  1027.     BAsmCode[PrefixCnt++] = Hi(POrder->Code);
  1028.     BAsmCode[PrefixCnt++] = Lo(POrder->Code);
  1029.   }
  1030.   else
  1031.     BAsmCode[PrefixCnt++] = Lo(POrder->Code);
  1032.   CodeLen = PrefixCnt;
  1033. }
  1034.  
  1035. static void DecodeHL(Word Index)
  1036. {
  1037.   BaseOrder *POrder = HLOrders + Index;
  1038.  
  1039.   if (!ChkArgCnt(0, 1)
  1040.    || !ChkMinCPU(POrder->MinCPU))
  1041.     return;
  1042.  
  1043.   if (ArgCnt && !DecodeAdr_HL(&ArgStr[1]))
  1044.     return;
  1045.  
  1046.   if (POrder->Len == 2)
  1047.   {
  1048.     BAsmCode[PrefixCnt++] = Hi(POrder->Code);
  1049.     BAsmCode[PrefixCnt++] = Lo(POrder->Code);
  1050.   }
  1051.   else
  1052.     BAsmCode[PrefixCnt++] = Lo(POrder->Code);
  1053.   CodeLen = PrefixCnt;
  1054. }
  1055.  
  1056. static void DecodeLD(Word IsLDW)
  1057. {
  1058.   Byte AdrByte,HLen;
  1059.   int z;
  1060.   Byte HVals[5];
  1061.  
  1062.   if (ChkArgCnt(2, 2))
  1063.   {
  1064.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModIndReg16 | MModAbs | MModSPRel
  1065.                         | (is_sharp() ? (MModIndReg8 | MModHLInc | MModHLDec) : (MModRef | MModInt)));
  1066.     switch (AdrMode)
  1067.     {
  1068.       case ModReg8:
  1069.         if (AdrPart == AccReg) /* LD A, ... */
  1070.         {
  1071.           OpSize = 0; DecodeAdr(&ArgStr[2], MModReg8 | MModReg16 | MModIndReg16 | MModImm | MModAbs | MModSPRel
  1072.                                           | (is_sharp() ? (MModIndReg8 | MModHLInc | MModHLDec) : (MModRef | MModInt)));
  1073.           switch (AdrMode)
  1074.           {
  1075.             case ModReg8: /* LD A, R8/RX8/(HL)/(XY+D) */
  1076.               BAsmCode[PrefixCnt] = 0x78 + AdrPart;
  1077.               memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1078.               CodeLen = PrefixCnt + 1 + AdrCnt;
  1079.               break;
  1080.             case ModIndReg8: /* LD A,(FF00+C) */
  1081.               BAsmCode[0] = 0xf2;
  1082.               CodeLen = 1;
  1083.               break;
  1084.             case ModHLInc: /* LD A,(HLI) */
  1085.               BAsmCode[0] = 0x2a;
  1086.               CodeLen = 1;
  1087.               break;
  1088.             case ModHLDec: /* LD A,(HLD) */
  1089.               BAsmCode[0] = 0x3a;
  1090.               CodeLen = 1;
  1091.               break;
  1092.             case ModIndReg16: /* LD A, (BC)/(DE) */
  1093.               BAsmCode[PrefixCnt++] = 0x0a + (AdrPart << 4);
  1094.               CodeLen = PrefixCnt;
  1095.               break;
  1096.             case ModImm: /* LD A, imm8 */
  1097.               BAsmCode[PrefixCnt++] = 0x3e;
  1098.               BAsmCode[PrefixCnt++] = AdrVals[0];
  1099.               CodeLen = PrefixCnt;
  1100.               break;
  1101.             case ModAbs: /* LD a, (adr) */
  1102.               if (is_sharp() && (AdrVals[1] == 0xff))
  1103.               {
  1104.                 BAsmCode[0] = 0xf0;
  1105.                 BAsmCode[1] = AdrVals[0];
  1106.                 CodeLen = 2;
  1107.               }
  1108.               else
  1109.               {
  1110.                 BAsmCode[PrefixCnt] = is_sharp() ? 0xfa : 0x3a;
  1111.                 memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1112.                 CodeLen = PrefixCnt + 1 + AdrCnt;
  1113.               }
  1114.               break;
  1115.             case ModRef: /* LD A, R */
  1116.               BAsmCode[PrefixCnt++] = 0xed;
  1117.               BAsmCode[PrefixCnt++] = 0x5f;
  1118.               CodeLen = PrefixCnt;
  1119.               break;
  1120.             case ModInt: /* LD A, I */
  1121.               BAsmCode[PrefixCnt++] = 0xed;
  1122.               BAsmCode[PrefixCnt++] = 0x57;
  1123.               CodeLen = PrefixCnt;
  1124.               break;
  1125.             default:
  1126.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1127.           }
  1128.         }
  1129.         else if ((AdrPart != 6) && (PrefixCnt == 0)) /* LD R8, ... */
  1130.         {
  1131.           AdrByte = AdrPart; OpSize = 0; DecodeAdr(&ArgStr[2], MModReg8 | MModImm);
  1132.           switch (AdrMode)
  1133.           {
  1134.             case ModReg8: /* LD R8, R8/RX8/(HL)/(XY+D) */
  1135.               /* if (I(XY)+d) as source, cannot use H/L as target ! */
  1136.               if (((AdrByte == 4) || (AdrByte == 5)) && IndexPrefix() && (AdrCnt == 0)) WrError(ErrNum_InvAddrMode);
  1137.               else
  1138.               {
  1139.                 BAsmCode[PrefixCnt] = 0x40 + (AdrByte << 3) + AdrPart;
  1140.                 memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1141.                 CodeLen = PrefixCnt + 1 + AdrCnt;
  1142.               }
  1143.               break;
  1144.             case ModImm: /* LD R8, imm8 */
  1145.               BAsmCode[0] = 0x06 + (AdrByte << 3); BAsmCode[1] = AdrVals[0];
  1146.               CodeLen = 2;
  1147.               break;
  1148.             default:
  1149.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1150.           }
  1151.         }
  1152.         else if ((AdrPart == 4) || (AdrPart == 5)) /* LD RX8, ... */
  1153.         {
  1154.           AdrByte = AdrPart; OpSize = 0; DecodeAdr(&ArgStr[2], MModAll);
  1155.           switch (AdrMode)
  1156.           {
  1157.             case ModReg8: /* LD RX8, R8/RX8 */
  1158.               if (AdrPart == 6) WrError(ErrNum_InvAddrMode);        /* stopped here */
  1159.               else if ((AdrPart >= 4) && (AdrPart <= 5) && (PrefixCnt != 2)) WrError(ErrNum_InvAddrMode);
  1160.               else if ((AdrPart >= 4) && (AdrPart <= 5) && (BAsmCode[0] != BAsmCode[1])) WrError(ErrNum_InvAddrMode);
  1161.               else
  1162.               {
  1163.                 if (PrefixCnt == 2) PrefixCnt--;
  1164.                 BAsmCode[PrefixCnt] = 0x40 + (AdrByte << 3) + AdrPart;
  1165.                 CodeLen = PrefixCnt + 1;
  1166.               }
  1167.               break;
  1168.             case ModImm: /* LD RX8,imm8 */
  1169.               BAsmCode[PrefixCnt]=0x06+(AdrByte << 3);
  1170.               BAsmCode[PrefixCnt+1]=AdrVals[0];
  1171.               CodeLen=PrefixCnt+2;
  1172.               break;
  1173.             default:
  1174.               if (AdrMode!=ModNone) WrError(ErrNum_InvAddrMode);
  1175.           }
  1176.         }
  1177.         else /* LD (HL)/(XY+d),... */
  1178.         {
  1179.           HLen = AdrCnt;
  1180.           memcpy(HVals, AdrVals, AdrCnt);
  1181.           z = PrefixCnt;
  1182.           if ((z == 0) && (IsLDW))
  1183.           {
  1184.             OpSize = 1;
  1185.             MayLW = True;
  1186.           }
  1187.           else
  1188.             OpSize = 0;
  1189.           DecodeAdr(&ArgStr[2], MModAll);
  1190.           switch (AdrMode)
  1191.           {
  1192.             case ModReg8: /* LD (HL)/(XY+D),R8 */
  1193.               if ((PrefixCnt != z) || (AdrPart == 6)) WrError(ErrNum_InvAddrMode);
  1194.               else
  1195.               {
  1196.                 BAsmCode[PrefixCnt] = 0x70 + AdrPart;
  1197.                 memcpy(BAsmCode + PrefixCnt + 1, HVals, HLen);
  1198.                 CodeLen=PrefixCnt + 1 + HLen;
  1199.               }
  1200.               break;
  1201.             case ModImm: /* LD (HL)/(XY+D),imm8:16:32 */
  1202.               if ((z == 0) && (IsLDW))
  1203.               {
  1204.                 if (ChkMinCPU(CPUZ380))
  1205.                 {
  1206.                   BAsmCode[PrefixCnt] = 0xed;
  1207.                   BAsmCode[PrefixCnt + 1] = 0x36;
  1208.                   memcpy(BAsmCode + PrefixCnt + 2, AdrVals, AdrCnt);
  1209.                   CodeLen = PrefixCnt + 2 + AdrCnt;
  1210.                 }
  1211.               }
  1212.               else
  1213.               {
  1214.                 BAsmCode[PrefixCnt] = 0x36;
  1215.                 memcpy(BAsmCode + 1 + PrefixCnt, HVals, HLen);
  1216.                 BAsmCode[PrefixCnt + 1 + HLen] = AdrVals[0];
  1217.                 CodeLen = PrefixCnt + 1 + HLen + AdrCnt;
  1218.               }
  1219.               break;
  1220.             case ModReg16: /* LD (HL)/(XY+D),R16/XY */
  1221.               if (!ChkMinCPU(CPUZ380));
  1222.               else if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  1223.               else if (HLen == 0)
  1224.               {
  1225.                 if (PrefixCnt == z) /* LD (HL),R16 */
  1226.                 {
  1227.                   if (AdrPart == 2)
  1228.                     AdrPart = 3;
  1229.                   BAsmCode[0] = 0xfd;
  1230.                   BAsmCode[1] = 0x0f + (AdrPart << 4);
  1231.                   CodeLen = 2;
  1232.                 }
  1233.                 else /* LD (HL),XY */
  1234.                 {
  1235.                   CodeLen = PrefixCnt + 1;
  1236.                   BAsmCode[PrefixCnt] = 0x31;
  1237.                   CodeLen = 1 + PrefixCnt;
  1238.                 }
  1239.               }
  1240.               else
  1241.               {
  1242.                 if (PrefixCnt == z) /* LD (XY+D),R16 */
  1243.                 {
  1244.                   if (AdrPart == 2)
  1245.                     AdrPart = 3;
  1246.                   BAsmCode[PrefixCnt] = 0xcb;
  1247.                   memcpy(BAsmCode + PrefixCnt + 1, HVals, HLen);
  1248.                   BAsmCode[PrefixCnt + 1 + HLen] = 0x0b + (AdrPart << 4);
  1249.                   CodeLen = PrefixCnt + 1 + HLen + 1;
  1250.                 }
  1251.                 else if (BAsmCode[0] == BAsmCode[1]) WrError(ErrNum_InvAddrMode);
  1252.                 else
  1253.                 {
  1254.                   PrefixCnt--;
  1255.                   BAsmCode[PrefixCnt] = 0xcb;
  1256.                   memcpy(BAsmCode+PrefixCnt + 1, HVals, HLen);
  1257.                   BAsmCode[PrefixCnt + 1 + HLen] = 0x2b;
  1258.                   CodeLen = PrefixCnt + 1 + HLen + 1;
  1259.                 }
  1260.               }
  1261.               break;
  1262.             default:
  1263.               if (AdrMode!=ModNone) WrError(ErrNum_InvAddrMode);
  1264.           }
  1265.         }
  1266.         break;
  1267.       case ModReg16:
  1268.         if (AdrPart == 3) /* LD SP,... */
  1269.         {
  1270.           OpSize = 1;
  1271.           MayLW = True;
  1272.           DecodeAdr(&ArgStr[2], MModAll);
  1273.           switch (AdrMode)
  1274.           {
  1275.             case ModReg16: /* LD SP,HL/XY */
  1276.               if (AdrPart != 2) WrError(ErrNum_InvAddrMode);
  1277.               else
  1278.               {
  1279.                 BAsmCode[PrefixCnt] = 0xf9;
  1280.                 CodeLen = PrefixCnt + 1;
  1281.               }
  1282.               break;
  1283.             case ModImm: /* LD SP,imm16:32 */
  1284.               BAsmCode[PrefixCnt] = 0x31;
  1285.               memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1286.               CodeLen = PrefixCnt + 1 + AdrCnt;
  1287.               break;
  1288.             case ModAbs: /* LD SP,(adr) */
  1289.               if (AChkMinCPUPos(CPUZ80, &ArgStr[2]))
  1290.               {
  1291.                 BAsmCode[PrefixCnt] = 0xed;
  1292.                 BAsmCode[PrefixCnt + 1] = 0x7b;
  1293.                 memcpy(BAsmCode + PrefixCnt + 2, AdrVals, AdrCnt);
  1294.                 CodeLen = PrefixCnt + 2 + AdrCnt;
  1295.               }
  1296.               break;
  1297.             default:
  1298.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1299.           }
  1300.         }
  1301.         else if (PrefixCnt == 0) /* LD R16,... */
  1302.         {
  1303.           unsigned ModeMask = MModAll;
  1304.  
  1305.           AdrByte = (AdrPart == 2) ? 3 : AdrPart;
  1306.           OpSize = 1;
  1307.           MayLW = True;
  1308.           if (is_sharp() && (AdrPart == 2))
  1309.             ModeMask |= MModSPAdd;
  1310.           DecodeAdr(&ArgStr[2], ModeMask);
  1311.           switch (AdrMode)
  1312.           {
  1313.             case ModInt: /* LD HL,I */
  1314.               if (!ChkMinCPU(CPUZ380));
  1315.               else if (AdrByte != 3) WrError(ErrNum_InvAddrMode);
  1316.               else
  1317.               {
  1318.                 BAsmCode[0] = 0xdd;
  1319.                 BAsmCode[1] = 0x57;
  1320.                 CodeLen = 2;
  1321.               }
  1322.               break;
  1323.             case ModReg8:
  1324.               if (AdrPart != 6) WrError(ErrNum_InvAddrMode);
  1325.               else if (!ChkMinCPU(CPUZ380));
  1326.               else if (PrefixCnt == 0) /* LD R16,(HL) */
  1327.               {
  1328.                 BAsmCode[0] = 0xdd;
  1329.                 BAsmCode[1] = 0x0f + (AdrByte << 4);
  1330.                 CodeLen = 2;
  1331.               }
  1332.               else /* LD R16,(XY+d) */
  1333.               {
  1334.                 BAsmCode[PrefixCnt] = 0xcb;
  1335.                 memcpy(BAsmCode+PrefixCnt + 1, AdrVals, AdrCnt);
  1336.                 BAsmCode[PrefixCnt + 1 + AdrCnt] = 0x03 + (AdrByte << 4);
  1337.                 CodeLen = PrefixCnt + 1 + AdrCnt + 1;
  1338.               }
  1339.               break;
  1340.             case ModReg16:
  1341.               if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  1342.               else if (!ChkMinCPU(CPUZ380));
  1343.               else if (PrefixCnt == 0) /* LD R16,R16 */
  1344.               {
  1345.                 if (AdrPart == 2)
  1346.                   AdrPart = 3;
  1347.                 else if (AdrPart == 0)
  1348.                   AdrPart = 2;
  1349.                 BAsmCode[0] = 0xcd + (AdrPart << 4);
  1350.                 BAsmCode[1] = 0x02 + (AdrByte << 4);
  1351.                 CodeLen = 2;
  1352.               }
  1353.               else /* LD R16,XY */
  1354.               {
  1355.                 BAsmCode[PrefixCnt] = 0x0b + (AdrByte << 4);
  1356.                 CodeLen=PrefixCnt + 1;
  1357.               }
  1358.               break;
  1359.             case ModIndReg16: /* LD R16,(R16) */
  1360.               if (ChkMinCPU(CPUZ380))
  1361.               {
  1362.                 CodeLen = 2;
  1363.                 BAsmCode[0] = 0xdd;
  1364.                 BAsmCode[1] = 0x0c + (AdrByte << 4) + AdrPart;
  1365.               }
  1366.               break;
  1367.             case ModImm: /* LD R16,imm */
  1368.               if (AdrByte == 3)
  1369.                 AdrByte = 2;
  1370.               CodeLen=PrefixCnt + 1 + AdrCnt;
  1371.               BAsmCode[PrefixCnt] = 0x01 + (AdrByte << 4);
  1372.               memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1373.               break;
  1374.             case ModAbs: /* LD R16,(adr) */
  1375.               if (!AChkMinCPUPos(CPUZ80, &ArgStr[2]));
  1376.               else if (AdrByte == 3)
  1377.               {
  1378.                 BAsmCode[PrefixCnt] = 0x2a;
  1379.                 memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1380.                 CodeLen = 1 + PrefixCnt + AdrCnt;
  1381.               }
  1382.               else
  1383.               {
  1384.                 BAsmCode[PrefixCnt] = 0xed;
  1385.                 BAsmCode[PrefixCnt+1] = 0x4b + (AdrByte << 4);
  1386.                 memcpy(BAsmCode + PrefixCnt + 2, AdrVals, AdrCnt);
  1387.                 CodeLen = PrefixCnt + 2 + AdrCnt;
  1388.               }
  1389.               break;
  1390.             case ModSPAdd:
  1391.               BAsmCode[0] = 0xf8;
  1392.               BAsmCode[1] = AdrVals[0];
  1393.               CodeLen = 2;
  1394.               break;
  1395.             case ModSPRel: /* LD R16,(SP+D) */
  1396.               if (ChkMinCPU(CPUZ380))
  1397.               {
  1398.                 BAsmCode[PrefixCnt] = 0xdd;
  1399.                 BAsmCode[PrefixCnt + 1] = 0xcb;
  1400.                 memcpy(BAsmCode + PrefixCnt + 2, AdrVals, AdrCnt);
  1401.                 BAsmCode[PrefixCnt + 2 + AdrCnt] = 0x01 + (AdrByte << 4);
  1402.                 CodeLen=PrefixCnt + 3 + AdrCnt;
  1403.               }
  1404.               break;
  1405.             default:
  1406.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1407.           }
  1408.         }
  1409.         else /* LD XY,... */
  1410.         {
  1411.           OpSize = 1;
  1412.           MayLW = True;
  1413.           DecodeAdr(&ArgStr[2], MModAll);
  1414.           switch (AdrMode)
  1415.           {
  1416.             case ModReg8:
  1417.               if (AdrPart != 6) WrError(ErrNum_InvAddrMode);
  1418.               else if (!ChkMinCPU(CPUZ380));
  1419.               else if (AdrCnt == 0) /* LD XY,(HL) */
  1420.               {
  1421.                 BAsmCode[PrefixCnt] = 0x33;
  1422.                 CodeLen = PrefixCnt + 1;
  1423.               }
  1424.               else if (BAsmCode[0] == BAsmCode[1]) WrError(ErrNum_InvAddrMode);
  1425.               else /* LD XY,(XY+D) */
  1426.               {
  1427.                 BAsmCode[0] = BAsmCode[1];
  1428.                 PrefixCnt--;
  1429.                 BAsmCode[PrefixCnt] = 0xcb;
  1430.                 memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1431.                 BAsmCode[PrefixCnt + 1 + AdrCnt] = 0x23;
  1432.                 CodeLen = PrefixCnt + 1 + AdrCnt + 1;
  1433.               }
  1434.               break;
  1435.             case ModReg16:
  1436.               if (!ChkMinCPU(CPUZ380));
  1437.               else if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  1438.               else if (PrefixCnt == 1) /* LD XY,R16 */
  1439.               {
  1440.                 if (AdrPart == 2) AdrPart = 3;
  1441.                 CodeLen = 1 + PrefixCnt;
  1442.                 BAsmCode[PrefixCnt] = 0x07 + (AdrPart << 4);
  1443.               }
  1444.               else if (BAsmCode[0] == BAsmCode[1]) WrError(ErrNum_InvAddrMode);
  1445.               else /* LD XY,XY */
  1446.               {
  1447.                 BAsmCode[--PrefixCnt] = 0x27;
  1448.                 CodeLen = 1 + PrefixCnt;
  1449.               }
  1450.               break;
  1451.             case ModIndReg16:
  1452.               if (ChkMinCPU(CPUZ380)) /* LD XY,(R16) */
  1453.               {
  1454.                 BAsmCode[PrefixCnt] = 0x03 + (AdrPart << 4);
  1455.                 CodeLen = PrefixCnt + 1;
  1456.               }
  1457.               break;
  1458.             case ModImm: /* LD XY,imm16:32 */
  1459.               BAsmCode[PrefixCnt] = 0x21;
  1460.               memcpy(BAsmCode+PrefixCnt + 1, AdrVals, AdrCnt);
  1461.               CodeLen = PrefixCnt + 1 + AdrCnt;
  1462.               break;
  1463.             case ModAbs: /* LD XY,(adr) */
  1464.               BAsmCode[PrefixCnt] = 0x2a;
  1465.               memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1466.               CodeLen = PrefixCnt + 1 + AdrCnt;
  1467.               break;
  1468.             case ModSPRel: /* LD XY,(SP+D) */
  1469.               if (ChkMinCPU(CPUZ380))
  1470.               {
  1471.                 BAsmCode[PrefixCnt] = 0xcb;
  1472.                 memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1473.                 BAsmCode[PrefixCnt + 1 + AdrCnt] = 0x21;
  1474.                 CodeLen = PrefixCnt + 1 + AdrCnt + 1;
  1475.               }
  1476.               break;
  1477.             default:
  1478.               if (AdrMode!=ModNone) WrError(ErrNum_InvAddrMode);
  1479.           }
  1480.         }
  1481.         break;
  1482.       case ModIndReg8:
  1483.         DecodeAdr(&ArgStr[2], MModReg8);
  1484.         switch (AdrMode)
  1485.         {
  1486.           case ModReg8:
  1487.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1488.             else
  1489.             {
  1490.               BAsmCode[0] = 0xe2;
  1491.               CodeLen = 1;
  1492.             }
  1493.             break;
  1494.           default:
  1495.             break;
  1496.         }
  1497.         break;
  1498.       case ModHLInc:
  1499.         DecodeAdr(&ArgStr[2], MModReg8);
  1500.         switch (AdrMode)
  1501.         {
  1502.           case ModReg8:
  1503.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1504.             else
  1505.             {
  1506.               BAsmCode[0] = 0x22;
  1507.               CodeLen = 1;
  1508.             }
  1509.             break;
  1510.           default:
  1511.             break;
  1512.         }
  1513.         break;
  1514.       case ModHLDec:
  1515.         DecodeAdr(&ArgStr[2], MModReg8);
  1516.         switch (AdrMode)
  1517.         {
  1518.           case ModReg8:
  1519.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1520.             else
  1521.             {
  1522.               BAsmCode[0] = 0x32;
  1523.               CodeLen = 1;
  1524.             }
  1525.             break;
  1526.           default:
  1527.             break;
  1528.         }
  1529.         break;
  1530.       case ModIndReg16:
  1531.         AdrByte = AdrPart;
  1532.         if (IsLDW)
  1533.         {
  1534.           OpSize = 1;
  1535.           MayLW = True;
  1536.         }
  1537.         else
  1538.           OpSize = 0;
  1539.         DecodeAdr(&ArgStr[2], MModAll);
  1540.         switch (AdrMode)
  1541.         {
  1542.           case ModReg8: /* LD (R16),A */
  1543.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1544.             else
  1545.             {
  1546.               CodeLen = 1;
  1547.               BAsmCode[0] = 0x02 + (AdrByte << 4);
  1548.             }
  1549.             break;
  1550.           case ModReg16:
  1551.             if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  1552.             else if (!ChkMinCPU(CPUZ380));
  1553.             else if (PrefixCnt == 0) /* LD (R16),R16 */
  1554.             {
  1555.               if (AdrPart == 2)
  1556.                 AdrPart = 3;
  1557.               BAsmCode[0] = 0xfd;
  1558.               BAsmCode[1] = 0x0c + AdrByte + (AdrPart << 4);
  1559.               CodeLen = 2;
  1560.             }
  1561.             else /* LD (R16),XY */
  1562.             {
  1563.               CodeLen = PrefixCnt;
  1564.               BAsmCode[CodeLen++] = 0x01 + (AdrByte << 4);
  1565.             }
  1566.             break;
  1567.           case ModImm:
  1568.             if (!IsLDW) WrError(ErrNum_InvAddrMode);
  1569.             else if (ChkMinCPU(CPUZ380))
  1570.             {
  1571.               CodeLen = PrefixCnt;
  1572.               BAsmCode[CodeLen++] = 0xed;
  1573.               BAsmCode[CodeLen++] = 0x06 + (AdrByte << 4);
  1574.               AppendAdrVals();
  1575.             }
  1576.             break;
  1577.           default:
  1578.             if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1579.         }
  1580.         break;
  1581.       case ModAbs:
  1582.         HLen = AdrCnt;
  1583.         memcpy(HVals, AdrVals, AdrCnt);
  1584.         OpSize = 0;
  1585.         DecodeAdr(&ArgStr[2], MModReg8 | MModReg16);
  1586.         switch (AdrMode)
  1587.         {
  1588.           case ModReg8: /* LD (adr),A */
  1589.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1590.             else if (is_sharp() && (HVals[1] == 0xff))
  1591.             {
  1592.               BAsmCode[0] = 0xe0;
  1593.               BAsmCode[1] = HVals[0];
  1594.               CodeLen = 2;
  1595.             }
  1596.             else
  1597.             {
  1598.               CodeLen = PrefixCnt;
  1599.               BAsmCode[CodeLen++] = is_sharp() ? 0xea : 0x32;
  1600.               AppendVals(HVals, HLen);
  1601.             }
  1602.             break;
  1603.           case ModReg16:
  1604.             if ((AdrPart == 3) && is_sharp())
  1605.             {
  1606.               BAsmCode[0] = 0x08;
  1607.               CodeLen = 1;
  1608.             }
  1609.             else if (!AChkMinCPUPos(CPUZ80, &ArgStr[1]));
  1610.             else if (AdrPart == 2) /* LD (adr),HL/XY */
  1611.             {
  1612.               CodeLen = PrefixCnt;
  1613.               BAsmCode[CodeLen++] = 0x22;
  1614.               AppendVals(HVals, HLen);
  1615.             }
  1616.             else /* LD (adr),R16 */
  1617.             {
  1618.               CodeLen = PrefixCnt;
  1619.               BAsmCode[CodeLen++] = 0xed;
  1620.               BAsmCode[CodeLen++] = 0x43 + (AdrPart << 4);
  1621.               AppendVals(HVals, HLen);
  1622.             }
  1623.             break;
  1624.           default:
  1625.             if (AdrMode!=ModNone) WrError(ErrNum_InvAddrMode);
  1626.         }
  1627.         break;
  1628.       case ModInt:
  1629.         switch (DecodeAdr(&ArgStr[2], MModReg8 | MModReg16))
  1630.         {
  1631.           case ModReg8: /* LD I,A */
  1632.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1633.             else
  1634.             {
  1635.               CodeLen = 2;
  1636.               BAsmCode[0] = 0xed;
  1637.               BAsmCode[1] = 0x47;
  1638.             }
  1639.             break;
  1640.           case ModReg16: /* LD I,HL */
  1641.             if ((AdrPart != HLReg) || PrefixCnt) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1642.             else if (ChkMinCPU(CPUZ380))
  1643.             {
  1644.               CodeLen = 2;
  1645.               BAsmCode[0] = 0xdd;
  1646.               BAsmCode[1] = 0x47;
  1647.             }
  1648.             break;
  1649.           default:
  1650.             break;
  1651.         }
  1652.         break;
  1653.       case ModRef:
  1654.         if (DecodeAdr_A(&ArgStr[2])) /* LD R,A */
  1655.         {
  1656.           CodeLen = 2;
  1657.           BAsmCode[0] = 0xed;
  1658.           BAsmCode[1] = 0x4f;
  1659.         }
  1660.         else WrError(ErrNum_InvAddrMode);
  1661.         break;
  1662.       case ModSPRel:
  1663.         if (ChkMinCPU(CPUZ380))
  1664.         {
  1665.           HLen = AdrCnt;
  1666.           memcpy(HVals, AdrVals, AdrCnt);
  1667.           OpSize = 0;
  1668.           DecodeAdr(&ArgStr[2], MModAll);
  1669.           switch (AdrMode)
  1670.           {
  1671.             case ModReg16:
  1672.               if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  1673.               else if (PrefixCnt == 0) /* LD (SP+D),R16 */
  1674.               {
  1675.                 if (AdrPart == 2)
  1676.                   AdrPart = 3;
  1677.                 CodeLen = PrefixCnt;
  1678.                 BAsmCode[CodeLen++] = 0xdd;
  1679.                 BAsmCode[CodeLen++] = 0xcb;
  1680.                 AppendVals(HVals, HLen);
  1681.                 BAsmCode[CodeLen++] = 0x09 + (AdrPart << 4);
  1682.               }
  1683.               else /* LD (SP+D),XY */
  1684.               {
  1685.                 CodeLen = PrefixCnt;
  1686.                 BAsmCode[CodeLen++] = 0xcb;
  1687.                 AppendVals(HVals, HLen);
  1688.                 BAsmCode[CodeLen++] = 0x29;
  1689.               }
  1690.               break;
  1691.             default:
  1692.               if (AdrMode!=ModNone) WrError(ErrNum_InvAddrMode);
  1693.           }
  1694.         }
  1695.         break;
  1696.       default:
  1697.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1698.     }  /* outer switch */
  1699.   }
  1700. }
  1701.  
  1702. /*!------------------------------------------------------------------------
  1703.  * \fn     DecodeLDHL(Word Code)
  1704.  * \brief  decode LDHL instruction (Sharp cores only)
  1705.  * ------------------------------------------------------------------------ */
  1706.  
  1707. static void DecodeLDHL(Word Code)
  1708. {
  1709.   Boolean OK;
  1710.  
  1711.   UNUSED(Code);
  1712.  
  1713.   if (!ChkArgCnt(2, 2)
  1714.    || (ChkExactCPUList(ErrNum_InstructionNotSupported, CPULR35902, CPUGBZ80, CPUNone) < 0))
  1715.     return;
  1716.   DecodeAdr(&ArgStr[1], MModReg16);
  1717.   if (AdrMode != ModReg16)
  1718.     return;
  1719.   if (AdrPart != 3)
  1720.   {
  1721.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1722.     return;    
  1723.   }
  1724.   BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], SInt8, &OK);
  1725.   if (OK)
  1726.   {
  1727.     BAsmCode[0] = 0xf8;
  1728.     CodeLen = 2;
  1729.   }
  1730. }
  1731.  
  1732. /*!------------------------------------------------------------------------
  1733.  * \fn     DecodeLDH(Word code)
  1734.  * \brief  Decode LDH instruction (Sharp cores only)
  1735.  * ------------------------------------------------------------------------ */
  1736.  
  1737. static Boolean ChkAbsUpperPage(Byte *p_dest)
  1738. {
  1739.   /* allow just lower byte (00..ff) or full address (ff00..ffff): */
  1740.  
  1741.   if ((AdrCnt == 2) && ((AdrVals[1] == 0x00) || (AdrVals[1] == 0xff)))
  1742.   {
  1743.     *p_dest = AdrVals[0];
  1744.     return True;
  1745.   }
  1746.   else
  1747.     return False;
  1748. }
  1749.  
  1750. static void DecodeLDH(Word code)
  1751. {
  1752.   UNUSED(code);
  1753.  
  1754.   if (!ChkArgCnt(2, 2)
  1755.    || (ChkExactCPUList(ErrNum_InstructionNotSupported, CPULR35902, CPUGBZ80, CPUNone) < 0))
  1756.     return;
  1757.  
  1758.   OpSize = 0;
  1759.   switch (DecodeAdr(&ArgStr[1], MModReg8 | MModIndReg8 | MModAbs))
  1760.   {
  1761.     case ModReg8:
  1762.       if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1763.       else switch (DecodeAdr(&ArgStr[2], MModIndReg8 | MModAbs))
  1764.       {
  1765.         case ModIndReg8:
  1766.           BAsmCode[0] = 0xf2;
  1767.           CodeLen = 1;
  1768.           break;
  1769.         case ModAbs:
  1770.           if (ChkAbsUpperPage(&BAsmCode[1]))
  1771.           {
  1772.             BAsmCode[0] = 0xf0;
  1773.             CodeLen = 2;
  1774.           }
  1775.           break;
  1776.         default:
  1777.           break;
  1778.       }
  1779.       break;
  1780.     case ModIndReg8:
  1781.       if (DecodeAdr_A(&ArgStr[2]))
  1782.       {
  1783.         BAsmCode[0] = 0xe2;
  1784.         CodeLen = 1;
  1785.       }
  1786.       break;
  1787.     case ModAbs:
  1788.       if (ChkAbsUpperPage(&BAsmCode[1]))
  1789.       {
  1790.         if (DecodeAdr_A(&ArgStr[2]))
  1791.         {
  1792.           BAsmCode[0] = 0xe0;
  1793.           CodeLen = 2;
  1794.         }
  1795.       }
  1796.       break;
  1797.     default:
  1798.       break;
  1799.   }
  1800. }
  1801.  
  1802. /*!------------------------------------------------------------------------
  1803.  * \fn     DecodeLDX(Word Code)
  1804.  * \brief  decode LDX instruction (Sharp cores only)
  1805.  * ------------------------------------------------------------------------ */
  1806.  
  1807. static void DecodeLDX(Word Code)
  1808. {
  1809.   UNUSED(Code);
  1810.  
  1811.   if (!ChkArgCnt(2, 2)
  1812.    || (ChkExactCPUList(ErrNum_InstructionNotSupported, CPULR35902, CPUGBZ80, CPUNone) < 0))
  1813.     return;
  1814.   DecodeAdr(&ArgStr[1], MModReg8 | MModAbs);
  1815.   switch (AdrMode)
  1816.   {
  1817.     case ModReg8:
  1818.       if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  1819.       else
  1820.       {
  1821.         DecodeAdr(&ArgStr[2], MModAbs);
  1822.         if (AdrMode == ModAbs)
  1823.         {
  1824.           BAsmCode[0] = 0xfa;
  1825.           memcpy(BAsmCode + 1, AdrVals, AdrCnt);
  1826.           CodeLen = 1 + AdrCnt;
  1827.         }
  1828.       }
  1829.       break;
  1830.     case ModAbs:
  1831.       memcpy(BAsmCode + 1, AdrVals, AdrCnt);
  1832.       DecodeAdr(&ArgStr[2], MModReg8);
  1833.       if (AdrMode == ModReg8)
  1834.       {
  1835.         if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
  1836.         else
  1837.         {
  1838.           BAsmCode[0] = 0xea;
  1839.           CodeLen = 3;
  1840.         }
  1841.       }
  1842.       break;
  1843.     default:
  1844.       break;
  1845.   }
  1846. }
  1847.  
  1848. static void DecodeALU8(Word Code)
  1849. {
  1850.   switch (ArgCnt)
  1851.   {
  1852.     case 1:
  1853.       AdrMode = ModReg8;
  1854.       AdrPart = AccReg;
  1855.       AdrCnt = 0;
  1856.       break;
  1857.     case 2:
  1858.       DecodeAdr(&ArgStr[1], MModReg8 | (MomCPU == CPUZ380? MModReg16 : 0));
  1859.       break;
  1860.     default:
  1861.       (void)ChkArgCnt(1, 2);
  1862.       return;
  1863.   }
  1864.  
  1865.   switch (AdrMode)
  1866.   {
  1867.     case ModReg16:
  1868.       if (Code != 2) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1869.       else if (AdrPart == HLReg)
  1870.       {
  1871.         OpSize = 1;
  1872.         if (DecodeAdr(&ArgStr[ArgCnt], MModAbs) == ModAbs)
  1873.         {
  1874.           CodeLen = PrefixCnt;
  1875.           BAsmCode[CodeLen++] = 0xed;
  1876.           BAsmCode[CodeLen++] = 0xd6;
  1877.           AppendAdrVals();
  1878.         }
  1879.       }
  1880.       else if (AdrPart == SPReg)
  1881.       {
  1882.         OpSize = 1;
  1883.         if (DecodeAdr(&ArgStr[ArgCnt], MModImm) == ModImm)
  1884.         {
  1885.           CodeLen = 0;
  1886.           BAsmCode[CodeLen++] = 0xed;
  1887.           BAsmCode[CodeLen++] = 0x92;
  1888.           AppendAdrVals();
  1889.           break;
  1890.         }
  1891.       }
  1892.       else
  1893.         WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1894.       break;
  1895.     case ModReg8:
  1896.       if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1897.       else
  1898.       {
  1899.         OpSize = 0;
  1900.         switch (DecodeAdr(&ArgStr[ArgCnt], MModReg8 | MModImm))
  1901.         {
  1902.           case ModReg8:
  1903.             CodeLen = PrefixCnt + 1 + AdrCnt;
  1904.             BAsmCode[PrefixCnt] = 0x80 + (Code << 3) + AdrPart;
  1905.             memcpy(BAsmCode + PrefixCnt + 1, AdrVals, AdrCnt);
  1906.             break;
  1907.           case ModImm:
  1908.             if (!ImmIs8()) WrStrErrorPos(ErrNum_OverRange, &ArgStr[ArgCnt]);
  1909.             else
  1910.             {
  1911.               CodeLen = 2;
  1912.               BAsmCode[0] = 0xc6 + (Code << 3);
  1913.               BAsmCode[1] = AdrVals[0];
  1914.             }
  1915.             break;
  1916.           default:
  1917.             break;
  1918.         }
  1919.         break;
  1920.       default:
  1921.         break;
  1922.     }
  1923.   }
  1924. }
  1925.  
  1926. static void DecodeALU16(Word Code)
  1927. {
  1928.   if (ChkArgCnt(1, 2)
  1929.    && ChkMinCPU(CPUZ380)
  1930.    && ((ArgCnt == 1) || DecodeAdr_HL(&ArgStr[1])))
  1931.   {
  1932.     OpSize = 1; DecodeAdr(&ArgStr[ArgCnt], MModAll);
  1933.     switch (AdrMode)
  1934.     {
  1935.       case ModReg16:
  1936.         if (PrefixCnt > 0)      /* wenn Register, dann nie DDIR! */
  1937.         {
  1938.           BAsmCode[PrefixCnt] = 0x87 + (Code << 3);
  1939.           CodeLen = 1 + PrefixCnt;
  1940.         }
  1941.         else if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  1942.         else
  1943.         {
  1944.           if (AdrPart == 2)
  1945.             AdrPart = 3;
  1946.           BAsmCode[0] = 0xed;
  1947.           BAsmCode[1] = 0x84 + (Code << 3) + AdrPart;
  1948.           CodeLen = 2;
  1949.         }
  1950.         break;
  1951.       case ModReg8:
  1952.         if ((AdrPart != 6) || (AdrCnt == 0)) WrError(ErrNum_InvAddrMode);
  1953.         else
  1954.         {
  1955.           CodeLen = PrefixCnt;
  1956.           BAsmCode[CodeLen++] = 0xc6 + (Code << 3);
  1957.           AppendAdrVals();
  1958.         }
  1959.         break;
  1960.       case ModImm:
  1961.         CodeLen = 0;
  1962.         BAsmCode[CodeLen++] = 0xed;
  1963.         BAsmCode[CodeLen++] = 0x86 + (Code << 3);
  1964.         AppendAdrVals();
  1965.         break;
  1966.       default:
  1967.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  1968.     }
  1969.   }
  1970. }
  1971.  
  1972. static void DecodeADD(Word Index)
  1973. {
  1974.   UNUSED(Index);
  1975.  
  1976.   if (ChkArgCnt(2, 2))
  1977.   {
  1978.     DecodeAdr(&ArgStr[1], MModNoImm);
  1979.     switch (AdrMode)
  1980.     {
  1981.       case ModReg8:
  1982.         if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1983.         else
  1984.         {
  1985.           OpSize = 0; DecodeAdr(&ArgStr[2], MModReg8 | MModImm);
  1986.           switch (AdrMode)
  1987.           {
  1988.             case ModReg8:
  1989.               CodeLen = PrefixCnt;
  1990.               BAsmCode[CodeLen++] = 0x80 + AdrPart;
  1991.               AppendAdrVals();
  1992.               break;
  1993.             case ModImm:
  1994.               CodeLen = PrefixCnt;
  1995.               BAsmCode[CodeLen++] = 0xc6;
  1996.               AppendAdrVals();
  1997.               break;
  1998.             default:
  1999.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2000.           }
  2001.         }
  2002.         break;
  2003.       case ModReg16:
  2004.         if (AdrPart == 3) /* SP */
  2005.         {
  2006.           OpSize = (MomCPU == CPUZ380) ? 1 : 0;
  2007.           DecodeAdr(&ArgStr[2], MModAll);
  2008.           switch (AdrMode)
  2009.           {
  2010.             case ModImm:
  2011.               switch (ChkExactCPUList(ErrNum_InstructionNotSupported, CPUZ380, CPUR2000, CPULR35902, CPUGBZ80, CPUNone))
  2012.               {
  2013.                 case 0:
  2014.                   BAsmCode[0] = 0xed; BAsmCode[1] = 0x82;
  2015.                   memcpy(BAsmCode + 2, AdrVals, AdrCnt);
  2016.                   CodeLen = 2 + AdrCnt;
  2017.                   break;
  2018.                 case 1:
  2019.                   BAsmCode[0] = 0x27; BAsmCode[1] = 0[AdrVals];
  2020.                   CodeLen = 2;
  2021.                   break;
  2022.                 case 2:
  2023.                 case 3:
  2024.                   if (!ImmIsS8()) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
  2025.                   else
  2026.                   {
  2027.                     BAsmCode[0] = 0xe8;
  2028.                     BAsmCode[1] = 0[AdrVals];
  2029.                     CodeLen = 2;
  2030.                   }
  2031.                   break;
  2032.               }
  2033.               break;
  2034.             default:
  2035.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2036.           }
  2037.         }
  2038.         else if (AdrPart != 2) WrError(ErrNum_InvAddrMode);
  2039.         else
  2040.         {
  2041.           Boolean HasPrefixes = (PrefixCnt> 0);
  2042.  
  2043.           OpSize = 1; DecodeAdr(&ArgStr[2], MModAll);
  2044.           switch (AdrMode)
  2045.           {
  2046.             case ModReg16:
  2047.               if ((AdrPart == 2) && (PrefixCnt != 0) && ((PrefixCnt != 2) || (BAsmCode[0] != BAsmCode[1]))) WrError(ErrNum_InvAddrMode);
  2048.               else
  2049.               {
  2050.                 if (PrefixCnt == 2)
  2051.                   PrefixCnt--;
  2052.                 CodeLen = PrefixCnt;
  2053.                 BAsmCode[CodeLen++] = 0x09 + (AdrPart << 4);
  2054.               }
  2055.               break;
  2056.             case ModAbs:
  2057.               if (HasPrefixes) WrError(ErrNum_InvAddrMode);
  2058.               else if (ChkMinCPU(CPUZ380))
  2059.               {
  2060.                 CodeLen = PrefixCnt;
  2061.                 BAsmCode[CodeLen++] = 0xed;
  2062.                 BAsmCode[CodeLen++] = 0xc2;
  2063.                 AppendAdrVals();
  2064.               }
  2065.               break;
  2066.             default:
  2067.               if (AdrMode!=ModNone) WrError(ErrNum_InvAddrMode);
  2068.           }
  2069.         }
  2070.         break;
  2071.       default:
  2072.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2073.     }
  2074.   }
  2075. }
  2076.  
  2077. static void DecodeADDW(Word Index)
  2078. {
  2079.   UNUSED(Index);
  2080.  
  2081.   if (ChkArgCnt(1, 2)
  2082.    && ChkMinCPU(CPUZ380)
  2083.    && ((ArgCnt == 1) || DecodeAdr_HL(&ArgStr[1])))
  2084.   {
  2085.     OpSize = 1; DecodeAdr(&ArgStr[ArgCnt], MModAll);
  2086.     switch (AdrMode)
  2087.     {
  2088.       case ModReg16:
  2089.         if (PrefixCnt > 0)      /* wenn Register, dann nie DDIR! */
  2090.         {
  2091.           BAsmCode[PrefixCnt] = 0x87;
  2092.           CodeLen = 1 + PrefixCnt;
  2093.         }
  2094.         else if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  2095.         else
  2096.         {
  2097.           if (AdrPart == 2)
  2098.             AdrPart = 3;
  2099.           BAsmCode[0] = 0xed;
  2100.           BAsmCode[1] = 0x84 + AdrPart;
  2101.           CodeLen = 2;
  2102.         }
  2103.         break;
  2104.       case ModReg8:
  2105.         if ((AdrPart != 6) || (AdrCnt == 0)) WrError(ErrNum_InvAddrMode);
  2106.         else
  2107.         {
  2108.           CodeLen = PrefixCnt;
  2109.           BAsmCode[CodeLen++] = 0xc6;
  2110.           AppendAdrVals();
  2111.         }
  2112.         break;
  2113.       case ModImm:
  2114.         BAsmCode[0] = 0xed;
  2115.         BAsmCode[1] = 0x86;
  2116.         memcpy(BAsmCode + 2, AdrVals, AdrCnt);
  2117.         CodeLen = 2 + AdrCnt;
  2118.         break;
  2119.       default:
  2120.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2121.     }
  2122.   }
  2123. }
  2124.  
  2125. static void DecodeADC_SBC(Word IsSBC)
  2126. {
  2127.   if (ChkArgCnt(2, 2))
  2128.   {
  2129.     DecodeAdr(&ArgStr[1], MModReg8 | (is_sharp() ? 0 : MModReg16));
  2130.     switch (AdrMode)
  2131.     {
  2132.       case ModReg8:
  2133.         if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2134.         else
  2135.         {
  2136.           OpSize = 0; DecodeAdr(&ArgStr[2], MModReg8 | MModImm);
  2137.           switch (AdrMode)
  2138.           {
  2139.             case ModReg8:
  2140.               CodeLen = PrefixCnt;
  2141.               BAsmCode[CodeLen++] = 0x88 + AdrPart;
  2142.               AppendAdrVals();
  2143.               break;
  2144.             case ModImm:
  2145.               CodeLen = PrefixCnt;
  2146.               BAsmCode[CodeLen++] = 0xce;
  2147.               AppendAdrVals();
  2148.               break;
  2149.             default:
  2150.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2151.           }
  2152.           if ((IsSBC) && (CodeLen != 0))
  2153.             BAsmCode[PrefixCnt] += 0x10;
  2154.         }
  2155.         break;
  2156.       case ModReg16:
  2157.         if ((AdrPart != 2) || (PrefixCnt != 0)) WrError(ErrNum_InvAddrMode);
  2158.         else
  2159.         {
  2160.           OpSize = 1; DecodeAdr(&ArgStr[2], MModAll);
  2161.           switch (AdrMode)
  2162.           {
  2163.             case ModReg16:
  2164.               if (PrefixCnt != 0) WrError(ErrNum_InvAddrMode);
  2165.               else
  2166.               {
  2167.                 CodeLen = 2;
  2168.                 BAsmCode[0] = 0xed;
  2169.                 BAsmCode[1] = 0x42 + (AdrPart << 4);
  2170.                 if (!IsSBC)
  2171.                   BAsmCode[1] += 8;
  2172.               }
  2173.               break;
  2174.             default:
  2175.               if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2176.           }
  2177.         }
  2178.         break;
  2179.       default:
  2180.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2181.     }
  2182.   }
  2183. }
  2184.  
  2185. static void DecodeADCW_SBCW(Word Code)
  2186. {
  2187.   if (ChkArgCnt(1, 2)
  2188.    && ChkMinCPU(CPUZ380)
  2189.    && ((ArgCnt == 1) || DecodeAdr_HL(&ArgStr[1])))
  2190.   {
  2191.     OpSize = 1; DecodeAdr(&ArgStr[ArgCnt], MModAll);
  2192.     switch (AdrMode)
  2193.     {
  2194.       case ModReg16:
  2195.         if (PrefixCnt > 0)      /* wenn Register, dann nie DDIR! */
  2196.         {
  2197.           BAsmCode[PrefixCnt] = 0x8f + Code;
  2198.           CodeLen = 1 + PrefixCnt;
  2199.         }
  2200.         else if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  2201.         else
  2202.         {
  2203.           if (AdrPart == 2)
  2204.             AdrPart = 3;
  2205.           BAsmCode[0] = 0xed;
  2206.           BAsmCode[1] = 0x8c + Code + AdrPart;
  2207.           CodeLen = 2;
  2208.         }
  2209.         break;
  2210.       case ModReg8:
  2211.         if ((AdrPart != 6) || (AdrCnt == 0)) WrError(ErrNum_InvAddrMode);
  2212.         else
  2213.         {
  2214.           CodeLen = PrefixCnt;
  2215.           BAsmCode[CodeLen++] = 0xce + Code; /* ANSI :-0 */
  2216.           AppendAdrVals();
  2217.         }
  2218.         break;
  2219.       case ModImm:
  2220.         CodeLen = 0;
  2221.         BAsmCode[CodeLen++] = 0xed;
  2222.         BAsmCode[CodeLen++] = 0x8e + Code;
  2223.         AppendAdrVals();
  2224.         break;
  2225.       default:
  2226.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2227.     }
  2228.   }
  2229. }
  2230.  
  2231. static void DecodeINC_DEC(Word Index)
  2232. {
  2233.   Word IsDEC = (Index & 1), IsWord = (Index & 2);
  2234.  
  2235.   if (ChkArgCnt(1, 1))
  2236.   {
  2237.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16);
  2238.     switch (AdrMode)
  2239.     {
  2240.       case ModReg8:
  2241.         if (IsWord) WrError(ErrNum_InvAddrMode);
  2242.         else
  2243.         {
  2244.           CodeLen = PrefixCnt;
  2245.           BAsmCode[CodeLen++] = 0x04 + (AdrPart << 3) + IsDEC;
  2246.           AppendAdrVals();
  2247.         }
  2248.         break;
  2249.       case ModReg16:
  2250.         CodeLen = PrefixCnt;
  2251.         BAsmCode[CodeLen++] = 0x03 + (AdrPart << 4) + (IsDEC << 3);
  2252.         break;
  2253.       default:
  2254.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2255.     }
  2256.   }
  2257. }
  2258.  
  2259. static void DecodeShift8(Word Code)
  2260. {
  2261.   Byte reg_num = 0;
  2262.   int mem_arg_index;
  2263.  
  2264.   if (!ChkArgCnt(1, (MomCPU == CPUZ80U) ? 2 : 1))
  2265.     return;
  2266.   if ((Code == 6) && !ChkExactCPU(CPUZ80U)) /* SLI(A)/SL1/SLS undok. Z80 */
  2267.     return;
  2268.  
  2269.   /* dual arg (Z80 undoc): which is the extra destination register? This must be a 'simple' register (A,B,C,D,E,H,L): */
  2270.  
  2271.   if (ArgCnt >= 2)
  2272.   {
  2273.     if (DecodeReg8Core(ArgStr[1].str.p_str, &reg_num) && !(reg_num & 0xc0))
  2274.       mem_arg_index = 2;
  2275.     else if (DecodeReg8Core(ArgStr[2].str.p_str, &reg_num) && !(reg_num & 0xc0))
  2276.       mem_arg_index = 1;
  2277.     else
  2278.     {
  2279.       WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  2280.       return;
  2281.     }
  2282.   }
  2283.  
  2284.   /* single arg (documented version): */
  2285.  
  2286.   else
  2287.     mem_arg_index = 1;
  2288.  
  2289.   /* now decode the 'official argument': */
  2290.  
  2291.   OpSize = 0;
  2292.   DecodeAdr(&ArgStr[mem_arg_index], MModReg8);
  2293.   if (AdrMode != ModReg8)
  2294.     return;
  2295.  
  2296.   /* forbid IXL..IYU: */
  2297.  
  2298.   if ((PrefixCnt > 0) && (AdrPart != 6))
  2299.   {
  2300.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[mem_arg_index]);
  2301.     return;
  2302.   }
  2303.  
  2304.   /* replace AdrPart for undocumented version.  Addressing mode must be IXd/IYd: */
  2305.  
  2306.   if (ArgCnt >= 2)
  2307.   {
  2308.     if ((AdrPart != 6) || (PrefixCnt != 1))
  2309.     {
  2310.       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[mem_arg_index]);
  2311.       return;
  2312.     }
  2313.     AdrPart = reg_num;
  2314.   }
  2315.  
  2316.   /* assemble instruction: */
  2317.  
  2318.   CodeLen = PrefixCnt;
  2319.   BAsmCode[CodeLen++] = 0xcb;
  2320.   AppendAdrVals();
  2321.   BAsmCode[CodeLen++] = (Code << 3) | AdrPart;
  2322. }
  2323.  
  2324. static void DecodeShift16(Word Code)
  2325. {
  2326.   if (!ChkArgCnt(1, 1));
  2327.   else if (ChkMinCPU(CPUZ380))
  2328.   {
  2329.     OpSize = 1; DecodeAdr(&ArgStr[1], MModNoImm);
  2330.     switch (AdrMode)
  2331.     {
  2332.       case ModReg16:
  2333.         if (PrefixCnt > 0)
  2334.         {
  2335.           BAsmCode[2] = 0x04 + (Code << 3) + ((BAsmCode[0] >> 5) & 1);
  2336.           BAsmCode[0] = 0xed;
  2337.           BAsmCode[1] = 0xcb;
  2338.           CodeLen = 3;
  2339.         }
  2340.         else if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  2341.         else
  2342.         {
  2343.           if (AdrPart == 2)
  2344.             AdrPart = 3;
  2345.           BAsmCode[0] = 0xed;
  2346.           BAsmCode[1] = 0xcb;
  2347.           BAsmCode[2] = (Code << 3) + AdrPart;
  2348.           CodeLen = 3;
  2349.         }
  2350.         break;
  2351.       case ModReg8:
  2352.         if (AdrPart != 6) WrError(ErrNum_InvAddrMode);
  2353.         else
  2354.         {
  2355.           if (AdrCnt == 0)
  2356.           {
  2357.             BAsmCode[0] = 0xed;
  2358.             PrefixCnt = 1;
  2359.           }
  2360.           CodeLen = PrefixCnt;
  2361.           BAsmCode[CodeLen++] = 0xcb;
  2362.           AppendAdrVals();
  2363.           BAsmCode[CodeLen++] = 0x02 + (Code << 3);
  2364.         }
  2365.         break;
  2366.       default:
  2367.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2368.     }
  2369.   }
  2370. }
  2371.  
  2372. static void DecodeBit(Word Code)
  2373. {
  2374.   Byte reg_num = 0;
  2375.   int mem_arg_index, bit_arg_index;
  2376.   Boolean ok;
  2377.  
  2378.   /* extra undocumented dest register is not allowed for BIT */
  2379.  
  2380.   if (!ChkArgCnt(1, ((MomCPU == CPUZ80U) && (Code != 0)) ? 3 : 2))
  2381.     return;
  2382.  
  2383.   /* triple arg (Z80 undoc): which is the extra destination register? This must be a 'simple' register (A,B,C,D,E,H,L): */
  2384.  
  2385.   if (ArgCnt >= 3)
  2386.   {
  2387.     if (DecodeReg8Core(ArgStr[1].str.p_str, &reg_num) && !(reg_num & 0xc0))
  2388.     {
  2389.       mem_arg_index = 3;
  2390.       bit_arg_index = 2;
  2391.     }
  2392.     else if (DecodeReg8Core(ArgStr[3].str.p_str, &reg_num) && !(reg_num & 0xc0))
  2393.     {
  2394.       mem_arg_index = 2;
  2395.       bit_arg_index = 1;
  2396.     }
  2397.     else
  2398.     {
  2399.       WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  2400.       return;
  2401.     }
  2402.   }
  2403.  
  2404.   /* single arg (documented version): */
  2405.  
  2406.   else
  2407.   {
  2408.     mem_arg_index = 2;
  2409.     bit_arg_index = 1;
  2410.   }
  2411.  
  2412.   /* now decode the 'official arguments': */
  2413.  
  2414.   OpSize = 0;
  2415.   DecodeAdr(&ArgStr[mem_arg_index], MModReg8);
  2416.   if (AdrMode != ModReg8)
  2417.     return;
  2418.  
  2419.   /* forbid IXL..IYU: */
  2420.  
  2421.   if ((PrefixCnt > 0) && (AdrPart != 6))
  2422.   {
  2423.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[mem_arg_index]);
  2424.     return;
  2425.   }
  2426.  
  2427.   /* parse bit # and form machine code: */
  2428.  
  2429.   Code = ((Code + 1) << 6) | (EvalStrIntExpression(&ArgStr[bit_arg_index], UInt3, &ok) << 3);
  2430.   if (!ok)
  2431.     return;
  2432.  
  2433.   /* replace AdrPart for undocumented version.  Addressing mode must be IXd/IYd: */
  2434.  
  2435.   if (ArgCnt >= 3)
  2436.   {
  2437.     if ((AdrPart != 6) || (PrefixCnt != 1))
  2438.     {
  2439.       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[mem_arg_index]);
  2440.       return;
  2441.     }
  2442.     AdrPart = reg_num;
  2443.   }
  2444.  
  2445.   /* assemble instruction: */
  2446.  
  2447.   CodeLen = PrefixCnt;
  2448.   BAsmCode[CodeLen++] = 0xcb;
  2449.   AppendAdrVals();
  2450.   BAsmCode[CodeLen++] = Code | AdrPart;
  2451. }
  2452.  
  2453. static void DecodeMLT(Word Index)
  2454. {
  2455.   UNUSED(Index);
  2456.  
  2457.   if (!ChkArgCnt(1, 1));
  2458.   else if (ChkMinCPU(CPUZ180))
  2459.   {
  2460.     DecodeAdr(&ArgStr[1], MModAll);
  2461.     if ((AdrMode != ModReg16) || (PrefixCnt != 0)) WrError(ErrNum_InvAddrMode);
  2462.     else
  2463.     {
  2464.       BAsmCode[CodeLen] = 0xed;
  2465.       BAsmCode[CodeLen + 1] = 0x4c + (AdrPart << 4);
  2466.       CodeLen = 2;
  2467.     }
  2468.   }
  2469. }
  2470.  
  2471. static void DecodeMULT_DIV(Word Code)
  2472. {
  2473.   const tStrComp *pSrcArg;
  2474.  
  2475.   if (!ChkMinCPU(CPUZ380)
  2476.    || !ChkArgCnt(1, 2))
  2477.     return;
  2478.  
  2479.   if (2 == ArgCnt)
  2480.   {
  2481.     if (!DecodeAdr_HL(&ArgStr[1]))
  2482.       return;
  2483.   }
  2484.  
  2485.   OpSize = 1;
  2486.   pSrcArg = &ArgStr[ArgCnt];
  2487.   switch (DecodeAdr(pSrcArg, MModReg8 | MModReg16 | MModImm))
  2488.   {
  2489.     case ModReg8:
  2490.       if ((AdrPart != 6) || (PrefixCnt == 0)) WrStrErrorPos(ErrNum_InvAddrMode, pSrcArg);
  2491.       else
  2492.       {
  2493.         CodeLen = PrefixCnt;
  2494.         BAsmCode[CodeLen++] = 0xcb;
  2495.         AppendAdrVals();
  2496.         BAsmCode[CodeLen++] = 0x92 | Code;
  2497.       }
  2498.       break;
  2499.     case ModReg16:
  2500.       if (AdrPart == SPReg) WrStrErrorPos(ErrNum_InvAddrMode, pSrcArg);
  2501.       else if (PrefixCnt == 0)
  2502.       {
  2503.         if (AdrPart == 2)
  2504.           AdrPart = 3;
  2505.         BAsmCode[0] = 0xed;
  2506.         BAsmCode[1] = 0xcb;
  2507.         BAsmCode[2] = 0x90 + AdrPart + Code;
  2508.         CodeLen = 3;
  2509.       }
  2510.       else
  2511.       {
  2512.         BAsmCode[2] = 0x94 + ((BAsmCode[0] >> 5) & 1) + Code;
  2513.         BAsmCode[0] = 0xed;
  2514.         BAsmCode[1] = 0xcb;
  2515.         CodeLen = 3;
  2516.       }
  2517.       break;
  2518.     case ModImm:
  2519.       CodeLen = 0;
  2520.       BAsmCode[CodeLen++] = 0xed;
  2521.       BAsmCode[CodeLen++] = 0xcb;
  2522.       BAsmCode[CodeLen++] = 0x97 + Code;
  2523.       AppendAdrVals();
  2524.       break;
  2525.     default:
  2526.       break;
  2527.   }
  2528. }
  2529.  
  2530. static void DecodeTST(Word Index)
  2531. {
  2532.   UNUSED(Index);
  2533.  
  2534.   if (!ChkArgCnt(1, 1));
  2535.   else if (ChkMinCPU(CPUZ180))
  2536.   {
  2537.     OpSize = 0; DecodeAdr(&ArgStr[1], MModAll);
  2538.     switch (AdrMode)
  2539.     {
  2540.       case ModReg8:
  2541.         if (PrefixCnt != 0) WrError(ErrNum_InvAddrMode);
  2542.         else
  2543.         {
  2544.           BAsmCode[0] = 0xed;
  2545.           BAsmCode[1] = 4 + (AdrPart << 3);
  2546.           CodeLen = 2;
  2547.         }
  2548.         break;
  2549.       case ModImm:
  2550.         BAsmCode[0] = 0xed;
  2551.         BAsmCode[1] = 0x64;
  2552.         BAsmCode[2] = AdrVals[0];
  2553.         CodeLen = 3;
  2554.         break;
  2555.       default:
  2556.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2557.     }
  2558.   }
  2559. }
  2560.  
  2561. static void DecodeSWAP(Word Index)
  2562. {
  2563.   UNUSED(Index);
  2564.  
  2565.   if (!ChkArgCnt(1, 1));
  2566.   else if (ChkExactCPUList(ErrNum_InstructionNotSupported, CPUZ380, CPUGBZ80, CPULR35902, CPUNone) >= 0)
  2567.   {
  2568.     DecodeAdr(&ArgStr[1], (MomCPU == CPUZ380) ? MModReg16 : MModReg8);
  2569.     switch (AdrMode)
  2570.     {
  2571.       case ModReg16:
  2572.         if (AdrPart == 3) WrError(ErrNum_InvAddrMode);
  2573.         else if (PrefixCnt == 0)
  2574.         {
  2575.           if (AdrPart == 2)
  2576.             AdrPart = 3;
  2577.           BAsmCode[0] = 0xed;
  2578.           BAsmCode[1] = 0x0e + (AdrPart << 4); /*?*/
  2579.           CodeLen = 2;
  2580.         }
  2581.         else
  2582.         {
  2583.           BAsmCode[PrefixCnt] = 0x3e;
  2584.           CodeLen = PrefixCnt + 1;
  2585.         }
  2586.         break;
  2587.       case ModReg8:
  2588.         BAsmCode[0] = 0xcb;
  2589.         BAsmCode[1] = 0x30 | AdrPart;
  2590.         CodeLen = 2;
  2591.         break;
  2592.       default:
  2593.         break;
  2594.     }
  2595.   }
  2596. }
  2597.  
  2598. /*!------------------------------------------------------------------------
  2599.  * \fn     DecodePUSH_POP(Word Code)
  2600.  * \brief  handle PUSH/POP instructions
  2601.  * \param  Code machine code (4 = PUSH family, 0 = POP family)
  2602.  * ------------------------------------------------------------------------ */
  2603.  
  2604. static void DecodePUSH_POP(Word Code)
  2605. {
  2606.   if (!ChkArgCnt(1, 1));
  2607.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "SR"))
  2608.   {
  2609.     if (ChkMinCPU(CPUZ380))
  2610.     {
  2611.       CodeLen = 2;
  2612.       BAsmCode[0] = 0xed;
  2613.       BAsmCode[1] = 0xc1 + Code;
  2614.     }
  2615.   }
  2616.   else
  2617.   {
  2618.     OpSize = 1; MayLW = True;
  2619.     if (!as_strcasecmp(ArgStr[1].str.p_str, "AF"))
  2620.     {
  2621.       AdrPart = SPReg;
  2622.       AdrMode = ModReg16;
  2623.     }
  2624.     else
  2625.       DecodeAdr(&ArgStr[1], MModReg16 | (((Code == 4) && (MomCPU == CPUZ380)) ? MModImm : 0));
  2626.     switch (AdrMode)
  2627.     {
  2628.       case ModReg16:
  2629.         CodeLen = 1 + PrefixCnt;
  2630.         BAsmCode[PrefixCnt] = 0xc1 + (AdrPart << 4) + Code;
  2631.         break;
  2632.       case ModImm:
  2633.         CodeLen = PrefixCnt;
  2634.         BAsmCode[CodeLen++] = 0xfd;
  2635.         BAsmCode[CodeLen++] = 0xf5;
  2636.         AppendAdrVals();
  2637.         break;
  2638.       default:
  2639.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2640.     }
  2641.   }
  2642. }
  2643.  
  2644. static void DecodeEX(Word Index)
  2645. {
  2646.   Boolean OK;
  2647.   Byte AdrByte;
  2648.  
  2649.   UNUSED(Index);
  2650.  
  2651.   /* No EX at all on GBZ80 */
  2652.  
  2653.   if (!ChkMinCPU(CPUZ80))
  2654.     return;
  2655.  
  2656.   /* work around the parser problem related to the ' character */
  2657.  
  2658.   if (!as_strncasecmp(ArgStr[2].str.p_str, "AF\'", 3))
  2659.     ArgStr[2].str.p_str[3] = '\0';
  2660.  
  2661.   if (!ChkArgCnt(2, 2));
  2662.   else if (ParPair("AF", "AF\'"))
  2663.   {
  2664.     BAsmCode[0] = 0x08;
  2665.     CodeLen = 1;
  2666.   }
  2667.   else if (ParPair("AF", "AF`"))
  2668.   {
  2669.     BAsmCode[0] = 0x08;
  2670.     CodeLen = 1;
  2671.   }
  2672.   else
  2673.   {
  2674.     if ((ArgStr[2].str.p_str[0]) && (ArgStr[2].str.p_str[strlen(ArgStr[2].str.p_str) - 1] == '\''))
  2675.     {
  2676.       OK = True;
  2677.       ArgStr[2].str.p_str[strlen(ArgStr[2].str.p_str) - 1] = '\0';
  2678.     }
  2679.     else
  2680.       OK = False;
  2681.  
  2682.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModSPRel | MModIndReg16);
  2683.     switch (AdrMode)
  2684.     {
  2685.       case ModReg8:
  2686.         if (AdrPart == 6)
  2687.         {
  2688.           if (PrefixCnt) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2689.           else if (DecodeAdr_A(&ArgStr[2]) && ChkMinCPU(CPUZ380)) /* (HL),A */
  2690.           {
  2691.             BAsmCode[0] = 0xed;
  2692.             BAsmCode[1] = 0x37;
  2693.             CodeLen = 2;
  2694.           }
  2695.         }
  2696.         else
  2697.         {
  2698.           AdrByte = AdrPart;
  2699.           DecodeAdr(&ArgStr[2], MModReg8);
  2700.           switch (AdrMode)
  2701.           {
  2702.             case ModReg8:
  2703.               if (AdrPart == 6)
  2704.               {
  2705.                 if ((AdrByte != AccReg) || PrefixCnt) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]); /* A<->(HL) */
  2706.                 else if (ChkMinCPU(CPUZ380))
  2707.                 {
  2708.                   BAsmCode[0] = 0xed;
  2709.                   BAsmCode[1] = 0x37;
  2710.                   CodeLen = 2;
  2711.                 }
  2712.               }
  2713.               else if (!ChkMinCPU(CPUZ380));
  2714.               else if ((AdrByte == AccReg) && !OK)
  2715.               {
  2716.                 BAsmCode[0] = 0xed;
  2717.                 BAsmCode[1] = 0x07 + (AdrPart << 3);
  2718.                 CodeLen = 2;
  2719.               }
  2720.               else if ((AdrPart == AccReg) && !OK)
  2721.               {
  2722.                 BAsmCode[0] = 0xed;
  2723.                 BAsmCode[1] = 0x07 + (AdrByte << 3);
  2724.                 CodeLen = 2;
  2725.               }
  2726.               else if (OK && (AdrPart == AdrByte))
  2727.               {
  2728.                 BAsmCode[0] = 0xcb;
  2729.                 BAsmCode[1] = 0x30 + AdrPart;
  2730.                 CodeLen = 2;
  2731.               }
  2732.               else WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2733.               break;
  2734.             default:
  2735.               break;
  2736.           }
  2737.         }
  2738.         break;
  2739.       case ModReg16:
  2740.         if (AdrPart == 3) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2741.         else if (PrefixCnt == 0) /* EX R16,... */
  2742.         {
  2743.           AdrByte = (AdrPart == HLReg) ? SPReg : AdrPart;
  2744.           DecodeAdr(&ArgStr[2], MModReg16 | ((AdrPart == HLReg) ? MModSPRel : 0));
  2745.           switch (AdrMode)
  2746.           {
  2747.             case ModReg16:
  2748.               /* For DE <-> IX/IY, use the DD/FD prefix and DE<->HL on Z80, but the newer coding on Z380 */
  2749.  
  2750.               if (((AdrByte == DEReg) && (AdrPart == HLReg) && (!PrefixCnt || (MomCPU != CPUZ380))) /* DE <-> HL */
  2751.                || ((AdrByte == SPReg) && (AdrPart == DEReg) && (!PrefixCnt || (MomCPU != CPUZ380))))
  2752.               {
  2753.                 BAsmCode[PrefixCnt] = 0xeb;
  2754.                 CodeLen = PrefixCnt + 1;
  2755.               }
  2756.               else if (AdrPart == 3) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2757.               else if (!ChkMinCPU(CPUZ380));
  2758.               else if (OK)
  2759.               {
  2760.                 if (AdrPart == 2)
  2761.                   AdrPart = 3;
  2762.                 if ((PrefixCnt != 0) || (AdrPart != AdrByte)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2763.                 else
  2764.                 {
  2765.                   BAsmCode[0] = 0xed;
  2766.                   BAsmCode[1] = 0xcb;
  2767.                   BAsmCode[2] = 0x30 + AdrByte;
  2768.                   CodeLen = 3;
  2769.                 }
  2770.               }
  2771.               else if (PrefixCnt == 0)
  2772.               {
  2773.                 if (AdrByte == 0)
  2774.                 {
  2775.                   if (AdrPart == 2)
  2776.                     AdrPart = 3;
  2777.                   BAsmCode[0] = 0xed;
  2778.                   BAsmCode[1] = 0x01 + (AdrPart << 2);
  2779.                   CodeLen = 2;
  2780.                 }
  2781.                 else if (AdrPart == 0)
  2782.                 {
  2783.                   BAsmCode[0] = 0xed;
  2784.                   BAsmCode[1] = 0x01 + (AdrByte << 2);
  2785.                   CodeLen = 2;
  2786.                 }
  2787.               }
  2788.               else
  2789.               {
  2790.                 if (AdrPart == 2)
  2791.                   AdrPart = 3;
  2792.                 BAsmCode[1] = 0x03 + ((BAsmCode[0] >> 2) & 8) + (AdrByte << 4);
  2793.                 BAsmCode[0] = 0xed;
  2794.                 CodeLen = 2;
  2795.               }
  2796.               break;
  2797.             case ModSPRel:
  2798.               if ((AdrCnt == 1) && !AdrVals[0]) /* HL <-> (SP) */
  2799.               {
  2800.                 BAsmCode[PrefixCnt] = 0xe3;
  2801.                 CodeLen = PrefixCnt + 1;
  2802.               }
  2803.               else
  2804.                 WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2805.               break;
  2806.             default:
  2807.               break;
  2808.           }
  2809.         }
  2810.         else /* EX XY,... */
  2811.         {
  2812.           DecodeAdr(&ArgStr[2], MModReg16 | MModSPRel);
  2813.           switch (AdrMode)
  2814.           {
  2815.             case ModReg16:
  2816.               if (AdrPart == 3) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2817.               else if (!ChkMinCPU(CPUZ380));
  2818.               else if (OK)
  2819.               {
  2820.                 if ((PrefixCnt != 2) || (BAsmCode[0] != BAsmCode[1])) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2821.                 else
  2822.                 {
  2823.                   BAsmCode[2] = ((BAsmCode[0] >> 5) & 1)+0x34;
  2824.                   BAsmCode[0] = 0xed;
  2825.                   BAsmCode[1] = 0xcb;
  2826.                   CodeLen = 3;
  2827.                 }
  2828.               }
  2829.               else if (PrefixCnt == 1)
  2830.               {
  2831.                 if (AdrPart == 2)
  2832.                   AdrPart = 3;
  2833.                 BAsmCode[1] = ((BAsmCode[0] >> 2) & 8) + 3 + (AdrPart << 4);
  2834.                 BAsmCode[0] = 0xed;
  2835.                 CodeLen = 2;
  2836.               }
  2837.               else if (BAsmCode[0] == BAsmCode[1]) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2838.               else
  2839.               {
  2840.                 BAsmCode[0] = 0xed;
  2841.                 BAsmCode[1] = 0x2b;
  2842.                 CodeLen = 2;
  2843.               }
  2844.               break;
  2845.             case ModSPRel:
  2846.               if ((AdrCnt == 1) && !AdrVals[0]) /* IX/IX <-> (SP) */
  2847.               {
  2848.                 BAsmCode[PrefixCnt] = 0xe3;
  2849.                 CodeLen = PrefixCnt + 1;
  2850.               }
  2851.               else
  2852.                 WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2853.               break;
  2854.             default:
  2855.               break;
  2856.           }
  2857.         }
  2858.         break;
  2859.       case ModSPRel:
  2860.         if ((AdrCnt != 1) || AdrVals[0]) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2861.         else switch (DecodeAdr(&ArgStr[2], MModReg16))
  2862.         {
  2863.           case ModReg16: /* (SP) <-> HL/IX/IX */
  2864.             if (AdrPart != HLReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2865.             else
  2866.             {
  2867.               BAsmCode[PrefixCnt] = 0xe3;
  2868.               CodeLen = PrefixCnt + 1;
  2869.             }
  2870.             break;
  2871.           default:
  2872.             break;
  2873.         }
  2874.         break;
  2875.       default:
  2876.         break;
  2877.     }
  2878.   }
  2879. }
  2880.  
  2881. static void DecodeTSTI(Word Code)
  2882. {
  2883.   UNUSED(Code);
  2884.  
  2885.   if (ChkExactCPU(CPUZ80U)
  2886.    && ChkArgCnt(0, 0))
  2887.   {
  2888.     BAsmCode[0] = 0xed;
  2889.     BAsmCode[1] = 0x70;
  2890.     CodeLen = 2;
  2891.   }
  2892. }
  2893.  
  2894. static void DecodeIN_OUT(Word IsOUT)
  2895. {
  2896.   if ((ArgCnt == 1) && !IsOUT)
  2897.   {
  2898.     if (ChkExactCPU(CPUZ80U)
  2899.      && (DecodeAdr(&ArgStr[1], MModIndReg8) == ModIndReg8))
  2900.     {
  2901.       BAsmCode[0] = 0xed;
  2902.       BAsmCode[1] = 0x70;
  2903.       CodeLen = 2;
  2904.     }
  2905.   }
  2906.   else if (ChkArgCnt(2, 2) && ChkMinCPU(CPUZ80))
  2907.   {
  2908.     const tStrComp *pPortArg = IsOUT ? &ArgStr[1] : &ArgStr[2],
  2909.                    *pRegArg = IsOUT ? &ArgStr[2] : &ArgStr[1];
  2910.  
  2911.     /* allow absolute I/O address also without (...) */
  2912.  
  2913.     OpSize = 0;
  2914.     switch (DecodeAdr(pPortArg, MModIndReg8 | MModIOAbs | MModImm))
  2915.     {
  2916.       case ModIndReg8:
  2917.         DecodeAdrWithF(pRegArg, !IsOUT);
  2918.         switch (AdrMode)
  2919.         {
  2920.           case ModReg8:
  2921.             if (PrefixCnt != 0) WrError(ErrNum_InvAddrMode);
  2922.             else
  2923.             {
  2924.               CodeLen = 2;
  2925.               BAsmCode[0] = 0xed;
  2926.               BAsmCode[1] = 0x40 + (AdrPart << 3);
  2927.               if (IsOUT)
  2928.                 BAsmCode[1]++;
  2929.             }
  2930.             break;
  2931.           case ModImm:
  2932.             if (!IsOUT) WrError(ErrNum_InvAddrMode);
  2933.             else if ((MomCPU == CPUZ80U) && (AdrVals[0] == 0))
  2934.             {
  2935.               BAsmCode[0] = 0xed;
  2936.               BAsmCode[1] = 0x71;
  2937.               CodeLen = 2;
  2938.             }
  2939.             else if (ChkMinCPU(CPUZ380))
  2940.             {
  2941.               BAsmCode[0] = 0xed;
  2942.               BAsmCode[1] = 0x71;
  2943.               BAsmCode[2] = AdrVals[0];
  2944.               CodeLen = 3;
  2945.             }
  2946.             break;
  2947.           default:
  2948.             if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  2949.         }
  2950.         break;
  2951.       case ModIOAbs:
  2952.       case ModImm:
  2953.         if (DecodeAdr_A(pRegArg))
  2954.         {
  2955.           CodeLen = 2;
  2956.           BAsmCode[0] = IsOUT ? 0xd3 : 0xdb;
  2957.           BAsmCode[1] = AdrVals[0];
  2958.         }
  2959.         break;
  2960.       default:
  2961.         break;
  2962.     }
  2963.   }
  2964. }
  2965.  
  2966. static void DecodeINW_OUTW(Word IsOUTW)
  2967. {
  2968.   const tStrComp *pPortArg, *pRegArg;
  2969.  
  2970.   if (!ChkArgCnt(2, 2) || !ChkMinCPU(CPUZ380))
  2971.     return;
  2972.  
  2973.   pPortArg = IsOUTW ? &ArgStr[1] : &ArgStr[2];
  2974.   pRegArg  = IsOUTW ? &ArgStr[2] : &ArgStr[1];
  2975.  
  2976.   if (DecodeAdr(pPortArg, MModIndReg8) != ModIndReg8)
  2977.     return;
  2978.  
  2979.   OpSize = 1;
  2980.   switch (DecodeAdr(pRegArg, MModReg16 | (IsOUTW ? MModImm : 0)))
  2981.   {
  2982.     case ModReg16:
  2983.       if ((AdrPart == 3) || (PrefixCnt > 0)) WrError(ErrNum_InvAddrMode);
  2984.       else
  2985.       {
  2986.         switch (AdrPart)
  2987.         {
  2988.           case 1: AdrPart = 2; break;
  2989.           case 2: AdrPart = 7; break;
  2990.         }
  2991.         BAsmCode[0] = 0xdd;
  2992.         BAsmCode[1] = 0x40 + (AdrPart << 3);
  2993.         if (IsOUTW)
  2994.           BAsmCode[1]++;
  2995.         CodeLen = 2;
  2996.       }
  2997.       break;
  2998.     case ModImm:
  2999.       CodeLen = 0;
  3000.       BAsmCode[CodeLen++] = 0xfd;
  3001.       BAsmCode[CodeLen++] = 0x79;
  3002.       AppendAdrVals();
  3003.       break;
  3004.     default:
  3005.       break;
  3006.   }
  3007. }
  3008.  
  3009. /*!------------------------------------------------------------------------
  3010.  * \fn     DecodeIN0_OUT0(Word IsOUT0)
  3011.  * \brief  Handle IN0/OUT0 instructions on Z180++
  3012.  * \param  IsOUT0 1 for OUT0, 0 for IN0
  3013.  * ------------------------------------------------------------------------ */
  3014.  
  3015. static void DecodeIN0_OUT0(Word IsOUT0)
  3016. {
  3017.   /* 'IN0 (C)' better should not be allowed at all, because it was a copy'n'waste from
  3018.      the undocumented Z80 'IN (C)' which should better have been named 'IN F,(C)'.  But
  3019.      I will leave it in for upward compatibility, and not implicitly assume A as register: */
  3020.  
  3021.   if (ChkArgCnt(IsOUT0 ? 2 : 1, 2)
  3022.    && ChkMinCPU(CPUZ180))
  3023.   {
  3024.     Boolean OK;
  3025.     const tStrComp *pRegArg, *pPortArg;
  3026.  
  3027.     if (IsOUT0)
  3028.     {
  3029.       pRegArg = (ArgCnt == 2) ? &ArgStr[2] : NULL;
  3030.       pPortArg = &ArgStr[1];
  3031.     }
  3032.     else
  3033.     {
  3034.       pRegArg = (ArgCnt == 2) ? &ArgStr[1] : NULL;
  3035.       pPortArg = &ArgStr[ArgCnt];
  3036.     }
  3037.     OpSize = 0;
  3038.     if (!pRegArg)
  3039.     {
  3040.       AdrPart = 6;
  3041.       OK = True;
  3042.     }
  3043.     else
  3044.     {
  3045.       DecodeAdrWithF(pRegArg, !IsOUT0);
  3046.       if ((AdrMode == ModReg8) && (PrefixCnt == 0)) OK = True;
  3047.       else
  3048.       {
  3049.         OK = False;
  3050.         if (AdrMode != ModNone) WrStrErrorPos(ErrNum_InvAddrMode, pRegArg);
  3051.       }
  3052.     }
  3053.     if (OK)
  3054.     {
  3055.       BAsmCode[2] = EvalStrIntExpression(pPortArg, UInt8, &OK);
  3056.       if (OK)
  3057.       {
  3058.         BAsmCode[0] = 0xed;
  3059.         BAsmCode[1] = AdrPart << 3;
  3060.         if (IsOUT0)
  3061.           BAsmCode[1]++;
  3062.         CodeLen = 3;
  3063.       }
  3064.     }
  3065.   }
  3066. }
  3067.  
  3068. static void DecodeINA_INAW_OUTA_OUTAW(Word Code)
  3069. {
  3070.   Word IsIn = Code & 8;
  3071.   LongWord AdrLong;
  3072.   tStrComp *pRegArg, *pPortArg;
  3073.   tEvalResult EvalResult;
  3074.  
  3075.   if (!ChkArgCnt(2, 2) || !ChkMinCPU(CPUZ380))
  3076.     return;
  3077.  
  3078.   pRegArg = IsIn ? &ArgStr[1] : &ArgStr[2];
  3079.   pPortArg = IsIn ? &ArgStr[2] : &ArgStr[1];
  3080.  
  3081.   OpSize = Code & 1;
  3082.   if (!(OpSize ? DecodeAdr_HL(pRegArg) : DecodeAdr_A(pRegArg)))
  3083.     return;
  3084.  
  3085.   AdrLong = EvalStrIntExpressionWithResult(pPortArg, ExtFlag ? Int32 : UInt8, &EvalResult);
  3086.   if (EvalResult.OK)
  3087.   {
  3088.     ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  3089.     if (AdrLong > 0xfffffful)
  3090.       ChangeDDPrefix(ePrefixIW);
  3091.     else if (AdrLong > 0xfffful)
  3092.       ChangeDDPrefix(ePrefixIB);
  3093.     CodeLen = PrefixCnt;
  3094.     BAsmCode[CodeLen++] = 0xed + (OpSize << 4);
  3095.     BAsmCode[CodeLen++] = 0xd3 + IsIn;
  3096.     BAsmCode[CodeLen++] = AdrLong & 0xff;
  3097.     BAsmCode[CodeLen++] = (AdrLong >> 8) & 0xff;
  3098.     if (AdrLong > 0xfffful)
  3099.       BAsmCode[CodeLen++] = (AdrLong >> 16) & 0xff;
  3100.     if (AdrLong > 0xfffffful)
  3101.       BAsmCode[CodeLen++] = (AdrLong >> 24) & 0xff;
  3102.   }
  3103. }
  3104.  
  3105. static void DecodeTSTIO(Word Code)
  3106. {
  3107.   UNUSED(Code);
  3108.  
  3109.   if (ChkArgCnt(1, 1)
  3110.    && ChkMinCPU(CPUZ180))
  3111.   {
  3112.     Boolean OK;
  3113.  
  3114.     BAsmCode[2] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
  3115.     if (OK)
  3116.     {
  3117.       BAsmCode[0] = 0xed;
  3118.       BAsmCode[1] = 0x74;
  3119.       CodeLen = 3;
  3120.     }
  3121.   }
  3122. }
  3123.  
  3124. static void DecodeRET(Word Code)
  3125. {
  3126.   int Cond;
  3127.  
  3128.   UNUSED(Code);
  3129.  
  3130.   if (ArgCnt == 0)
  3131.   {
  3132.     CodeLen = 1;
  3133.     BAsmCode[0] = 0xc9;
  3134.   }
  3135.   else if (!ChkArgCnt(0, 1));
  3136.   else if (!DecodeCondition(ArgStr[1].str.p_str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  3137.   else
  3138.   {
  3139.     CodeLen = 1;
  3140.     BAsmCode[0] = 0xc0 + (Cond << 3);
  3141.   }
  3142. }
  3143.  
  3144. static void DecodeJP(Word Code)
  3145. {
  3146.   int Cond;
  3147.  
  3148.   UNUSED(Code);
  3149.  
  3150.   switch (ArgCnt)
  3151.   {
  3152.     case 1:
  3153.       Cond = 1;
  3154.       break;
  3155.     case 2:
  3156.       if (!DecodeCondition(ArgStr[1].str.p_str, &Cond))
  3157.       {
  3158.         WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  3159.         return;
  3160.       }
  3161.       Cond <<= 3;
  3162.       break;
  3163.     default:
  3164.       (void)ChkArgCnt(1, 2);
  3165.       return;
  3166.   }
  3167.  
  3168.   switch (DecodeAdr(&ArgStr[ArgCnt], MModImmIsAbs | MModAbs | ((Cond == 1) ? MModReg8 : 0)))
  3169.   {
  3170.     case ModReg8:
  3171.       if ((AdrPart != 6) || ((AdrCnt > 0) && AdrVals[0])) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[ArgCnt]);
  3172.       else
  3173.       {
  3174.         BAsmCode[PrefixCnt] = 0xe9;
  3175.         CodeLen = PrefixCnt + 1;
  3176.       }
  3177.       break;
  3178.     case ModAbs:
  3179.     {
  3180.       BAsmCode[PrefixCnt] = 0xc2 + Cond;
  3181.       CodeLen = PrefixCnt + 1;
  3182.       AppendAdrVals();
  3183.       break;
  3184.     }
  3185.   }
  3186. }
  3187.  
  3188. static void DecodeCALL(Word Code)
  3189. {
  3190.   Boolean OK;
  3191.   int Condition;
  3192.  
  3193.   UNUSED(Code);
  3194.  
  3195.   switch (ArgCnt)
  3196.   {
  3197.     case 1:
  3198.       Condition = 9;
  3199.       OK = True;
  3200.       break;
  3201.     case 2:
  3202.       OK = DecodeCondition(ArgStr[1].str.p_str, &Condition);
  3203.       if (OK)
  3204.         Condition <<= 3;
  3205.       else
  3206.         WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  3207.       break;
  3208.     default:
  3209.       (void)ChkArgCnt(1, 2);
  3210.       OK = False;
  3211.   }
  3212.  
  3213.   if (OK)
  3214.   {
  3215.     LongWord AdrLong;
  3216.     tEvalResult EvalResult;
  3217.  
  3218.     AdrLong = EvalAbsAdrExpression(&ArgStr[ArgCnt], &EvalResult);
  3219.     if (EvalResult.OK)
  3220.     {
  3221.       if (AdrLong <= 0xfffful)
  3222.       {
  3223.         CodeLen = 3;
  3224.         BAsmCode[0] = 0xc4 + Condition;
  3225.         BAsmCode[1] = Lo(AdrLong);
  3226.         BAsmCode[2] = Hi(AdrLong);
  3227.       }
  3228.       else if (AdrLong <= 0xfffffful)
  3229.       {
  3230.         ChangeDDPrefix(ePrefixIB);
  3231.         CodeLen = PrefixCnt;
  3232.         BAsmCode[CodeLen++] = 0xc4 + Condition;
  3233.         BAsmCode[CodeLen++] = Lo(AdrLong);
  3234.         BAsmCode[CodeLen++] = Hi(AdrLong);
  3235.         BAsmCode[CodeLen++] = Hi(AdrLong >> 8);
  3236.       }
  3237.       else
  3238.       {
  3239.         ChangeDDPrefix(ePrefixIW);
  3240.         CodeLen = PrefixCnt;
  3241.         BAsmCode[CodeLen++] = 0xc4 + Condition;
  3242.         BAsmCode[CodeLen++] = Lo(AdrLong);
  3243.         BAsmCode[CodeLen++] = Hi(AdrLong);
  3244.         BAsmCode[CodeLen++] = Hi(AdrLong >> 8);
  3245.         BAsmCode[CodeLen++] = Hi(AdrLong >> 16);
  3246.       }
  3247.     }
  3248.   }
  3249. }
  3250.  
  3251. static void DecodeJR(Word Code)
  3252. {
  3253.   Boolean OK;
  3254.   int Condition;
  3255.  
  3256.   UNUSED(Code);
  3257.  
  3258.   switch (ArgCnt)
  3259.   {
  3260.     case 1:
  3261.       Condition = 3;
  3262.       OK = True;
  3263.       break;
  3264.     case 2:
  3265.       OK = DecodeCondition(ArgStr[1].str.p_str, &Condition);
  3266.       if ((OK) && (Condition > 3))
  3267.         OK = False;
  3268.       if (OK)
  3269.         Condition += 4;
  3270.       else
  3271.         WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  3272.       break;
  3273.     default:
  3274.       (void)ChkArgCnt(1, 2);
  3275.       OK = False;
  3276.   }
  3277.  
  3278.   if (OK)
  3279.   {
  3280.     LongInt AdrLInt;
  3281.     tEvalResult EvalResult;
  3282.  
  3283.     AdrLInt = EvalAbsAdrExpression(&ArgStr[ArgCnt], &EvalResult);
  3284.     if (EvalResult.OK)
  3285.     {
  3286.       IntType dist_type;
  3287.  
  3288.       AdrLInt -= EProgCounter() + 2;
  3289.  
  3290.       if ((MomCPU < CPUZ380) || RangeCheck(AdrLInt, SInt8))
  3291.         dist_type = SInt8;
  3292.       else
  3293.       {
  3294.         AdrLInt -= 2;
  3295.         if (RangeCheck(AdrLInt, SInt16))
  3296.           dist_type = SInt16;
  3297.         else
  3298.         {
  3299.           AdrLInt--;
  3300.           dist_type = SInt24;
  3301.         }
  3302.       }
  3303.  
  3304.       if (!mFirstPassUnknownOrQuestionable(EvalResult.Flags) && !RangeCheck(AdrLInt, dist_type)) WrError(ErrNum_JmpDistTooBig);
  3305.       else switch (dist_type)
  3306.       {
  3307.         case SInt8:
  3308.           CodeLen = 2;
  3309.           BAsmCode[0] = Condition << 3;
  3310.           BAsmCode[1] = AdrLInt & 0xff;
  3311.           break;
  3312.         case SInt16:
  3313.           CodeLen = 4;
  3314.           BAsmCode[0] = 0xdd;
  3315.           BAsmCode[1] = Condition << 3;
  3316.           BAsmCode[2] = AdrLInt & 0xff;
  3317.           BAsmCode[3] = (AdrLInt >> 8) & 0xff;
  3318.           break;
  3319.         case SInt24:
  3320.           CodeLen = 5;
  3321.           BAsmCode[0] = 0xfd;
  3322.           BAsmCode[1] = Condition << 3;
  3323.           BAsmCode[2] = AdrLInt & 0xff;
  3324.           BAsmCode[3] = (AdrLInt >> 8) & 0xff;
  3325.           BAsmCode[4] = (AdrLInt >> 16) & 0xff;
  3326.           break;
  3327.         default:
  3328.           break;
  3329.       }
  3330.     }
  3331.   }
  3332. }
  3333.  
  3334. static void DecodeCALR(Word Code)
  3335. {
  3336.   Boolean OK;
  3337.   int Condition;
  3338.  
  3339.   UNUSED(Code);
  3340.  
  3341.   switch (ArgCnt)
  3342.   {
  3343.     case 1:
  3344.       Condition = 9;
  3345.       OK = True;
  3346.       break;
  3347.     case 2:
  3348.       OK = DecodeCondition(ArgStr[1].str.p_str, &Condition);
  3349.       if (OK)
  3350.         Condition <<= 3;
  3351.       else
  3352.         WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  3353.       break;
  3354.     default:
  3355.       (void)ChkArgCnt(1, 2);
  3356.       OK = False;
  3357.   }
  3358.  
  3359.   if (OK)
  3360.   {
  3361.     if (ChkMinCPU(CPUZ380))
  3362.     {
  3363.       LongInt AdrLInt;
  3364.       tEvalResult EvalResult;
  3365.  
  3366.       AdrLInt = EvalAbsAdrExpression(&ArgStr[ArgCnt], &EvalResult);
  3367.       if (EvalResult.OK)
  3368.       {
  3369.         AdrLInt -= EProgCounter() + 3;
  3370.         if ((AdrLInt <= 0x7fl) && (AdrLInt >= -0x80l))
  3371.         {
  3372.           CodeLen = 3;
  3373.           BAsmCode[0] = 0xed;
  3374.           BAsmCode[1] = 0xc4 | Condition;
  3375.           BAsmCode[2] = AdrLInt & 0xff;
  3376.         }
  3377.         else
  3378.         {
  3379.           AdrLInt--;
  3380.           if ((AdrLInt <= 0x7fffl) && (AdrLInt >= -0x8000l))
  3381.           {
  3382.             CodeLen = 4;
  3383.             BAsmCode[0] = 0xdd;
  3384.             BAsmCode[1] = 0xc4 + Condition;
  3385.             BAsmCode[2] = AdrLInt & 0xff;
  3386.             BAsmCode[3] = (AdrLInt >> 8) & 0xff;
  3387.           }
  3388.           else
  3389.           {
  3390.             AdrLInt--;
  3391.             if ((AdrLInt <= 0x7fffffl) && (AdrLInt >= -0x800000l))
  3392.             {
  3393.               CodeLen = 5;
  3394.               BAsmCode[0] = 0xfd;
  3395.               BAsmCode[1] = 0xc4 + Condition;
  3396.               BAsmCode[2] = AdrLInt & 0xff;
  3397.               BAsmCode[3] = (AdrLInt >> 8) & 0xff;
  3398.               BAsmCode[4] = (AdrLInt >> 16) & 0xff;
  3399.             }
  3400.             else WrError(ErrNum_JmpDistTooBig);
  3401.           }
  3402.         }
  3403.       }
  3404.     }
  3405.   }
  3406. }
  3407.  
  3408. static void DecodeDJNZ(Word Code)
  3409. {
  3410.   UNUSED(Code);
  3411.  
  3412.   if (ChkArgCnt(1, 1) && ChkMinCPU(CPUZ80))
  3413.   {
  3414.     tEvalResult EvalResult;
  3415.     LongInt AdrLInt;
  3416.  
  3417.     AdrLInt = EvalAbsAdrExpression(&ArgStr[1], &EvalResult);
  3418.     if (EvalResult.OK)
  3419.     {
  3420.       AdrLInt -= EProgCounter() + 2;
  3421.       if ((AdrLInt <= 0x7fl) & (AdrLInt >= -0x80l))
  3422.       {
  3423.         CodeLen = 2;
  3424.         BAsmCode[0] = 0x10;
  3425.         BAsmCode[1] = Lo(AdrLInt);
  3426.       }
  3427.       else if (MomCPU<CPUZ380) WrError(ErrNum_JmpDistTooBig);
  3428.       else
  3429.       {
  3430.         AdrLInt -= 2;
  3431.         if ((AdrLInt <= 0x7fffl) && (AdrLInt >= -0x8000l))
  3432.         {
  3433.           CodeLen = 4;
  3434.           BAsmCode[0] = 0xdd;
  3435.           BAsmCode[1] = 0x10;
  3436.           BAsmCode[2] = AdrLInt & 0xff;
  3437.           BAsmCode[3] = (AdrLInt >> 8) & 0xff;
  3438.         }
  3439.         else
  3440.         {
  3441.           AdrLInt--;
  3442.           if ((AdrLInt <= 0x7fffffl) && (AdrLInt >= -0x800000l))
  3443.           {
  3444.             CodeLen = 5;
  3445.             BAsmCode[0] = 0xfd;
  3446.             BAsmCode[1] = 0x10;
  3447.             BAsmCode[2] = AdrLInt & 0xff;
  3448.             BAsmCode[3] = (AdrLInt >> 8) & 0xff;
  3449.             BAsmCode[4] = (AdrLInt >> 16) & 0xff;
  3450.           }
  3451.           else WrError(ErrNum_JmpDistTooBig);
  3452.         }
  3453.       }
  3454.     }
  3455.   }
  3456. }
  3457.  
  3458. static void DecodeRST(Word Code)
  3459. {
  3460.   UNUSED(Code);
  3461.  
  3462.   if (ChkArgCnt(1, 1))
  3463.   {
  3464.     Boolean OK;
  3465.     tSymbolFlags Flags;
  3466.     Byte AdrByte;
  3467.     int SaveRadixBase = RadixBase;
  3468.  
  3469. #if 0
  3470.     /* some people like to regard the RST argument as a literal
  3471.        and leave away the 'h' to mark 38 as a hex number... */
  3472.     RadixBase = 16;
  3473. #endif
  3474.  
  3475.     AdrByte = EvalStrIntExpressionWithFlags(&ArgStr[1], Int8, &OK, &Flags);
  3476.     RadixBase = SaveRadixBase;
  3477.  
  3478.     if (mFirstPassUnknown(Flags))
  3479.       AdrByte = AdrByte & 0x38;
  3480.     if (OK)
  3481.     {
  3482.       if ((AdrByte > 0x38) || (AdrByte & 7)) WrError(ErrNum_NotFromThisAddress);
  3483.       else
  3484.       {
  3485.         CodeLen = 1;
  3486.         BAsmCode[0] = 0xc7 + AdrByte;
  3487.       }
  3488.     }
  3489.   }
  3490. }
  3491.  
  3492. static void DecodeEI_DI(Word Code)
  3493. {
  3494.   if (ArgCnt == 0)
  3495.   {
  3496.     BAsmCode[0] = 0xf3 + Code;
  3497.     CodeLen = 1;
  3498.   }
  3499.   else if (ChkArgCnt(1, 1)
  3500.         && ChkMinCPU(CPUZ380))
  3501.   {
  3502.     Boolean OK;
  3503.  
  3504.     BAsmCode[2] = EvalStrIntExpression(&ArgStr[1], UInt8, &OK);
  3505.     if (OK)
  3506.     {
  3507.       BAsmCode[0] = 0xdd;
  3508.       BAsmCode[1] = 0xf3 + Code;
  3509.       CodeLen = 3;
  3510.     }
  3511.   }
  3512. }
  3513.  
  3514. static void DecodeIM(Word Code)
  3515. {
  3516.   UNUSED(Code);
  3517.  
  3518.   if (ChkArgCnt(1, 1)
  3519.    && ChkMinCPU(CPUZ80))
  3520.   {
  3521.     Byte AdrByte;
  3522.     Boolean OK;
  3523.  
  3524.     AdrByte = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  3525.     if (OK)
  3526.     {
  3527.       if (AdrByte > 3) WrError(ErrNum_OverRange);
  3528.       else if ((AdrByte == 3) && (!ChkMinCPU(CPUZ380)));
  3529.       else
  3530.       {
  3531.         if (AdrByte == 3)
  3532.           AdrByte = 1;
  3533.         else if (AdrByte >= 1)
  3534.           AdrByte++;
  3535.         CodeLen = 2;
  3536.         BAsmCode[0] = 0xed;
  3537.         BAsmCode[1] = 0x46 + (AdrByte << 3);
  3538.       }
  3539.     }
  3540.   }
  3541. }
  3542.  
  3543. static void DecodeLDCTL(Word Code)
  3544. {
  3545.   Byte AdrByte;
  3546.  
  3547.   UNUSED(Code);
  3548.  
  3549.   OpSize = 0;
  3550.   if (!ChkArgCnt(2, 2));
  3551.   else if (!ChkMinCPU(CPUZ380));
  3552.   else if (DecodeSFR(ArgStr[1].str.p_str, &AdrByte))
  3553.   {
  3554.     DecodeAdr(&ArgStr[2], MModAll);
  3555.     switch (AdrMode)
  3556.     {
  3557.       case ModReg8:
  3558.         if (AdrPart != AccReg) WrError(ErrNum_InvAddrMode);
  3559.         else
  3560.         {
  3561.           BAsmCode[0] = 0xcd + ((AdrByte & 3) << 4);
  3562.           BAsmCode[1] = 0xc8 + ((AdrByte & 4) << 2);
  3563.           CodeLen = 2;
  3564.         }
  3565.         break;
  3566.       case ModReg16:
  3567.         if ((AdrByte != 1) || (AdrPart != 2) || (PrefixCnt != 0)) WrError(ErrNum_InvAddrMode);
  3568.         else
  3569.         {
  3570.           BAsmCode[0] = 0xed;
  3571.           BAsmCode[1] = 0xc8;
  3572.           CodeLen = 2;
  3573.         }
  3574.         break;
  3575.       case ModImm:
  3576.         BAsmCode[0] = 0xcd +((AdrByte & 3) << 4);
  3577.         BAsmCode[1] = 0xca +((AdrByte & 4) << 2);
  3578.         BAsmCode[2] = AdrVals[0];
  3579.         CodeLen = 3;
  3580.         break;
  3581.       default:
  3582.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  3583.     }
  3584.   }
  3585.   else if (DecodeSFR(ArgStr[2].str.p_str, &AdrByte))
  3586.   {
  3587.     DecodeAdr(&ArgStr[1], MModAll);
  3588.     switch (AdrMode)
  3589.     {
  3590.       case ModReg8:
  3591.         if ((AdrPart != 7) || (AdrByte == 1)) WrError(ErrNum_InvAddrMode);
  3592.         else
  3593.         {
  3594.           BAsmCode[0] = 0xcd + ((AdrByte & 3) << 4);
  3595.           BAsmCode[1] = 0xd0;
  3596.           CodeLen = 2;
  3597.         }
  3598.         break;
  3599.       case ModReg16:
  3600.         if ((AdrByte != 1) || (AdrPart != 2) || (PrefixCnt != 0)) WrError(ErrNum_InvAddrMode);
  3601.         else
  3602.         {
  3603.           BAsmCode[0] = 0xed;
  3604.           BAsmCode[1] = 0xc0;
  3605.           CodeLen = 2;
  3606.         }
  3607.         break;
  3608.       default:
  3609.         if (AdrMode != ModNone) WrError(ErrNum_InvAddrMode);
  3610.     }
  3611.   }
  3612.   else
  3613.     WrError(ErrNum_InvAddrMode);
  3614. }
  3615.  
  3616. static void DecodeRESC_SETC(Word Code)
  3617. {
  3618.   if (ChkArgCnt(1, 1)
  3619.    && ChkMinCPU(CPUZ380))
  3620.   {
  3621.     Byte AdrByte = 0xff;
  3622.  
  3623.     NLS_UpString(ArgStr[1].str.p_str);
  3624.     if (!strcmp(ArgStr[1].str.p_str, "LW")) AdrByte = 1;
  3625.     else if (!strcmp(ArgStr[1].str.p_str, "LCK")) AdrByte = 2;
  3626.     else if (!strcmp(ArgStr[1].str.p_str, "XM")) AdrByte = 3;
  3627.     else WrError(ErrNum_InvCtrlReg);
  3628.     if (AdrByte != 0xff)
  3629.     {
  3630.       CodeLen = 2;
  3631.       BAsmCode[0] = 0xcd + (AdrByte << 4);
  3632.       BAsmCode[1] = 0xf7 + Code;
  3633.     }
  3634.   }
  3635. }
  3636.  
  3637. static void DecodeDDIR(Word Code)
  3638. {
  3639.   UNUSED(Code);
  3640.  
  3641.   if (ChkArgCnt(1, 2)
  3642.    && ChkMinCPU(CPUZ380))
  3643.   {
  3644.     Boolean OK;
  3645.     int z;
  3646.  
  3647.     OK = True;
  3648.     for (z = 1; z <= ArgCnt; z++)
  3649.     {
  3650.       if (OK)
  3651.       {
  3652.         OK = ExtendPrefix(&CurrPrefix, DecodePrefix(ArgStr[z].str.p_str));
  3653.         if (!OK) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[z]);
  3654.       }
  3655.     }
  3656.     if (OK)
  3657.     {
  3658.       GetPrefixCode(CurrPrefix, BAsmCode + 0, BAsmCode + 1);
  3659.       CodeLen = 2;
  3660.     }
  3661.   }
  3662. }
  3663.  
  3664. static void DecodePORT(Word Code)
  3665. {
  3666.   UNUSED(Code);
  3667.  
  3668.   CodeEquate(SegIO, 0, PortEnd());
  3669. }
  3670.  
  3671. static void DecodeLDI_LDD(Word Code)
  3672. {
  3673.   if (ChkArgCnt(2,2) && (ChkExactCPUList(ErrNum_InstructionNotSupported, CPUGBZ80, CPULR35902, CPUNone) >= 0))
  3674.   {
  3675.     DecodeAdr(&ArgStr[1], MModReg8);
  3676.     if (AdrMode == ModReg8)
  3677.       switch (AdrPart)
  3678.       {
  3679.         case 7:
  3680.           DecodeAdr(&ArgStr[2], MModReg8);
  3681.           if (AdrMode == ModReg8)
  3682.           {
  3683.             if (AdrPart != 6) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  3684.             else
  3685.             {
  3686.               BAsmCode[0] = Code | 0x08;
  3687.               CodeLen = 1;
  3688.             }
  3689.           }
  3690.           break;
  3691.         case 6:
  3692.           DecodeAdr(&ArgStr[2], MModReg8);
  3693.           if (AdrMode == ModReg8)
  3694.           {
  3695.             if (AdrPart != AccReg) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  3696.             else
  3697.             {
  3698.               BAsmCode[0] = Code;
  3699.               CodeLen = 1;
  3700.             }
  3701.           }
  3702.           break;
  3703.         default:
  3704.           WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  3705.       }
  3706.   }
  3707. }
  3708.  
  3709. static void DecodePRWINS(Word Code)
  3710. {
  3711.   UNUSED(Code);
  3712.  
  3713.   if (ChkExactCPU(CPUZ180))
  3714.   {
  3715.     printf("\nCBAR 0%02xh BBR 0%02xh CBR 0%02xh\n",
  3716.            (unsigned)Reg_CBAR, (unsigned)Reg_BBR, (unsigned)Reg_CBR);
  3717.     cpu_2_phys_area_dump(SegCode, stdout);
  3718.   }
  3719. }
  3720.  
  3721. static void ModIntel(Word Code)
  3722. {
  3723.   UNUSED(Code);
  3724.  
  3725.   /* M80 compatibility: DEFB->DB, DEFW->DW */
  3726.  
  3727.   strmov(OpPart.str.p_str + 1, OpPart.str.p_str + 3);
  3728.   DecodeIntelPseudo(False);
  3729. }
  3730.  
  3731. /*!------------------------------------------------------------------------
  3732.  * \fn     valid_cbar(void)
  3733.  * \brief  allowed CBAR value?
  3734.  * \return True if valid
  3735.  * ------------------------------------------------------------------------ */
  3736.  
  3737. static Boolean valid_cbar(void)
  3738. {
  3739.   return ((Reg_CBAR & 0x0f) <= ((Reg_CBAR >> 4) & 0x0f));
  3740. }
  3741.  
  3742. /*!------------------------------------------------------------------------
  3743.  * \fn     update_z180_areas(void)
  3744.  * \brief  recompute Z180 mapped areas
  3745.  * ------------------------------------------------------------------------ */
  3746.  
  3747. static void update_z180_areas(void)
  3748. {
  3749.   if (valid_cbar())
  3750.   {
  3751.     Word common_area_start = ((Reg_CBAR >> 4) & 0x0f) << 12,
  3752.          bank_area_start = (Reg_CBAR & 0x0f) << 12;
  3753.  
  3754.     cpu_2_phys_area_clear(SegCode);
  3755.  
  3756.     /* Common Area 0 */
  3757.  
  3758.     if (bank_area_start > 0)
  3759.       cpu_2_phys_area_add(SegCode, 0, 0, bank_area_start);
  3760.  
  3761.     /* Bank Area */
  3762.  
  3763.     if (common_area_start > bank_area_start)
  3764.       cpu_2_phys_area_add(SegCode, bank_area_start, (Reg_BBR << 12) + bank_area_start, common_area_start - bank_area_start);
  3765.  
  3766.     /* Common Area 1 - always present since upper nibble of CBAR is always < 0x10 */
  3767.  
  3768.     cpu_2_phys_area_add(SegCode, common_area_start, (Reg_CBR << 12) + common_area_start, 0x10000ul - common_area_start);
  3769.  
  3770.     /* this *SHOULD* be a NOP, since completely filled the 64K CPU space: */
  3771.  
  3772.     cpu_2_phys_area_fill(SegCode, 0, 0xffff);
  3773.   }
  3774. }
  3775.  
  3776. /*!------------------------------------------------------------------------
  3777.  * \fn     check_cbar(void)
  3778.  * \brief  check valid CBAR value
  3779.  * ------------------------------------------------------------------------ */
  3780.  
  3781. static void check_cbar(void)
  3782. {
  3783.   if (valid_cbar())
  3784.     update_z180_areas();
  3785.   else
  3786.     WrError(ErrNum_InvCBAR);
  3787. }
  3788.  
  3789. /*==========================================================================*/
  3790. /* Codetabellenerzeugung */
  3791.  
  3792. static void AddFixed(const char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
  3793. {
  3794.   order_array_rsv_end(FixedOrders, BaseOrder);
  3795.   FixedOrders[InstrZ].MinCPU = NewMin;
  3796.   FixedOrders[InstrZ].Len = NewLen;
  3797.   FixedOrders[InstrZ].Code = NewCode;
  3798.   AddInstTable(InstTable, NewName, InstrZ++, DecodeFixed);
  3799. }
  3800.  
  3801. static void AddAcc(const char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
  3802. {
  3803.   order_array_rsv_end(AccOrders, BaseOrder);
  3804.   AccOrders[InstrZ].MinCPU = NewMin;
  3805.   AccOrders[InstrZ].Len = NewLen;
  3806.   AccOrders[InstrZ].Code = NewCode;
  3807.   AddInstTable(InstTable, NewName, InstrZ++, DecodeAcc);
  3808. }
  3809.  
  3810. static void AddHL(const char *NewName, CPUVar NewMin, Byte NewLen, Word NewCode)
  3811. {
  3812.   order_array_rsv_end(HLOrders, BaseOrder);
  3813.   HLOrders[InstrZ].MinCPU = NewMin;
  3814.   HLOrders[InstrZ].Len = NewLen;
  3815.   HLOrders[InstrZ].Code = NewCode;
  3816.   AddInstTable(InstTable, NewName, InstrZ++, DecodeHL);
  3817. }
  3818.  
  3819. static void AddALU(const char *Name8, const char *Name16, Byte Code)
  3820. {
  3821.   AddInstTable(InstTable, Name8 , Code, DecodeALU8);
  3822.   AddInstTable(InstTable, Name16, Code, DecodeALU16);
  3823. }
  3824.  
  3825. static void AddShift(const char *Name8, const char *Name16, Byte Code)
  3826. {
  3827.   AddInstTable(InstTable, Name8 , Code, DecodeShift8);
  3828.   if (Name16)
  3829.     AddInstTable(InstTable, Name16, Code, DecodeShift16);
  3830. }
  3831.  
  3832. static void AddBit(const char *NName, Word Code)
  3833. {
  3834.   AddInstTable(InstTable, NName, Code, DecodeBit);
  3835. }
  3836.  
  3837. static void AddCondition(const char *NewName, Byte NewCode)
  3838. {
  3839.   order_array_rsv_end(Conditions, Condition);
  3840.   Conditions[InstrZ].Name = NewName;
  3841.   Conditions[InstrZ++].Code = NewCode;
  3842. }
  3843.  
  3844. static void InitFields(void)
  3845. {
  3846.   InstTable = CreateInstTable(203);
  3847.  
  3848.   AddInstTable(InstTable, "LD" , 0, DecodeLD);
  3849.   AddInstTable(InstTable, "LDW", 1, DecodeLD);
  3850.   AddInstTable(InstTable, "LDHL", 0, DecodeLDHL);
  3851.   AddInstTable(InstTable, "LDH", 0, DecodeLDH);
  3852.   AddInstTable(InstTable, "LDX", 0, DecodeLDX);
  3853.   AddInstTable(InstTable, "ADD", 0, DecodeADD);
  3854.   AddInstTable(InstTable, "ADDW", 0, DecodeADDW);
  3855.   AddInstTable(InstTable, "ADC" , 0, DecodeADC_SBC);
  3856.   AddInstTable(InstTable, "SBC" , 1, DecodeADC_SBC);
  3857.   AddInstTable(InstTable, "ADCW", 0, DecodeADCW_SBCW);
  3858.   AddInstTable(InstTable, "SBCW",16, DecodeADCW_SBCW);
  3859.   AddInstTable(InstTable, "INC" , 0, DecodeINC_DEC);
  3860.   AddInstTable(InstTable, "DEC" , 1, DecodeINC_DEC);
  3861.   AddInstTable(InstTable, "INCW", 2, DecodeINC_DEC);
  3862.   AddInstTable(InstTable, "DECW", 3, DecodeINC_DEC);
  3863.   AddInstTable(InstTable, "MLT" , 0, DecodeMLT);
  3864.   AddInstTable(InstTable, "DIVUW" , 0x28, DecodeMULT_DIV);
  3865.   AddInstTable(InstTable, "MULTW" , 0x00, DecodeMULT_DIV);
  3866.   AddInstTable(InstTable, "MULTUW", 0x08, DecodeMULT_DIV);
  3867.   AddInstTable(InstTable, "TST", 0, DecodeTST);
  3868.   AddInstTable(InstTable, "SWAP", 0, DecodeSWAP);
  3869.   AddInstTable(InstTable, "PUSH", 4, DecodePUSH_POP);
  3870.   AddInstTable(InstTable, "POP" , 0, DecodePUSH_POP);
  3871.   AddInstTable(InstTable, "EX"  , 0, DecodeEX);
  3872.   AddInstTable(InstTable, "TSTI", 0, DecodeTSTI);
  3873.   AddInstTable(InstTable, "IN"  , 0, DecodeIN_OUT);
  3874.   AddInstTable(InstTable, "OUT" , 1, DecodeIN_OUT);
  3875.   AddInstTable(InstTable, "INW"  , 0, DecodeINW_OUTW);
  3876.   AddInstTable(InstTable, "OUTW" , 1, DecodeINW_OUTW);
  3877.   AddInstTable(InstTable, "IN0"  , 0, DecodeIN0_OUT0);
  3878.   AddInstTable(InstTable, "OUT0" , 1, DecodeIN0_OUT0);
  3879.   AddInstTable(InstTable, "INA"  , 8, DecodeINA_INAW_OUTA_OUTAW);
  3880.   AddInstTable(InstTable, "INAW" , 9, DecodeINA_INAW_OUTA_OUTAW);
  3881.   AddInstTable(InstTable, "OUTA" , 0, DecodeINA_INAW_OUTA_OUTAW);
  3882.   AddInstTable(InstTable, "OUTAW", 1, DecodeINA_INAW_OUTA_OUTAW);
  3883.   AddInstTable(InstTable, "TSTIO", 0, DecodeTSTIO);
  3884.   AddInstTable(InstTable, "RET" , 0, DecodeRET);
  3885.   AddInstTable(InstTable, "JP" , 0, DecodeJP);
  3886.   AddInstTable(InstTable, "CALL", 0, DecodeCALL);
  3887.   AddInstTable(InstTable, "JR" , 0, DecodeJR);
  3888.   AddInstTable(InstTable, "CALR", 0, DecodeCALR);
  3889.   AddInstTable(InstTable, "DJNZ", 0, DecodeDJNZ);
  3890.   AddInstTable(InstTable, "RST", 0, DecodeRST);
  3891.   AddInstTable(InstTable, "DI", 0, DecodeEI_DI);
  3892.   AddInstTable(InstTable, "EI", 8, DecodeEI_DI);
  3893.   AddInstTable(InstTable, "IM", 0, DecodeIM);
  3894.   AddInstTable(InstTable, "LDCTL", 0, DecodeLDCTL);
  3895.   AddInstTable(InstTable, "RESC", 8, DecodeRESC_SETC);
  3896.   AddInstTable(InstTable, "SETC", 0, DecodeRESC_SETC);
  3897.   AddInstTable(InstTable, "DDIR", 0, DecodeDDIR);
  3898.   AddInstTable(InstTable, "PORT", 0, DecodePORT);
  3899.   AddInstTable(InstTable, "DEFB", 0, ModIntel);
  3900.   AddInstTable(InstTable, "DEFW", 0, ModIntel);
  3901.  
  3902.   InstrZ = 0;
  3903.   AddCondition("NZ", 0); AddCondition("Z" , 1);
  3904.   AddCondition("NC", 2); AddCondition("C" , 3);
  3905.   if (!is_sharp())
  3906.   {
  3907.     AddCondition("PO", 4); AddCondition("NV", 4);
  3908.     AddCondition("PE", 5); AddCondition("V" , 5);
  3909.     AddCondition("P" , 6); AddCondition("NS", 6);
  3910.     AddCondition("M" , 7); AddCondition("S" , 7);
  3911.   }
  3912.   AddCondition(NULL, 0);
  3913.  
  3914.   InstrZ = 0;
  3915.   AddFixed("EXX"  , CPUZ80   , 1, 0x00d9);
  3916.   if (is_sharp())
  3917.   {
  3918.     AddInstTable(InstTable, "LDI", 0x22, DecodeLDI_LDD);
  3919.     AddInstTable(InstTable, "LDD", 0x32, DecodeLDI_LDD);
  3920.   }
  3921.   else
  3922.   {
  3923.     AddFixed("LDI"  , CPUZ80   , 2, 0xeda0);
  3924.     AddFixed("LDD"  , CPUZ80   , 2, 0xeda8);
  3925.   }
  3926.   AddFixed("LDIR" , CPUZ80   , 2, 0xedb0);
  3927.   AddFixed("LDDR" , CPUZ80   , 2, 0xedb8);
  3928.   AddFixed("CPI"  , CPUZ80   , 2, 0xeda1);
  3929.   AddFixed("CPIR" , CPUZ80   , 2, 0xedb1);
  3930.   AddFixed("CPD"  , CPUZ80   , 2, 0xeda9);
  3931.   AddFixed("CPDR" , CPUZ80   , 2, 0xedb9);
  3932.   AddFixed("RLCA" , CPUGBZ80 , 1, 0x0007);
  3933.   AddFixed("RRCA" , CPUGBZ80 , 1, 0x000f);
  3934.   AddFixed("RLA"  , CPUGBZ80 , 1, 0x0017);
  3935.   AddFixed("RRA"  , CPUGBZ80 , 1, 0x001f);
  3936.   AddFixed("RLD"  , CPUZ80   , 2, 0xed6f);
  3937.   AddFixed("RRD"  , CPUZ80   , 2, 0xed67);
  3938.   AddFixed("DAA"  , CPUGBZ80 , 1, 0x0027);
  3939.   AddFixed("CCF"  , CPUGBZ80 , 1, 0x003f);
  3940.   AddFixed("SCF"  , CPUGBZ80 , 1, 0x0037);
  3941.   AddFixed("NOP"  , CPUGBZ80 , 1, 0x0000);
  3942.   AddFixed("HALT" , CPUGBZ80 , 1, 0x0076);
  3943.   AddFixed("RETI" , CPUGBZ80 ,
  3944.            is_sharp() ? 1 : 2,
  3945.            is_sharp() ? 0x00d9 : 0xed4d);
  3946.   AddFixed("RETN" , CPUZ80   , 2, 0xed45);
  3947.   AddFixed("INI"  , CPUZ80   , 2, 0xeda2);
  3948.   AddFixed("INIR" , CPUZ80   , 2, 0xedb2);
  3949.   AddFixed("IND"  , CPUZ80   , 2, 0xedaa);
  3950.   AddFixed("INDR" , CPUZ80   , 2, 0xedba);
  3951.   AddFixed("OUTI" , CPUZ80   , 2, 0xeda3);
  3952.   AddFixed("OTIR" , CPUZ80   , 2, 0xedb3);
  3953.   AddFixed("OUTD" , CPUZ80   , 2, 0xedab);
  3954.   AddFixed("OTDR" , CPUZ80   , 2, 0xedbb);
  3955.   AddFixed("EXA"  , CPUZ80   , 1, 0x0008);
  3956.   AddFixed("EXD"  , CPUZ80   , 1, 0x00eb);
  3957.   AddFixed("SLP"  , CPUZ180  , 2, 0xed76);
  3958.   AddFixed("OTIM" , CPUZ180  , 2, 0xed83);
  3959.   AddFixed("OTIMR", CPUZ180  , 2, 0xed93);
  3960.   AddFixed("OTDM" , CPUZ180  , 2, 0xed8b);
  3961.   AddFixed("OTDMR", CPUZ180  , 2, 0xed9b);
  3962.   AddFixed("BTEST", CPUZ380  , 2, 0xedcf);
  3963.   AddFixed("EXALL", CPUZ380  , 2, 0xedd9);
  3964.   AddFixed("EXXX" , CPUZ380  , 2, 0xddd9);
  3965.   AddFixed("EXXY" , CPUZ380  , 2, 0xfdd9);
  3966.   AddFixed("INDW" , CPUZ380  , 2, 0xedea);
  3967.   AddFixed("INDRW", CPUZ380  , 2, 0xedfa);
  3968.   AddFixed("INIW" , CPUZ380  , 2, 0xede2);
  3969.   AddFixed("INIRW", CPUZ380  , 2, 0xedf2);
  3970.   AddFixed("LDDW" , CPUZ380  , 2, 0xede8);
  3971.   AddFixed("LDDRW", CPUZ380  , 2, 0xedf8);
  3972.   AddFixed("LDIW" , CPUZ380  , 2, 0xede0);
  3973.   AddFixed("LDIRW", CPUZ380  , 2, 0xedf0);
  3974.   AddFixed("MTEST", CPUZ380  , 2, 0xddcf);
  3975.   AddFixed("OTDRW", CPUZ380  , 2, 0xedfb);
  3976.   AddFixed("OTIRW", CPUZ380  , 2, 0xedf3);
  3977.   AddFixed("OUTDW", CPUZ380  , 2, 0xedeb);
  3978.   AddFixed("OUTIW", CPUZ380  , 2, 0xede3);
  3979.   AddFixed("RETB" , CPUZ380  , 2, 0xed55);
  3980.   AddInstTable(InstTable, "STOP", 0x0010, DecodeSTOP);
  3981.  
  3982.   InstrZ = 0;
  3983.   AddAcc("CPL"  , CPUGBZ80 , 1, 0x002f);
  3984.   AddAcc("NEG"  , CPUZ80   , 2, 0xed44);
  3985.   AddAcc("EXTS" , CPUZ380  , 2, 0xed65);
  3986.  
  3987.   InstrZ = 0;
  3988.   AddHL("CPLW" , CPUZ380, 2, 0xdd2f);
  3989.   AddHL("NEGW" , CPUZ380, 2, 0xed54);
  3990.   AddHL("EXTSW", CPUZ380, 2, 0xed75);
  3991.  
  3992.   AddALU("SUB", "SUBW", 2); AddALU("AND", "ANDW", 4);
  3993.   AddALU("OR" , "ORW" , 6); AddALU("XOR", "XORW", 5);
  3994.   AddALU("CP" , "CPW" , 7);
  3995.  
  3996.   AddShift("RLC" , "RLCW" , 0); AddShift("RRC", "RRCW", 1);
  3997.   AddShift("RL"  , "RLW"  , 2); AddShift("RR" , "RRW" , 3);
  3998.   AddShift("SLA" , "SLAW" , 4); AddShift("SRA", "SRAW", 5);
  3999.   AddShift("SLIA", NULL   , 6); AddShift("SRL", "SRLW", 7);
  4000.   AddShift("SLS" , NULL   , 6); AddShift("SLI", NULL  , 6);
  4001.   AddShift("SL1" , NULL   , 6);
  4002.  
  4003.   AddBit("BIT", 0); AddBit("RES", 1); AddBit("SET", 2);
  4004.  
  4005.   AddInstTable(InstTable, "REG" , 0, CodeREG);
  4006.  
  4007.   AddInstTable(InstTable, "PRWINS", 0, DecodePRWINS);
  4008. }
  4009.  
  4010. static void DeinitFields(void)
  4011. {
  4012.   order_array_free(Conditions);
  4013.   order_array_free(FixedOrders);
  4014.   order_array_free(AccOrders);
  4015.   order_array_free(HLOrders);
  4016.  
  4017.   DestroyInstTable(InstTable);
  4018. }
  4019.  
  4020. /*=========================================================================*/
  4021.  
  4022. static void StripPref(const char *Arg, Byte Opcode)
  4023. {
  4024.   char *ptr, *ptr2;
  4025.   int z;
  4026.  
  4027.   /* do we have a prefix ? */
  4028.  
  4029.   if (!strcmp(OpPart.str.p_str, Arg))
  4030.   {
  4031.     /* add to code */
  4032.  
  4033.     BAsmCode[PrefixCnt++] = Opcode;
  4034.     StrCompReset(&OpPart);
  4035.  
  4036.     /* cut true opcode out of next argument */
  4037.  
  4038.     if (ArgCnt)
  4039.     {
  4040.       /* look for end of string */
  4041.  
  4042.       for (ptr = ArgStr[1].str.p_str; *ptr; ptr++)
  4043.         if (as_isspace(*ptr))
  4044.           break;
  4045.  
  4046.       /* look for beginning of next string */
  4047.  
  4048.       for (ptr2 = ptr; *ptr2; ptr2++)
  4049.         if (!as_isspace(*ptr2))
  4050.           break;
  4051.  
  4052.       /* copy out new opcode */
  4053.  
  4054.       OpPart.Pos.StartCol = ArgStr[1].Pos.StartCol;
  4055.       OpPart.Pos.Len = strmemcpy(OpPart.str.p_str, STRINGSIZE, ArgStr[1].str.p_str, ptr - ArgStr[1].str.p_str);
  4056.       NLS_UpString(OpPart.str.p_str);
  4057.  
  4058.       /* cut down arg or eliminate it completely */
  4059.  
  4060.       if (*ptr2)
  4061.       {
  4062.         strmov(ArgStr[1].str.p_str, ptr2);
  4063.         ArgStr[1].Pos.StartCol += ptr2 - ArgStr[1].str.p_str;
  4064.         ArgStr[1].Pos.Len -= ptr2 - ArgStr[1].str.p_str;
  4065.       }
  4066.       else
  4067.       {
  4068.         for (z = 1; z < ArgCnt; z++)
  4069.           StrCompCopy(&ArgStr[z], &ArgStr[z + 1]);
  4070.         ArgCnt--;
  4071.       }
  4072.     }
  4073.  
  4074.     /* if no further argument, that's all folks */
  4075.  
  4076.     else
  4077.       CodeLen = PrefixCnt;
  4078.   }
  4079. }
  4080.  
  4081. static void MakeCode_Z80(void)
  4082. {
  4083.   CodeLen = 0;
  4084.   DontPrint = False;
  4085.   PrefixCnt = 0;
  4086.   OpSize = 0xff;
  4087.   MayLW = False;
  4088.  
  4089. /*--------------------------------------------------------------------------*/
  4090. /* Rabbit 2000 prefixes */
  4091.  
  4092.   if (MomCPU == CPUR2000)
  4093.   {
  4094.     StripPref("ALTD", 0x76);
  4095.   }
  4096.  
  4097.   /* zu ignorierendes */
  4098.  
  4099.   if (Memo("")) return;
  4100.  
  4101.   /* letzten Praefix umkopieren */
  4102.  
  4103.   LastPrefix = CurrPrefix;
  4104.   CurrPrefix = Pref_IN_N;
  4105.  
  4106.   /* evtl. Datenablage */
  4107.  
  4108.   if (DecodeIntelPseudo(False)) return;
  4109.  
  4110.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  4111.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  4112. }
  4113.  
  4114. static void InitCode_Z80(void)
  4115. {
  4116.   Reg_CBAR = 0xf0;
  4117.   Reg_CBR = Reg_BBR = 0x00;
  4118. }
  4119.  
  4120. static Boolean IsDef_Z80(void)
  4121. {
  4122.   return Memo("PORT") || Memo("REG");
  4123. }
  4124.  
  4125. /* Treat special case of AF' which is no quoting: */
  4126.  
  4127. static Boolean QualifyQuote_Z80(const char *pStart, const char *pQuotePos)
  4128. {
  4129.   if ((*pQuotePos == '\'')
  4130.    && (pQuotePos >= pStart + 2)
  4131.    && (as_toupper(*(pQuotePos - 2)) == 'A')
  4132.    && (as_toupper(*(pQuotePos - 1)) == 'F'))
  4133.     return False;
  4134.   return True;
  4135. }
  4136.  
  4137. /*!------------------------------------------------------------------------
  4138.  * \fn     DissectReg_Z80(char *p_dest, size_t dest_size, tRegInt value, tSymbolSize inp_size)
  4139.  * \brief  dissect register symbols - Z80 variant
  4140.  * \param  p_dest destination buffer
  4141.  * \param  dest_size destination buffer size
  4142.  * \param  value numeric register value
  4143.  * \param  inp_size register size
  4144.  * ------------------------------------------------------------------------ */
  4145.  
  4146. static void DissectReg_Z80(char *p_dest, size_t dest_size, tRegInt value, tSymbolSize inp_size)
  4147. {
  4148.   switch (inp_size)
  4149.   {
  4150.     case eSymbolSize8Bit:
  4151.       if ((value & 0xf0) == (IXPrefix & 0xf0))
  4152.         as_snprintf(p_dest, dest_size, "%s%c", Reg16Names[4], (value & 1) ? 'L' : ((MomCPU == CPUZ80U) ? 'H' : 'U'));
  4153.       else if ((value & 0xf0) == (IYPrefix & 0xf0))
  4154.         as_snprintf(p_dest, dest_size, "%s%c", Reg16Names[5], (value & 1) ? 'L' : ((MomCPU == CPUZ80U) ? 'H' : 'U'));
  4155.       else if ((value < 8) && (value != 6))
  4156.         as_snprintf(p_dest, dest_size, "%c", Reg8Names[value]);
  4157.       else
  4158.         goto none;
  4159.       break;
  4160.     case eSymbolSize16Bit:
  4161.       if ((value & 0xf0) == (IXPrefix & 0xf0))
  4162.         as_snprintf(p_dest, dest_size, Reg16Names[4]);
  4163.       else if ((value & 0xf0) == (IYPrefix & 0xf0))
  4164.         as_snprintf(p_dest, dest_size, Reg16Names[5]);
  4165.       else if (value < 4)
  4166.         as_snprintf(p_dest, dest_size, "%s", Reg16Names[value]);
  4167.       else
  4168.         goto none;
  4169.       break;
  4170.     none:
  4171.     default:
  4172.       as_snprintf(p_dest, dest_size, "%d-%u", (int)inp_size, (unsigned)value);
  4173.   }
  4174. }
  4175.  
  4176. /*!------------------------------------------------------------------------
  4177.  * \fn     InternSymbol_Z80(char *p_arg, TempResult *p_result)
  4178.  * \brief  handle built-in (register) symbols for Z80
  4179.  * \param  p_arg source argument
  4180.  * \param  p_result result buffer
  4181.  * ------------------------------------------------------------------------ */
  4182.  
  4183. static void InternSymbol_Z80(char *p_arg, TempResult *p_result)
  4184. {
  4185.   Byte reg_num;
  4186.  
  4187.   if (DecodeReg8Core(p_arg, &reg_num))
  4188.   {
  4189.     p_result->Typ = TempReg;
  4190.     p_result->DataSize = eSymbolSize8Bit;
  4191.     p_result->Contents.RegDescr.Reg = reg_num;
  4192.     p_result->Contents.RegDescr.Dissect = DissectReg_Z80;
  4193.     p_result->Contents.RegDescr.compare = NULL;
  4194.   }
  4195.   else if (DecodeReg16Core(p_arg, &reg_num))
  4196.   {
  4197.     p_result->Typ = TempReg;
  4198.     p_result->DataSize = eSymbolSize16Bit;
  4199.     p_result->Contents.RegDescr.Reg = reg_num;
  4200.     p_result->Contents.RegDescr.Dissect = DissectReg_Z80;
  4201.     p_result->Contents.RegDescr.compare = NULL;
  4202.   }
  4203. }
  4204.  
  4205. static Boolean ChkMoreOneArg(void)
  4206. {
  4207.   return (ArgCnt > 1);
  4208. }
  4209.  
  4210. static Boolean chk_pc_z380(LargeWord addr)
  4211. {
  4212.   switch (ActPC)
  4213.   {
  4214.     case SegCode:
  4215.       return (addr < (ExtFlag ? 0xfffffffful : 0xffffu));
  4216.     default:
  4217.       return True;
  4218.   }
  4219. }
  4220.  
  4221. static void SwitchTo_Z80(void)
  4222. {
  4223.   TurnWords = False;
  4224.   SetIntConstMode(eIntConstModeIntel);
  4225.   SetIsOccupiedFnc = ChkMoreOneArg;
  4226.  
  4227.   PCSymbol = "$"; HeaderID = 0x51; NOPCode = 0x00;
  4228.   DivideChars = ","; HasAttrs = False;
  4229.  
  4230.   ValidSegs = 1 << SegCode;
  4231.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  4232.   if (MomCPU == CPUZ380)
  4233.   {
  4234.     SegLimits[SegCode] = 0xfffffffful;
  4235.     ChkPC = chk_pc_z380;
  4236.   }
  4237.   else if (MomCPU == CPUZ180)
  4238.     SegLimits[SegCode] = 0x7fffful;
  4239.   else if (MomCPU == CPUZ80U) SegLimits[SegCode] = 0xfffffffful;
  4240.   else
  4241.     SegLimits[SegCode] = 0xffffu;
  4242.  
  4243.   /* Gameboy Z80 does not have I/O space, and no IX/IY, do not test for them and allow as normal symbols: */
  4244.  
  4245.   if (!is_sharp())
  4246.   {
  4247.     ValidSegs |= 1 << SegIO;
  4248.     Grans[SegIO  ] = 1; ListGrans[SegIO  ] = 1; SegInits[SegIO  ] = 0;
  4249.     SegLimits[SegIO  ] = PortEnd();
  4250.     Reg16Cnt = 6;
  4251.   }
  4252.   else
  4253.     Reg16Cnt = 4;
  4254.  
  4255.   MakeCode = MakeCode_Z80;
  4256.   IsDef = IsDef_Z80;
  4257.   QualifyQuote = QualifyQuote_Z80;
  4258.   InternSymbol = InternSymbol_Z80;
  4259.   SwitchFrom = DeinitFields; InitFields();
  4260.   DissectReg = DissectReg_Z80;
  4261.  
  4262.   /* Extended Modes only on Z380 */
  4263.  
  4264.   if (MomCPU >= CPUZ380)
  4265.   {
  4266.     if (!onoff_test_and_set(e_onoff_reg_extmode))
  4267.       SetFlag(&ExtFlag, ExtModeSymName, False);
  4268.     AddONOFF(ExtModeCmdName, &ExtFlag, ExtModeSymName, False);
  4269.     if (!onoff_test_and_set(e_onoff_reg_lwordmode))
  4270.       SetFlag(&LWordFlag, LWordModeSymName, False);
  4271.     AddONOFF(LWordModeCmdName, &LWordFlag , LWordModeSymName , False);
  4272.   }
  4273.  
  4274.   if (MomCPU == CPUZ180)
  4275.   {
  4276.     static const ASSUMERec ASSUMEZ180s[] =
  4277.     {
  4278.       { "CBAR" , &Reg_CBAR , 0,  0xff, 0xf0, check_cbar },
  4279.       { "CBR"  , &Reg_CBR  , 0,  0xff, 0   , update_z180_areas },
  4280.       { "BBR"  , &Reg_BBR  , 0,  0xff, 0   , update_z180_areas },
  4281.     };
  4282.  
  4283.     pASSUMERecs = ASSUMEZ180s;
  4284.     ASSUMERecCnt = as_array_size(ASSUMEZ180s);
  4285.     update_z180_areas();
  4286.   }
  4287. }
  4288.  
  4289. void codez80_init(void)
  4290. {
  4291.   CPUGBZ80 = AddCPU("GBZ80"     , SwitchTo_Z80);
  4292.   CPULR35902 = AddCPU("LR35902" , SwitchTo_Z80);
  4293.   CPUZ80   = AddCPU("Z80"       , SwitchTo_Z80);
  4294.   CPUZ80U  = AddCPU("Z80UNDOC"  , SwitchTo_Z80);
  4295.   CPUZ180  = AddCPU("Z180"      , SwitchTo_Z80);
  4296.   CPUR2000 = AddCPU("RABBIT2000", SwitchTo_Z80);
  4297.   CPUZ380  = AddCPU("Z380"      , SwitchTo_Z80);
  4298.  
  4299.   AddInitPassProc(InitCode_Z80);
  4300. }
  4301.