Subversion Repositories pentevo

Rev

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

  1. /* code78c10.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator NEC uPD78(C)(0|1)x                                          */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <ctype.h>
  13. #include <string.h>
  14.  
  15. #include "bpemu.h"
  16. #include "strutil.h"
  17. #include "asmdef.h"
  18. #include "asmsub.h"
  19. #include "asmpars.h"
  20. #include "asmstructs.h"
  21. #include "asmitree.h"
  22. #include "asmcode.h"
  23. #include "codepseudo.h"
  24. #include "intpseudo.h"
  25. #include "codevars.h"
  26. #include "errmsg.h"
  27. #include "headids.h"
  28.  
  29. #include "code78c10.h"
  30.  
  31. /*---------------------------------------------------------------------------*/
  32.  
  33. typedef struct
  34. {
  35.   const char *p_name;
  36.   Byte code;
  37. } intflag_t;
  38.  
  39. typedef struct
  40. {
  41.   const char name[5];
  42.   Byte code, flags;
  43. } reg_t;
  44.  
  45. typedef struct
  46. {
  47.   const char *p_name;
  48.   Byte code, flags, core_mask;
  49. } sreg_t;
  50.  
  51. typedef struct
  52. {
  53.   const char *pName;
  54.   Byte Code;
  55.   Byte MayIndirect;
  56. } tAdrMode;
  57.  
  58. typedef enum
  59. {
  60.   eCoreNone,
  61.   eCore7800Low,
  62.   eCore7800High,
  63.   eCore7807,
  64.   eCore7810
  65. } tCore;
  66.  
  67. #define core_mask_no_low ((1 << eCore7800High) | (1 << eCore7807) | (1 << eCore7810))
  68. #define core_mask_7800 ((1 << eCore7800Low) | (1 << eCore7800High))
  69. #define core_mask_7800_low (1 << eCore7800Low)
  70. #define core_mask_7800_high (1 << eCore7800High)
  71. #define core_mask_7807 (1 << eCore7807)
  72. #define core_mask_7810 (1 << eCore7810)
  73. #define core_mask_7807_7810 ((1 << eCore7807) | (1 << eCore7810))
  74. #define core_mask_all ((1 << eCore7800Low) | (1 << eCore7800High) | (1 << eCore7807) | (1 << eCore7810))
  75. #define core_mask_cmos 0x80
  76.  
  77. enum
  78. {
  79.   eFlagHasV = 1 << 0,
  80.   eFlagCMOS = 1 << 1,
  81.   eFlagSR   = 1 << 2, /* sr  -> may be written from A */
  82.   eFlagSR1  = 1 << 3, /* sr1 -> may be read to A */
  83.   eFlagSR2  = 1 << 4, /* sr2 -> load or read/modify/write with immediate */
  84.   eFlagSR3  = 1 << 5, /* sr3 -> may be written from EA */
  85.   eFlagSR4  = 1 << 6  /* sr4 -> may be read to EA */
  86. };
  87.  
  88. /* Flags in high byte of ALU operations: */
  89.  
  90. #define ALUImm_SR (1 << 0)
  91. #define ALUReg_Src (1 << 1)
  92. #define ALUReg_Dest (1 << 2)
  93. #define ALUReg_MayZ80 (1 << 3)
  94.  
  95. typedef struct
  96. {
  97.   char Name[6];
  98.   Byte Core;
  99.   Byte Flags;
  100. } tCPUProps;
  101.  
  102. typedef enum { e_decode_reg_unknown, e_decode_reg_ok, e_decode_reg_error } decode_reg_res_t;
  103.  
  104. typedef struct
  105. {
  106.   Word code;
  107.   unsigned core_mask;
  108. } order_t;
  109.  
  110. typedef enum
  111. {
  112.   e_mod_none = -1,
  113.   e_mod_reg8 = 0,
  114.   e_mod_reg16 = 1,
  115.   e_mod_imm = 2,
  116.   e_mod_indir = 3,
  117.   e_mod_wa = 4,
  118.   e_mod_abs = 5,
  119.   e_mod_sreg8 = 6,
  120.   e_mod_sreg16 = 7
  121. } z80_adr_mode_t;
  122.  
  123. #define MModReg8 (1 << e_mod_reg8)
  124. #define MModReg16 (1 << e_mod_reg16)
  125. #define MModImm (1 << e_mod_imm)
  126. #define MModIndir (1 << e_mod_indir)
  127. #define MModWA (1 << e_mod_wa)
  128. #define MModAbs (1 << e_mod_abs)
  129. #define MModSReg8 (1 << e_mod_sreg8)
  130. #define MModSReg16 (1 << e_mod_sreg16)
  131.  
  132. #define REG_V 0
  133. #define REG_A 1
  134. #define REG_B 2
  135. #define REG_C 3
  136. #define REG_D 4
  137. #define REG_H 6
  138. #define REG_EAH 8
  139. #define REG_BC 1
  140. #define REG_DE 2
  141. #define REG_HL 3
  142. #define REG_EA 4
  143.  
  144. typedef struct
  145. {
  146.   z80_adr_mode_t mode;
  147.   unsigned count;
  148.   Boolean force_long;
  149.   Byte val, vals[2];
  150. } z80_adr_vals_t;
  151.  
  152. static Boolean is_7807_781x;
  153.  
  154. static LongInt WorkArea;
  155.  
  156. static const tCPUProps *pCurrCPUProps;
  157.  
  158. static order_t *fixed_orders, *reg2_orders;
  159. static sreg_t *s_regs8, *s_regs16;
  160. static intflag_t *int_flags;
  161. static tSymbolSize z80_op_size, z80_def_op_size;
  162.  
  163. /*--------------------------------------------------------------------------------*/
  164.  
  165. /*!------------------------------------------------------------------------
  166.  * \fn     check_core(unsigned core_mask)
  167.  * \brief  check whether active target uses given core
  168.  * \param  core_mask list of allowed cores
  169.  * \return True if OK
  170.  * ------------------------------------------------------------------------ */
  171.  
  172. static Boolean check_core(unsigned core_mask)
  173. {
  174.   if ((core_mask & core_mask_cmos) && !(pCurrCPUProps->Flags & eFlagCMOS))
  175.     return False;
  176.   return !!((core_mask >> pCurrCPUProps->Core) & 1);
  177. }
  178.  
  179. /*!------------------------------------------------------------------------
  180.  * \fn     decode_reg8(const char *p_arg, Byte *p_res)
  181.  * \brief  decode 8 bit register
  182.  * \param  p_arg source argument
  183.  * \param  p_res encoded name
  184.  * \return True if valid name
  185.  * ------------------------------------------------------------------------ */
  186.  
  187. static Boolean decode_reg8(const char *p_arg, Byte *p_res)
  188. {
  189.   switch (strlen(p_arg))
  190.   {
  191.     case 1:
  192.     {
  193.       static const char names[] = "VABCDEHL";
  194.       const char *p;
  195.       int no_v = !(pCurrCPUProps->Flags & eFlagHasV);
  196.  
  197.       p = strchr(&names[no_v], as_toupper(*p_arg));
  198.       if (!p)
  199.         return False;
  200.       *p_res = p - names;
  201.       return True;
  202.     }
  203.     case 3:
  204.       if (!is_7807_781x
  205.        || (as_toupper(p_arg[0]) != 'E')
  206.        || (as_toupper(p_arg[1]) != 'A'))
  207.         return False;
  208.       if (as_toupper(p_arg[2]) == 'L')
  209.         *p_res = REG_EAH + 1;
  210.       else if (as_toupper(p_arg[2]) == 'H')
  211.         *p_res = REG_EAH;
  212.       else
  213.         return False;
  214.       return True;
  215.     default:
  216.       return False;
  217.   }
  218. }
  219.  
  220. /*!------------------------------------------------------------------------
  221.  * \fn     decode_r(const tStrComp *p_arg, Byte *p_res)
  222.  * \brief  decode name of 8 bit register
  223.  * \param  p_arg source argument
  224.  * \param  p_res return buffer
  225.  * \return e_decode_reg_ok -> register known & OK
  226.  * ------------------------------------------------------------------------ */
  227.  
  228. static decode_reg_res_t decode_r(const tStrComp *p_arg, Byte *p_res)
  229. {
  230.   if (!decode_reg8(p_arg->str.p_str, p_res))
  231.     return e_decode_reg_unknown;
  232.   if (*p_res >= 8)
  233.   {
  234.     WrStrErrorPos(ErrNum_InvReg, p_arg);
  235.     return e_decode_reg_error;
  236.   }
  237.   else
  238.     return e_decode_reg_ok;
  239. }
  240.  
  241. /*!------------------------------------------------------------------------
  242.  * \fn     decode_r1(const tStrComp *p_arg, Byte *p_res)
  243.  * \brief  decode name of 8 bit register, plus EAL/H on 78C1x
  244.  * \param  p_arg source argument
  245.  * \param  p_res return buffer
  246.  * \return e_decode_reg_ok -> register known & OK
  247.  * ------------------------------------------------------------------------ */
  248.  
  249. static decode_reg_res_t decode_r1(const tStrComp *p_arg, Byte *p_res)
  250. {
  251.   if (!decode_reg8(p_arg->str.p_str, p_res))
  252.     return e_decode_reg_unknown;
  253.   if (*p_res < 2)
  254.   {
  255.     WrStrErrorPos(ErrNum_InvReg, p_arg);
  256.     return e_decode_reg_error;
  257.   }
  258.   *p_res &= 7;
  259.   return e_decode_reg_ok;
  260. }
  261.  
  262. /*!------------------------------------------------------------------------
  263.  * \fn     decode_r2(const tStrComp *p_arg, Byte *p_res)
  264.  * \brief  decode name of 8 bit register A, B, or C
  265.  * \param  p_arg source argument
  266.  * \param  p_res return buffer
  267.  * \return e_decode_reg_ok -> register known & OK
  268.  * ------------------------------------------------------------------------ */
  269.  
  270. static decode_reg_res_t decode_r2(const tStrComp *p_arg, Byte *p_res)
  271. {
  272.   if (!decode_reg8(p_arg->str.p_str, p_res))
  273.     return e_decode_reg_unknown;
  274.   if ((*p_res == 0) || (*p_res >= 4))
  275.   {
  276.     WrStrErrorPos(ErrNum_InvReg, p_arg);
  277.     return e_decode_reg_error;
  278.   }
  279.   return e_decode_reg_ok;
  280. }
  281.  
  282. /*!------------------------------------------------------------------------
  283.  * \fn     decode_reg16(char *p_arg, Byte *p_res, Boolean allow_single_letter)
  284.  * \brief  decode 16 bit register argument
  285.  * \param  p_arg source argument
  286.  * \param  p_res result value
  287.  * \param  allow_single_letter allow register names with single letters (not for Z80 syntax)
  288.  * \return True if success
  289.  * ------------------------------------------------------------------------ */
  290.  
  291. static Boolean decode_reg16(char *p_arg, Byte *p_res, Boolean allow_single_letter)
  292. {
  293.   static const reg_t regs[] =
  294.   {
  295.     { "SP" , 0, 0 },
  296.     { "B"  , REG_BC, 0 },
  297.     { "BC" , REG_BC, 0 },
  298.     { "D"  , REG_DE, 0 },
  299.     { "DE" , REG_DE, 0 },
  300.     { "H"  , REG_HL, 0 },
  301.     { "HL" , REG_HL, 0 },
  302.     { "EA" , REG_EA, 0 },
  303.     { ""   , 0, 0 },
  304.   };
  305.  
  306.   for (*p_res = 0; regs[*p_res].name[0]; (*p_res)++)
  307.     if (!as_strcasecmp(p_arg, regs[*p_res].name))
  308.     {
  309.       if (!p_arg[1] && !allow_single_letter)
  310.         return False;
  311.       *p_res = regs[*p_res].code;
  312.       return True;
  313.     }
  314.   return False;
  315. }
  316.  
  317. /*!------------------------------------------------------------------------
  318.  * \fn     Decode_rp(char *Asc, Byte *Erg)
  319.  * \brief  decode rp2 argument (SP/BC/DE/HL/EA)
  320.  * \param  Asc source argument
  321.  * \param  Erg resulting register #
  322.  * \return True if success
  323.  * ------------------------------------------------------------------------ */
  324.  
  325. static Boolean Decode_rp2(char *p_arg, Byte *p_res)
  326. {
  327.   return decode_reg16(p_arg, p_res, True);
  328. }
  329.  
  330. /*!------------------------------------------------------------------------
  331.  * \fn     Decode_rp(char *Asc, Byte *Erg)
  332.  * \brief  decode rp argument (SP/BC/DE/HL)
  333.  * \param  Asc source argument
  334.  * \param  Erg resulting register #
  335.  * \return True if success
  336.  * ------------------------------------------------------------------------ */
  337.  
  338. static Boolean Decode_rp(char *Asc, Byte *Erg)
  339. {
  340.   if (!Decode_rp2(Asc, Erg)) return False;
  341.   return (*Erg < 4);
  342. }
  343.  
  344. /*!------------------------------------------------------------------------
  345.  * \fn     Decode_rp1(char *Asc, Byte *Erg)
  346.  * \brief  decode rp1 argument (VA/BC/DE/HL/EA)
  347.  * \param  Asc source argument
  348.  * \param  Erg resulting register #
  349.  * \return True if success
  350.  * ------------------------------------------------------------------------ */
  351.  
  352. static Boolean Decode_rp1(char *Asc, Byte *Erg)
  353. {
  354.   if (!as_strcasecmp(Asc, "V")) *Erg = 0;
  355.   else
  356.   {
  357.     if (!Decode_rp2(Asc, Erg)) return False;
  358.     return (*Erg != 0);
  359.   }
  360.   return True;
  361. }
  362.  
  363. /*!------------------------------------------------------------------------
  364.  * \fn     Decode_rp3(char *Asc, Byte *Erg)
  365.  * \brief  decode rp3 argument (BC/DE/HL)
  366.  * \param  Asc source argument
  367.  * \param  Erg resulting register #
  368.  * \return True if success
  369.  * ------------------------------------------------------------------------ */
  370.  
  371. static Boolean Decode_rp3(char *Asc, Byte *Erg)
  372. {
  373.   if (!Decode_rp2(Asc, Erg)) return False;
  374.   return ((*Erg < 4) && (*Erg > 0));
  375. }
  376.  
  377. /*!------------------------------------------------------------------------
  378.  * \fn     parse_rpa(const tStrComp *p_arg, z80_adr_vals_t *p_vals, unsigned mode_mask, int *p_auto_val, Boolean force)
  379.  * \brief  parse indirect address expression
  380.  * \param  p_arg source argument
  381.  * \param  p_vals buffer for parse result
  382.  * \param  mode_mask allowed addressing modes
  383.  * \param  p_auto_val returns auto-in/decrement value
  384.  * \param  force assume expression is indirect, even without outer (...)
  385.  * \return True if expression was detected as indirect (parsing may still have failed)
  386.  * ------------------------------------------------------------------------ */
  387.  
  388. static int split_auto_val(tStrComp *p_arg)
  389. {
  390.   int l = strlen(p_arg->str.p_str);
  391.  
  392.   if (l >= 2)
  393.   {
  394.     if (!strcmp(p_arg->str.p_str + l - 2, "--"))
  395.     {
  396.       StrCompShorten(p_arg, 2);
  397.       return - 2;
  398.     }
  399.     if (!strcmp(p_arg->str.p_str + l - 2, "++"))
  400.     {
  401.       StrCompShorten(p_arg, 2);
  402.       return + 2;
  403.     }
  404.   }
  405.  
  406.   if (l >= 1)
  407.   {
  408.     if (p_arg->str.p_str[l - 1] == '-')
  409.     {
  410.       StrCompShorten(p_arg, 1);
  411.       return -1;
  412.     }
  413.     if (p_arg->str.p_str[l - 1] == '+')
  414.     {
  415.       StrCompShorten(p_arg, 1);
  416.       return +1;
  417.     }
  418.   }
  419.  
  420.   return 0;
  421. }
  422.  
  423. static void parse_indirect_list(z80_adr_vals_t *p_vals, const tStrComp *p_arg, unsigned mode_mask, int auto_val)
  424. {
  425.   char *p;
  426.   tStrComp rem, arg;
  427.   Byte reg, base = 0, index = 0;
  428.   LongInt disp_acc = 0;
  429.   Boolean bad_reg, first_unknown = False, this_minus, next_minus;
  430.  
  431.   StrCompRefRight(&arg, p_arg, 0);
  432.   KillPostBlanksStrComp(&arg);
  433.   this_minus = False;
  434.   do
  435.   {
  436.     /* split off one component */
  437.  
  438.     KillPrefBlanksStrCompRef(&arg);
  439.     next_minus = False;
  440.     p = indir_split_pos(arg.str.p_str); /* TODO: parentheses */
  441.     if (p)
  442.     {
  443.       next_minus = (*p == '-');
  444.       StrCompSplitRef(&arg, &rem, &arg, p);
  445.       KillPostBlanksStrComp(&arg);
  446.     }
  447.     bad_reg = False;
  448.  
  449.     /* 8 bit register? Note that a B/D/H may actually mean BC/DE/HL
  450.        in 'old syntax': */
  451.  
  452.     if (decode_reg8(arg.str.p_str, &reg))
  453.     {
  454.       if (this_minus)
  455.         bad_reg = True;
  456.       else switch (reg)
  457.       {
  458.         case REG_A:
  459.           if (index)
  460.             bad_reg = True;
  461.           else
  462.             index = reg;
  463.           break;
  464.         case REG_B:
  465.           if (!index)
  466.             index = reg;
  467.           else if (!base)
  468.             base = REG_BC;
  469.           else
  470.             bad_reg = True;
  471.           break;
  472.         case REG_D:
  473.           if (!base)
  474.             base = REG_DE;
  475.           else
  476.             bad_reg = True;
  477.           break;
  478.         case REG_H:
  479.           if (!base)
  480.             base = REG_HL;
  481.           else
  482.             bad_reg = True;
  483.           break;
  484.         default:
  485.           bad_reg = True;
  486.       }
  487.     }
  488.  
  489.     /* 16 bit register? */
  490.  
  491.     else if (decode_reg16(arg.str.p_str, &reg, False))
  492.     {
  493.       if (this_minus)
  494.         bad_reg = True;
  495.       else switch (reg)
  496.       {
  497.         case REG_EA:
  498.           if (index)
  499.             bad_reg = True;
  500.           else
  501.             index = reg;
  502.           break;
  503.         case REG_BC:
  504.         case REG_DE:
  505.         case REG_HL:
  506.           if (base)
  507.             bad_reg = True;
  508.           else
  509.             base = reg;
  510.           break;
  511.         default:
  512.           bad_reg = True;
  513.       }
  514.     }
  515.     else
  516.     {
  517.       tEvalResult eval_result;
  518.       Word value;
  519.  
  520.       value = EvalStrIntExpressionWithResult(&arg, UInt16, &eval_result);
  521.       if (!eval_result.OK)
  522.         return;
  523.       if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
  524.         first_unknown = True;
  525.       disp_acc = this_minus ? (disp_acc - value) : (disp_acc + value);
  526.     }
  527.  
  528.     if (bad_reg)
  529.     {
  530.       WrStrErrorPos(ErrNum_InvReg, &arg);
  531.       return;
  532.     }
  533.  
  534.     if (p)
  535.     {
  536.       arg = rem;
  537.       this_minus = next_minus;
  538.     }
  539.   }
  540.   while (p);
  541.  
  542.   /* Dissolve ambiguities */
  543.  
  544.   if ((index == REG_B) && !base)
  545.   {
  546.     index = 0;
  547.     base = REG_BC;
  548.   }
  549.  
  550.   /* For auto-in/decrement, only a plain base register DE/HL is allowed.
  551.      Furthermore, (..)-- is not implemented: */
  552.  
  553.   if (auto_val)
  554.   {
  555.     if (index || (base < REG_BC) || (base > REG_HL) || disp_acc || (auto_val == -2))
  556.       WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  557.     else
  558.     {
  559.       p_vals->val = (base + 2) + (2 * !!(auto_val < 0));
  560.       p_vals->mode = e_mod_indir;
  561.     }
  562.   }
  563.   else
  564.   {
  565.     /* (BC) (DE) (HL) */
  566.     if ((base >= REG_BC) && (base <= REG_HL) && !index && !disp_acc)
  567.     {
  568.       p_vals->val = base;
  569.       p_vals->mode = e_mod_indir;
  570.     }
  571.     /* (DE+byte) (HL+byte) */
  572.     else if ((base >= REG_DE) && (base <= REG_HL) && !index)
  573.     {
  574.       if (first_unknown)
  575.         disp_acc &= 0xff;
  576.       if ((disp_acc > 0xff) || (disp_acc < -0x80))
  577.       {
  578.         WrStrErrorPos(ErrNum_OverRange, p_arg);
  579.         return;
  580.       }
  581.       p_vals->val = (base << 2) + 3;
  582.       p_vals->mode = e_mod_indir;
  583.       p_vals->vals[p_vals->count++] = Lo(disp_acc);
  584.     }
  585.     /* (HL+A) (HL+B) */
  586.     else if ((base == REG_HL) && (index >= REG_A) && (index <= REG_B) && !disp_acc)
  587.     {
  588.       p_vals->val = index + 11;
  589.       p_vals->mode = e_mod_indir;
  590.     }
  591.     /* (HL+EA) */
  592.     else if ((base == REG_HL) && (index == REG_EA) && !disp_acc)
  593.     {
  594.       p_vals->val = 14;
  595.       p_vals->mode = e_mod_indir;
  596.     }
  597.     /* abs/wa */
  598.     else if (!base && !index)
  599.     {
  600.       Boolean is_wa = (Hi(disp_acc) == WorkArea),
  601.               may_wa = !!(mode_mask & MModWA);
  602.  
  603.       p_vals->vals[p_vals->count++] = Lo(disp_acc);
  604.       if ((may_wa && is_wa) || (!may_wa && first_unknown))
  605.         p_vals->mode = e_mod_wa;
  606.       else
  607.       {
  608.         p_vals->vals[p_vals->count++] = Hi(disp_acc);
  609.         p_vals->mode = e_mod_abs;
  610.       }
  611.     }
  612.     else
  613.       WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  614.   }
  615. }
  616.  
  617. static Boolean parse_rpa(const tStrComp *p_arg, z80_adr_vals_t *p_vals, unsigned mode_mask, int *p_auto_val, Boolean force)
  618. {
  619.   tStrComp arg;
  620.   Boolean is_indirect;
  621.  
  622.   /* split off auto-in/decrement */
  623.  
  624.   StrCompRefRight(&arg, p_arg, 0);
  625.   *p_auto_val = split_auto_val(&arg);
  626.  
  627.   /* Indirect? */
  628.  
  629.   is_indirect = IsIndirect(arg.str.p_str);
  630.   if (is_indirect)
  631.   {
  632.     StrCompIncRefLeft(&arg, 1);
  633.     StrCompShorten(&arg, 1);
  634.     KillPostBlanksStrComp(&arg);
  635.     if (!*p_auto_val)
  636.       *p_auto_val = split_auto_val(&arg);
  637.   }
  638.  
  639.   /* Auto-in/decrement enforces indirect parsing: */
  640.  
  641.   if (is_indirect || *p_auto_val || force)
  642.   {
  643.     parse_indirect_list(p_vals, &arg, mode_mask, *p_auto_val);
  644.     return True;
  645.   }
  646.   else
  647.     return False;
  648. }
  649.  
  650. /*!------------------------------------------------------------------------
  651.  * \fn     reset_z80_adr_vals(z80_adr_vals_t *p_vals)
  652.  * \brief  clear encoded addressing mode container
  653.  * \param  p_vals container to clear
  654.  * ------------------------------------------------------------------------ */
  655.  
  656. static void reset_z80_adr_vals(z80_adr_vals_t *p_vals)
  657. {
  658.   p_vals->mode = e_mod_none;
  659.   p_vals->force_long = 0;
  660.   p_vals->val = 0;
  661.   p_vals->count = 0;
  662. }
  663.  
  664. /*!------------------------------------------------------------------------
  665.  * \fn     Decode_rpa2(const tStrComp *pArg, Byte *Erg, Byte *Disp)
  666.  * \brief  Decode rpa2 argument (indirect 8 bit argument in memory)
  667.  * \param  pArg source argument
  668.  * \param  Erg resulting addressing mode
  669.  * \param  Disp resulting addressing displacement
  670.  * \return True if success
  671.  * ------------------------------------------------------------------------ */
  672.  
  673. static Boolean Decode_rpa2(const tStrComp *pArg, Byte *Erg, Byte *Disp)
  674. {
  675.   z80_adr_vals_t vals;
  676.   int auto_val;
  677.  
  678.   /* We force parsing as indirect, so the return value is always true: */
  679.  
  680.   reset_z80_adr_vals(&vals);
  681.   (void)parse_rpa(pArg, &vals, MModIndir, &auto_val, True);
  682.   switch (vals.mode)
  683.   {
  684.     case e_mod_indir:
  685.       if ((auto_val < -1) || (auto_val > 1))
  686.         goto bad_mode;
  687.       *Erg = vals.val;
  688.       *Disp = (vals.count > 0) ? vals.vals[0] : 0;
  689.       return True;
  690.     case e_mod_wa:
  691.     case e_mod_abs:
  692.     bad_mode:
  693.       WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  694.       return False;
  695.     default:
  696.       return False;
  697.   }
  698. }
  699.  
  700. /*!------------------------------------------------------------------------
  701.  * \fn     Decode_rpa(const tStrComp *pArg, Byte *Erg)
  702.  * \brief  Decode rpa argument (indirect 8 bit argument in memory, without index)
  703.  * \param  pArg source argument
  704.  * \param  Erg resulting addressing mode
  705.  * \return True if success
  706.  * ------------------------------------------------------------------------ */
  707.  
  708. static Boolean is_rpa(Byte value)
  709. {
  710.   return (value >= 1) && (value <= 7);
  711. }
  712.  
  713. static Boolean Decode_rpa(const tStrComp *pArg, Byte *Erg)
  714. {
  715.   Byte Dummy;
  716.  
  717.   if (!Decode_rpa2(pArg, Erg, &Dummy)) return False;
  718.   if (!is_rpa(*Erg))
  719.   {
  720.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  721.     return False;
  722.   }
  723.   return True;
  724. }
  725.  
  726. /*!------------------------------------------------------------------------
  727.  * \fn     Decode_rpa1(const tStrComp *pArg, Byte *Erg)
  728.  * \brief  Decode rpa1 argument (indirect 8 bit argument in memory, without index or auto-in/decrement)
  729.  * \param  pArg source argument
  730.  * \param  Erg resulting addressing mode
  731.  * \return True if success
  732.  * ------------------------------------------------------------------------ */
  733.  
  734. static Boolean is_rpa1(Byte value)
  735. {
  736.   return (value >= 1) && (value <= 3);
  737. }
  738.  
  739. static Boolean Decode_rpa1(const tStrComp *pArg, Byte *Erg)
  740. {
  741.   Byte Dummy;
  742.  
  743.   if (!Decode_rpa2(pArg, Erg, &Dummy)) return False;
  744.   if (!is_rpa1(*Erg))
  745.   {
  746.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  747.     return False;
  748.   }
  749.   return True;
  750. }
  751.  
  752. /*!------------------------------------------------------------------------
  753.  * \fn     Decode_rpa3(const tStrComp *pArg, Byte *Erg, ShortInt *Disp)
  754.  * \brief  Decode rpa3 argument (indirect 16 bit argument in memory)
  755.  * \param  pArg source argument
  756.  * \param  Erg resulting addressing mode
  757.  * \param  Disp resulting addressing displacement
  758.  * \return True if success
  759.  * ------------------------------------------------------------------------ */
  760.  
  761. static Boolean is_rpa3(Byte value)
  762. {
  763.   return ((value >= 2) && (value <= 5))
  764.       || ((value >= 11) && (value <= 15));
  765. }
  766.  
  767. static Boolean Decode_rpa3(const tStrComp *pArg, Byte *Erg, Byte *Disp)
  768. {
  769.   z80_adr_vals_t vals;
  770.   int auto_val;
  771.  
  772.   /* We force parsing as indirect, so the return value is always true: */
  773.  
  774.   reset_z80_adr_vals(&vals);
  775.   (void)parse_rpa(pArg, &vals, MModIndir, &auto_val, True);
  776.   switch (vals.mode)
  777.   {
  778.     case e_mod_indir:
  779.       if ((auto_val != -2) && (auto_val != 0) && (auto_val != 2))
  780.         goto bad_mode;
  781.       if (!is_rpa3(vals.val))
  782.         goto bad_mode;
  783.       *Erg = vals.val;
  784.       *Disp = (vals.count > 0) ? vals.vals[0] : 0;
  785.       return True;
  786.     case e_mod_wa:
  787.     case e_mod_abs:
  788.     bad_mode:
  789.       WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  790.       return False;
  791.     default:
  792.       return False;
  793.   }
  794. }
  795.  
  796. /*!------------------------------------------------------------------------
  797.  * \fn     Decode_f(char *Asc, Byte *Erg)
  798.  * \brief  descode status flag
  799.  * \param  Asc source argument
  800.  * \param  Erg returns encoded flag
  801.  * \return True if success
  802.  * ------------------------------------------------------------------------ */
  803.  
  804. static Boolean Decode_f(char *Asc, Byte *Erg)
  805. {
  806. #define FlagCnt 3
  807.   static const char Flags[FlagCnt][3] = {"CY", "HC", "Z"};
  808.  
  809.   for (*Erg = 0; *Erg < FlagCnt; (*Erg)++)
  810.    if (!as_strcasecmp(Flags[*Erg], Asc)) break;
  811.   *Erg += 2; return (*Erg <= 4);
  812. }
  813.  
  814. /*!------------------------------------------------------------------------
  815.  * \fn     decode_sr_core(const tStrComp *p_arg)
  816.  * \brief  core register list decode
  817.  * \param  p_arg source argument
  818.  * \return * to record of decoded register
  819.  * ------------------------------------------------------------------------ */
  820.  
  821. static const sreg_t *decode_sr_core(const sreg_t *p_sregs, const tStrComp *p_arg)
  822. {
  823.   for (; p_sregs->p_name; p_sregs++)
  824.     if (check_core(p_sregs->core_mask) && !as_strcasecmp(p_arg->str.p_str, p_sregs->p_name))
  825.       return p_sregs;
  826.   return NULL;
  827. }
  828.  
  829. /*!------------------------------------------------------------------------
  830.  * \fn     check_sr_flag(Byte reg_flags, Byte req_flag, const tStrComp *p_arg)
  831.  * \brief  check whether special register's flags fulfill requirement, and
  832.            issue error if not
  833.  * \param  reg_flags register's suppoerted flags
  834.  * \param  req_flag required flag
  835.  * \param  p_arg source argument
  836.  * \return True if OK
  837.  * ------------------------------------------------------------------------ */
  838.  
  839. static Boolean check_sr_flag(Byte reg_flags, Byte req_flag, const tStrComp *p_arg)
  840. {
  841.   if (reg_flags & req_flag)
  842.     return True;
  843.   WrStrErrorPos(reg_flags ? ErrNum_InvOpOnReg : ErrNum_InvReg, p_arg);
  844.   return False;
  845. }
  846.  
  847. static decode_reg_res_t decode_sr_flag(const tStrComp *p_arg, const sreg_t *p_sregs, Byte *p_res, Byte flag)
  848. {
  849.   const sreg_t *p_reg = decode_sr_core(p_sregs, p_arg);
  850.  
  851.   if (p_reg)
  852.   {
  853.     if (check_sr_flag(p_reg->flags, flag, p_arg))
  854.     {
  855.       *p_res = p_reg->code;
  856.       return e_decode_reg_ok;
  857.     }
  858.     else
  859.       return e_decode_reg_error;
  860.   }
  861.   else
  862.     return e_decode_reg_unknown;
  863. }
  864.  
  865. #define decode_sr1(p_arg, p_res) decode_sr_flag(p_arg, s_regs8, p_res, eFlagSR1)
  866. #define decode_sr(p_arg, p_res) decode_sr_flag(p_arg, s_regs8, p_res, eFlagSR)
  867. #define decode_sr2(p_arg, p_res) decode_sr_flag(p_arg, s_regs8, p_res, eFlagSR2)
  868.  
  869. /*!------------------------------------------------------------------------
  870.  * \fn     Decode_irf(const tStrComp *p_arg, ShortInt *p_res)
  871.  * \brief  decode interrupt flag argument
  872.  * \param  p_arg source argument
  873.  * \param  p_res resulting flag #
  874.  * \return True if success
  875.  * ------------------------------------------------------------------------ */
  876.  
  877. static Boolean Decode_irf(const tStrComp *p_arg, ShortInt *p_res)
  878. {
  879.   for (*p_res = 0; int_flags[*p_res].p_name; (*p_res)++)
  880.     if (!as_strcasecmp(int_flags[*p_res].p_name, p_arg->str.p_str))
  881.     {
  882.       *p_res = int_flags[*p_res].code;
  883.       return True;
  884.     }
  885.   WrStrErrorPos(ErrNum_UnknownInt, p_arg);
  886.   return False;
  887. }
  888.  
  889. /*!------------------------------------------------------------------------
  890.  * \fn     Decode_wa(const tStrComp *pArg, Byte *Erg, Byte max_address)
  891.  * \brief  decode working area address argument
  892.  * \param  pArg source argument
  893.  * \param  Erg resulting (short) address
  894.  * \param  max_address range limit
  895.  * \return True if success
  896.  * ------------------------------------------------------------------------ */
  897.  
  898. static Boolean Decode_wa(const tStrComp *pArg, Byte *Erg, Byte max_address)
  899. {
  900.   Word Adr;
  901.   Boolean OK;
  902.   tSymbolFlags Flags;
  903.  
  904.   Adr = EvalStrIntExpressionWithFlags(pArg, Int16, &OK, &Flags);
  905.   if (!OK)
  906.     return False;
  907.  
  908.   if (!mFirstPassUnknown(Flags) && (Hi(Adr) != WorkArea)) WrStrErrorPos(ErrNum_InAccPage, pArg);
  909.   *Erg = Lo(Adr);
  910.  
  911.   if (mFirstPassUnknownOrQuestionable(Flags))
  912.     *Erg &= max_address;
  913.  
  914.   return ChkRangePos(*Erg, 0, max_address, pArg);
  915. }
  916.  
  917. static Boolean HasDisp(ShortInt Mode)
  918. {
  919.   return ((Mode & 11) == 11);
  920. }
  921.  
  922. /*!------------------------------------------------------------------------
  923.  * \fn     set_op_size(tSymbolSize new_op_size, const tStrComp *p_arg)
  924.  * \brief  Set operand size and throw error in case of conflict
  925.  * \param  new_op_size operand size to set
  926.  * \param  p_arg source argument carrying this size
  927.  * ------------------------------------------------------------------------ */
  928.  
  929. static Boolean set_op_size(tSymbolSize new_op_size, const tStrComp *p_arg)
  930. {
  931.   if (z80_op_size == eSymbolSizeUnknown)
  932.     z80_op_size = new_op_size;
  933.   else if (z80_op_size != new_op_size)
  934.   {
  935.     WrStrErrorPos(ErrNum_ConfOpSizes, p_arg);
  936.     return False;
  937.   }
  938.   return True;
  939. }
  940.  
  941. /*!------------------------------------------------------------------------
  942.  * \fn     decode_z80_adr(const tStrComp *p_arg, z80_adr_vals_t *p_vals, unsigned mode_mask)
  943.  * \brief  decode Z80 style address expression
  944.  * \param  p_arg source argument
  945.  * \param  p_vals encoded values
  946.  * \param  mode_mask bit mask of allowe daddressing modes
  947.  * \return resulting addressing mode
  948.  * ------------------------------------------------------------------------ */
  949.  
  950. static z80_adr_mode_t decode_z80_adr(const tStrComp *p_arg, z80_adr_vals_t *p_vals, unsigned mode_mask)
  951. {
  952.   Boolean ok;
  953.   int auto_val;
  954.   const sreg_t *p_sreg;
  955.  
  956.   reset_z80_adr_vals(p_vals);
  957.  
  958.   /* Registers: */
  959.  
  960.   if (!as_strcasecmp(p_arg->str.p_str, ">A"))
  961.   {
  962.     if (set_op_size(eSymbolSize8Bit, p_arg))
  963.     {
  964.       p_vals->force_long = True;
  965.       p_vals->val = REG_A;
  966.       p_vals->mode = e_mod_reg8;
  967.     }
  968.     goto found;
  969.   }
  970.  
  971.   if (decode_reg8(p_arg->str.p_str, &p_vals->val))
  972.   {
  973.     /* No V register on low function core */
  974.     if ((pCurrCPUProps->Core == eCore7800Low) && (p_vals->val == REG_V));
  975.     /* EA register only on 7807++ */
  976.     else if ((pCurrCPUProps->Core < eCore7807) && (p_vals->val >= REG_EAH));
  977.     else
  978.     {
  979.       if (set_op_size(eSymbolSize8Bit, p_arg))
  980.         p_vals->mode = e_mod_reg8;
  981.       goto found;
  982.     }
  983.   }
  984.  
  985.   if (decode_reg16(p_arg->str.p_str, &p_vals->val, False))
  986.   {
  987.     /* EA register only on 7807++ */
  988.     if ((pCurrCPUProps->Core < eCore7807) && (p_vals->val >= REG_EA));
  989.     else
  990.     {
  991.       if (set_op_size(eSymbolSize16Bit, p_arg))
  992.         p_vals->mode = e_mod_reg16;
  993.       goto found;
  994.     }
  995.   }
  996.  
  997.   p_sreg = decode_sr_core(s_regs8, p_arg);
  998.   if (p_sreg)
  999.   {
  1000.     if (set_op_size(eSymbolSize8Bit, p_arg))
  1001.     {
  1002.       p_vals->mode = e_mod_sreg8;
  1003.       p_vals->val = p_sreg->code;
  1004.       p_vals->vals[0] = p_sreg->flags;
  1005.     }
  1006.     goto found;
  1007.   }
  1008.  
  1009.   p_sreg = decode_sr_core(s_regs16, p_arg);
  1010.   if (p_sreg)
  1011.   {
  1012.     if (set_op_size(eSymbolSize16Bit, p_arg))
  1013.     {
  1014.       p_vals->mode = e_mod_sreg16;
  1015.       p_vals->val = p_sreg->code;
  1016.       p_vals->vals[0] = p_sreg->flags;
  1017.     }
  1018.     goto found;
  1019.   }
  1020.  
  1021.   /* indirect stuff: */
  1022.  
  1023.   if (parse_rpa(p_arg, p_vals, mode_mask, &auto_val, False))
  1024.   {
  1025.     /* single or double auto-in/decrement implicitly describes operand size: */
  1026.  
  1027.     if (auto_val)
  1028.     {
  1029.       if (!set_op_size(((auto_val == 1) || (auto_val == -1)) ? eSymbolSize8Bit : eSymbolSize16Bit, p_arg))
  1030.         reset_z80_adr_vals(p_vals);
  1031.     }
  1032.     goto found;
  1033.   }
  1034.  
  1035.   /* Immediate: */
  1036.  
  1037.   if (!(mode_mask & MModImm))
  1038.   {
  1039.     WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  1040.     goto found;
  1041.   }
  1042.   if (z80_op_size == eSymbolSizeUnknown)
  1043.   {
  1044.     z80_op_size = z80_def_op_size;
  1045.     z80_def_op_size = eSymbolSizeUnknown;
  1046.   }
  1047.   switch (z80_op_size)
  1048.   {
  1049.     case eSymbolSize8Bit:
  1050.       p_vals->vals[0] = EvalStrIntExpression(p_arg, Int8, &ok);
  1051.       if (ok)
  1052.       {
  1053.         p_vals->count = 1;
  1054.         p_vals->mode = e_mod_imm;
  1055.       }
  1056.       break;
  1057.     case eSymbolSize16Bit:
  1058.     {
  1059.       Word tmp = EvalStrIntExpression(p_arg, Int16, &ok);
  1060.       if (ok)
  1061.       {
  1062.         p_vals->vals[p_vals->count++] = Lo(tmp);
  1063.         p_vals->vals[p_vals->count++] = Hi(tmp);
  1064.         p_vals->mode = e_mod_imm;
  1065.       }
  1066.       break;
  1067.     }
  1068.     default:
  1069.       WrStrErrorPos(ErrNum_UndefOpSizes, p_arg);
  1070.   }
  1071.  
  1072. found:
  1073.   if ((p_vals->mode != e_mod_none) && !((mode_mask >> p_vals->mode) & 1))
  1074.   {
  1075.     WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  1076.     reset_z80_adr_vals(p_vals);
  1077.   }
  1078.   return p_vals->mode;
  1079. }
  1080.  
  1081. /*!------------------------------------------------------------------------
  1082.  * \fn     append_adr_vals(const z80_adr_vals_t *p_vals)
  1083.  * \brief  append encoded addess extension bytes to instruction
  1084.  * \param  p_vals contains bytes to append
  1085.  * ------------------------------------------------------------------------ */
  1086.  
  1087. static void append_adr_vals(const z80_adr_vals_t *p_vals)
  1088. {
  1089.   memcpy(&BAsmCode[CodeLen], p_vals->vals, p_vals->count);
  1090.   CodeLen += p_vals->count;
  1091. }
  1092.  
  1093. /*--------------------------------------------------------------------------*/
  1094. /* Bit Symbol Handling (uPD7807...7809 only) */
  1095.  
  1096. /*
  1097.  * Compact representation of bits in symbol table:
  1098.  * bits 0..2: bit position
  1099.  * bits 3...6/18: address in I/O or memory space
  1100.  * bit 19: 0 for memory space, 1 for I/O space
  1101.  * bits 20..23: core type
  1102.  */
  1103.  
  1104. /*!------------------------------------------------------------------------
  1105.  * \fn     eval_bit_position(const tStrComp *p_arg, Boolean *p_ok)
  1106.  * \brief  evaluate bit position
  1107.  * \param  bit position argument
  1108.  * \param  p_ok parsing OK?
  1109.  * \return numeric bit position
  1110.  * ------------------------------------------------------------------------ */
  1111.  
  1112. static LongWord eval_bit_position(const tStrComp *p_arg, Boolean *p_ok)
  1113. {
  1114.   return EvalStrIntExpression(p_arg, UInt3, p_ok);
  1115. }
  1116.  
  1117. /*!------------------------------------------------------------------------
  1118.  * \fn     assemble_bit_symbol(Byte core, Boolean is_io, Word address, Byte bit_pos)
  1119.  * \brief  transform bit symbol components into compact representation
  1120.  * \param  core core used to define this bit
  1121.  * \param  is_io special register or memory bit?
  1122.  * \param  address (I/O) register address
  1123.  * \param  bit_pos bit position
  1124.  * \return compact storage value
  1125.  * ------------------------------------------------------------------------ */
  1126.  
  1127. static LongWord assemble_bit_symbol(Byte core, Boolean is_io, Word address, Byte bit_pos)
  1128. {
  1129.   LongWord result = bit_pos | ((LongWord)address << 3);
  1130.  
  1131.   if (is_io)
  1132.     result |= 1ul << 19;
  1133.   result |= ((LongWord)core) << 20;
  1134.   return result;
  1135. }
  1136.  
  1137. /*!------------------------------------------------------------------------
  1138.  * \fn     decode_bit_arg_2(LongWord *p_result, const tStrComp *p_reg_arg, const tStrComp *p_bit_arg)
  1139.  * \brief  encode a bit symbol, address & bit position separated
  1140.  * \param  p_result resulting encoded bit
  1141.  * \param  p_reg_arg register argument
  1142.  * \param  p_bit_arg bit argument
  1143.  * \return True if success
  1144.  * ------------------------------------------------------------------------ */
  1145.  
  1146. static Boolean decode_bit_arg_2(LongWord *p_result, const tStrComp *p_reg_arg, const tStrComp *p_bit_arg)
  1147. {
  1148.   Boolean ok;
  1149.   LongWord addr;
  1150.   Boolean is_io;
  1151.   Byte bit_pos;
  1152.   Byte s_reg;
  1153.  
  1154.   bit_pos = eval_bit_position(p_bit_arg, &ok);
  1155.   if (!ok)
  1156.     return False;
  1157.  
  1158.   if (decode_sr_flag(p_reg_arg, s_regs8, &s_reg, eFlagSR2) == e_decode_reg_ok)
  1159.   {
  1160.     if (s_reg > 0x0f)
  1161.     {
  1162.       WrStrErrorPos(ErrNum_InvReg, p_reg_arg);
  1163.       return False;
  1164.     }
  1165.     is_io = True;
  1166.     addr = s_reg;
  1167.   }
  1168.  
  1169.   else
  1170.   {
  1171.     addr = EvalStrIntExpression(p_reg_arg, UInt16, &ok);
  1172.     if (!ok)
  1173.       return False;
  1174.     is_io = False;
  1175.   }
  1176.  
  1177.   *p_result = assemble_bit_symbol(pCurrCPUProps->Core, is_io, addr, bit_pos);
  1178.   return True;
  1179. }
  1180.  
  1181. /*!------------------------------------------------------------------------
  1182.  * \fn     decode_bit_arg(LongWord *p_result, int start, int stop)
  1183.  * \brief  encode a bit symbol from instruction argument(s)
  1184.  * \param  p_result resulting encoded bit
  1185.  * \param  start first argument
  1186.  * \param  stop last argument
  1187.  * \return True if success
  1188.  * ------------------------------------------------------------------------ */
  1189.  
  1190. static Boolean decode_bit_arg(LongWord *p_result, int start, int stop)
  1191. {
  1192.   *p_result = 0;
  1193.  
  1194.   /* Just one argument -> parse as bit argument */
  1195.  
  1196.   if (start == stop)
  1197.   {
  1198.     char *p_sep = RQuotPos(ArgStr[start].str.p_str, '.');
  1199.  
  1200.     if (p_sep)
  1201.     {
  1202.       tStrComp reg_comp, bit_comp;
  1203.  
  1204.       StrCompSplitRef(&reg_comp, &bit_comp, &ArgStr[start], p_sep);
  1205.       return decode_bit_arg_2(p_result, &reg_comp, &bit_comp);
  1206.     }
  1207.     else
  1208.     {
  1209.       tEvalResult eval_result;
  1210.  
  1211.       *p_result = EvalStrIntExpressionWithResult(&ArgStr[start], UInt24, &eval_result);
  1212.       if (eval_result.OK)
  1213.         ChkSpace(SegBData, eval_result.AddrSpaceMask);
  1214.       return eval_result.OK;
  1215.     }
  1216.   }
  1217.  
  1218.   /* register & bit position are given as separate arguments */
  1219.  
  1220.   else if (stop == start + 1)
  1221.     return decode_bit_arg_2(p_result, &ArgStr[start], &ArgStr[stop]);
  1222.  
  1223.   /* other # of arguments not allowed */
  1224.  
  1225.   else
  1226.   {
  1227.     WrError(ErrNum_WrongArgCnt);
  1228.     return False;
  1229.   }
  1230. }
  1231.  
  1232. /*!------------------------------------------------------------------------
  1233.  * \fn     dissect_bit_symbol(LongWord bit_symbol, Byte *p_core, Boolean *p_is_io, Word *p_address, Byte *p_bit_pos)
  1234.  * \brief  transform compact representation of bit (field) symbol into components
  1235.  * \param  bit_symbol compact storage
  1236.  * \param  p_core core used to define bit
  1237.  * \param  p_is_io special register or memory bit?
  1238.  * \param  p_address (I/O) register address
  1239.  * \param  p_bit_pos (start) bit position
  1240.  * \return constant True
  1241.  * ------------------------------------------------------------------------ */
  1242.  
  1243. static Boolean dissect_bit_symbol(LongWord bit_symbol, Byte *p_core, Boolean *p_is_io, Word *p_address, Byte *p_bit_pos)
  1244. {
  1245.   *p_core = (bit_symbol >> 20) & 15;
  1246.   *p_is_io = (bit_symbol >> 19) & 1;
  1247.   *p_address = (bit_symbol >> 3) & (*p_is_io ? 0xf : 0xffff);
  1248.   *p_bit_pos = bit_symbol & 7;
  1249.   return True;
  1250. }
  1251.  
  1252. /*!------------------------------------------------------------------------
  1253.  * \fn     dissect_bit_7807(char *p_dest, size_t dest_size, LargeWord inp)
  1254.  * \brief  dissect compact storage of bit (field) into readable form for listing
  1255.  * \param  p_dest destination for ASCII representation
  1256.  * \param  dest_size destination buffer size
  1257.  * \param  inp compact storage
  1258.  * ------------------------------------------------------------------------ */
  1259.  
  1260. static void dissect_bit_7807(char *p_dest, size_t dest_size, LargeWord inp)
  1261. {
  1262.   Byte bit_pos, core;
  1263.   Word address;
  1264.   Boolean is_io;
  1265.  
  1266.   dissect_bit_symbol(inp, &core, &is_io, &address, &bit_pos);
  1267.  
  1268.   if (is_io)
  1269.   {
  1270.     const sreg_t *p_sreg;
  1271.  
  1272.     for (p_sreg = s_regs8; p_sreg->p_name; p_sreg++)
  1273.     {
  1274.       if (!((p_sreg->core_mask >> core) & 1))
  1275.         continue;
  1276.       if (address == p_sreg->code)
  1277.       {
  1278.         as_snprintf(p_dest, dest_size, "%s.%u", p_sreg->p_name, (unsigned)bit_pos);
  1279.         return;
  1280.       }
  1281.     }
  1282.     as_snprintf(p_dest, dest_size, "SR%u.%u", address, (unsigned)bit_pos);
  1283.   }
  1284.   else
  1285.     as_snprintf(p_dest, dest_size, "%~.*u%s.%u",
  1286.                 ListRadixBase, (unsigned)address, GetIntConstIntelSuffix(ListRadixBase),
  1287.                 (unsigned)bit_pos);
  1288. }
  1289.  
  1290. /*!------------------------------------------------------------------------
  1291.  * \fn     expand_bit_7807(const tStrComp *p_var_name, const struct sStructElem *p_struct_elem, LargeWord base)
  1292.  * \brief  expands bit definition when a structure is instantiated
  1293.  * \param  p_var_name desired symbol name
  1294.  * \param  p_struct_elem element definition
  1295.  * \param  base base address of instantiated structure
  1296.  * ------------------------------------------------------------------------ */
  1297.  
  1298. static void expand_bit_7807(const tStrComp *p_var_name, const struct sStructElem *p_struct_elem, LargeWord base)
  1299. {
  1300.   LongWord address = base + p_struct_elem->Offset;
  1301.  
  1302.   if (pInnermostNamedStruct)
  1303.   {
  1304.     PStructElem p_elem = CloneStructElem(p_var_name, p_struct_elem);
  1305.  
  1306.     if (!p_elem)
  1307.       return;
  1308.     p_elem->Offset = address;
  1309.     AddStructElem(pInnermostNamedStruct->StructRec, p_elem);
  1310.   }
  1311.   else
  1312.   {
  1313.     if (!ChkRange(address, 0, 0xffff)
  1314.      || !ChkRange(p_struct_elem->BitPos, 0, 7))
  1315.       return;
  1316.  
  1317.     PushLocHandle(-1);
  1318.     EnterIntSymbol(p_var_name, assemble_bit_symbol(pCurrCPUProps->Core, False, address, p_struct_elem->BitPos), SegBData, False);
  1319.     PopLocHandle();
  1320.     /* TODO: MakeUseList? */
  1321.   }
  1322. }
  1323.  
  1324. /*--------------------------------------------------------------------------------*/
  1325.  
  1326. static Boolean check_core_and_error(unsigned core_mask)
  1327. {
  1328.   Boolean ret = check_core(core_mask);
  1329.  
  1330.   if (!ret)
  1331.     WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
  1332.   return ret;
  1333. }
  1334.  
  1335. static void PutCode(Word Code)
  1336. {
  1337.   if (Hi(Code) != 0)
  1338.     BAsmCode[CodeLen++] = Hi(Code);
  1339.   BAsmCode[CodeLen++] = Lo(Code);
  1340. }
  1341.  
  1342. /*!------------------------------------------------------------------------
  1343.  * \fn     decode_bit_7807_core(const tStrComp *p_arg, Byte code)
  1344.  * \brief  core routine for uPD7807 bit-oriented instructions
  1345.  * \param  p_arg source bit argument
  1346.  * \param  code machine code of instruction
  1347.  * ------------------------------------------------------------------------ */
  1348.  
  1349. static void decode_bit_7807_core(int arg_idx, Byte code)
  1350. {
  1351.   LongWord packed_bit;
  1352.   Boolean is_io;
  1353.   Word address;
  1354.   Byte bit_pos, core;
  1355.  
  1356.   if (!decode_bit_arg(&packed_bit, arg_idx, arg_idx))
  1357.     return;
  1358.   dissect_bit_symbol(packed_bit, &core, &is_io, &address, &bit_pos);
  1359.  
  1360.   if (!is_io)
  1361.   {
  1362.     if ((Hi(address) != WorkArea) || (Lo(address) > 15))
  1363.       WrStrErrorPos(ErrNum_InAccPage, &ArgStr[arg_idx]);
  1364.   }
  1365.  
  1366.   BAsmCode[1] = (is_io ? 0x80 : 0x00)
  1367.               | ((address & 15) << 3)
  1368.               | (bit_pos & 7);
  1369.   BAsmCode[0] = code;
  1370.   CodeLen = 2;
  1371. }
  1372.  
  1373. /*!------------------------------------------------------------------------
  1374.  * \fn     DecodeFixed(Word Code)
  1375.  * \brief  Handle instructions without arguments
  1376.  * \param  index index into instruction table
  1377.  * ------------------------------------------------------------------------ */
  1378.  
  1379. static void DecodeFixed(Word index)
  1380. {
  1381.   const order_t *p_order = &fixed_orders[index];
  1382.  
  1383.   if (ChkArgCnt(0, 0) && check_core_and_error(p_order->core_mask))
  1384.     PutCode(p_order->code);
  1385. }
  1386.  
  1387. /*!------------------------------------------------------------------------
  1388.  * \fn     DecodeMOV(Word Code)
  1389.  * \brief  handle MOV instruction
  1390.  * ------------------------------------------------------------------------ */
  1391.  
  1392. static void DecodeMOV(Word Code)
  1393. {
  1394.   Boolean OK;
  1395.   Byte HReg;
  1396.   Integer AdrInt;
  1397.   decode_reg_res_t res1;
  1398.  
  1399.   UNUSED(Code);
  1400.  
  1401.   if (!ChkArgCnt(2, 2));
  1402.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
  1403.   {
  1404.     decode_reg_res_t res2;
  1405.  
  1406.     if ((res2 = decode_sr1(&ArgStr[2], &HReg)) != e_decode_reg_unknown)
  1407.     {
  1408.       if (res2 == e_decode_reg_ok)
  1409.       {
  1410.         CodeLen = 2;
  1411.         BAsmCode[0] = 0x4c;
  1412.         BAsmCode[1] = 0xc0 + HReg;
  1413.       }
  1414.     }
  1415.     else if ((res2 = decode_r1(&ArgStr[2], &HReg)) != e_decode_reg_unknown)
  1416.     {
  1417.       if (res2 == e_decode_reg_ok)
  1418.       {
  1419.         CodeLen = 1;
  1420.         BAsmCode[0] = 0x08 + HReg;
  1421.       }
  1422.     }
  1423.     else
  1424.     {
  1425.       AdrInt = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
  1426.       if (OK)
  1427.       {
  1428.         CodeLen = 4;
  1429.         BAsmCode[0] = 0x70;
  1430.         BAsmCode[1] = 0x69;
  1431.         BAsmCode[2] = Lo(AdrInt);
  1432.         BAsmCode[3] = Hi(AdrInt);
  1433.       }
  1434.     }
  1435.   }
  1436.   else if (!as_strcasecmp(ArgStr[2].str.p_str, "A"))
  1437.   {
  1438.     decode_reg_res_t res2;
  1439.  
  1440.     if ((res2 = decode_sr(&ArgStr[1], &HReg)) != e_decode_reg_unknown)
  1441.     {
  1442.       if (res2 == e_decode_reg_ok)
  1443.       {
  1444.         CodeLen = 2;
  1445.         BAsmCode[0] = 0x4d;
  1446.         BAsmCode[1] = 0xc0 + HReg;
  1447.       }
  1448.     }
  1449.     else if ((res2 = decode_r1(&ArgStr[1], &HReg)) != e_decode_reg_unknown)
  1450.     {
  1451.       if (res2 == e_decode_reg_ok)
  1452.       {
  1453.         CodeLen = 1;
  1454.         BAsmCode[0] = 0x18 + HReg;
  1455.       }
  1456.     }
  1457.     else
  1458.     {
  1459.       AdrInt = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
  1460.       if (OK)
  1461.       {
  1462.         CodeLen = 4;
  1463.         BAsmCode[0] = 0x70;
  1464.         BAsmCode[1] = 0x79;
  1465.         BAsmCode[2] = Lo(AdrInt);
  1466.         BAsmCode[3] = Hi(AdrInt);
  1467.       }
  1468.     }
  1469.   }
  1470.   else if ((pCurrCPUProps->Core == eCore7807) && !as_strcasecmp(ArgStr[1].str.p_str, "CY"))
  1471.     decode_bit_7807_core(2, 0x5f);
  1472.   else if ((pCurrCPUProps->Core == eCore7807) && !as_strcasecmp(ArgStr[2].str.p_str, "CY"))
  1473.     decode_bit_7807_core(1, 0x5a);
  1474.   else if ((res1 = decode_r(&ArgStr[1], &HReg)) != e_decode_reg_unknown)
  1475.   {
  1476.     if (res1 == e_decode_reg_ok)
  1477.     {
  1478.       AdrInt = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
  1479.       if (OK)
  1480.       {
  1481.         CodeLen = 4;
  1482.         BAsmCode[0] = 0x70;
  1483.         BAsmCode[1] = 0x68 + HReg;
  1484.         BAsmCode[2] = Lo(AdrInt);
  1485.         BAsmCode[3] = Hi(AdrInt);
  1486.       }
  1487.     }
  1488.   }
  1489.   else if ((res1 = decode_r(&ArgStr[2], &HReg)) != e_decode_reg_unknown)
  1490.   {
  1491.     if (res1 == e_decode_reg_ok)
  1492.     {
  1493.       AdrInt = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
  1494.       if (OK)
  1495.       {
  1496.         CodeLen = 4;
  1497.         BAsmCode[0] = 0x70;
  1498.         BAsmCode[1] = 0x78 + HReg;
  1499.         BAsmCode[2] = Lo(AdrInt);
  1500.         BAsmCode[3] = Hi(AdrInt);
  1501.       }
  1502.     }
  1503.   }
  1504.  
  1505.   /* Cannot say in this case if src or dest is invalid register: */
  1506.  
  1507.   else
  1508.     WrError(ErrNum_InvReg);
  1509. }
  1510.  
  1511. /*!------------------------------------------------------------------------
  1512.  * \fn     DecodeMVI(Word Code)
  1513.  * \brief  handle MVI instruction
  1514.  * ------------------------------------------------------------------------ */
  1515.  
  1516. static void DecodeMVI(Word Code)
  1517. {
  1518.   UNUSED(Code);
  1519.  
  1520.   if (ChkArgCnt(2, 2))
  1521.   {
  1522.     Byte HReg;
  1523.     Boolean OK;
  1524.  
  1525.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  1526.     if (OK)
  1527.     {
  1528.       decode_reg_res_t res;
  1529.  
  1530.       if ((res = decode_r(&ArgStr[1], &HReg)) != e_decode_reg_unknown)
  1531.       {
  1532.         if (res == e_decode_reg_ok)
  1533.         {
  1534.           CodeLen = 2;
  1535.           BAsmCode[0] = 0x68 + HReg;
  1536.         }
  1537.       }
  1538.       else if ((res = decode_sr2(&ArgStr[1], &HReg)) != e_decode_reg_unknown)
  1539.       {
  1540.         if (res == e_decode_reg_ok)
  1541.         {
  1542.           if (!is_7807_781x) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1543.           else
  1544.           {
  1545.             CodeLen = 3;
  1546.             BAsmCode[2] = BAsmCode[1];
  1547.             BAsmCode[0] = 0x64;
  1548.             BAsmCode[1] = (HReg & 7) + ((HReg & 8) << 4);
  1549.           }
  1550.         }
  1551.       }
  1552.       else WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  1553.     }
  1554.   }
  1555. }
  1556.  
  1557. /*!------------------------------------------------------------------------
  1558.  * \fn     DecodeMVIW(Word Code)
  1559.  * \brief  handle MVIW instruction
  1560.  * ------------------------------------------------------------------------ */
  1561.  
  1562. static void DecodeMVIW(Word Code)
  1563. {
  1564.   Boolean OK;
  1565.  
  1566.   UNUSED(Code);
  1567.  
  1568.   if (!ChkArgCnt(2, 2) || !check_core_and_error(core_mask_no_low));
  1569.   else if (Decode_wa(&ArgStr[1], BAsmCode + 1, 0xff))
  1570.   {
  1571.     BAsmCode[2] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  1572.     if (OK)
  1573.     {
  1574.       CodeLen = 3;
  1575.       BAsmCode[0] = 0x71;
  1576.     }
  1577.   }
  1578. }
  1579.  
  1580. /*!------------------------------------------------------------------------
  1581.  * \fn     DecodeMVIX(Word Code)
  1582.  * \brief  handle MVIX instruction
  1583.  * ------------------------------------------------------------------------ */
  1584.  
  1585. static void DecodeMVIX(Word Code)
  1586. {
  1587.   Boolean OK;
  1588.   Byte HReg;
  1589.  
  1590.   UNUSED(Code);
  1591.  
  1592.   if (!ChkArgCnt(2, 2) || !check_core_and_error(core_mask_no_low));
  1593.   else if (Decode_rpa1(&ArgStr[1], &HReg))
  1594.   {
  1595.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  1596.     if (OK)
  1597.     {
  1598.       BAsmCode[0] = 0x48 + HReg;
  1599.       CodeLen = 2;
  1600.     }
  1601.   }
  1602. }
  1603.  
  1604. /*!------------------------------------------------------------------------
  1605.  * \fn     DecodeLDAX_STAX(Word Code)
  1606.  * \brief  handle LDAX/STAX instructions
  1607.  * \param  Code machine code
  1608.  * ------------------------------------------------------------------------ */
  1609.  
  1610. static void DecodeLDAX_STAX(Word Code)
  1611. {
  1612.   Byte HReg;
  1613.  
  1614.   if (ChkArgCnt(1, 1))
  1615.   {
  1616.     Boolean ok = is_7807_781x
  1617.                ? Decode_rpa2(&ArgStr[1], &HReg, &BAsmCode[1])
  1618.                : Decode_rpa(&ArgStr[1], &HReg);
  1619.  
  1620.     if (ok)
  1621.     {
  1622.       CodeLen = 1 + Ord(HasDisp(HReg));
  1623.       BAsmCode[0] = Code + ((HReg & 8) << 4) + (HReg & 7);
  1624.     }
  1625.   }
  1626. }
  1627.  
  1628. /*!------------------------------------------------------------------------
  1629.  * \fn     DecodeLDEAX_STEAX(Word Code)
  1630.  * \brief  handle LDEAX/STEAX instructions
  1631.  * \param  Code machine code
  1632.  * ------------------------------------------------------------------------ */
  1633.  
  1634. static void DecodeLDEAX_STEAX(Word Code)
  1635. {
  1636.   Byte HReg;
  1637.  
  1638.   if (ChkArgCnt(1, 1)
  1639.    && check_core_and_error(core_mask_7807_7810)
  1640.    && Decode_rpa3(&ArgStr[1], &HReg, &BAsmCode[2]))
  1641.   {
  1642.     CodeLen = 2 + Ord(HasDisp(HReg));
  1643.     BAsmCode[0] = 0x48;
  1644.     BAsmCode[1] = Code + HReg;
  1645.   }
  1646. }
  1647.  
  1648. /*!------------------------------------------------------------------------
  1649.  * \fn     DecodeLXI(Word Code)
  1650.  * \brief  Handle LXI instruction
  1651.  * \param  Code machine code
  1652.  * ------------------------------------------------------------------------ */
  1653.  
  1654. static void DecodeLXI(Word Code)
  1655. {
  1656.   Byte HReg;
  1657.   Integer AdrInt;
  1658.   Boolean OK;
  1659.  
  1660.   UNUSED(Code);
  1661.  
  1662.   if (!ChkArgCnt(2, 2))
  1663.     return;
  1664.   OK = (pCurrCPUProps->Core >= eCore7807)
  1665.      ? Decode_rp2(ArgStr[1].str.p_str, &HReg)
  1666.      : Decode_rp(ArgStr[1].str.p_str, &HReg);
  1667.   if (!OK) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1668.   else
  1669.   {
  1670.     AdrInt = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
  1671.     if (OK)
  1672.     {
  1673.       CodeLen = 3;
  1674.       BAsmCode[0] = 0x04 + (HReg << 4);
  1675.       BAsmCode[1] = Lo(AdrInt);
  1676.       BAsmCode[2] = Hi(AdrInt);
  1677.     }
  1678.   }
  1679. }
  1680.  
  1681. /*!------------------------------------------------------------------------
  1682.  * \fn     DecodePUSH_POP(Word Code)
  1683.  * \brief  Handle PUSH/POP instruction
  1684.  * \param  Code machine code
  1685.  * ------------------------------------------------------------------------ */
  1686.  
  1687. static void DecodePUSH_POP(Word Code)
  1688. {
  1689.   Byte HReg;
  1690.  
  1691.   if (!ChkArgCnt(1, 1));
  1692.   else if (!Decode_rp1(ArgStr[1].str.p_str, &HReg)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1693.   else
  1694.     PutCode(Code | (HReg << (Hi(Code) ? 4 : 0)));
  1695. }
  1696.  
  1697. /*!------------------------------------------------------------------------
  1698.  * \fn     DecodeDMOV(Word Code)
  1699.  * \brief  Handle DMOV instruction
  1700.  * ------------------------------------------------------------------------ */
  1701.  
  1702. static void DecodeDMOV(Word Code)
  1703. {
  1704.   Byte HReg, SReg;
  1705.  
  1706.   UNUSED(Code);
  1707.  
  1708.   if (ChkArgCnt(2, 2) && check_core_and_error(core_mask_7807_7810))
  1709.   {
  1710.     Boolean Swap = as_strcasecmp(ArgStr[1].str.p_str, "EA") || False;
  1711.     const tStrComp *pArg1 = Swap ? &ArgStr[2] : &ArgStr[1],
  1712.                    *pArg2 = Swap ? &ArgStr[1] : &ArgStr[2];
  1713.  
  1714.     if (as_strcasecmp(pArg1->str.p_str, "EA")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  1715.     else if (Decode_rp3(pArg2->str.p_str, &HReg))
  1716.     {
  1717.       CodeLen = 1;
  1718.       BAsmCode[0] = 0xa4 + HReg;
  1719.       if (Swap)
  1720.         BAsmCode[0] += 0x10;
  1721.     }
  1722.     else switch (decode_sr_flag(pArg2, s_regs16, &SReg, Swap ? eFlagSR3 : eFlagSR4))
  1723.     {
  1724.       case e_decode_reg_ok:
  1725.         CodeLen = 2;
  1726.         BAsmCode[0] = 0x48;
  1727.         BAsmCode[1] = 0xc0 + SReg;
  1728.         if (Swap)
  1729.           BAsmCode[1] += 0x12;
  1730.         break;
  1731.       case e_decode_reg_error:
  1732.         WrStrErrorPos(ErrNum_InvCtrlReg, pArg2);
  1733.         break;
  1734.       default:
  1735.         WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
  1736.     }
  1737.   }
  1738. }
  1739.  
  1740. /*!------------------------------------------------------------------------
  1741.  * \fn     decode_alu_z80(Word code)
  1742.  * \brief  handle ALU instruction, Z80-style
  1743.  * \param  code machine code & flags
  1744.  * ------------------------------------------------------------------------ */
  1745.  
  1746. static void decode_alu_z80(Word code)
  1747. {
  1748.   if (ChkArgCnt(2, 2)
  1749.    && ChkZ80Syntax(eSyntaxZ80))
  1750.   {
  1751.     const Byte flags = Hi(code);
  1752.     z80_adr_vals_t src_adr_vals, dest_adr_vals;
  1753.     code = Lo(code);
  1754.  
  1755.     switch (decode_z80_adr(&ArgStr[1], &dest_adr_vals,
  1756.                            MModReg8 | MModReg16 | MModSReg8
  1757.                          | ((code & 1) ? MModWA : 0)))
  1758.     {
  1759.       case e_mod_reg8:
  1760.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals,
  1761.                                MModReg8
  1762.                              | MModImm
  1763.                              | ((dest_adr_vals.val == REG_A) ? MModIndir : 0)
  1764.                              | (((dest_adr_vals.val == REG_A) && (pCurrCPUProps->Core >= eCore7800High)) ? MModWA : 0)))
  1765.         {
  1766.           case e_mod_reg8:
  1767.             if ((dest_adr_vals.val == REG_A) && !dest_adr_vals.force_long && (src_adr_vals.val < 8) && (flags & ALUReg_Src))
  1768.             {
  1769.               BAsmCode[CodeLen++] = 0x60;
  1770.               BAsmCode[CodeLen++] = 0x80 | (code << 3) | src_adr_vals.val;
  1771.             }
  1772.             else if ((src_adr_vals.val == REG_A) && !src_adr_vals.force_long && (dest_adr_vals.val  < 8) && (flags & ALUReg_Dest))
  1773.             {
  1774.               BAsmCode[CodeLen++] = 0x60;
  1775.               BAsmCode[CodeLen++] = (code << 3) | dest_adr_vals.val;
  1776.               /* ONA/OFFA only exist as A,r, but since binary AND is commutative, we can just swap operands: */
  1777.               if ((code == 9) || (code == 11))
  1778.                 BAsmCode[CodeLen - 1] |= 0x80;
  1779.             }
  1780.             else
  1781.               WrError(ErrNum_InvAddrMode);
  1782.             break;
  1783.           case e_mod_imm:
  1784.             if ((dest_adr_vals.val == REG_A) && !dest_adr_vals.force_long)
  1785.               BAsmCode[CodeLen++] = 0x06 | ((code & 14) << 3) | (code & 1);
  1786.             else if (pCurrCPUProps->Core < eCore7800High) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1787.             else
  1788.             {
  1789.               BAsmCode[CodeLen++] = 0x74;
  1790.               BAsmCode[CodeLen++] = (code << 3) | dest_adr_vals.val;
  1791.             }
  1792.             if (CodeLen > 0)
  1793.               BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  1794.             break;
  1795.           case e_mod_indir:
  1796.             if (!is_rpa(src_adr_vals.val)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1797.             else
  1798.             {
  1799.               BAsmCode[CodeLen++] = 0x70;
  1800.               BAsmCode[CodeLen++] = 0x80 | (code << 3) | src_adr_vals.val;
  1801.             }
  1802.             break;
  1803.           case e_mod_wa:
  1804.             BAsmCode[CodeLen++] = 0x74;
  1805.             BAsmCode[CodeLen++] = 0x80 | (code << 3);
  1806.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  1807.             break;
  1808.           default:
  1809.             break;
  1810.         }
  1811.         break;
  1812.       case e_mod_reg16:
  1813.       {
  1814.         unsigned mask = MModReg16;
  1815.  
  1816.         if (dest_adr_vals.val != REG_EA)
  1817.         {
  1818.           WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1819.           return;
  1820.         }
  1821.         if ((code == 8) || (code == 12))
  1822.         {
  1823.           mask |= MModReg8;
  1824.           z80_op_size = eSymbolSizeUnknown;
  1825.         }
  1826.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, mask))
  1827.         {
  1828.           case e_mod_reg8:
  1829.             if ((src_adr_vals.val < REG_A) || (src_adr_vals.val > REG_C)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1830.             else
  1831.             {
  1832.               BAsmCode[CodeLen++] = 0x70;
  1833.               BAsmCode[CodeLen++] = (code << 3) | src_adr_vals.val;
  1834.             }
  1835.             break;
  1836.           case e_mod_reg16:
  1837.             if ((src_adr_vals.val < REG_BC) || (src_adr_vals.val > REG_HL)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  1838.             else
  1839.             {
  1840.               BAsmCode[CodeLen++] = 0x74;
  1841.               BAsmCode[CodeLen++] = 0x84 | (code << 3) | src_adr_vals.val;
  1842.             }
  1843.             break;
  1844.           default:
  1845.             break;
  1846.         }
  1847.         break;
  1848.       }
  1849.       case e_mod_sreg8:
  1850.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, (flags & ALUImm_SR) ? MModImm : 0))
  1851.         {
  1852.           case e_mod_imm:
  1853.             if (check_sr_flag(dest_adr_vals.vals[0], eFlagSR2, &ArgStr[1]))
  1854.             {
  1855.               BAsmCode[CodeLen++] = 0x64;
  1856.               BAsmCode[CodeLen++] = (code << 3)
  1857.                                   | ((pCurrCPUProps->Core < eCore7800High) ? 0x80 : 0x00)
  1858.                                   | (dest_adr_vals.val & 7)
  1859.                                   | ((dest_adr_vals.val & 8) << 4);
  1860.               BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  1861.             }
  1862.             break;
  1863.           default:
  1864.             break;
  1865.         }
  1866.         break;
  1867.       case e_mod_wa:
  1868.         z80_def_op_size = eSymbolSize8Bit;
  1869.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, MModImm))
  1870.         {
  1871.           case e_mod_imm:
  1872.             BAsmCode[CodeLen++] = ((code & 0x0e) << 3) | 0x05;
  1873.             BAsmCode[CodeLen++] = dest_adr_vals.vals[0];
  1874.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  1875.             break;
  1876.           default:
  1877.             break;
  1878.         }
  1879.         break;
  1880.       default:
  1881.         break;
  1882.     }
  1883.   }
  1884. }
  1885.  
  1886. /*!------------------------------------------------------------------------
  1887.  * \fn     DecodeALUImm(Word Code)
  1888.  * \brief  handle 8 Bit ALU instructions with immediate source
  1889.  * \param  Code machine code
  1890.  * ------------------------------------------------------------------------ */
  1891.  
  1892. static void DecodeALUImm(Word Code)
  1893. {
  1894.   ShortInt HVal8;
  1895.   Byte HReg;
  1896.   Boolean OK;
  1897.   Byte Flags;
  1898.  
  1899.   Flags = Hi(Code);
  1900.   Code = Lo(Code);
  1901.  
  1902.   if (ChkArgCnt(2, 2))
  1903.   {
  1904.     HVal8 = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  1905.     if (OK)
  1906.     {
  1907.       tStrComp Arg1;
  1908.       decode_reg_res_t res;
  1909.  
  1910.       /* allow >A to enforce long addressing */
  1911.  
  1912.       StrCompRefRight(&Arg1, &ArgStr[1], as_strcasecmp(ArgStr[1].str.p_str, ">A") ? 0 : 1);
  1913.       if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
  1914.       {
  1915.         CodeLen = 2;
  1916.         BAsmCode[0] = 0x06 + ((Code & 14) << 3) + (Code & 1);
  1917.         BAsmCode[1] = HVal8;
  1918.       }
  1919.       else if ((res = decode_r(&Arg1, &HReg)) != e_decode_reg_unknown)
  1920.       {
  1921.         if (res != e_decode_reg_ok);
  1922.         else if (pCurrCPUProps->Core == eCore7800Low) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1923.         else
  1924.         {
  1925.           CodeLen = 3;
  1926.           BAsmCode[0] = is_7807_781x ? 0x74 : 0x64;
  1927.           BAsmCode[2] = HVal8;
  1928.           BAsmCode[1] = HReg + (Code << 3);
  1929.         }
  1930.       }
  1931.       else if ((res = decode_sr2(&ArgStr[1], &HReg)) != e_decode_reg_unknown)
  1932.       {
  1933.         if (res != e_decode_reg_ok);
  1934.         else if (!(Flags & ALUImm_SR)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1935.         else
  1936.         {
  1937.           CodeLen = 3;
  1938.           BAsmCode[0] = 0x64;
  1939.           BAsmCode[1] = (HReg & 7) | (Code << 3)
  1940.                       | (is_7807_781x ? ((HReg & 8) << 4) : 0x80);
  1941.           BAsmCode[2] = HVal8;
  1942.         }
  1943.       }
  1944.       else WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  1945.     }
  1946.   }
  1947. }
  1948.  
  1949. /*!------------------------------------------------------------------------
  1950.  * \fn     DecodeALUReg(Word Code)
  1951.  * \brief  Handle ALU instructions with A and register as argument
  1952.  * \param  Code machine code
  1953.  * ------------------------------------------------------------------------ */
  1954.  
  1955. static void DecodeALUReg(Word Code)
  1956. {
  1957.   Byte HReg;
  1958.   Byte Flags;
  1959.  
  1960.   Flags = Hi(Code);
  1961.   if ((CurrZ80Syntax & eSyntaxZ80) && (Flags & ALUReg_MayZ80))
  1962.   {
  1963.     decode_alu_z80(Code);
  1964.     return;
  1965.   }
  1966.   Code = Lo(Code);
  1967.  
  1968.   if (ChkArgCnt(2, 2))
  1969.   {
  1970.     Boolean NoSwap = !as_strcasecmp(ArgStr[1].str.p_str, "A");
  1971.     tStrComp *pArg1 = NoSwap ? &ArgStr[1] : &ArgStr[2],
  1972.              *pArg2 = NoSwap ? &ArgStr[2] : &ArgStr[1],
  1973.              Arg2;
  1974.     decode_reg_res_t res;
  1975.  
  1976.     /* allow >A to enforce <op> r,A instrad of <op> A,r */
  1977.  
  1978.     StrCompRefRight(&Arg2, pArg2, as_strcasecmp(pArg2->str.p_str, ">A") ? 0 : 1);
  1979.  
  1980.     if (as_strcasecmp(pArg1->str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  1981.     else if ((res = decode_r(&Arg2, &HReg)) == e_decode_reg_unknown) WrStrErrorPos(ErrNum_InvReg, &Arg2);
  1982.     else if (res == e_decode_reg_ok)
  1983.     {
  1984.       if (NoSwap && !(Flags & ALUReg_Src)) WrStrErrorPos(ErrNum_InvAddrMode, &Arg2);
  1985.       else if (!NoSwap && !(Flags & ALUReg_Dest)) WrStrErrorPos(ErrNum_InvAddrMode, &Arg2);
  1986.       else
  1987.       {
  1988.         CodeLen = 2;
  1989.         BAsmCode[0] = 0x60;
  1990.         BAsmCode[1] = (Code << 3) + HReg;
  1991.         if ((NoSwap) || (Memo("ONA")) || (Memo("OFFA")))
  1992.           BAsmCode[1] += 0x80;
  1993.       }
  1994.     }
  1995.   }
  1996. }
  1997.  
  1998. static void DecodeALURegW(Word Code)
  1999. {
  2000.   if (ChkArgCnt(1, 1)
  2001.    && check_core_and_error(core_mask_no_low)
  2002.    && Decode_wa(&ArgStr[1], BAsmCode + 2, 0xff))
  2003.   {
  2004.     CodeLen = 3;
  2005.     BAsmCode[0] = 0x74;
  2006.     BAsmCode[1] = 0x80 + (Code << 3);
  2007.   }
  2008. }
  2009.  
  2010. static void DecodeALURegX(Word Code)
  2011. {
  2012.   Byte HReg;
  2013.  
  2014.   if (!ChkArgCnt(1, 1));
  2015.   else if (Decode_rpa(&ArgStr[1], &HReg))
  2016.   {
  2017.     CodeLen = 2;
  2018.     BAsmCode[0] = 0x70;
  2019.     BAsmCode[1] = 0x80 + (Code << 3) + HReg;
  2020.   }
  2021. }
  2022.  
  2023. static void DecodeALUEA(Word Code)
  2024. {
  2025.   Byte HReg;
  2026.  
  2027.   if (!ChkArgCnt(2, 2));
  2028.   else if (!check_core_and_error(core_mask_7807_7810));
  2029.   else if (as_strcasecmp(ArgStr[1].str.p_str, "EA")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2030.   else if (!Decode_rp3(ArgStr[2].str.p_str, &HReg)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2031.   else
  2032.   {
  2033.     CodeLen = 2;
  2034.     BAsmCode[0] = 0x74;
  2035.     BAsmCode[1] = 0x84 + (Code << 3) + HReg;
  2036.   }
  2037. }
  2038.  
  2039. static void DecodeALUImmW(Word Code)
  2040. {
  2041.   Boolean OK;
  2042.  
  2043.   if (!ChkArgCnt(2, 2));
  2044.   else if (Decode_wa(&ArgStr[1], BAsmCode + 1, 0xff))
  2045.   {
  2046.     BAsmCode[2] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  2047.     if (OK)
  2048.     {
  2049.       CodeLen = 3;
  2050.       BAsmCode[0] = 0x05 + ((Code >> 1) << 4);
  2051.     }
  2052.   }
  2053. }
  2054.  
  2055. /*!------------------------------------------------------------------------
  2056.  * \fn     DecodeAbs(Word Code)
  2057.  * \brief  Handle instructions with absolute address as argument
  2058.  * \param  Code machine code
  2059.  * ------------------------------------------------------------------------ */
  2060.  
  2061. static void DecodeAbs(Word Code)
  2062. {
  2063.   if (!ChkArgCnt(1, 1));
  2064.   else
  2065.   {
  2066.     Boolean OK;
  2067.     Integer AdrInt;
  2068.  
  2069.     AdrInt = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
  2070.     if (OK)
  2071.     {
  2072.       PutCode(Code);
  2073.       BAsmCode[CodeLen++] = Lo(AdrInt);
  2074.       BAsmCode[CodeLen++] = Hi(AdrInt);
  2075.     }
  2076.   }
  2077. }
  2078.  
  2079. /*!------------------------------------------------------------------------
  2080.  * \fn     DecodeReg2(Word index)
  2081.  * \brief  Handle instructions with r2 as argument
  2082.  * \param  index index into instruction table
  2083.  * ------------------------------------------------------------------------ */
  2084.  
  2085. static void DecodeReg2(Word index)
  2086. {
  2087.   const order_t *p_order = &reg2_orders[index];
  2088.   Byte HReg;
  2089.   decode_reg_res_t res;
  2090.  
  2091.   if (!ChkArgCnt(1, 1) || !check_core_and_error(p_order->core_mask));
  2092.   else if ((res = decode_r2(&ArgStr[1], &HReg)) == e_decode_reg_unknown) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2093.   else if (res == e_decode_reg_ok)
  2094.     PutCode(p_order->code + HReg);
  2095. }
  2096.  
  2097. /*!------------------------------------------------------------------------
  2098.  * \fn     DecodeWA(Word Code)
  2099.  * \brief  Handle instructions with work area address as argument
  2100.  * \param  Code machine code
  2101.  * ------------------------------------------------------------------------ */
  2102.  
  2103. static void DecodeWork(Word Code)
  2104. {
  2105.   if (ChkArgCnt(1, 1)
  2106.    && Decode_wa(&ArgStr[1], BAsmCode + 1, 0xff))
  2107.   {
  2108.     CodeLen = 2;
  2109.     BAsmCode[0] = Code;
  2110.   }
  2111. }
  2112.  
  2113. /*!------------------------------------------------------------------------
  2114.  * \fn     DecodeA(Word Code)
  2115.  * \brief  Handle instructions with A as argument
  2116.  * \param  Code machine code
  2117.  * ------------------------------------------------------------------------ */
  2118.  
  2119. static void DecodeA(Word Code)
  2120. {
  2121.   if (!ChkArgCnt(1, 1));
  2122.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2123.   else
  2124.     PutCode(Code);
  2125. }
  2126.  
  2127. /*!------------------------------------------------------------------------
  2128.  * \fn     DecodeEA(Word Code)
  2129.  * \brief  Handle instructions with EA as argument
  2130.  * \param  Code machine code
  2131.  * ------------------------------------------------------------------------ */
  2132.  
  2133. static void DecodeEA(Word Code)
  2134. {
  2135.   if (!ChkArgCnt(1, 1) || !check_core_and_error(core_mask_7807_7810));
  2136.   else if (as_strcasecmp(ArgStr[1].str.p_str, "EA")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2137.   else
  2138.   {
  2139.     CodeLen = 2;
  2140.     BAsmCode[0] = Hi(Code);
  2141.     BAsmCode[1] = Lo(Code);
  2142.   }
  2143. }
  2144.  
  2145. /*!------------------------------------------------------------------------
  2146.  * \fn     DecodeDCX_INX(Word Code)
  2147.  * \brief  Handle INX/DCX Instructions
  2148.  * \param  Code machine code
  2149.  * ------------------------------------------------------------------------ */
  2150.  
  2151. static void DecodeDCX_INX(Word Code)
  2152. {
  2153.   Byte HReg;
  2154.  
  2155.   if (!ChkArgCnt(1, 1));
  2156.   else if (check_core(core_mask_7807_7810) && !as_strcasecmp(ArgStr[1].str.p_str, "EA"))
  2157.   {
  2158.     CodeLen = 1;
  2159.     BAsmCode[0] = 0xa8 + Code;
  2160.   }
  2161.   else if (Decode_rp(ArgStr[1].str.p_str, &HReg))
  2162.   {
  2163.     CodeLen = 1;
  2164.     BAsmCode[0] = 0x02 + Code + (HReg << 4);
  2165.   }
  2166.   else
  2167.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2168. }
  2169.  
  2170. /*!------------------------------------------------------------------------
  2171.  * \fn     decode_inc_dec(word code)
  2172.  * \brief  Handle Z80-style INC/DEC instructions
  2173.  * \param  code machine code
  2174.  * ------------------------------------------------------------------------ */
  2175.  
  2176. static void decode_inc_dec(Word code)
  2177. {
  2178.   if (ChkArgCnt(1, 1)
  2179.    && ChkZ80Syntax(eSyntaxZ80))
  2180.   {
  2181.     z80_adr_vals_t adr_vals;
  2182.  
  2183.     switch (decode_z80_adr(&ArgStr[1], &adr_vals, MModReg8 | MModReg16 | MModWA))
  2184.     {
  2185.       case e_mod_reg8:
  2186.         if ((adr_vals.val < REG_A) || (adr_vals.val > REG_C)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2187.         else
  2188.           BAsmCode[CodeLen++] = 0x40 | (code << 4) | adr_vals.val;
  2189.         break;
  2190.       case e_mod_reg16:
  2191.         BAsmCode[CodeLen++] = (adr_vals.val == REG_EA)
  2192.                             ? 0xa8 | code
  2193.                             : 0x02 | code | (adr_vals.val << 4);
  2194.         break;
  2195.       case e_mod_wa:
  2196.         BAsmCode[CodeLen++] = 0x20 | (code << 4);
  2197.         BAsmCode[CodeLen++] = adr_vals.vals[0];
  2198.         break;
  2199.       default:
  2200.         break;
  2201.     }
  2202.   }
  2203. }
  2204.  
  2205. static void DecodeEADD_ESUB(Word Code)
  2206. {
  2207.   Byte HReg;
  2208.   decode_reg_res_t res;
  2209.  
  2210.   if (!ChkArgCnt(2, 2) || !check_core_and_error(core_mask_7807_7810));
  2211.   else if (as_strcasecmp(ArgStr[1].str.p_str, "EA")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2212.   else if ((res = decode_r2(&ArgStr[2], &HReg)) == e_decode_reg_unknown) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2213.   else if (res == e_decode_reg_ok)
  2214.   {
  2215.     CodeLen = 2;
  2216.     BAsmCode[0] = 0x70;
  2217.     BAsmCode[1] = Code + HReg;
  2218.   }
  2219. }
  2220.  
  2221. static void DecodeJ_JR_JRE(Word Type)
  2222. {
  2223.   Boolean OK;
  2224.   Integer AdrInt;
  2225.   tSymbolFlags Flags;
  2226.  
  2227.   if (!ChkArgCnt(1, 1))
  2228.     return;
  2229.  
  2230.   AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags) - (EProgCounter() + 1);
  2231.   if (!OK)
  2232.     return;
  2233.  
  2234.   if (!Type) /* generic J */
  2235.     Type = RangeCheck(AdrInt, SInt6) ? 1 : 2;
  2236.  
  2237.   switch (Type)
  2238.   {
  2239.     case 1: /* JR */
  2240.       if (!mSymbolQuestionable(Flags) && !RangeCheck(AdrInt, SInt6)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
  2241.       else
  2242.       {
  2243.         CodeLen = 1;
  2244.         BAsmCode[0] = 0xc0 + (AdrInt & 0x3f);
  2245.       }
  2246.       break;
  2247.     case 2:
  2248.       AdrInt--; /* JRE is 2 bytes long */
  2249.       if (!mSymbolQuestionable(Flags) && !RangeCheck(AdrInt, SInt9)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
  2250.       else
  2251.       {
  2252.         CodeLen = 2;
  2253.         BAsmCode[0] = 0x4e + (Hi(AdrInt) & 1);
  2254.         BAsmCode[1] = Lo(AdrInt);
  2255.       }
  2256.       break;
  2257.   }
  2258. }
  2259.  
  2260. static void DecodeCALF(Word Code)
  2261. {
  2262.   UNUSED(Code);
  2263.  
  2264.   if (ChkArgCnt(1, 1))
  2265.   {
  2266.     Boolean OK;
  2267.     Integer AdrInt;
  2268.     tSymbolFlags Flags;
  2269.  
  2270.     AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags);
  2271.     if (OK)
  2272.     {
  2273.       if (!mFirstPassUnknown(Flags) && ((AdrInt >> 11) != 1)) WrStrErrorPos(ErrNum_NotFromThisAddress, &ArgStr[1]);
  2274.       else
  2275.       {
  2276.         CodeLen = 2;
  2277.         BAsmCode[0] = Hi(AdrInt) + 0x70;
  2278.         BAsmCode[1] = Lo(AdrInt);
  2279.       }
  2280.     }
  2281.   }
  2282. }
  2283.  
  2284. static void DecodeCALT(Word Code)
  2285. {
  2286.   UNUSED(Code);
  2287.  
  2288.   if (ChkArgCnt(1, 1))
  2289.   {
  2290.     Boolean OK;
  2291.     Integer AdrInt;
  2292.     tSymbolFlags Flags;
  2293.  
  2294.     AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags);
  2295.     if (OK)
  2296.     {
  2297.       Word AdrMask = is_7807_781x ? 0xffc1 : 0xff81;
  2298.  
  2299.       if (!mFirstPassUnknown(Flags) && ((AdrInt & AdrMask) != 0x80)) WrStrErrorPos(ErrNum_NotFromThisAddress, &ArgStr[1]);
  2300.       else
  2301.       {
  2302.         CodeLen = 1;
  2303.         BAsmCode[0] = 0x80 + ((AdrInt & ~AdrMask) >> 1);
  2304.       }
  2305.     }
  2306.   }
  2307. }
  2308.  
  2309. static void DecodeBIT(Word Code)
  2310. {
  2311.   UNUSED(Code);
  2312.  
  2313.   if (ChkArgCnt(2, 2) && check_core_and_error(core_mask_no_low))
  2314.   {
  2315.     Boolean OK;
  2316.     ShortInt HReg;
  2317.  
  2318.     HReg = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
  2319.     if (OK)
  2320.      if (Decode_wa(&ArgStr[2], BAsmCode + 1, 0xff))
  2321.      {
  2322.        CodeLen = 2; BAsmCode[0] = 0x58 + HReg;
  2323.      }
  2324.   }
  2325. }
  2326.  
  2327. static void DecodeSK_SKN(Word Code)
  2328. {
  2329.   Byte HReg;
  2330.  
  2331.   if (!ChkArgCnt(1, 1) || !check_core_and_error(Hi(Code)));
  2332.   else if (Decode_f(ArgStr[1].str.p_str, &HReg))
  2333.   {
  2334.     CodeLen = 2;
  2335.     BAsmCode[0] = 0x48;
  2336.     BAsmCode[1] = Lo(Code) + HReg;
  2337.   }
  2338.   else if (pCurrCPUProps->Core == eCore7807)
  2339.     decode_bit_7807_core(1, (Code & 0x10) ? 0x50 :0x5d);
  2340.   else
  2341.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2342. }
  2343.  
  2344. static void DecodeSKIT_SKNIT(Word Code)
  2345. {
  2346.   ShortInt HReg;
  2347.  
  2348.   if (ChkArgCnt(1, 1)
  2349.    && check_core_and_error(Hi(Code))
  2350.    && Decode_irf(&ArgStr[1], &HReg))
  2351.   {
  2352.     CodeLen = 2;
  2353.     BAsmCode[0] = 0x48;
  2354.     BAsmCode[1] = Lo(Code) + HReg;
  2355.   }
  2356. }
  2357.  
  2358. static void DecodeIN_OUT(Word Code)
  2359. {
  2360.   const tStrComp *p_port_arg;
  2361.  
  2362.   switch (ArgCnt)
  2363.   {
  2364.     case 2:
  2365.     {
  2366.       const tStrComp *p_acc_arg = &ArgStr[(Code & 1) + 1];
  2367.  
  2368.       if (as_strcasecmp(p_acc_arg->str.p_str, "A"))
  2369.       {
  2370.         WrStrErrorPos(ErrNum_InvAddrMode, p_acc_arg);
  2371.         return;
  2372.       }
  2373.       p_port_arg = &ArgStr[2 - (Code & 1)];
  2374.       goto common;
  2375.     }
  2376.     case 1:
  2377.       p_port_arg = &ArgStr[1];
  2378.       /* fall-thru */
  2379.     common:
  2380.     {
  2381.       Boolean OK;
  2382.  
  2383.       BAsmCode[1] = EvalStrIntExpression(p_port_arg, UInt8, &OK);
  2384.       if (OK)
  2385.       {
  2386.         BAsmCode[0] = Code;
  2387.         CodeLen = 2;
  2388.       }
  2389.       break;
  2390.     }
  2391.     default:
  2392.       (void)ChkArgCnt(1, 2);
  2393.   }
  2394. }
  2395.  
  2396. /*!------------------------------------------------------------------------
  2397.  * \fn     DecodeBLOCK_7807(Word code)
  2398.  * \brief  Handle 7807-style BLOCK instruction
  2399.  * \param  code machine code
  2400.  * ------------------------------------------------------------------------ */
  2401.  
  2402. static void DecodeBLOCK_7807(Word code)
  2403. {
  2404.   if (ChkArgCnt(1, 1))
  2405.   {
  2406.     Byte mode;
  2407.  
  2408.     if (Decode_rpa(&ArgStr[1], &mode))
  2409.     {
  2410.       if ((mode != 4) && (mode != 6)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2411.       else
  2412.       {
  2413.         BAsmCode[0] = code | ((mode >> 1) & 1);
  2414.         CodeLen = 1;
  2415.       }
  2416.     }
  2417.   }
  2418. }
  2419.  
  2420. /*!------------------------------------------------------------------------
  2421.  * \fn     DecodeBit1_7807(Word code)
  2422.  * \brief  handle 7807-specific bit operations with one operand
  2423.  * \param  code machine code
  2424.  * ------------------------------------------------------------------------ */
  2425.  
  2426. static void DecodeBit1_7807(Word code)
  2427. {
  2428.   if (!ChkArgCnt(1, 1));
  2429.   else if (!check_core_and_error(core_mask_7807));
  2430.   else
  2431.     decode_bit_7807_core(1, code);
  2432. }
  2433.  
  2434. /*!------------------------------------------------------------------------
  2435.  * \fn     DecodeBit2_7807(Word code)
  2436.  * \brief  handle 7807-specific bit operations with two operands,
  2437.            and Z80-style logical instructions
  2438.  * \param  code machine code
  2439.  * ------------------------------------------------------------------------ */
  2440.  
  2441. static void DecodeBit2_7807(Word code)
  2442. {
  2443.   if (!ChkArgCnt(2, 2));
  2444.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "CY"))
  2445.   {
  2446.     if (check_core_and_error(core_mask_7807))
  2447.       decode_bit_7807_core(2, Lo(code));
  2448.   }
  2449.   else if (CurrZ80Syntax & eSyntaxZ80)
  2450.   {
  2451.     Word Flags = ALUReg_Src;
  2452.     if (pCurrCPUProps->Core != eCore7800Low)
  2453.       Flags |= ALUReg_Dest | ALUImm_SR;
  2454.     else if (Hi(code) != 2)
  2455.       Flags |= ALUImm_SR;
  2456.     decode_alu_z80((Flags << 8) | Hi(code));
  2457.   }
  2458.   else
  2459.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2460. }
  2461.  
  2462. /*!------------------------------------------------------------------------
  2463.  * \fn     DecodeDEFBIT(Word code)
  2464.  * \brief  handle DEFBIT instruction (7807...7809 only)
  2465.  * ------------------------------------------------------------------------ */
  2466.  
  2467. static void DecodeDEFBIT(Word code)
  2468. {
  2469.   LongWord BitSpec;
  2470.  
  2471.   UNUSED(code);
  2472.  
  2473.   /* if in structure definition, add special element to structure */
  2474.  
  2475.   if (ActPC == StructSeg)
  2476.   {
  2477.     Boolean OK;
  2478.     Byte BitPos;
  2479.     PStructElem pElement;
  2480.  
  2481.     if (!ChkArgCnt(2, 2))
  2482.       return;
  2483.     BitPos = eval_bit_position(&ArgStr[2], &OK);
  2484.     if (!OK)
  2485.       return;
  2486.     pElement = CreateStructElem(&LabPart);
  2487.     if (!pElement)
  2488.       return;
  2489.     pElement->pRefElemName = as_strdup(ArgStr[1].str.p_str);
  2490.     pElement->OpSize = eSymbolSize8Bit;
  2491.     pElement->BitPos = BitPos;
  2492.     pElement->ExpandFnc = expand_bit_7807;
  2493.     AddStructElem(pInnermostNamedStruct->StructRec, pElement);
  2494.   }
  2495.   else
  2496.   {
  2497.     if (decode_bit_arg(&BitSpec, 1, ArgCnt))
  2498.     {
  2499.       *ListLine = '=';
  2500.       dissect_bit_7807(ListLine + 1, STRINGSIZE - 3, BitSpec);
  2501.       PushLocHandle(-1);
  2502.       EnterIntSymbol(&LabPart, BitSpec, SegBData, False);
  2503.       PopLocHandle();
  2504.       /* TODO: MakeUseList? */
  2505.     }
  2506.   }
  2507. }
  2508.  
  2509. /*!------------------------------------------------------------------------
  2510.  * \fn     decode_ld(Word code)
  2511.  * \brief  handle LD (Z80 style) instruction
  2512.  * ------------------------------------------------------------------------ */
  2513.  
  2514. static void decode_ld(Word code)
  2515. {
  2516.   UNUSED(code);
  2517.  
  2518.   if (ChkArgCnt(2, 2)
  2519.    && ChkZ80Syntax(eSyntaxZ80))
  2520.   {
  2521.     z80_adr_vals_t dest_adr_vals, src_adr_vals;
  2522.  
  2523.     switch (decode_z80_adr(&ArgStr[1], &dest_adr_vals, MModReg8 | MModReg16 | MModAbs | MModWA | MModIndir | MModSReg8 | MModSReg16))
  2524.     {
  2525.       case e_mod_reg8:
  2526.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals,
  2527.                                MModReg8
  2528.                              | ((dest_adr_vals.val < 8) ? MModImm : 0)
  2529.                              | ((dest_adr_vals.val < 8) ? MModAbs : 0)
  2530.                              | ((dest_adr_vals.val == REG_A) ? MModWA : 0)
  2531.                              | ((dest_adr_vals.val == REG_A) ? MModIndir : 0)
  2532.                              | ((dest_adr_vals.val == REG_A) ? MModSReg8 : 0)))
  2533.         {
  2534.           case e_mod_imm:
  2535.             BAsmCode[CodeLen++] = 0x68 + dest_adr_vals.val;
  2536.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2537.             break;
  2538.           case e_mod_abs:
  2539.             BAsmCode[CodeLen++] = 0x70;
  2540.             BAsmCode[CodeLen++] = 0x68 + dest_adr_vals.val;
  2541.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2542.             BAsmCode[CodeLen++] = src_adr_vals.vals[1];
  2543.             break;
  2544.           case e_mod_wa:
  2545.             BAsmCode[CodeLen++] = (pCurrCPUProps->Core >= eCore7800High) ? 0x01 : 0x28;
  2546.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2547.             break;
  2548.           case e_mod_reg8:
  2549.             if ((src_adr_vals.val == REG_A) && (dest_adr_vals.val >= 2))
  2550.               BAsmCode[CodeLen++] = 0x18 | (dest_adr_vals.val & 7);
  2551.             else if ((dest_adr_vals.val == REG_A) && (src_adr_vals.val >= 2))
  2552.               BAsmCode[CodeLen++] = 0x08 | (src_adr_vals.val & 7);
  2553.             else
  2554.               WrError(ErrNum_InvAddrMode);
  2555.             break;
  2556.           case e_mod_indir:
  2557.             if ((pCurrCPUProps->Core <= eCore7800High) && !is_rpa(src_adr_vals.val)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2558.             else
  2559.             {
  2560.               BAsmCode[CodeLen++] = 0x28 | (src_adr_vals.val & 0x07) | ((src_adr_vals.val & 0x08) << 4);
  2561.               append_adr_vals(&src_adr_vals);
  2562.             }
  2563.             break;
  2564.           case e_mod_sreg8:
  2565.             if (check_sr_flag(src_adr_vals.vals[0], eFlagSR1, &ArgStr[2]))
  2566.             {
  2567.               BAsmCode[CodeLen++] = 0x4c;
  2568.               BAsmCode[CodeLen++] = 0xc0 | src_adr_vals.val;
  2569.             }
  2570.             break;
  2571.           default:
  2572.             break;
  2573.         }
  2574.         break;
  2575.       case e_mod_reg16:
  2576.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals,
  2577.                                MModImm
  2578.                              | MModReg16
  2579.                              | ((dest_adr_vals.val < REG_EA) ? MModAbs : 0)
  2580.                              | ((dest_adr_vals.val == REG_EA) ? MModIndir : 0)
  2581.                              | ((dest_adr_vals.val == REG_EA) ? MModSReg16 : 0)))
  2582.         {
  2583.           case e_mod_imm:
  2584.             BAsmCode[CodeLen++] = 0x04 | (dest_adr_vals.val << 4);
  2585.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2586.             BAsmCode[CodeLen++] = src_adr_vals.vals[1];
  2587.             break;
  2588.           case e_mod_reg16:
  2589.             if ((dest_adr_vals.val == REG_EA) && (src_adr_vals.val >= REG_BC) && (src_adr_vals.val <= REG_HL))
  2590.               BAsmCode[CodeLen++] = 0xa4 | src_adr_vals.val;
  2591.             else if ((src_adr_vals.val == REG_EA) && (dest_adr_vals.val >= REG_BC) && (dest_adr_vals.val <= REG_HL))
  2592.               BAsmCode[CodeLen++] = 0xb4 | dest_adr_vals.val;
  2593.             else
  2594.               WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2595.             break;
  2596.           case e_mod_abs:
  2597.             BAsmCode[CodeLen++] = 0x70;
  2598.             BAsmCode[CodeLen++] = 0x0f | (dest_adr_vals.val << 4);
  2599.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2600.             BAsmCode[CodeLen++] = src_adr_vals.vals[1];
  2601.             break;
  2602.           case e_mod_indir:
  2603.             if (!is_rpa3(src_adr_vals.val)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2604.             else
  2605.             {
  2606.               BAsmCode[CodeLen++] = 0x48;
  2607.               BAsmCode[CodeLen++] = 0x80 | src_adr_vals.val;
  2608.               append_adr_vals(&src_adr_vals);
  2609.             }
  2610.             break;
  2611.           case e_mod_sreg16:
  2612.             if (check_sr_flag(src_adr_vals.vals[0], eFlagSR4, &ArgStr[2]))
  2613.             {
  2614.               BAsmCode[CodeLen++] = 0x48;
  2615.               BAsmCode[CodeLen++] = 0xc0 | src_adr_vals.val;
  2616.             }
  2617.             break;
  2618.           default:
  2619.             break;
  2620.         }
  2621.         break;
  2622.       case e_mod_abs:
  2623.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, MModReg8 | MModReg16))
  2624.         {
  2625.           case e_mod_reg8:
  2626.             if (src_adr_vals.val > 7) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2627.             else
  2628.             {
  2629.               BAsmCode[CodeLen++] = 0x70;
  2630.               BAsmCode[CodeLen++] = 0x78 | src_adr_vals.val;
  2631.               append_adr_vals(&dest_adr_vals);
  2632.             }
  2633.             break;
  2634.           case e_mod_reg16:
  2635.             if (src_adr_vals.val >= REG_EA) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2636.             else
  2637.             {
  2638.               BAsmCode[CodeLen++] = 0x70;
  2639.               BAsmCode[CodeLen++] = 0x0e | (src_adr_vals.val << 4);
  2640.               append_adr_vals(&dest_adr_vals);
  2641.             }
  2642.             break;
  2643.           default:
  2644.             break;
  2645.         }
  2646.         break;
  2647.       case e_mod_wa:
  2648.         z80_def_op_size = eSymbolSize8Bit;
  2649.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, MModReg8 | MModReg16
  2650.                                | ((pCurrCPUProps->Core >= eCore7800High) ? MModImm : 0)
  2651.                               ))
  2652.         {
  2653.           case e_mod_reg8:
  2654.             if (src_adr_vals.val == REG_A)
  2655.             {
  2656.               BAsmCode[CodeLen++] = (pCurrCPUProps->Core >= eCore7800High) ? 0x63 : 0x38;
  2657.               BAsmCode[CodeLen++] = dest_adr_vals.vals[0];
  2658.             }
  2659.             else if (src_adr_vals.val <= 7) /* map to absolute addressing */
  2660.             {
  2661.               BAsmCode[CodeLen++] = 0x70;
  2662.               BAsmCode[CodeLen++] = 0x78 | src_adr_vals.val;
  2663.               BAsmCode[CodeLen++] = dest_adr_vals.vals[0];
  2664.               BAsmCode[CodeLen++] = WorkArea;
  2665.             }
  2666.             else
  2667.               WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2668.             break;
  2669.           case e_mod_reg16: /* map to absolute addressing */
  2670.             if (src_adr_vals.val >= REG_EA) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2671.             else
  2672.             {
  2673.               BAsmCode[CodeLen++] = 0x70;
  2674.               BAsmCode[CodeLen++] = 0x0e | (src_adr_vals.val << 4);
  2675.               BAsmCode[CodeLen++] = dest_adr_vals.vals[0];
  2676.               BAsmCode[CodeLen++] = WorkArea;
  2677.             }
  2678.             break;
  2679.           case e_mod_imm:
  2680.             BAsmCode[CodeLen++] = 0x71;
  2681.             BAsmCode[CodeLen++] = dest_adr_vals.vals[0];
  2682.             BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2683.             break;
  2684.           default:
  2685.             break;
  2686.         }
  2687.         break;
  2688.       case e_mod_indir:
  2689.         z80_def_op_size = eSymbolSize8Bit;
  2690.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, MModReg8 | MModReg16
  2691.                             | ((pCurrCPUProps->Core >= eCore7800High) ? MModImm : 0)))
  2692.         {
  2693.           case e_mod_reg8:
  2694.             if (src_adr_vals.val != REG_A) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2695.             else if ((pCurrCPUProps->Core <= eCore7800High) && !is_rpa(dest_adr_vals.val)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2696.             else
  2697.             {
  2698.               BAsmCode[CodeLen++] = 0x38 | (dest_adr_vals.val & 0x07) | ((dest_adr_vals.val & 0x08) << 4);
  2699.               append_adr_vals(&dest_adr_vals);
  2700.             }
  2701.             break;
  2702.           case e_mod_reg16:
  2703.             if (src_adr_vals.val != REG_EA) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2704.             else if (!is_rpa3(dest_adr_vals.val)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2705.             else
  2706.             {
  2707.               BAsmCode[CodeLen++] = 0x48;
  2708.               BAsmCode[CodeLen++] = 0x90 | dest_adr_vals.val;
  2709.               append_adr_vals(&dest_adr_vals);
  2710.             }
  2711.             break;
  2712.           case e_mod_imm:
  2713.             if (!is_rpa1(dest_adr_vals.val)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  2714.             else
  2715.             {
  2716.               BAsmCode[CodeLen++] = 0x48 | dest_adr_vals.val;
  2717.               BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2718.             }
  2719.             break;
  2720.           default:
  2721.             break;
  2722.         }
  2723.         break;
  2724.       case e_mod_sreg8:
  2725.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, MModReg8 | MModImm))
  2726.         {
  2727.           case e_mod_reg8:
  2728.             if (src_adr_vals.val != REG_A) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2729.             else if (check_sr_flag(dest_adr_vals.vals[0], eFlagSR, &ArgStr[1]))
  2730.             {
  2731.               BAsmCode[CodeLen++] = 0x4d;
  2732.               BAsmCode[CodeLen++] = 0xc0 | dest_adr_vals.val;
  2733.             }
  2734.             break;
  2735.           case e_mod_imm:
  2736.             if (check_sr_flag(dest_adr_vals.vals[0], eFlagSR2, &ArgStr[1]))
  2737.             {
  2738.               BAsmCode[CodeLen++] = 0x64;
  2739.               BAsmCode[CodeLen++] = (dest_adr_vals.val & 0x07) | ((dest_adr_vals.val & 0x08) << 4);
  2740.               BAsmCode[CodeLen++] = src_adr_vals.vals[0];
  2741.             }
  2742.           default:
  2743.             break;
  2744.         }
  2745.         break;
  2746.       case e_mod_sreg16:
  2747.         switch (decode_z80_adr(&ArgStr[2], &src_adr_vals, MModReg16))
  2748.         {
  2749.           case e_mod_reg16:
  2750.             if (src_adr_vals.val != REG_EA) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  2751.             else if (check_sr_flag(dest_adr_vals.vals[0], eFlagSR3, &ArgStr[1]))
  2752.             {
  2753.               BAsmCode[CodeLen++] = 0x48;
  2754.               BAsmCode[CodeLen++] = 0xd2 | dest_adr_vals.val;
  2755.             }
  2756.             break;
  2757.           default:
  2758.             break;
  2759.         }
  2760.         break;
  2761.       default:
  2762.         break;
  2763.     }
  2764.   }
  2765. }
  2766.  
  2767. /*--------------------------------------------------------------------------------*/
  2768. /* Dynamic Code Table Handling */
  2769.  
  2770. static void AddFixed(const char *p_name, Word code, unsigned core_mask)
  2771. {
  2772.   order_array_rsv_end(fixed_orders, order_t);
  2773.   fixed_orders[InstrZ].code = code;
  2774.   fixed_orders[InstrZ].core_mask = core_mask;
  2775.   AddInstTable(InstTable, p_name, InstrZ++, DecodeFixed);
  2776. }
  2777.  
  2778. static void AddIntFlag(const char *p_name, Byte code)
  2779. {
  2780.   order_array_rsv_end(int_flags, intflag_t);
  2781.   int_flags[InstrZ].p_name = p_name;
  2782.   int_flags[InstrZ++].code = code;
  2783. }
  2784.  
  2785. static void AddALU(Byte NCode, Word Flags, const char *NNameI, const char *NNameReg, const char *NNameEA, const char *NNameZ80)
  2786. {
  2787.   char Name[20];
  2788.  
  2789.   AddInstTable(InstTable, NNameI, ((Flags & ALUImm_SR) << 8) | NCode, DecodeALUImm);
  2790.   AddInstTable(InstTable, NNameReg, ((Flags & (ALUReg_Src | ALUReg_Dest | ALUImm_SR | ALUReg_MayZ80)) << 8) | NCode, DecodeALUReg);
  2791.   AddInstTable(InstTable, NNameEA, NCode, DecodeALUEA);
  2792.   as_snprintf(Name, sizeof(Name), "%sW", NNameReg);
  2793.   AddInstTable(InstTable, Name, NCode, DecodeALURegW);
  2794.   as_snprintf(Name, sizeof(Name), "%sX", NNameReg);
  2795.   AddInstTable(InstTable, Name, NCode, DecodeALURegX);
  2796.   if (NCode & 1)
  2797.   {
  2798.     as_snprintf(Name, sizeof(Name), "%sW", NNameI);
  2799.     AddInstTable(InstTable, Name, NCode, DecodeALUImmW);
  2800.   }
  2801.   if (NNameZ80)
  2802.     AddInstTable(InstTable, NNameZ80, NCode, decode_alu_z80);
  2803. }
  2804.  
  2805. static void add_alu_z80(const char *p_name, Byte code, Word flags)
  2806. {
  2807.   AddInstTable(InstTable, p_name, (flags << 8) | code, decode_alu_z80);
  2808. }
  2809.  
  2810. static void AddAbs(const char *NName, Word NCode)
  2811. {
  2812.   AddInstTable(InstTable, NName, NCode, DecodeAbs);
  2813. }
  2814.  
  2815. static void AddReg2(const char *p_name, Word code, unsigned core_mask)
  2816. {
  2817.   order_array_rsv_end(reg2_orders, order_t);
  2818.   reg2_orders[InstrZ].code = code;
  2819.   reg2_orders[InstrZ].core_mask = core_mask;
  2820.   AddInstTable(InstTable, p_name, InstrZ++, DecodeReg2);
  2821. }
  2822.  
  2823. static void add_sreg8(const char *p_name, Byte code, Byte flags, Byte core_mask)
  2824. {
  2825.   order_array_rsv_end(s_regs8, sreg_t);
  2826.   s_regs8[InstrZ].p_name = p_name;
  2827.   s_regs8[InstrZ].code = code;
  2828.   s_regs8[InstrZ].flags = flags;
  2829.   s_regs8[InstrZ].core_mask = core_mask;
  2830.   InstrZ++;
  2831. }
  2832.  
  2833. static void add_sreg16(const char *p_name, Byte code, Byte flags, Byte core_mask)
  2834. {
  2835.   order_array_rsv_end(s_regs16, sreg_t);
  2836.   s_regs16[InstrZ].p_name = p_name;
  2837.   s_regs16[InstrZ].code = code;
  2838.   s_regs16[InstrZ].flags = flags;
  2839.   s_regs16[InstrZ].core_mask = core_mask;
  2840.   InstrZ++;
  2841. }
  2842.  
  2843. static void AddWork(const char *NName, Word NCode)
  2844. {
  2845.   AddInstTable(InstTable, NName, NCode, DecodeWork);
  2846. }
  2847.  
  2848. static void AddA(const char *NName, Word NCode)
  2849. {
  2850.   AddInstTable(InstTable, NName, NCode, DecodeA);
  2851. }
  2852.  
  2853. static void AddEA(const char *NName, Word NCode)
  2854. {
  2855.   AddInstTable(InstTable, NName, NCode, DecodeEA);
  2856. }
  2857.  
  2858. static void InitFields(void)
  2859. {
  2860.   Boolean IsLow = pCurrCPUProps->Core == eCore7800Low,
  2861.           IsHigh = pCurrCPUProps->Core == eCore7800High,
  2862.           Is7807 = pCurrCPUProps->Core == eCore7807,
  2863.           Is781x = pCurrCPUProps->Core == eCore7810;
  2864.  
  2865.   InstTable = CreateInstTable(301);
  2866.   SetDynamicInstTable(InstTable);
  2867.  
  2868.   AddInstTable(InstTable, "MOV", 0, DecodeMOV);
  2869.   AddInstTable(InstTable, "MVI", 0, DecodeMVI);
  2870.   AddInstTable(InstTable, "MVIW", 0, DecodeMVIW);
  2871.   AddInstTable(InstTable, "MVIX", 0, DecodeMVIX);
  2872.   AddInstTable(InstTable, "LDAX", 0x28, DecodeLDAX_STAX);
  2873.   AddInstTable(InstTable, "STAX", 0x38, DecodeLDAX_STAX);
  2874.   AddInstTable(InstTable, "LDEAX", 0x80, DecodeLDEAX_STEAX);
  2875.   AddInstTable(InstTable, "STEAX", 0x90, DecodeLDEAX_STEAX);
  2876.   AddInstTable(InstTable, "LXI", 0, DecodeLXI);
  2877.   AddInstTable(InstTable, "PUSH", is_7807_781x ? 0xb0 : 0x480e, DecodePUSH_POP);
  2878.   AddInstTable(InstTable, "POP", is_7807_781x ? 0xa0 : 0x480f, DecodePUSH_POP);
  2879.   AddInstTable(InstTable, "DMOV", 0, DecodeDMOV);
  2880.   AddInstTable(InstTable, "DCX", 1, DecodeDCX_INX);
  2881.   AddInstTable(InstTable, "INX", 0, DecodeDCX_INX);
  2882.   AddInstTable(InstTable, "EADD", 0x40, DecodeEADD_ESUB);
  2883.   AddInstTable(InstTable, "ESUB", 0x60, DecodeEADD_ESUB);
  2884.   AddInstTable(InstTable, "JR", 1, DecodeJ_JR_JRE);
  2885.   AddInstTable(InstTable, "JRE", 2, DecodeJ_JR_JRE);
  2886.   AddInstTable(InstTable, "J", 0, DecodeJ_JR_JRE);
  2887.   AddInstTable(InstTable, "CALF", 0, DecodeCALF);
  2888.   AddInstTable(InstTable, "CALT", 0, DecodeCALT);
  2889.   AddInstTable(InstTable, "BIT", 0, DecodeBIT);
  2890.   AddInstTable(InstTable, "SK" , (core_mask_no_low << 8) | 0x08, DecodeSK_SKN);
  2891.   AddInstTable(InstTable, "SKN", (core_mask_all    << 8) | 0x18, DecodeSK_SKN);
  2892.   AddInstTable(InstTable, "SKIT" , (core_mask_no_low << 8) | (is_7807_781x ? 0x40 : 0x00), DecodeSKIT_SKNIT);
  2893.   AddInstTable(InstTable, "SKNIT", (core_mask_all    << 8) | (is_7807_781x ? 0x60 : 0x10), DecodeSKIT_SKNIT);
  2894.  
  2895.   InstrZ = 0;
  2896.   AddFixed("EX"   , 0x0010                   , (1 << eCore7800High));
  2897.   AddFixed("PEN"  , 0x482c                   , (1 << eCore7800High));
  2898.   AddFixed("RCL"  , 0x4832                   , (1 << eCore7800High));
  2899.   AddFixed("RCR"  , 0x4833                   , (1 << eCore7800High));
  2900.   AddFixed("SHAL" , 0x4834                   , (1 << eCore7800High));
  2901.   AddFixed("SHAR" , 0x4835                   , (1 << eCore7800High));
  2902.   AddFixed("SHCL" , 0x4836                   , (1 << eCore7800High));
  2903.   AddFixed("SHCR" , 0x4837                   , (1 << eCore7800High));
  2904.   AddFixed("EXX"  , Is7807 ? 0x48af : 0x0011 , core_mask_no_low);
  2905.   AddFixed("EXA"  , Is7807 ? 0x48ac : 0x0010 , core_mask_all);
  2906.   AddFixed("EXH"  , Is7807 ? 0x48ae : 0x0050 , core_mask_all);
  2907.   AddFixed("EXR"  , 0x48ad                   , core_mask_7807);
  2908.   if (Is7807)
  2909.     AddInstTable(InstTable, "BLOCK", 0x0010, DecodeBLOCK_7807);
  2910.   else
  2911.     AddFixed("BLOCK", 0x0031                   , core_mask_no_low);
  2912.   AddFixed("TABLE", is_7807_781x ? 0x48a8 : 0x0021 , core_mask_no_low);
  2913.   AddFixed("DAA"  , 0x0061                   , core_mask_all);
  2914.   AddFixed("STC"  , 0x482b                   , core_mask_all);
  2915.   AddFixed("CLC"  , 0x482a                   , core_mask_all);
  2916.   AddFixed("CMC"  , 0x48aa                   , core_mask_7807);
  2917.   AddFixed("NEGA" , 0x483a                   , core_mask_all);
  2918.   AddFixed("RLD"  , 0x4838                   , core_mask_all);
  2919.   AddFixed("RRD"  , 0x4839                   , core_mask_all);
  2920.   AddFixed("JB"   , is_7807_781x ? 0x0021 : 0x0073 , core_mask_all);
  2921.   AddFixed("JEA"  , 0x4828                   , core_mask_all);
  2922.   AddFixed("CALB" , is_7807_781x ? 0x4829 : 0x0063 , core_mask_no_low);
  2923.   AddFixed("SOFTI", 0x0072                   , core_mask_no_low);
  2924.   AddFixed("RET"  , is_7807_781x ? 0x00b8 : 0x0008 , core_mask_all);
  2925.   AddFixed("RETS" , is_7807_781x ? 0x00b9 : 0x0018 , core_mask_all);
  2926.   AddFixed("RETI" , 0x0062                   , core_mask_all);
  2927.   AddFixed("NOP"  , 0x0000                   , core_mask_all);
  2928.   AddFixed("EI"   , is_7807_781x ? 0x00aa : 0x4820 , core_mask_all);
  2929.   AddFixed("DI"   , is_7807_781x ? 0x00ba : 0x4824 , core_mask_all);
  2930.   AddFixed("HLT"  , is_7807_781x ? 0x483b : 0x0001 , core_mask_no_low);
  2931.   AddFixed("SIO"  , 0x0009                   , core_mask_7800);
  2932.   AddFixed("STM"  , 0x0019                   , core_mask_7800);
  2933.   AddFixed("PEX"  , 0x482d                   , core_mask_7800);
  2934.   AddFixed("RAL"  , is_7807_781x ? 0x4835 : 0x4830 , core_mask_all);
  2935.   AddFixed("RAR"  , 0x4831                   , core_mask_all);
  2936.   AddFixed("PER"  , 0x483c                   , core_mask_7800);
  2937.   if (pCurrCPUProps->Flags & eFlagCMOS)
  2938.     AddFixed("STOP" , 0x48bb, core_mask_all);
  2939.  
  2940.   if (is_7807_781x)
  2941.   {
  2942.     if (Is781x)
  2943.     {
  2944.     }
  2945.     else
  2946.     {
  2947.     }
  2948.     /* 0x28 eFlagSR ? */
  2949.   }
  2950.   else
  2951.   {
  2952.   }
  2953.  
  2954.   InstrZ = 0;
  2955.   if (is_7807_781x)
  2956.   {
  2957.     AddIntFlag("NMI" , 0);
  2958.     AddIntFlag("FT0" , 1);
  2959.     AddIntFlag("FT1" , 2);
  2960.     AddIntFlag("F1"  , 3);
  2961.     AddIntFlag("F2"  , 4);
  2962.     AddIntFlag("FE0" , 5);
  2963.     AddIntFlag("FE1" , 6);
  2964.     AddIntFlag("FEIN", 7);
  2965.     AddIntFlag("FSR" , 9);
  2966.     AddIntFlag("FST" ,10);
  2967.     AddIntFlag("ER"  ,11);
  2968.     AddIntFlag("OV"  ,12);
  2969.     AddIntFlag("SB"  ,20);
  2970.     if (Is781x)
  2971.     {
  2972.       AddIntFlag("FAD" , 8);
  2973.       AddIntFlag("AN4" ,16);
  2974.       AddIntFlag("AN5" ,17);
  2975.       AddIntFlag("AN6" ,18);
  2976.       AddIntFlag("AN7" ,19);
  2977.     }
  2978.     else
  2979.     {
  2980.       /* value yet unknown */
  2981.       /* AddIntFlag("IFE2", ...); */
  2982.     }
  2983.   }
  2984.   else
  2985.   {
  2986.     AddIntFlag("F0"  , 0);
  2987.     AddIntFlag("FT"  , 1);
  2988.     AddIntFlag("F1"  , 2);
  2989.     if (IsHigh)
  2990.       AddIntFlag("F2"  , 3);
  2991.     AddIntFlag("FS"  , 4);
  2992.   }
  2993.   AddIntFlag(NULL, 0);
  2994.  
  2995.   AddALU(10, IsLow ?             ALUReg_Src | ALUReg_MayZ80 : ALUImm_SR | ALUReg_Src | ALUReg_Dest | ALUReg_MayZ80, "ACI"  , "ADC"  , "DADC"  , NULL );
  2996.   AddALU( 4, IsLow ?             ALUReg_Src | ALUReg_MayZ80 : ALUImm_SR | ALUReg_Src | ALUReg_Dest | ALUReg_MayZ80, "ADINC", "ADDNC", "DADDNC", NULL );
  2997.   AddALU( 8, IsLow ?             ALUReg_Src | ALUReg_MayZ80 : ALUImm_SR | ALUReg_Src | ALUReg_Dest | ALUReg_MayZ80, "ADI"  , "ADD"  , "DADD"  , NULL );
  2998.   AddALU( 1, IsLow ? ALUImm_SR | ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "ANI"  , "ANA"  , "DAN"   , NULL );
  2999.   AddALU(15, IsLow ?             ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "EQI"  , "EQA"  , "DEQ"   , NULL );
  3000.   AddALU( 5, IsLow ?             ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "GTI"  , "GTA"  , "DGT"   , NULL );
  3001.   AddALU( 7, IsLow ?             ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "LTI"  , "LTA"  , "DLT"   , NULL );
  3002.   AddALU(13, IsLow ?             ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "NEI"  , "NEA"  , "DNE"   , NULL );
  3003.   AddALU(11, IsLow ? ALUImm_SR                              : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "OFFI" , "OFFA" , "DOFF"  , NULL );
  3004.   AddALU( 9, IsLow ? ALUImm_SR                              : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "ONI"  , "ONA"  , "DON"   , NULL );
  3005.   AddALU( 3, IsLow ? ALUImm_SR | ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "ORI"  , "ORA"  , "DOR"   , NULL );
  3006.   AddALU(14, IsLow ?             ALUReg_Src | ALUReg_MayZ80 : ALUImm_SR | ALUReg_Src | ALUReg_Dest | ALUReg_MayZ80, "SBI"  , "SBB"  , "DSBB"  , NULL );
  3007.   AddALU( 6, IsLow ?             ALUReg_Src | ALUReg_MayZ80 : ALUImm_SR | ALUReg_Src | ALUReg_Dest | ALUReg_MayZ80, "SUINB", "SUBNB", "DSUBNB", NULL );
  3008.   AddALU(12, IsLow ?             ALUReg_Src | ALUReg_MayZ80 : ALUImm_SR | ALUReg_Src | ALUReg_Dest | ALUReg_MayZ80, "SUI"  , "SUB"  , "DSUB"  , NULL );
  3009.   AddALU( 2, IsLow ?             ALUReg_Src                 : ALUImm_SR | ALUReg_Src | ALUReg_Dest                , "XRI"  , "XRA"  , "DXR"   , NULL );
  3010.  
  3011.   AddAbs("CALL", is_7807_781x ? 0x0040 : 0x0044);
  3012.   AddAbs("JMP" , 0x0054);
  3013.   AddAbs("LBCD", 0x701f);
  3014.   AddAbs("LDED", 0x702f);
  3015.   AddAbs("LHLD", 0x703f);
  3016.   AddAbs("LSPD", 0x700f);
  3017.   AddAbs("SBCD", 0x701e);
  3018.   AddAbs("SDED", 0x702e);
  3019.   AddAbs("SHLD", 0x703e);
  3020.   AddAbs("SSPD", 0x700e);
  3021.  
  3022.   InstrZ = 0;
  3023.   AddReg2("DCR" , 0x0050, core_mask_all);
  3024.   AddReg2("DIV" , 0x483c, core_mask_7807_7810);
  3025.   AddReg2("INR" , 0x0040, core_mask_all);
  3026.   AddReg2("MUL" , 0x482c, core_mask_7807_7810);
  3027.   if (is_7807_781x)
  3028.   {
  3029.     AddReg2("RLL" , 0x4834, core_mask_7807_7810);
  3030.     AddReg2("RLR" , 0x4830, core_mask_7807_7810);
  3031.   }
  3032.   else
  3033.   {
  3034.     AddA("RLL", 0x4830);
  3035.     AddA("RLR", 0x4831);
  3036.   }
  3037.   AddReg2("SLL" , 0x4824, core_mask_7807_7810);
  3038.   AddReg2("SLR" , 0x4820, core_mask_7807_7810);
  3039.   AddReg2("SLLC", 0x4804, core_mask_7807_7810);
  3040.   AddReg2("SLRC", 0x4800, core_mask_7807_7810);
  3041.  
  3042.   AddWork("DCRW", 0x30);
  3043.   AddWork("INRW", 0x20);
  3044.   AddWork("LDAW", is_7807_781x ? 0x01 : 0x28);
  3045.   AddWork("STAW", is_7807_781x ? 0x63 : 0x38);
  3046.  
  3047.   AddEA("DRLL", 0x48b4); AddEA("DRLR", 0x48b0);
  3048.   AddEA("DSLL", 0x48a4); AddEA("DSLR", 0x48a0);
  3049.  
  3050.   if (!is_7807_781x)
  3051.   {
  3052.     AddInstTable(InstTable, "IN" , 0x4c, DecodeIN_OUT);
  3053.     AddInstTable(InstTable, "OUT", 0x4d, DecodeIN_OUT);
  3054.   }
  3055.  
  3056.   AddInstTable(InstTable, "AND" , 0x0131, DecodeBit2_7807);
  3057.   AddInstTable(InstTable, "OR"  , 0x035c, DecodeBit2_7807);
  3058.   AddInstTable(InstTable, "XOR" , 0x025e, DecodeBit2_7807);
  3059.   AddInstTable(InstTable, "SETB", 0x58, DecodeBit1_7807);
  3060.   AddInstTable(InstTable, "CLR" , 0x5b, DecodeBit1_7807);
  3061.   AddInstTable(InstTable, "NOT" , 0x59, DecodeBit1_7807);
  3062.  
  3063.   /* Array with special regs is created upon first usage and remains
  3064.      allocated, because we need it in dissect_bit_7807(), which may
  3065.      be called after we switched away fro mtarget (e.g. when printing
  3066.      symbol table: */
  3067.  
  3068.   if (!s_regs8)
  3069.   {
  3070.     InstrZ = 0;
  3071.     add_sreg8("PA"  , 0x00, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_all);
  3072.     add_sreg8("PB"  , 0x01, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_all);
  3073.     add_sreg8("PC"  , 0x02, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3074.     add_sreg8("PD"  , 0x03, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3075.     add_sreg8("PF"  , 0x05, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3076.     add_sreg8("MKH" , 0x06, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3077.     add_sreg8("MKL" , 0x07, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3078.     add_sreg8("SMH" , 0x09, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3079.     add_sreg8("SML" , 0x0a, eFlagSR                      , core_mask_7807_7810);
  3080.     add_sreg8("EOM" , 0x0b, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3081.     add_sreg8("ETMM", 0x0c, eFlagSR                      , core_mask_7807_7810);
  3082.     add_sreg8("TMM" , 0x0d, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807_7810);
  3083.     add_sreg8("MM"  , 0x10, eFlagSR                      , core_mask_7807_7810);
  3084.     add_sreg8("MCC" , 0x11, eFlagSR                      , core_mask_7807_7810);
  3085.     add_sreg8("MA"  , 0x12, eFlagSR                      , core_mask_7807_7810);
  3086.     add_sreg8("MB"  , 0x13, eFlagSR                      , core_mask_7807_7810);
  3087.     add_sreg8("MC"  , 0x14, eFlagSR                      , core_mask_7807_7810);
  3088.     add_sreg8("MF"  , 0x17, eFlagSR                      , core_mask_7807_7810);
  3089.     add_sreg8("TXB" , 0x18, eFlagSR                      , core_mask_7807_7810);
  3090.     add_sreg8("RXB" , 0x19, eFlagSR1                     , core_mask_7807_7810);
  3091.     add_sreg8("TM0" , 0x1a, eFlagSR                      , core_mask_7807_7810);
  3092.     add_sreg8("TM1" , 0x1b, eFlagSR                      , core_mask_7807_7810);
  3093.     add_sreg8("ZCM" , 0x28, eFlagSR                      , core_mask_7807_7810 | core_mask_cmos);
  3094.     add_sreg8("ANM" , 0x08, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7810     );
  3095.     add_sreg8("CR0" , 0x20, eFlagSR1                     , core_mask_7810     );
  3096.     add_sreg8("CR1" , 0x21, eFlagSR1                     , core_mask_7810     );
  3097.     add_sreg8("CR2" , 0x22, eFlagSR1                     , core_mask_7810     );
  3098.     add_sreg8("CR3" , 0x23, eFlagSR1                     , core_mask_7810     );
  3099.     add_sreg8("PT"  , 0x0e, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7807     );
  3100.     add_sreg8("WDM" , 0x20, eFlagSR | eFlagSR1           , core_mask_7807     );
  3101.     add_sreg8("MT"  , 0x21, eFlagSR | eFlagSR1           , core_mask_7807     );
  3102.     add_sreg8("MK"  , 0x03, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7800     );
  3103.     add_sreg8("MB"  , 0x04, eFlagSR                      , core_mask_7800     );
  3104.     add_sreg8("PC"  , 0x02, eFlagSR | eFlagSR1 | eFlagSR2, core_mask_7800_high);
  3105.     add_sreg8("PC"  , 0x02, eFlagSR1 | eFlagSR2          , core_mask_7800_low );
  3106.     add_sreg8("MC"  , 0x05, eFlagSR                      , core_mask_7800_high);
  3107.     add_sreg8("MC"  , 0x05, 0                            , core_mask_7800_low );
  3108.     add_sreg8("TM0" , 0x06, eFlagSR                      , core_mask_7800_high);
  3109.     add_sreg8("TM0" , 0x06, 0                            , core_mask_7800_low );
  3110.     add_sreg8("TM1" , 0x07, eFlagSR                      , core_mask_7800_high);
  3111.     add_sreg8("TM1" , 0x07, 0                            , core_mask_7800_low );
  3112.     add_sreg8("TM"  , 0x06, eFlagSR                      , core_mask_7800_low );
  3113.     add_sreg8("TM"  , 0x06, 0                            , core_mask_7800_high);
  3114.     add_sreg8("SM"  , 0x0a, eFlagSR | eFlagSR1           , core_mask_7800_low );
  3115.     add_sreg8("SM"  , 0x0a, 0                            , core_mask_7800_high);
  3116.     add_sreg8("SC"  , 0x0b, eFlagSR | eFlagSR1           , core_mask_7800_low );
  3117.     add_sreg8("SC"  , 0x0b, 0                            , core_mask_7800_high);
  3118.     add_sreg8("S"   , 0x08, eFlagSR | eFlagSR1           , core_mask_7800     );
  3119.     add_sreg8("TMM" , 0x09, eFlagSR | eFlagSR1           , core_mask_7800     );
  3120.     add_sreg8(NULL  , 0x00, 0                            , 0                  );
  3121.   }
  3122.  
  3123.   InstrZ = 0;
  3124.   add_sreg16("ETM0" , 0x00, eFlagSR3, core_mask_all );
  3125.   add_sreg16("ETM1" , 0x01, eFlagSR3, core_mask_all );
  3126.   add_sreg16("ECNT" , 0x00, eFlagSR4, core_mask_all );
  3127.   add_sreg16("ECPT" , 0x01, eFlagSR4, core_mask_7810);
  3128.   add_sreg16("ECPT0", 0x01, eFlagSR4, core_mask_7807);
  3129.   add_sreg16("ECPT1", 0x02, eFlagSR4, core_mask_7807);
  3130.   add_sreg16(NULL   , 0x00, 0       , 0             );
  3131.  
  3132.   if (Is7807)
  3133.     AddInstTable(InstTable, "DEFBIT", 0, DecodeDEFBIT);
  3134.  
  3135.   AddZ80Syntax(InstTable);
  3136.   AddInstTable(InstTable, "LD", 0, decode_ld);
  3137.   AddInstTable(InstTable, "INC", 0, decode_inc_dec);
  3138.   AddInstTable(InstTable, "DEC", 1, decode_inc_dec);
  3139.   add_alu_z80("SKGT", 5, IsLow ? ALUReg_Src : ALUImm_SR | ALUReg_Src | ALUReg_Dest);
  3140.   add_alu_z80("SKLT", 7, IsLow ? ALUReg_Src : ALUImm_SR | ALUReg_Src | ALUReg_Dest);
  3141.   add_alu_z80("SKNE",13, IsLow ? ALUReg_Src : ALUImm_SR | ALUReg_Src | ALUReg_Dest);
  3142.   add_alu_z80("SKEQ",15, IsLow ? ALUReg_Src : ALUImm_SR | ALUReg_Src | ALUReg_Dest);
  3143.   add_alu_z80("SKON", 9, IsLow ? ALUImm_SR  : ALUImm_SR | ALUReg_Src | ALUReg_Dest);
  3144.   add_alu_z80("SKOFF",11, IsLow ? ALUImm_SR  : ALUImm_SR | ALUReg_Src | ALUReg_Dest);
  3145. }
  3146.  
  3147. static void DeinitFields(void)
  3148. {
  3149.   DestroyInstTable(InstTable);
  3150.   order_array_free(int_flags);
  3151.   order_array_free(fixed_orders);
  3152.   order_array_free(reg2_orders);
  3153.   /* See above why s_regs8 does not get freed upon deinit: */
  3154.   /*order_array_free(s_regs8);*/
  3155.   order_array_free(s_regs16);
  3156. }
  3157.  
  3158. /*--------------------------------------------------------------------------*/
  3159.  
  3160. /*!------------------------------------------------------------------------
  3161.  * \fn     MakeCode_78C10(void)
  3162.  * \brief  generate code from source code line
  3163.  * ------------------------------------------------------------------------ */
  3164.  
  3165. static void MakeCode_78C10(void)
  3166. {
  3167.   CodeLen = 0;
  3168.   DontPrint = False;
  3169.   z80_op_size =
  3170.   z80_def_op_size = eSymbolSizeUnknown;
  3171.  
  3172.   /* zu ignorierendes */
  3173.  
  3174.   if (Memo("")) return;
  3175.  
  3176.   /* Pseudoanweisungen */
  3177.  
  3178.   if (DecodeIntelPseudo(False)) return;
  3179.  
  3180.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  3181.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  3182. }
  3183.  
  3184. /*!------------------------------------------------------------------------
  3185.  * \fn     InitCode_78C10(void)
  3186.  * \brief  target-specific initializations at begin of pass
  3187.  * ------------------------------------------------------------------------ */
  3188.  
  3189. static void InitCode_78C10(void)
  3190. {
  3191.   WorkArea = 0x100;
  3192. }
  3193.  
  3194. /*!------------------------------------------------------------------------
  3195.  * \fn     IsDef_78C10(void)
  3196.  * \brief  check whether instruction consumes label field itself
  3197.  * \return True if yes
  3198.  * ------------------------------------------------------------------------ */
  3199.  
  3200. static Boolean IsDef_78C10(void)
  3201. {
  3202.   return (pCurrCPUProps->Core == eCore7807) && Memo("DEFBIT");
  3203. }
  3204.  
  3205. /*!------------------------------------------------------------------------
  3206.  * \fn     SwitchFrom_78C10(void)
  3207.  * \brief  cleanups when switching away from target
  3208.  * ------------------------------------------------------------------------ */
  3209.  
  3210. static void SwitchFrom_78C10(void)
  3211. {
  3212.   DeinitFields();
  3213. }
  3214.  
  3215. /*!------------------------------------------------------------------------
  3216.  * \fn     SwitchTo_78C10(void *pUser)
  3217.  * \brief  initializations when switching to target
  3218.  * \param  pUser * to target details
  3219.  * ------------------------------------------------------------------------ */
  3220.  
  3221. static void SwitchTo_78C10(void *pUser)
  3222. {
  3223.   const TFamilyDescr *pDescr = FindFamilyByName("78(C)xx");
  3224.  
  3225.   pCurrCPUProps = (const tCPUProps*)pUser;
  3226.   TurnWords = False;
  3227.   SetIntConstMode(eIntConstModeIntel);
  3228.  
  3229.   PCSymbol = "$"; HeaderID = pDescr->Id; NOPCode = 0x00;
  3230.   DivideChars = ","; HasAttrs = False;
  3231.  
  3232.   ValidSegs = 1 << SegCode;
  3233.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  3234.   SegLimits[SegCode] = 0xffff;
  3235.  
  3236.   if (pCurrCPUProps->Flags & eFlagHasV)
  3237.   {
  3238.     static ASSUMERec ASSUME78C10s[] =
  3239.     {
  3240.       {"V" , &WorkArea, 0, 0xff, 0x100, NULL}
  3241.     };
  3242.  
  3243.     pASSUMERecs = ASSUME78C10s;
  3244.     ASSUMERecCnt = sizeof(ASSUME78C10s) / sizeof(*ASSUME78C10s);
  3245.   }
  3246.   else
  3247.     WorkArea = 0xff;
  3248.   is_7807_781x = (pCurrCPUProps->Core == eCore7807) || (pCurrCPUProps->Core == eCore7810);
  3249.  
  3250.   MakeCode = MakeCode_78C10; IsDef = IsDef_78C10;
  3251.   SwitchFrom = SwitchFrom_78C10;
  3252.   if (pCurrCPUProps->Core == eCore7807)
  3253.     DissectBit = dissect_bit_7807;
  3254.   InitFields();
  3255. }
  3256.  
  3257. /*!------------------------------------------------------------------------
  3258.  * \fn     code78c10_init(void)
  3259.  * \brief  Attach 78Cxx target
  3260.  * ------------------------------------------------------------------------ */
  3261.  
  3262. static const tCPUProps CPUProps[] =
  3263. {
  3264.   { "7800" , eCore7800High, eFlagHasV             }, /* ROMless , 128B RAM */
  3265.   { "7801" , eCore7800High, eFlagHasV             }, /* 4KB ROM , 128B RAM */
  3266.   { "7802" , eCore7800High, eFlagHasV             }, /* 6KB ROM , 128B RAM */
  3267.   { "78C05", eCore7800Low,  0                     }, /* ROMless , 128B RAM */
  3268.   { "78C06", eCore7800Low,  0                     }, /* 4KB ROM , 128B RAM */
  3269.   { "7807" , eCore7807,     eFlagHasV             }, /* ROMless , 256B RAM */
  3270.   { "7808" , eCore7807,     eFlagHasV             }, /* 4KB ROM , 256B RAM */
  3271.   { "7809" , eCore7807,     eFlagHasV             }, /* 8KB ROM , 256B RAM */
  3272.   { "7810" , eCore7810,     eFlagHasV             }, /* ROMless , 256B RAM */
  3273.   { "78C10", eCore7810,     eFlagHasV | eFlagCMOS }, /* ROMless , 256B RAM */
  3274.   { "78C11", eCore7810,     eFlagHasV | eFlagCMOS }, /* 4KB ROM , 256B RAM */
  3275.   { "78C12", eCore7810,     eFlagHasV | eFlagCMOS }, /* 8KB ROM , 256B RAM */
  3276.   { "78C14", eCore7810,     eFlagHasV | eFlagCMOS }, /* 16KB ROM, 256B RAM */
  3277.   { "78C17", eCore7810,     eFlagHasV | eFlagCMOS }, /* ROMless ,  1KB RAM */
  3278.   { "78C18", eCore7810,     eFlagHasV | eFlagCMOS }, /* 32KB ROM,  1KB RAM */
  3279.   { ""     , eCoreNone,     0                     },
  3280. };
  3281.  
  3282. void code78c10_init(void)
  3283. {
  3284.   const tCPUProps *pProp;
  3285.  
  3286.   for (pProp = CPUProps; pProp->Name[0]; pProp++)
  3287.     (void)AddCPUUserWithArgs(pProp->Name, SwitchTo_78C10, (void*)pProp, NULL, NULL);
  3288.  
  3289.   AddInitPassProc(InitCode_78C10);
  3290. }
  3291.