Subversion Repositories pentevo

Rev

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

  1. /* codecp3f.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS                                                                        */
  6. /*                                                                           */
  7. /* Code Generator Olympia CP-3F                                              */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include <string.h>
  14. #include <ctype.h>
  15.  
  16. #include "bpemu.h"
  17. #include "strutil.h"
  18. #include "headids.h"
  19. #include "asmdef.h"
  20. #include "asmsub.h"
  21. #include "asmpars.h"
  22. #include "asmitree.h"
  23. #include "codepseudo.h"
  24. #include "motpseudo.h"
  25. #include "codevars.h"
  26. #include "errmsg.h"
  27.  
  28. #include "codecp3f.h"
  29.  
  30. /*---------------------------------------------------------------------------*/
  31. /* Address Decoders */
  32.  
  33. typedef enum
  34. {
  35.   e_mode_none = -1,
  36.   e_mode_a = 0,
  37.   e_mode_v = 1,
  38.   e_mode_w = 2,
  39.   e_mode_x = 3,
  40.   e_mode_y = 4,
  41.   e_mode_s = 5,
  42.   e_mode_t = 6,
  43.   e_mode_st = 7,
  44.   e_mode_imm = 8,
  45.   e_mode_imm_short = 9,
  46.   e_mode_dir = 10,
  47.   e_mode_q = 11,
  48.   e_mode_z = 12,
  49.   e_mode_iz = 13
  50. } adr_mode_t;
  51.  
  52. #define MModeA (1 << e_mode_a)
  53. #define MModeV (1 << e_mode_v)
  54. #define MModeW (1 << e_mode_w)
  55. #define MModeX (1 << e_mode_x)
  56. #define MModeY (1 << e_mode_y)
  57. #define MModeS (1 << e_mode_s)
  58. #define MModeT (1 << e_mode_t)
  59. #define MModeST (1 << e_mode_st)
  60. #define MModeQ (1 << e_mode_q)
  61. #define MModeZ (1 << e_mode_z)
  62. #define MModeIZ (1 << e_mode_iz)
  63. #define MModeImm (1 << e_mode_imm)
  64. #define MModeImmShort (1 << e_mode_imm_short)
  65. #define MModeDir (1 << e_mode_dir)
  66.  
  67. typedef struct
  68. {
  69.   adr_mode_t mode;
  70.   Byte value;
  71. } adr_vals_t;
  72.  
  73. /*!------------------------------------------------------------------------
  74.  * \fn     reset_adr_vals(adr_vals_t *p_vals)
  75.  * \brief  reset ecoded address argument to none
  76.  * \param  p_vals argument to reset
  77.  * ------------------------------------------------------------------------ */
  78.  
  79. static void reset_adr_vals(adr_vals_t *p_vals)
  80. {
  81.   p_vals->mode = e_mode_none;
  82.   p_vals->value = 0;
  83. }
  84.  
  85. /*!------------------------------------------------------------------------
  86.  * \fn     decode_adr(const tStrComp *p_arg, adr_vals_t *p_vals, unsigned mask, tSymbolSize op_size)
  87.  * \brief  decode address expression
  88.  * \param  p_arg source argument
  89.  * \param  p_vals encoded mode
  90.  * \param  mask bit mask of allowed modes
  91.  * \return deduced address mode
  92.  * ------------------------------------------------------------------------ */
  93.  
  94. static int chk_xy(const char *p_arg, const char *p_pattern, Byte *p_reg)
  95. {
  96.   for (; *p_arg && *p_pattern; p_arg++, p_pattern++)
  97.   {
  98.     if (*p_pattern == '*')
  99.     {
  100.       switch (as_toupper(*p_arg))
  101.       {
  102.         case 'X': *p_reg = 0; break;
  103.         case 'Y': *p_reg = 1; break;
  104.         default: return 1;
  105.       }
  106.     }
  107.     else if (as_toupper(*p_arg) != as_toupper(*p_pattern))
  108.       return 1;
  109.   }
  110.   return !(!*p_arg && !*p_pattern);
  111. }
  112.  
  113. static adr_mode_t decode_adr(const tStrComp *p_arg, adr_vals_t *p_vals, unsigned mask, tSymbolSize op_size)
  114. {
  115.   size_t l = strlen(p_arg->str.p_str);
  116.   tEvalResult eval_result;
  117.  
  118.   reset_adr_vals(p_vals);
  119.  
  120.   if (l == 1)
  121.   {
  122.     const char reg_names[] = "AVWXYST";
  123.     const char *p_pos = strchr(reg_names, as_toupper(p_arg->str.p_str[0]));
  124.  
  125.     if (p_pos)
  126.     {
  127.       p_vals->mode = (adr_mode_t)(e_mode_a + (p_pos - reg_names));
  128.       goto fini;
  129.     }
  130.   }
  131.  
  132.   if (*p_arg->str.p_str == '#')
  133.   {
  134.     int offset = 1;
  135.  
  136.     switch (op_size)
  137.     {
  138.       case eSymbolSize24Bit:
  139.         p_vals->value = EvalStrIntExpressionOffsWithResult(p_arg, offset, UInt3, &eval_result);
  140.         if (eval_result.OK)
  141.           p_vals->mode = e_mode_imm;
  142.         goto fini;
  143.       case eSymbolSize8Bit:
  144.       {
  145.         Boolean force_short = False,
  146.                 force_long = False,
  147.                 opt_short = !!(mask & MModeImmShort);
  148.  
  149.         if (opt_short)
  150.           switch (p_arg->str.p_str[offset])
  151.           {
  152.             case '<':
  153.               force_short = True;
  154.               offset++;
  155.               break;
  156.             case '>':
  157.               force_long = True;
  158.               offset++;
  159.               break;
  160.             default:
  161.               break;
  162.           }
  163.         p_vals->value = EvalStrIntExpressionOffsWithResult(p_arg, offset, force_short ? UInt4 : Int8, &eval_result);
  164.         if (eval_result.OK)
  165.         {
  166.           if (!opt_short)
  167.             p_vals->mode = e_mode_imm;
  168.           else if (force_long)
  169.             p_vals->mode = e_mode_imm;
  170.           else
  171.             p_vals->mode = (p_vals->value < 16) ? e_mode_imm_short : e_mode_imm;
  172.         }
  173.         goto fini;
  174.       }
  175.       default:
  176.         WrStrErrorPos(ErrNum_UndefOpSizes, p_arg);
  177.         goto fini;
  178.     }
  179.   }
  180.  
  181.   if (!as_strcasecmp(p_arg->str.p_str, "ST"))
  182.   {
  183.     p_vals->mode = e_mode_st;
  184.     goto fini;
  185.   }
  186.   if (!as_strcasecmp(p_arg->str.p_str, "(ST)"))
  187.   {
  188.     p_vals->mode = e_mode_dir;
  189.     p_vals->value = 12;
  190.     goto fini;
  191.   }
  192.   if (!as_strcasecmp(p_arg->str.p_str, "(ST)-"))
  193.   {
  194.     p_vals->mode = e_mode_dir;
  195.     p_vals->value = 13;
  196.     goto fini;
  197.   }
  198.   if (!as_strcasecmp(p_arg->str.p_str, "(ST)+"))
  199.   {
  200.     p_vals->mode = e_mode_dir;
  201.     p_vals->value = 14;
  202.     goto fini;
  203.   }
  204.   if (!chk_xy(p_arg->str.p_str, "Q(*)", &p_vals->value))
  205.   {
  206.     p_vals->mode = e_mode_q;
  207.     goto fini;
  208.   }
  209.   if (!chk_xy(p_arg->str.p_str, "Z(*)", &p_vals->value))
  210.   {
  211.     p_vals->mode = e_mode_z;
  212.     goto fini;
  213.   }
  214.   if (!chk_xy(p_arg->str.p_str, "(Z(*))", &p_vals->value))
  215.   {
  216.     p_vals->mode = e_mode_iz;
  217.     goto fini;
  218.   }
  219.  
  220.   p_vals->value = EvalStrIntExpressionWithResult(p_arg, UInt4, &eval_result);
  221.   if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
  222.     p_vals->value &= 7;
  223.   if (ChkRange(p_vals->value, 0, 11))
  224.   {
  225.     ChkSpace(SegData, eval_result.AddrSpaceMask);
  226.     p_vals->mode = e_mode_dir;
  227.     goto fini;
  228.   }
  229.  
  230. fini:
  231.   if ((p_vals->mode != e_mode_none) && !((mask >> p_vals->mode) & 1))
  232.   {
  233.     WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  234.     reset_adr_vals(p_vals);
  235.   }
  236.   return p_vals->mode;
  237. }
  238.  
  239. /*---------------------------------------------------------------------------*/
  240. /* Instruction Decoders */
  241.  
  242. /*!------------------------------------------------------------------------
  243.  * \fn     decode_imm_4(Word code)
  244.  * \brief  handle instructions with 4 bit immediate operand
  245.  * \param  code machine code
  246.  * ------------------------------------------------------------------------ */
  247.  
  248. static void decode_imm_4(Word code)
  249. {
  250.   if (ChkArgCnt(1, 1))
  251.   {
  252.     Boolean ok;
  253.  
  254.     BAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt4, &ok);
  255.     if (ok)
  256.     {
  257.       BAsmCode[0] = code | (BAsmCode[0] & 0x0f);
  258.       CodeLen = 1;
  259.     }
  260.   }
  261. }
  262.  
  263. /*!------------------------------------------------------------------------
  264.  * \fn     decode_imm_3(Word code)
  265.  * \brief  handle instructions with 3 bit immediate operand
  266.  * \param  code machine code
  267.  * ------------------------------------------------------------------------ */
  268.  
  269. static void decode_imm_3(Word code)
  270. {
  271.   if (ChkArgCnt(1, 1))
  272.   {
  273.     Boolean ok;
  274.  
  275.     BAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt3, &ok);
  276.     if (ok)
  277.     {
  278.       BAsmCode[0] = code | (BAsmCode[0] & 0x07);
  279.       CodeLen = 1;
  280.     }
  281.   }
  282. }
  283.  
  284. /*!------------------------------------------------------------------------
  285.  * \fn     decode_imm_8(Word code)
  286.  * \brief  handle instructions with 8 bit immediate operand
  287.  * \param  code machine code
  288.  * ------------------------------------------------------------------------ */
  289.  
  290. static void decode_imm_8(Word code)
  291. {
  292.   if (ChkArgCnt(1, 1))
  293.   {
  294.     Boolean ok;
  295.  
  296.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int8, &ok);
  297.     if (ok)
  298.     {
  299.       BAsmCode[0] = code;
  300.       CodeLen = 2;
  301.     }
  302.   }
  303. }
  304.  
  305. /*!------------------------------------------------------------------------
  306.  * \fn     decode_fixed(Word code)
  307.  * \brief  handle instructions with no argument
  308.  * \param  code machine code
  309.  * ------------------------------------------------------------------------ */
  310.  
  311. static void decode_fixed(Word code)
  312. {
  313.   if (ChkArgCnt(0, 0))
  314.   {
  315.     BAsmCode[0] = code;
  316.     CodeLen = 1;
  317.   }
  318. }
  319.  
  320. /*!------------------------------------------------------------------------
  321.  * \fn     decode_reg(Word code)
  322.  * \brief  handle instructions with register argument
  323.  * \param  code machine code
  324.  * ------------------------------------------------------------------------ */
  325.  
  326. /* Original syntax assumes programmer knows that 12..14 refer
  327.    to (ST), (ST)+, (ST)-... */
  328.  
  329. static void decode_reg(Word code)
  330. {
  331.   if (ChkArgCnt(1, 1))
  332.   {
  333.     tEvalResult eval_result;
  334.  
  335.     BAsmCode[0] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt4, &eval_result);
  336.     if (eval_result.OK)
  337.     {
  338.       if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
  339.         BAsmCode[0] = 0;
  340.       if (ChkRange(BAsmCode[0], 0, 14))
  341.       {
  342.         BAsmCode[0] |= code;
  343.         CodeLen = 1;
  344.       }
  345.     }
  346.   }
  347. }
  348.  
  349. /*!------------------------------------------------------------------------
  350.  * \fn     decode_io(Word code)
  351.  * \brief  handle instructions with I/O address operand
  352.  * \param  code machine code
  353.  * ------------------------------------------------------------------------ */
  354.  
  355. static void decode_io(Word code)
  356. {
  357.   if (ChkArgCnt(1, 1))
  358.   {
  359.     tEvalResult eval_result;
  360.  
  361.     BAsmCode[0] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt3, &eval_result);
  362.     if (eval_result.OK)
  363.     {
  364.       ChkSpace(SegIO, eval_result.AddrSpaceMask);
  365.       BAsmCode[0] = code | (BAsmCode[0] & 0x07);
  366.       CodeLen = 1;
  367.     }
  368.   }
  369. }
  370.  
  371. /*!------------------------------------------------------------------------
  372.  * \fn     decode_port(Word code)
  373.  * \brief  handle PORt instruction
  374.  * ------------------------------------------------------------------------ */
  375.  
  376. static void decode_port(Word code)
  377. {
  378.   UNUSED(code);
  379.  
  380.   CodeEquate(SegIO, 0, SegLimits[SegIO]);
  381. }
  382.  
  383. /*!------------------------------------------------------------------------
  384.  * \fn     decode_jmp(Word code)
  385.  * \brief  handle instructions with target address operand
  386.  * \param  code machine code
  387.  * ------------------------------------------------------------------------ */
  388.  
  389. static void decode_jmp(Word code)
  390. {
  391.   if (ChkArgCnt(1, 1))
  392.   {
  393.     tEvalResult eval_result;
  394.     Word address = EvalStrIntExpressionWithResult(&ArgStr[1], UInt14, &eval_result);
  395.  
  396.     if (eval_result.OK
  397.      && ChkSamePage(EProgCounter(), address, 11, eval_result.Flags))
  398.     {
  399.       BAsmCode[0] = code | (Hi(address) & 7);
  400.       BAsmCode[1] = Lo(address);
  401.       CodeLen = 2;
  402.     }
  403.   }
  404. }
  405.  
  406. /*!------------------------------------------------------------------------
  407.  * \fn     void decode_ld(Word code)
  408.  * \brief  decode virtual LD instruction
  409.  * ------------------------------------------------------------------------ */
  410.  
  411. static void decode_ld(Word code)
  412. {
  413.   adr_vals_t src_adr_vals, dest_adr_vals;
  414.  
  415.   UNUSED(code);
  416.  
  417.   if (ChkArgCnt(2, 2))
  418.     switch (decode_adr(&ArgStr[1], &dest_adr_vals, MModeA | MModeV | MModeW | MModeX | MModeY | MModeS | MModeT | MModeST | MModeDir | MModeQ | MModeZ | MModeIZ, eSymbolSizeUnknown))
  419.     {
  420.       case e_mode_a:
  421.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeV | MModeW | MModeX | MModeY | MModeDir | MModeImm | MModeImmShort | MModeIZ, eSymbolSize8Bit))
  422.         {
  423.           case e_mode_v:
  424.           case e_mode_w:
  425.           case e_mode_x:
  426.           case e_mode_y:
  427.             BAsmCode[0] = 0x08 | (src_adr_vals.mode - e_mode_v);
  428.             CodeLen = 1;
  429.             break;
  430.           case e_mode_dir:
  431.             BAsmCode[0] = 0x80 | src_adr_vals.value;
  432.             CodeLen = 1;
  433.             break;
  434.           case e_mode_imm:
  435.             BAsmCode[0] = 0x04;
  436.             BAsmCode[1] = src_adr_vals.value;
  437.             CodeLen = 2;
  438.             break;
  439.           case e_mode_imm_short:
  440.             BAsmCode[0] = 0xf0 | (src_adr_vals.value & 15);
  441.             CodeLen = 1;
  442.             break;
  443.           case e_mode_iz:
  444.             BAsmCode[0] = 0x06 | src_adr_vals.value;
  445.             CodeLen = 1;
  446.             break;
  447.           default:
  448.             break;
  449.         }
  450.         break;
  451.       case e_mode_v:
  452.       case e_mode_w:
  453.       case e_mode_x:
  454.       case e_mode_y:
  455.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA, eSymbolSize8Bit))
  456.         {
  457.           case e_mode_a:
  458.             BAsmCode[0] = 0x18 | (dest_adr_vals.mode - e_mode_v);
  459.             CodeLen = 1;
  460.             break;
  461.           default:
  462.             break;
  463.         }
  464.         break;
  465.       case e_mode_s:
  466.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeImm, eSymbolSize24Bit))
  467.         {
  468.           case e_mode_imm:
  469.             BAsmCode[0] = 0x28 | (src_adr_vals.value & 7);
  470.             CodeLen = 1;
  471.             break;
  472.           default:
  473.             break;
  474.         }
  475.         break;
  476.       case e_mode_t:
  477.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA | MModeImm, eSymbolSize24Bit))
  478.         {
  479.           case e_mode_a:
  480.             BAsmCode[0] = 0x01;
  481.             CodeLen = 1;
  482.             break;
  483.           case e_mode_imm:
  484.             BAsmCode[0] = 0x38 | (src_adr_vals.value & 7);
  485.             CodeLen = 1;
  486.             break;
  487.           default:
  488.             break;
  489.         }
  490.         break;
  491.       case e_mode_st:
  492.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA, eSymbolSizeUnknown))
  493.         {
  494.           case e_mode_a:
  495.             BAsmCode[0] = 0x03;
  496.             CodeLen = 1;
  497.             break;
  498.           default:
  499.             break;
  500.         }
  501.         break;
  502.       case e_mode_q:
  503.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA, eSymbolSizeUnknown))
  504.         {
  505.           case e_mode_a:
  506.             BAsmCode[0] = 0x16 | dest_adr_vals.value;
  507.             CodeLen = 1;
  508.             break;
  509.           default:
  510.             break;
  511.         }
  512.         break;
  513.       case e_mode_z:
  514.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA, eSymbolSizeUnknown))
  515.         {
  516.           case e_mode_a:
  517.             BAsmCode[0] = 0x12 | dest_adr_vals.value;
  518.             CodeLen = 1;
  519.             break;
  520.           default:
  521.             break;
  522.         }
  523.         break;
  524.       case e_mode_iz:
  525.         if (dest_adr_vals.value) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  526.         else switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA, eSymbolSizeUnknown))
  527.         {
  528.           case e_mode_a:
  529.             BAsmCode[0] = 0x02 | dest_adr_vals.value;
  530.             CodeLen = 1;
  531.             break;
  532.           default:
  533.             break;
  534.         }
  535.         break;
  536.       case e_mode_dir:
  537.         switch (decode_adr(&ArgStr[2], &src_adr_vals, MModeA, eSymbolSize8Bit))
  538.         {
  539.           case e_mode_a:
  540.             BAsmCode[0] = 0x90 | dest_adr_vals.value;
  541.             CodeLen = 1;
  542.             break;
  543.           default:
  544.             break;
  545.         }
  546.         break;
  547.       default:
  548.         break;
  549.     }
  550. }
  551.  
  552. /*!------------------------------------------------------------------------
  553.  * \fn     void decode_ari(Word code)
  554.  * \brief  decode virtual arithmetic instruction
  555.  * ------------------------------------------------------------------------ */
  556.  
  557. static void decode_ari(Word code)
  558. {
  559.   adr_vals_t src_adr_vals, dest_adr_vals;
  560.   unsigned mask;
  561.   Byte imm_code = Hi(code), dir_code = Lo(code);
  562.  
  563.   if (!ChkArgCnt(1, 2))
  564.     return;
  565.  
  566.   if (ArgCnt == 2)
  567.   {
  568.     if (decode_adr(&ArgStr[1], &dest_adr_vals, MModeA, eSymbolSize8Bit) != e_mode_a)
  569.       return;
  570.   }
  571.  
  572.   mask = ((imm_code == 0xff) ? 0 : MModeImm)
  573.        | ((dir_code == 0xff) ? 0 : MModeDir);
  574.   switch (decode_adr(&ArgStr[ArgCnt], &src_adr_vals, mask, eSymbolSize8Bit))
  575.   {
  576.     case e_mode_dir:
  577.       BAsmCode[0] = dir_code | src_adr_vals.value;
  578.       CodeLen = 1;
  579.       break;
  580.     case e_mode_imm:
  581.       BAsmCode[0] = imm_code;
  582.       BAsmCode[1] = src_adr_vals.value;
  583.       CodeLen = 2;
  584.       break;
  585.     default:
  586.       break;
  587.   }
  588. }
  589.  
  590. /*!------------------------------------------------------------------------
  591.  * \fn     decode_srl_sla(Word code)
  592.  * \brief  decode virtual shift instructions
  593.  * \param  code machine code for single bit shift
  594.  * ------------------------------------------------------------------------ */
  595.  
  596. static void decode_srl_sla(Word code)
  597. {
  598.   int shift_arg_index;
  599.   Byte shift_cnt;
  600.  
  601.   switch (ArgCnt)
  602.   {
  603.     case 1:
  604.       if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
  605.         goto acc_1;
  606.       shift_arg_index = 1;
  607.       goto eval_shift;
  608.     case 0:
  609.     acc_1:
  610.       shift_cnt = 1;
  611.       break;
  612.     case 2:
  613.     {
  614.       adr_vals_t adr_vals;
  615.  
  616.       if (decode_adr(&ArgStr[1], &adr_vals, MModeA, eSymbolSize8Bit) != e_mode_a)
  617.         return;
  618.       shift_arg_index = 2;
  619.       /* FALL-THRU */
  620.     }
  621.     eval_shift:
  622.     {
  623.       tEvalResult eval_result;
  624.       shift_cnt = EvalStrIntExpressionWithResult(&ArgStr[shift_arg_index], UInt8, &eval_result);
  625.       if (!eval_result.OK)
  626.         return;
  627.       if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
  628.         shift_cnt = 1;
  629.       if ((shift_cnt != 1) && (shift_cnt != 4))
  630.       {
  631.         WrStrErrorPos(ErrNum_InvShiftArg, &ArgStr[shift_arg_index]);
  632.         return;
  633.       }
  634.       break;
  635.     }
  636.     default:
  637.       (void)ChkArgCnt(0, 2);
  638.       return;
  639.   }
  640.  
  641.   BAsmCode[0] = code | ((shift_cnt > 1) ? 2 : 0);
  642.   CodeLen = 1;
  643. }
  644.  
  645. /*---------------------------------------------------------------------------*/
  646. /* Code Table Handling */
  647.  
  648. /*!------------------------------------------------------------------------
  649.  * \fn     init_fields(void)
  650.  * \brief  build up instruction hash table
  651.  * ------------------------------------------------------------------------ */
  652.  
  653. static void init_fields(void)
  654. {
  655.   InstTable = CreateInstTable(101);
  656.  
  657.   AddInstTable(InstTable, "LAS", 0xf0, decode_imm_4);
  658.   AddInstTable(InstTable, "LSS", 0x28, decode_imm_3);
  659.   AddInstTable(InstTable, "LTS", 0x38, decode_imm_3);
  660.   AddInstTable(InstTable, "LAL", 0x04, decode_imm_8);
  661.   AddInstTable(InstTable, "ANL", 0x05, decode_imm_8);
  662.   AddInstTable(InstTable, "EOL", 0x0c, decode_imm_8);
  663.   AddInstTable(InstTable, "ORL", 0x0d, decode_imm_8);
  664.   AddInstTable(InstTable, "ADL", 0x0e, decode_imm_8);
  665.   AddInstTable(InstTable, "CML", 0x0f, decode_imm_8);
  666.  
  667.   AddInstTable(InstTable, "LAV", 0x08, decode_fixed);
  668.   AddInstTable(InstTable, "LAW", 0x09, decode_fixed);
  669.   AddInstTable(InstTable, "LAX", 0x0a, decode_fixed);
  670.   AddInstTable(InstTable, "LAY", 0x0b, decode_fixed);
  671.   AddInstTable(InstTable, "SAV", 0x18, decode_fixed);
  672.   AddInstTable(InstTable, "SAW", 0x19, decode_fixed);
  673.   AddInstTable(InstTable, "SAX", 0x1a, decode_fixed);
  674.   AddInstTable(InstTable, "SAY", 0x1b, decode_fixed);
  675.   AddInstTable(InstTable, "SAT", 0x01, decode_fixed);
  676.   AddInstTable(InstTable, "SST", 0x03, decode_fixed);
  677.   AddInstTable(InstTable, "ALS", 0x1c, decode_fixed);
  678.   AddInstTable(InstTable, "ARS", 0x1d, decode_fixed);
  679.   AddInstTable(InstTable, "ALF", 0x1e, decode_fixed);
  680.   AddInstTable(InstTable, "ARF", 0x1f, decode_fixed);
  681.   AddInstTable(InstTable, "RET", 0x00, decode_fixed);
  682.   AddInstTable(InstTable, "SIX", 0x02, decode_fixed);
  683.   AddInstTable(InstTable, "LIX", 0x06, decode_fixed);
  684.   AddInstTable(InstTable, "LIY", 0x07, decode_fixed);
  685.   AddInstTable(InstTable, "SQX", 0x16, decode_fixed);
  686.   AddInstTable(InstTable, "SQY", 0x17, decode_fixed);
  687.   AddInstTable(InstTable, "SZX", 0x12, decode_fixed);
  688.   AddInstTable(InstTable, "SZY", 0x13, decode_fixed);
  689.  
  690.   AddInstTable(InstTable, "LAR", 0x80, decode_reg);
  691.   AddInstTable(InstTable, "SAR", 0x90, decode_reg);
  692.   AddInstTable(InstTable, "ADR", 0xa0, decode_reg);
  693.   AddInstTable(InstTable, "ANR", 0xb0, decode_reg);
  694.   AddInstTable(InstTable, "EOR", 0xc0, decode_reg);
  695.   AddInstTable(InstTable, "DER", 0xd0, decode_reg);
  696.   AddInstTable(InstTable, "DAR", 0xe0, decode_reg);
  697.  
  698.   AddInstTable(InstTable, "INP", 0x20, decode_io);
  699.   AddInstTable(InstTable, "OUT", 0x30, decode_io);
  700.   AddInstTable(InstTable, "PORT", 0, decode_port);
  701.  
  702.   AddInstTable(InstTable, "JMP", 0x40, decode_jmp);
  703.   AddInstTable(InstTable, "JAZ", 0x48, decode_jmp);
  704.   AddInstTable(InstTable, "JAN", 0x50, decode_jmp);
  705.   AddInstTable(InstTable, "JAP", 0x58, decode_jmp);
  706.   AddInstTable(InstTable, "JSD", 0x60, decode_jmp);
  707.   AddInstTable(InstTable, "JCN", 0x68, decode_jmp);
  708.   AddInstTable(InstTable, "JCZ", 0x70, decode_jmp);
  709.   AddInstTable(InstTable, "JSB", 0x78, decode_jmp);
  710.   AddInstTable(InstTable, "GOS", 0x78, decode_jmp);
  711.  
  712.   AddInstTable(InstTable, "LD", 0, decode_ld);
  713.   AddInstTable(InstTable, "ADD", 0x0ea0, decode_ari);
  714.   AddInstTable(InstTable, "AND", 0x05b0, decode_ari);
  715.   AddInstTable(InstTable, "XOR", 0x0cc0, decode_ari);
  716.   AddInstTable(InstTable, "OR" , 0x0dff, decode_ari);
  717.         AddInstTable(InstTable, "CP" , 0x0fff, decode_ari);
  718.   AddInstTable(InstTable, "DEC", 0xffd0, decode_ari);
  719.   AddInstTable(InstTable, "SLA", 0x1c, decode_srl_sla);
  720.   AddInstTable(InstTable, "SRL", 0x1d, decode_srl_sla);
  721.  
  722.   AddInstTable(InstTable, "DC", 0, DecodeMotoBYT);
  723.   AddInstTable(InstTable, "DS", 0, DecodeMotoDFS);
  724. }
  725.  
  726. /*!------------------------------------------------------------------------
  727.  * \fn     deinit_fields(void)
  728.  * \brief  tear down instruction hash table
  729.  * ------------------------------------------------------------------------ */
  730.  
  731. static void deinit_fields(void)
  732. {
  733.   DestroyInstTable(InstTable);
  734. }
  735.  
  736. /*---------------------------------------------------------------------------*/
  737. /* Interface Functions */
  738.  
  739. /*!------------------------------------------------------------------------
  740.  * \fn     make_code_cp3f(void)
  741.  * \brief  machine instruction dispatcher
  742.  * ------------------------------------------------------------------------ */
  743.  
  744. static void make_code_cp3f(void)
  745. {
  746.   CodeLen = 0; DontPrint = False;
  747.  
  748.   /* to be ignored */
  749.  
  750.   if (Memo("")) return;
  751.  
  752.   /* pseudo instructions */
  753.  
  754.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  755.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  756. }
  757.  
  758. /*!------------------------------------------------------------------------
  759.  * \fn     switch_from_cp3f(void)
  760.  * \brief  cleanups after switch from target
  761.  * ------------------------------------------------------------------------ */
  762.  
  763. static void switch_from_cp3f(void)
  764. {
  765.   deinit_fields();
  766. }
  767.  
  768. /*!------------------------------------------------------------------------
  769.  * \fn     is_def_cp_3f(void)
  770.  * \brief  does instruction use label field?
  771.  * ------------------------------------------------------------------------ */
  772.  
  773. static Boolean is_def_cp3f(void)
  774. {
  775.   return Memo("PORT");
  776. }
  777.  
  778. /*!------------------------------------------------------------------------
  779.  * \fn     switch_to_cp_3f(void)
  780.  * \brief  prepare to assemble code for this target
  781.  * ------------------------------------------------------------------------ */
  782.  
  783. static void switch_to_cp3f(void)
  784. {
  785.   const TFamilyDescr *p_descr = FindFamilyByName("CP-3F");
  786.  
  787.   TurnWords = False;
  788.   SetIntConstMode(eIntConstModeIntel);
  789.  
  790.   p_descr = FindFamilyByName("CP-3F");
  791.   PCSymbol = "$";
  792.   HeaderID = p_descr->Id;
  793.   NOPCode = 0x00;
  794.   DivideChars = ",";
  795.   HasAttrs = False;
  796.  
  797.   ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
  798.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegLimits[SegCode] = 0x3fff;
  799.   Grans[SegData] = 1; ListGrans[SegData] = 1; SegLimits[SegData] = 0x2f;
  800.   Grans[SegIO  ] = 1; ListGrans[SegIO  ] = 1; SegLimits[SegIO  ] = 0x7;
  801.  
  802.   MakeCode = make_code_cp3f;
  803.   SwitchFrom = switch_from_cp3f;
  804.   IsDef = is_def_cp3f;
  805.   init_fields();
  806. }
  807.  
  808. /*!------------------------------------------------------------------------
  809.  * \fn     codecp3f__init(void)
  810.  * \brief  register CP-3F target
  811.  * ------------------------------------------------------------------------ */
  812.  
  813. void codecp3f_init(void)
  814. {
  815.   (void)AddCPU("CP-3F"    , switch_to_cp3f);
  816.   (void)AddCPU("M380"     , switch_to_cp3f);
  817.   (void)AddCPU("LP8000"   , switch_to_cp3f);
  818. }
  819.