Subversion Repositories pentevo

Rev

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

  1. /* code870c.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator TLCS-870/C                                                  */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include <ctype.h>
  14. #include <string.h>
  15.  
  16. #include "nls.h"
  17. #include "bpemu.h"
  18. #include "strutil.h"
  19. #include "asmdef.h"
  20. #include "asmsub.h"
  21. #include "asmpars.h"
  22. #include "asmitree.h"
  23. #include "asmcode.h"
  24. #include "codepseudo.h"
  25. #include "intpseudo.h"
  26. #include "codevars.h"
  27. #include "headids.h"
  28. #include "errmsg.h"
  29.  
  30. #include "code870c.h"
  31.  
  32. typedef struct
  33. {
  34.   const char *Name;
  35.   Word Code;
  36. } CondRec;
  37.  
  38. enum
  39. {
  40.   ModNone = -1,
  41.   ModReg8 = 0,
  42.   ModReg16 = 1,
  43.   ModImm = 2,
  44.   ModMem = 3
  45. };
  46.  
  47. #define MModReg8 (1 << ModReg8)
  48. #define MModReg16 (1 << ModReg16)
  49. #define MModImm (1 << ModImm)
  50. #define MModAbs (1 << ModAbs)
  51. #define MModMem (1 << ModMem)
  52.  
  53. #define AccReg 0
  54. #define WAReg 0
  55.  
  56. #define COND_CODE_TRUE 0xde
  57.  
  58. #define Reg8Cnt 8
  59. static const char Reg8Names[] = "AWCBEDLH";
  60.  
  61. static CPUVar CPU870C;
  62. static ShortInt OpSize;
  63. static Byte AdrVals[4];
  64. static ShortInt AdrType;
  65. static Byte AdrMode;
  66.  
  67. static CondRec *Conditions;
  68.  
  69. /*--------------------------------------------------------------------------*/
  70.  
  71. typedef struct
  72. {
  73.   as_eval_cb_data_t cb_data;
  74.   Word reg_flag;
  75. } tlcs870c1_eval_cb_data_t;
  76.  
  77. #define REGFLAG_DISP 0x100
  78.  
  79. DECLARE_AS_EVAL_CB(tlcs870c1_eval_cb)
  80. {
  81.   tlcs870c1_eval_cb_data_t *p_tlcs870c1_eval_cb_data = (tlcs870c1_eval_cb_data_t*)p_data;
  82.   size_t z;
  83.   static const char AdrRegs[][3] =
  84.   {
  85.     "DE", "HL", "IX", "IY", "SP", "C", "PC", "A"
  86.   };
  87.  
  88.   for (z = 0; z < as_array_size(AdrRegs); z++)
  89.     if (!as_strcasecmp(p_arg->str.p_str, AdrRegs[z]))
  90.     {
  91.       if ((p_tlcs870c1_eval_cb_data->reg_flag & (1 << z))
  92.        || !as_eval_cb_data_stack_plain_add(p_data->p_stack))
  93.       {
  94.         WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
  95.         return e_eval_fail;
  96.       }
  97.       p_tlcs870c1_eval_cb_data->reg_flag |= 1 << z;
  98.       as_tempres_set_int(p_res, 0);
  99.       return e_eval_ok;
  100.     }
  101.   return e_eval_none;
  102. }
  103.  
  104. static void DecodeAdr(const tStrComp *pArg, Byte Erl, Boolean IsDest)
  105. {
  106.   static const char Reg16Names[][3] =
  107.   {
  108.     "WA", "BC", "DE", "HL", "IX", "IY", "SP"
  109.   };
  110.   static const int Reg16Cnt = sizeof(Reg16Names) / sizeof(*Reg16Names);
  111.  
  112.   int z;
  113.   LongInt DispAcc;
  114.   Boolean OK;
  115.  
  116.   AdrType = ModNone;
  117.   AdrCnt = 0;
  118.  
  119.   if (strlen(pArg->str.p_str) == 1)
  120.   {
  121.     for (z = 0; z < Reg8Cnt; z++)
  122.       if (as_toupper(*pArg->str.p_str) == Reg8Names[z])
  123.       {
  124.         AdrType = ModReg8;
  125.         OpSize = 0;
  126.         AdrMode = z;
  127.         goto chk;
  128.       }
  129.   }
  130.  
  131.   for (z = 0; z < Reg16Cnt; z++)
  132.     if (!as_strcasecmp(pArg->str.p_str, Reg16Names[z]))
  133.     {
  134.       AdrType = ModReg16;
  135.       OpSize = 1;
  136.       AdrMode = z;
  137.       goto chk;
  138.     }
  139.  
  140.   if (IsIndirect(pArg->str.p_str))
  141.   {
  142.     tStrComp Arg;
  143.     tEvalResult eval_result;
  144.     tlcs870c1_eval_cb_data_t tlcs870c1_eval_cb_data;
  145.  
  146.     StrCompRefRight(&Arg, pArg, 1);
  147.     StrCompShorten(&Arg, 1);
  148.  
  149.     if ((!as_strcasecmp(Arg.str.p_str, "+SP")) && (!IsDest))
  150.     {
  151.       AdrType = ModMem;
  152.       AdrMode = 0xe6;
  153.       goto chk;
  154.     }
  155.     if ((!as_strcasecmp(Arg.str.p_str, "SP-")) && (IsDest))
  156.     {
  157.       AdrType = ModMem;
  158.       AdrMode = 0xe6;
  159.       goto chk;
  160.     }
  161.  
  162.     as_eval_cb_data_ini(&tlcs870c1_eval_cb_data.cb_data, tlcs870c1_eval_cb);
  163.     tlcs870c1_eval_cb_data.reg_flag = 0;
  164.     DispAcc = EvalStrIntExprWithResultAndCallback(&Arg, Int32, &eval_result, &tlcs870c1_eval_cb_data.cb_data);
  165.     if (DispAcc || !tlcs870c1_eval_cb_data.reg_flag)
  166.       tlcs870c1_eval_cb_data.reg_flag |= REGFLAG_DISP;
  167.     if (eval_result.OK)
  168.       switch (tlcs870c1_eval_cb_data.reg_flag)
  169.       {
  170.         case REGFLAG_DISP: /* (nnnn) (nn) */
  171.           AdrType = ModMem;
  172.           AdrVals[0] = DispAcc & 0xff;
  173.           if (DispAcc > 0xff)
  174.           {
  175.             AdrMode = 0xe1;
  176.             AdrCnt = 2;
  177.             AdrVals[1] = (DispAcc >> 8) & 0xff;
  178.           }
  179.           else
  180.           {
  181.             AdrMode = 0xe0;
  182.             AdrCnt = 1;
  183.           }
  184.           break;
  185.         case 0x08: /* (IY) */
  186.           AdrType = ModMem;
  187.           AdrMode = 0xe5;
  188.           break;
  189.         case 0x04: /* (IX) */
  190.           AdrType = ModMem;
  191.           AdrMode = 0xe4;
  192.           break;
  193.         case 0x02: /* (HL) */
  194.           AdrType = ModMem;
  195.           AdrMode = 0xe3;
  196.           break;
  197.         case 0x01: /* (DE) */
  198.           AdrType = ModMem;
  199.           AdrMode = 0xe2;
  200.           break;
  201.         case 0xc0: /* (PC+A) */
  202.           AdrType = ModMem;
  203.           AdrMode = 0x4f;
  204.           break;
  205.         case REGFLAG_DISP | 0x10: /* (SP+dd) */
  206.           if (mFirstPassUnknown(eval_result.Flags))
  207.             DispAcc &= 0x7f;
  208.           if (ChkRange(DispAcc, -128, 127))
  209.           {
  210.             AdrType = ModMem;
  211.             AdrMode = 0xd6;
  212.             AdrCnt = 1;
  213.             AdrVals[0] = DispAcc & 0xff;
  214.           }
  215.           break;
  216.         case REGFLAG_DISP | 0x08: /* (IY+dd) */
  217.           if (mFirstPassUnknown(eval_result.Flags))
  218.             DispAcc &= 0x7f;
  219.           if (ChkRange(DispAcc, -128, 127))
  220.           {
  221.             AdrType = ModMem;
  222.             AdrMode = 0xd5;
  223.             AdrCnt = 1;
  224.             AdrVals[0] = DispAcc & 0xff;
  225.           }
  226.           break;
  227.         case REGFLAG_DISP | 0x04: /* (IX+dd) */
  228.           if (mFirstPassUnknown(eval_result.Flags))
  229.             DispAcc &= 0x7f;
  230.           if (ChkRange(DispAcc, -128, 127))
  231.           {
  232.             AdrType = ModMem;
  233.             AdrMode = 0xd4;
  234.             AdrCnt = 1;
  235.             AdrVals[0] = DispAcc & 0xff;
  236.           }
  237.           break;
  238.         case REGFLAG_DISP | 0x02: /* (HL+dd) */
  239.           if (mFirstPassUnknown(eval_result.Flags))
  240.             DispAcc &= 0x7f;
  241.           if (ChkRange(DispAcc, -128, 127))
  242.           {
  243.             AdrType = ModMem;
  244.             AdrMode = 0xd7;
  245.             AdrCnt = 1;
  246.             AdrVals[0] = DispAcc & 0xff;
  247.           }
  248.           break;
  249.         case 0x22:  /* (HL+c) */
  250.           AdrType = ModMem;
  251.           AdrMode = 0xe7;
  252.           break;
  253.         default:
  254.           WrStrErrorPos(ErrNum_InvAddrMode, &Arg);
  255.       }
  256.     goto chk;
  257.   }
  258.   else
  259.   {
  260.     switch (OpSize)
  261.     {
  262.       case -1:
  263.         WrError(ErrNum_UndefOpSizes);
  264.         break;
  265.       case 0:
  266.         AdrVals[0] = EvalStrIntExpression(pArg, Int8, &OK);
  267.         if (OK)
  268.         {
  269.           AdrType = ModImm;
  270.           AdrCnt = 1;
  271.         }
  272.         break;
  273.       case 1:
  274.         DispAcc = EvalStrIntExpression(pArg, Int16, &OK);
  275.         if (OK)
  276.         {
  277.           AdrType = ModImm;
  278.           AdrCnt = 2;
  279.           AdrVals[0] = DispAcc & 0xff;
  280.           AdrVals[1] = (DispAcc >> 8) & 0xff;
  281.         }
  282.         break;
  283.     }
  284.   }
  285.  
  286. chk:
  287.   if ((AdrType != ModNone) && (!((1<<AdrType) & Erl)))
  288.   {
  289.     AdrType = ModNone;
  290.     AdrCnt = 0;
  291.     WrError(ErrNum_InvAddrMode);
  292.   }
  293. }
  294.  
  295. static Byte MakeDestMode(Byte AdrMode)
  296. {
  297.   if ((AdrMode & 0xf0) == 0xe0)
  298.     return AdrMode + 0x10;
  299.   else
  300.     return AdrMode - 0x80;
  301. }
  302.  
  303. static Boolean DecodeSPDisp(const tStrComp *pArg, Byte *pDisp, Boolean *pDispNeg)
  304. {
  305.   Boolean OK;
  306.   LongInt DispAcc;
  307.   tSymbolFlags Flags;
  308.  
  309.   *pDisp = 0;
  310.   *pDispNeg = False;
  311.  
  312.   /* avoid ambiguities - LD SP,SP should be coded as LD rr,rr */
  313.  
  314.   if (IsIndirect(pArg->str.p_str))
  315.     return False;
  316.   if (as_strncasecmp(pArg->str.p_str, "SP", 2))
  317.     return False;
  318.   if (strlen(pArg->str.p_str) < 3)
  319.     return False;
  320.  
  321.   DispAcc = EvalStrIntExpressionOffsWithFlags(pArg, 2, Int16, &OK, &Flags);
  322.   if (!OK)
  323.     return False;
  324.  
  325.   if (mFirstPassUnknown(Flags))
  326.     DispAcc &= 0xff;
  327.   if (ChkRange(DispAcc, -255, 255))
  328.   {
  329.     *pDispNeg = DispAcc < 0;
  330.     *pDisp = *pDispNeg ? -DispAcc : DispAcc;
  331.   }
  332.   return True; /* return True even if disp is out of range, addressing mode was properly detected */
  333. }
  334.  
  335. static Boolean SplitBit(tStrComp *pArg, Byte *Erg)
  336. {
  337.   tStrComp BitArg;
  338.   char *p;
  339.  
  340.   p = RQuotPos(pArg->str.p_str, '.');
  341.   if (!p)
  342.     return False;
  343.   StrCompSplitRef(pArg, &BitArg, pArg, p);
  344.  
  345.   if (strlen(BitArg.str.p_str) != 1) return False;
  346.   else if ((*BitArg.str.p_str >= '0') && (*BitArg.str.p_str <= '7'))
  347.   {
  348.     *Erg = *BitArg.str.p_str - '0';
  349.     return True;
  350.   }
  351.   else if (toupper(*BitArg.str.p_str) == 'A')
  352.   {
  353.     *Erg = 8;
  354.     return True;
  355.   }
  356.   else
  357.     return False;
  358. }
  359.  
  360. static void CodeMem(Byte Entry, Byte Opcode)
  361. {
  362.   BAsmCode[0] = Entry + AdrMode;
  363.   memcpy(BAsmCode + 1, AdrVals, AdrCnt);
  364.   BAsmCode[1 + AdrCnt] = Opcode;
  365. }
  366.  
  367. /*!------------------------------------------------------------------------
  368.  * \fn     decode_condition(const char *p_cond_str, Word *p_cond_code)
  369.  * \brief  parse condition code
  370.  * \param  p_cond_str source argument
  371.  * \param  p_cond_code machine code if found
  372.  * \return True if found
  373.  * ------------------------------------------------------------------------ */
  374.  
  375. static Boolean decode_condition(const char *p_cond_str, Word *p_cond_code)
  376. {
  377.   int z;
  378.  
  379.   for (z = 0; Conditions[z].Name; z++)
  380.     if (!as_strcasecmp(p_cond_str, Conditions[z].Name))
  381.     {
  382.       *p_cond_code = Conditions[z].Code;
  383.       return True;
  384.     }
  385.  
  386.   return False;
  387. }
  388.  
  389. /*!------------------------------------------------------------------------
  390.  * \fn     cond_code_tf(Word cond_code)
  391.  * \brief  check if condition is true or false
  392.  * \param  cond_code condition code to check
  393.  * \return True if yes
  394.  * ------------------------------------------------------------------------ */
  395.  
  396. static Boolean cond_code_tf(Word cond_code)
  397. {
  398.   return (cond_code == COND_CODE_TRUE)
  399.       || (cond_code == 0xdf);
  400. }
  401.  
  402. /*--------------------------------------------------------------------------*/
  403.  
  404. static void DecodeFixed(Word Code)
  405. {
  406.   if (ChkArgCnt(0, 0))
  407.   {
  408.     CodeLen = 0;
  409.     if (Hi(Code) != 0)
  410.       BAsmCode[CodeLen++] = Hi(Code);
  411.     BAsmCode[CodeLen++] = Lo(Code);
  412.   }
  413. }
  414.  
  415. static void DecodeLD(Word Code)
  416. {
  417.   Byte HReg, Bit, HCnt, HMode, HVals[2];
  418.   Boolean OK, NegFlag;
  419.  
  420.   UNUSED(Code);
  421.  
  422.   if (!ChkArgCnt(2, 2));
  423.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "PSW"))
  424.   {
  425.     BAsmCode[2] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  426.     if (OK)
  427.     {
  428.       BAsmCode[0] = 0xe8;
  429.       BAsmCode[1] = 0xde;
  430.       CodeLen = 3;
  431.     }
  432.   }
  433.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "RBS"))
  434.   {
  435.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt1, &OK) << 1;
  436.     if (OK)
  437.     {
  438.       BAsmCode[0] = 0xf9;
  439.       CodeLen = 2;
  440.     }
  441.   }
  442.   else if ((!as_strcasecmp(ArgStr[1].str.p_str, "SP")) && (DecodeSPDisp(&ArgStr[2], BAsmCode + 1, &NegFlag)))
  443.   {
  444.     BAsmCode[0] = NegFlag ? 0x3f : 0x37;
  445.     CodeLen = 2;
  446.   }
  447.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "CF"))
  448.   {
  449.     if (!SplitBit(&ArgStr[2], &Bit)) WrError(ErrNum_InvBitPos);
  450.     else
  451.     {
  452.       DecodeAdr(&ArgStr[2], (Bit < 8 ? MModReg8 : 0) | MModMem, False);
  453.       switch (AdrType)
  454.       {
  455.         case ModReg8:
  456.           CodeLen = 2;
  457.           BAsmCode[0] = 0xe8 | AdrMode;
  458.           BAsmCode[1] = 0x58 | Bit;
  459.           break;
  460.         case ModMem:
  461.           if ((Bit < 8) && (AdrMode == 0xe0))
  462.           {
  463.             CodeLen = 2;
  464.             BAsmCode[0] = 0x58 | Bit;
  465.             BAsmCode[1] = AdrVals[0];
  466.           }
  467.           else if (Bit < 8)
  468.           {
  469.             CodeLen = 2 + AdrCnt;
  470.             CodeMem(0x00, 0x58 | Bit);
  471.           }
  472.           else
  473.           {
  474.             CodeLen = 2 + AdrCnt;
  475.             CodeMem(0x00, 0xfc);
  476.           }
  477.           break;
  478.       }
  479.     }
  480.   }
  481.   else if (!as_strcasecmp(ArgStr[2].str.p_str, "CF"))
  482.   {
  483.     if (!SplitBit(&ArgStr[1], &Bit)) WrError(ErrNum_InvBitPos);
  484.     else
  485.     {
  486.       DecodeAdr(&ArgStr[1], (Bit < 8 ? MModReg8 : 0) | MModMem, False);
  487.       switch (AdrType)
  488.       {
  489.         case ModReg8:
  490.           CodeLen = 2;
  491.           BAsmCode[0] = 0xe8 | AdrMode;
  492.           BAsmCode[1] = 0xe8 | Bit;
  493.           break;
  494.         case ModMem:
  495.           if (Bit < 8)
  496.           {
  497.             CodeLen = 2 + AdrCnt;
  498.             CodeMem(0x00, 0xe8 | Bit);
  499.           }
  500.           else
  501.           {
  502.             CodeLen = 2 + AdrCnt;
  503.             CodeMem(0x00, 0xf3);
  504.           }
  505.           break;
  506.       }
  507.     }
  508.   }
  509.   else
  510.   {
  511.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, TRUE);
  512.     switch (AdrType)
  513.     {
  514.       case ModReg8:
  515.         HReg = AdrMode;
  516.         DecodeAdr(&ArgStr[2], MModReg8 | MModMem | MModImm, FALSE);
  517.         switch (AdrType)
  518.         {
  519.           case ModReg8:
  520.             if (HReg == AccReg)
  521.             {
  522.               CodeLen = 1; /* OK */
  523.               BAsmCode[0] = 0x10 | AdrMode;
  524.             }
  525.             else if (AdrMode == AccReg)
  526.             {
  527.               CodeLen = 1; /* OK */
  528.               BAsmCode[0] = 0x40 | HReg;
  529.             }
  530.             else
  531.             {
  532.               CodeLen = 2; /* OK */
  533.               BAsmCode[0] = 0xe8 | AdrMode;
  534.               BAsmCode[1] = 0x40 | HReg;
  535.             }
  536.             break;
  537.           case ModMem:
  538.             if ((HReg == AccReg) && (AdrMode == 0xe3))   /* A,(HL) */
  539.             {
  540.               CodeLen = 1; /* OK */
  541.               BAsmCode[0] = 0x0d;
  542.             }
  543.             else if ((HReg == AccReg) && (AdrMode == 0xe0)) /* A,(nn) */
  544.             {
  545.               CodeLen = 2; /* OK */
  546.               BAsmCode[0] = 0x0c;
  547.               BAsmCode[1] = AdrVals[0];
  548.             }
  549.             else
  550.             {
  551.               CodeLen = 2 + AdrCnt; /* OK */
  552.               CodeMem(0x00, 0x40 | HReg);
  553.             }
  554.             break;
  555.           case ModImm:
  556.             CodeLen = 2; /* OK */
  557.             BAsmCode[0] = 0x18 | HReg;
  558.             BAsmCode[1] = AdrVals[0];
  559.             break;
  560.         }
  561.         break;
  562.       case ModReg16:
  563.         HReg = AdrMode;
  564.         DecodeAdr(&ArgStr[2], MModReg16 | MModMem | MModImm, FALSE);
  565.         switch (AdrType)
  566.         {
  567.           case ModReg16:
  568.             CodeLen = 2; /* OK */
  569.             BAsmCode[0] = 0xe8 | AdrMode;
  570.             BAsmCode[1] = 0x18 | HReg;
  571.             break;
  572.           case ModMem:
  573.             CodeLen = 2 + AdrCnt; /* OK */
  574.             BAsmCode[0] = AdrMode;
  575.             memcpy(BAsmCode + 1, AdrVals, AdrCnt);
  576.             BAsmCode[1 + AdrCnt] = 0x48 + HReg;
  577.             break;
  578.           case ModImm:
  579.             CodeLen = 3; /* OK */
  580.             BAsmCode[0] = 0x48 | HReg;
  581.             memcpy(BAsmCode + 1, AdrVals, 2);
  582.             break;
  583.         }
  584.         break;
  585.       case ModMem:
  586.         memcpy(HVals, AdrVals, AdrCnt);
  587.         HCnt = AdrCnt;
  588.         HMode = AdrMode;
  589.         OpSize = 0;
  590.         DecodeAdr(&ArgStr[2], MModReg8 | MModReg16 | MModImm, FALSE);
  591.         switch (AdrType)
  592.         {
  593.           case ModReg8:
  594.             if ((HMode == 0xe3) && (AdrMode == AccReg))   /* (HL),A */
  595.             {
  596.               CodeLen = 1; /* OK */
  597.               BAsmCode[0] = 0x0f;
  598.             }
  599.             else if ((HMode == 0xe0) && (AdrMode == AccReg))
  600.             {
  601.               CodeLen = 2; /* OK */
  602.               BAsmCode[0] = 0x0e;
  603.               BAsmCode[1] = AdrVals[0];
  604.             }
  605.             else
  606.             {
  607.               CodeLen = 2 + HCnt; /* OK */
  608.               BAsmCode[0] = MakeDestMode(HMode);
  609.               memcpy(BAsmCode + 1, HVals, HCnt);
  610.               BAsmCode[1 + HCnt] = 0x78 | AdrMode;
  611.             }
  612.             break;
  613.           case ModReg16:
  614.             CodeLen = 2 + HCnt; /* OK */
  615.             BAsmCode[0] = MakeDestMode(HMode);
  616.             memcpy(BAsmCode + 1, HVals, HCnt);
  617.             BAsmCode[1 + HCnt] = 0x68 | AdrMode;
  618.             break;
  619.           case ModImm:
  620.             if (HMode == 0xe0) /* (nn),nn */
  621.             {
  622.               CodeLen = 3;
  623.               BAsmCode[0] = 0x0a;
  624.               BAsmCode[1] = HVals[0];
  625.               BAsmCode[2] = AdrVals[0];
  626.             }
  627.             else
  628.             {
  629.               CodeLen = 1 + HCnt + 1 + AdrCnt;
  630.               BAsmCode[0] = MakeDestMode(HMode);
  631.               memcpy(BAsmCode + 1, HVals, HCnt);
  632.               BAsmCode[1 + HCnt] = 0xf9;
  633.               BAsmCode[2 + HCnt] = AdrVals[0];
  634.             }
  635.             break;
  636.         }
  637.         break;
  638.     }
  639.   }
  640. }
  641.  
  642. static void DecodeLDW(Word Code)
  643. {
  644.   UNUSED(Code);
  645.  
  646.   if (ChkArgCnt(2, 2))
  647.   {
  648.     Boolean OK;
  649.     Integer AdrInt = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
  650.     if (OK)
  651.     {
  652.       DecodeAdr(&ArgStr[1], MModReg16 | MModMem, TRUE);
  653.       switch (AdrType)
  654.       {
  655.         case ModReg16:
  656.           CodeLen = 3;
  657.           BAsmCode[0] = 0x48 | AdrMode;
  658.           BAsmCode[1] = AdrInt & 0xff;
  659.           BAsmCode[2] = AdrInt >> 8;
  660.           break;
  661.         case ModMem:
  662.           if (AdrMode == 0xe3) /* HL */
  663.           {
  664.             CodeLen = 3;
  665.             BAsmCode[0] = 0x09;
  666.             BAsmCode[1] = AdrInt & 0xff;
  667.             BAsmCode[2] = AdrInt >> 8;
  668.           }
  669.           else if (AdrMode != 0xe0) WrError(ErrNum_InvAddrMode);  /* (nn) */
  670.           else
  671.           {
  672.             CodeLen = 3;
  673.             BAsmCode[0] = 0x08;
  674.             BAsmCode[1] = AdrInt & 0xff;
  675.             BAsmCode[2] = AdrInt >> 8;
  676.           }
  677.           break;
  678.       }
  679.     }
  680.   }
  681. }
  682.  
  683. static void DecodePUSH_POP(Word Code)
  684. {
  685.   if (!ChkArgCnt(1, 1));
  686.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "PSW"))
  687.   {
  688.     CodeLen = 2;
  689.     BAsmCode[0] = 0xe8;
  690.     BAsmCode[1] = 0xdc | Code;
  691.   }
  692.   else
  693.   {
  694.     DecodeAdr(&ArgStr[1], MModReg16, False);
  695.     if (AdrType != ModNone)
  696.     {
  697.       if (AdrMode < 4)
  698.       {
  699.         CodeLen = 1;
  700.         BAsmCode[0] = (Code << 7) | 0x50 | AdrMode;
  701.       }
  702.       else
  703.       {
  704.         CodeLen = 2;
  705.         BAsmCode[0] = 0xe8 | AdrMode;
  706.         BAsmCode[1] = 0xd8 | Code;
  707.       }
  708.     }
  709.   }
  710. }
  711.  
  712. static void DecodeXCH(Word Code)
  713. {
  714.   Byte HReg, HCnt;
  715.  
  716.   UNUSED(Code);
  717.  
  718.   if (ChkArgCnt(2, 2))
  719.   {
  720.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, FALSE); /* set IsDest FALSE for mirrored MemOp */
  721.     switch (AdrType)
  722.     {
  723.       case ModReg8:
  724.         HReg = AdrMode;
  725.         DecodeAdr(&ArgStr[2], MModReg8 | MModMem, FALSE);
  726.         switch (AdrType)
  727.         {
  728.           case ModReg8:
  729.             CodeLen = 2;
  730.             BAsmCode[0] = 0xe8 | AdrMode;
  731.             BAsmCode[1] = 0x70 | HReg;
  732.             break;
  733.           case ModMem:
  734.             CodeLen = 2 + AdrCnt;
  735.             CodeMem(0x00, 0x70 | HReg);
  736.             break;
  737.         }
  738.         break;
  739.       case ModReg16:
  740.         HReg = AdrMode;
  741.         DecodeAdr(&ArgStr[2], MModReg16 | MModMem, FALSE);
  742.         switch (AdrType)
  743.         {
  744.           case ModReg16:
  745.             CodeLen = 2;
  746.             BAsmCode[0] = 0xe8 | AdrMode;
  747.             BAsmCode[1] = 0x78 | HReg;
  748.             break;
  749.           case ModMem:
  750.             CodeLen = 2 + AdrCnt;
  751.             CodeMem(0x00, 0xd8 | HReg);
  752.             break;
  753.         }
  754.         break;
  755.       case ModMem:
  756.         BAsmCode[0] = AdrMode;
  757.         memcpy(BAsmCode + 1, AdrVals, AdrCnt);
  758.         HCnt = AdrCnt;
  759.         DecodeAdr(&ArgStr[2], MModReg8 | MModReg16, FALSE);
  760.         switch (AdrType)
  761.         {
  762.           case ModReg8:
  763.             CodeLen = 2 + HCnt;
  764.             BAsmCode[1 + HCnt] = 0x70 | AdrMode;
  765.             break;
  766.           case ModReg16:
  767.             CodeLen = 2 + HCnt;
  768.             BAsmCode[1 + HCnt] = 0xd8 | AdrMode;
  769.             break;
  770.         }
  771.         break;
  772.     }
  773.   }
  774. }
  775.  
  776. static void DecodeALU(Word Code)
  777. {
  778.   Byte HReg, HLen;
  779.  
  780.   if (!ChkArgCnt(2, 2));
  781.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "CF"))
  782.   {
  783.     Byte Bit;
  784.  
  785.     if (Code != 5) WrError(ErrNum_InvAddrMode); /* XOR only */
  786.     else if (!SplitBit(&ArgStr[2], &Bit)) WrError(ErrNum_InvBitPos);
  787.     else if (Bit >= 8) WrError(ErrNum_InvAddrMode); /* only fixed bit # */
  788.     else
  789.     {
  790.       DecodeAdr(&ArgStr[2], MModReg8 | MModMem, False);
  791.       switch (AdrType)
  792.       {
  793.         case ModReg8:
  794.           CodeLen = 2;
  795.           BAsmCode[0] = 0xe8 | AdrMode;
  796.           BAsmCode[1] = 0x50 | Bit;
  797.           break;
  798.         case ModMem:
  799.           CodeLen = 2 + AdrCnt;
  800.           CodeMem(0x00, 0x50 | Bit);
  801.           break;
  802.       }
  803.     }
  804.   }
  805.   else
  806.   {
  807.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, FALSE); /* (+SP) allowed as dest mem op instead of (SP-) */
  808.     switch (AdrType)
  809.     {
  810.       case ModReg8:
  811.         HReg = AdrMode;
  812.         DecodeAdr(&ArgStr[2], MModReg8 | MModMem | MModImm, FALSE);
  813.         switch (AdrType)
  814.         {
  815.           case ModReg8:
  816.             CodeLen = 2;
  817.             BAsmCode[0] = 0xe8 | AdrMode;
  818.             BAsmCode[1] = (HReg << 3) | Code;
  819.             break;
  820.           case ModMem:
  821.             CodeLen = 2 + AdrCnt;
  822.             CodeMem(0x00, (HReg << 3) | Code);
  823.             break;
  824.           case ModImm:
  825.             if (HReg == AccReg)
  826.             {
  827.               CodeLen = 2;
  828.               BAsmCode[0] = 0x60 | Code;
  829.               BAsmCode[1] = AdrVals[0];
  830.             }
  831.             else
  832.             {
  833.               CodeLen = 3;
  834.               BAsmCode[0] = 0xe8 | HReg;
  835.               BAsmCode[1] = 0x60 | Code;
  836.               BAsmCode[2] = AdrVals[0];
  837.             }
  838.             break;
  839.         }
  840.         break;
  841.       case ModReg16:
  842.         HReg = AdrMode;
  843.         DecodeAdr(&ArgStr[2], MModImm | MModMem | MModReg16, FALSE);
  844.         switch (AdrType)
  845.         {
  846.           case ModImm:
  847.             CodeLen = 4;
  848.             BAsmCode[0] = 0xe8 | HReg;
  849.             BAsmCode[1] = 0x68 | Code;
  850.             memcpy(BAsmCode + 2, AdrVals, AdrCnt);
  851.             break;
  852.           case ModMem:
  853.             CodeLen = 2 + AdrCnt;
  854.             CodeMem(0x00, 0x80 | (HReg << 3) | Code);
  855.             break;
  856.           case ModReg16:
  857.             CodeLen = 2;
  858.             BAsmCode[0] = 0xe8 | AdrMode;
  859.             BAsmCode[1] = 0x80 | (HReg << 3) | Code;
  860.             break;
  861.         }
  862.         break;
  863.       case ModMem:
  864.         if ((0xe0 == AdrMode) && (Code == 7))
  865.         {
  866.           BAsmCode[0] = Code;
  867.           BAsmCode[1] = AdrVals[0];
  868.           HLen = 2;
  869.         }
  870.         else
  871.         {
  872.           CodeMem(0x00, 0x60 | Code);
  873.           HLen = 2 + AdrCnt;
  874.         }
  875.         OpSize = 0;
  876.         DecodeAdr(&ArgStr[2], MModImm, FALSE);
  877.         if (AdrType == ModImm)
  878.         {
  879.           BAsmCode[HLen] = AdrVals[0];
  880.           CodeLen = HLen + 1;
  881.         }
  882.         break;
  883.     }
  884.   }
  885. }
  886.  
  887. static void DecodeINC_DEC(Word Code)
  888. {
  889.   if (ChkArgCnt(1, 1))
  890.   {
  891.     DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, False);
  892.     switch (AdrType)
  893.     {
  894.       case ModReg8:
  895.         CodeLen = 1;
  896.         BAsmCode[0] = 0x20 | Code | AdrMode;
  897.         break;
  898.       case ModReg16:
  899.         CodeLen = 1;
  900.         BAsmCode[0] = 0x30 | Code | AdrMode;
  901.         break;
  902.       case ModMem:
  903.         CodeLen = 2 + AdrCnt;
  904.         CodeMem(0x00, 0xf0 | Code);
  905.         break;
  906.     }
  907.   }
  908. }
  909.  
  910. static void DecodeReg(Word Code)
  911. {
  912.   if (ChkArgCnt(1, 1))
  913.   {
  914.     DecodeAdr(&ArgStr[1], MModReg8, False);
  915.     if (AdrType != ModNone)
  916.     {
  917.       CodeLen = 1;
  918.       BAsmCode[0] = Lo(Code) | AdrMode;
  919.       if (Hi(Code))
  920.         BAsmCode[CodeLen++] = Hi(Code);
  921.     }
  922.   }
  923. }
  924.  
  925. static void DecodeReg16(Word Code)
  926. {
  927.   if (ChkArgCnt(1, 1))
  928.   {
  929.     DecodeAdr(&ArgStr[1], MModReg16, False);
  930.     if (AdrType != ModNone)
  931.     {
  932.       CodeLen = 1;
  933.       BAsmCode[0] = Lo(Code) | AdrMode;
  934.       if (Hi(Code))
  935.         BAsmCode[CodeLen++] = Hi(Code);
  936.     }
  937.   }
  938. }
  939.  
  940. static void DecodeMUL(Word Code)
  941. {
  942.   UNUSED(Code);
  943.  
  944.   if (ChkArgCnt(2, 2))
  945.   {
  946.     DecodeAdr(&ArgStr[1], MModReg8, False);
  947.     if (AdrType == ModReg8)
  948.     {
  949.       Byte HReg = AdrMode;
  950.       DecodeAdr(&ArgStr[2], MModReg8, False);
  951.       if (AdrType == ModReg8)
  952.       {
  953.         if ((HReg ^ AdrMode) != 1) WrError(ErrNum_InvRegPair);
  954.         else
  955.         {
  956.           CodeLen = 2;
  957.           BAsmCode[0] = 0xe8 | (HReg >> 1);
  958.           BAsmCode[1] = 0xf2;
  959.         }
  960.       }
  961.     }
  962.   }
  963. }
  964.  
  965. static void DecodeDIV(Word Code)
  966. {
  967.   UNUSED(Code);
  968.  
  969.   if (ChkArgCnt(2, 2))
  970.   {
  971.     DecodeAdr(&ArgStr[1], MModReg16, False);
  972.     if (AdrType == ModReg16)
  973.     {
  974.       if ((AdrMode == 1) || (AdrMode > 3)) WrError(ErrNum_InvAddrMode); /* WA DE HL */
  975.       else
  976.       {
  977.         Byte HReg = AdrMode;
  978.         DecodeAdr(&ArgStr[2], MModReg8, False);
  979.         if (AdrType == ModReg8)
  980.         {
  981.           if (AdrMode != 2) WrError(ErrNum_InvAddrMode);  /* C */
  982.           else
  983.           {
  984.             CodeLen = 2;
  985.             BAsmCode[0] = 0xe8 | HReg;
  986.             BAsmCode[1] = 0xf3;
  987.           }
  988.         }
  989.       }
  990.     }
  991.   }
  992. }
  993.  
  994. static void DecodeNEG(Word Code)
  995. {
  996.   UNUSED(Code);
  997.  
  998.   if (!ChkArgCnt(2, 2));
  999.   else if (as_strcasecmp(ArgStr[1].str.p_str, "CS")) WrError(ErrNum_InvAddrMode);
  1000.   else
  1001.   {
  1002.     DecodeAdr(&ArgStr[2], MModReg16, False);
  1003.     if (AdrType == ModReg16)
  1004.     {
  1005.       CodeLen = 2;
  1006.       BAsmCode[0] = 0xe8 | AdrMode;
  1007.       BAsmCode[1] = 0xfa;
  1008.     }
  1009.   }
  1010. }
  1011.  
  1012. static void DecodeROLD_RORD(Word Code)
  1013. {
  1014.   if (!ChkArgCnt(2, 2));
  1015.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrError(ErrNum_InvAddrMode);
  1016.   else
  1017.   {
  1018.     DecodeAdr(&ArgStr[2], MModMem, False);
  1019.     if (AdrType != ModNone)
  1020.     {
  1021.       CodeLen = 2 + AdrCnt;
  1022.       CodeMem(0x00, Code);
  1023.     }
  1024.   }
  1025. }
  1026.  
  1027. static void DecodeTEST_CPL_SET_CLR(Word Code)
  1028. {
  1029.   Byte Bit;
  1030.  
  1031.   if (!ChkArgCnt(1, 1));
  1032.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "CF"))
  1033.   {
  1034.     switch (Lo(Code))
  1035.     {
  1036.       case 0xc0:
  1037.         BAsmCode[0] = 0xc5;
  1038.         CodeLen = 1;
  1039.         break;
  1040.       case 0xc8:
  1041.         BAsmCode[0] = 0xc4;
  1042.         CodeLen = 1;
  1043.         break;
  1044.       case 0xe0:
  1045.         BAsmCode[0] = 0xc6;
  1046.         CodeLen = 1;
  1047.         break;
  1048.       default:
  1049.         WrError(ErrNum_InvAddrMode);
  1050.     }
  1051.   }
  1052.   else if (!SplitBit(&ArgStr[1], &Bit)) WrError(ErrNum_InvBitPos);
  1053.   else
  1054.   {
  1055.     DecodeAdr(&ArgStr[1], (Bit < 8 ? MModReg8 : 0) | MModMem, False);
  1056.     switch (AdrType)
  1057.     {
  1058.       case ModReg8:
  1059.         CodeLen = 2;
  1060.         BAsmCode[0] = 0xe8 | AdrMode;
  1061.         BAsmCode[1] = Lo(Code) | Bit;
  1062.         break;
  1063.       case ModMem:
  1064.         if ((Bit < 8) && (AdrMode == 0xe0) && (Lo(Code) != 0xe0)) /* no short addr. for CPL */
  1065.         {
  1066.           CodeLen = 2;
  1067.           BAsmCode[0] = Lo(Code) | Bit;
  1068.           BAsmCode[1] = AdrVals[0];
  1069.         }
  1070.         else if (Bit < 8)
  1071.         {
  1072.           CodeLen = 2 + AdrCnt;
  1073.           CodeMem(0x00, Lo(Code) | Bit);
  1074.         }
  1075.         else
  1076.         {
  1077.           CodeLen = 2 + AdrCnt;
  1078.           CodeMem(0x00, Hi(Code));
  1079.         }
  1080.         break;
  1081.     }
  1082.   }
  1083. }
  1084.  
  1085. static void DecodeJRS(Word Code)
  1086. {
  1087.   UNUSED(Code);
  1088.  
  1089.   if (ChkArgCnt(2, 2))
  1090.   {
  1091.     Integer AdrInt;
  1092.     Word cond_code;
  1093.     Boolean OK;
  1094.     tSymbolFlags Flags;
  1095.  
  1096.     /* only T/F allowed */
  1097.     if (!decode_condition(ArgStr[1].str.p_str, &cond_code) || !cond_code_tf(cond_code)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  1098.     else
  1099.     {
  1100.       AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[2], Int16, &OK, &Flags) - (EProgCounter() + 2);
  1101.       if (OK)
  1102.       {
  1103.         if (((AdrInt < -16) || (AdrInt > 15)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
  1104.         else
  1105.         {
  1106.           CodeLen = 1;
  1107.           BAsmCode[0] = 0x80 | ((cond_code - 0xde) << 5) | (AdrInt & 0x1f);
  1108.         }
  1109.       }
  1110.     }
  1111.   }
  1112. }
  1113.  
  1114. static void DecodeJR(Word Code)
  1115. {
  1116.   UNUSED(Code);
  1117.  
  1118.   if (ChkArgCnt(1, 2))
  1119.   {
  1120.     Word cond_code;
  1121.     Integer AdrInt;
  1122.     int Delta;
  1123.     Boolean OK;
  1124.     tSymbolFlags Flags;
  1125.  
  1126.     if (ArgCnt == 1)
  1127.       cond_code = COND_CODE_TRUE;
  1128.     else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
  1129.     {
  1130.       WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  1131.       return;
  1132.     }
  1133.  
  1134.       Delta = ((ArgCnt == 1) || (!Hi(cond_code))) ? 2 : 3;
  1135.  
  1136.       AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int16, &OK, &Flags) - (EProgCounter() + Delta);
  1137.       if (OK)
  1138.       {
  1139.         if (((AdrInt < -128) || (AdrInt > 127)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
  1140.         else
  1141.         {
  1142.           if (3 == Delta)
  1143.             BAsmCode[CodeLen++] = Hi(cond_code);
  1144.           BAsmCode[CodeLen++] = (ArgCnt == 1) ?  0xfc : Lo(cond_code);
  1145.           BAsmCode[CodeLen++] = AdrInt & 0xff;
  1146.         }
  1147.       }
  1148.   }
  1149. }
  1150.  
  1151. static void DecodeJ(Word Code)
  1152. {
  1153.   UNUSED(Code);
  1154.  
  1155.   if (ChkArgCnt(1, 2))
  1156.   {
  1157.     Word cond_code;
  1158.  
  1159.     if (ArgCnt == 1)
  1160.       cond_code = COND_CODE_TRUE;
  1161.     else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
  1162.     {
  1163.       WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  1164.       return;
  1165.     }
  1166.  
  1167.     OpSize = 1;
  1168.     DecodeAdr(&ArgStr[ArgCnt], MModReg16 | MModMem | MModImm, False);
  1169.     switch (AdrType)
  1170.     {
  1171.       case ModReg16: /* -> JP */
  1172.         if (cond_code != COND_CODE_TRUE) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  1173.         else
  1174.         {
  1175.           CodeLen = 2;
  1176.           BAsmCode[0] = 0xe8 | AdrMode;
  1177.           BAsmCode[1] = Code;
  1178.         }
  1179.         break;
  1180.       case ModMem: /* -> JP */
  1181.         if (cond_code != COND_CODE_TRUE) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  1182.         else
  1183.         {
  1184.           CodeLen = 2 + AdrCnt;
  1185.           CodeMem(0x00, Code);
  1186.         }
  1187.         break;
  1188.       case ModImm:
  1189.       {
  1190.         Word Adr = ((Word)(AdrVals[1] << 8)) | AdrVals[0];
  1191.         Integer Dist = Adr - (EProgCounter() + 2);
  1192.         int Delta = ((ArgCnt == 1) || !Hi(cond_code)) ? 2 : 3;
  1193.  
  1194.         /* TODO: the ArgCnt != 1 check is only necessary to get same
  1195.            encoding as previous versions.  Encoding 'J xxx' as 'JRS T,XXX'
  1196.            if possible would actually be smarter: */
  1197.  
  1198.         if ((Dist >= -16) && (Dist < 15) && (ArgCnt != 1) && cond_code_tf(cond_code)) /* JRS T/F */
  1199.         {
  1200.           CodeLen = 1;
  1201.           BAsmCode[0] = 0x80 | ((cond_code - 0xde) << 5) | (Dist & 0x1f);
  1202.         }
  1203.         else if ((Dist >= -128) && (Dist < 127))
  1204.         {
  1205.           if (ArgCnt == 1) /* JR dist */
  1206.           {
  1207.             BAsmCode[CodeLen++] = 0xfc;
  1208.             BAsmCode[CodeLen++] = Dist & 0xff;
  1209.           }
  1210.           else /* JR cc, dist */
  1211.           {
  1212.             if (3 == Delta)
  1213.               BAsmCode[CodeLen++] = Hi(cond_code);
  1214.             BAsmCode[CodeLen++] = Lo(cond_code);
  1215.             BAsmCode[CodeLen++] = Dist & 0xff;
  1216.           }
  1217.         }
  1218.         else
  1219.         {
  1220.           if (ArgCnt == 1) /* JP dest */
  1221.           {
  1222.             BAsmCode[CodeLen++] = 0xfe;
  1223.             BAsmCode[CodeLen++] = Lo(Adr);
  1224.             BAsmCode[CodeLen++] = Hi(Adr);
  1225.           }
  1226.           else /* JR !cc, JP dest */
  1227.           {
  1228.             cond_code ^= 1;
  1229.             if (3 == Delta)
  1230.               BAsmCode[CodeLen++] = Hi(cond_code);
  1231.             BAsmCode[CodeLen++] = Lo(cond_code);
  1232.             BAsmCode[CodeLen++] = 3;
  1233.             BAsmCode[CodeLen++] = 0xfe;
  1234.             BAsmCode[CodeLen++] = Lo(Adr);
  1235.             BAsmCode[CodeLen++] = Hi(Adr);
  1236.           }
  1237.         }
  1238.         break;
  1239.       }
  1240.     }
  1241.   }
  1242. }
  1243.  
  1244. static void DecodeJP_CALL(Word Code)
  1245. {
  1246.   UNUSED(Code);
  1247.  
  1248.   if (ChkArgCnt(1, 1))
  1249.   {
  1250.     OpSize = 1;
  1251.     DecodeAdr(&ArgStr[1], MModReg16 | MModMem | MModImm, False);
  1252.     switch (AdrType)
  1253.     {
  1254.       case ModReg16:
  1255.         CodeLen = 2;
  1256.         BAsmCode[0] = 0xe8 | AdrMode;
  1257.         BAsmCode[1] = Code;
  1258.         break;
  1259.       case ModMem:
  1260.         CodeLen = 2 + AdrCnt;
  1261.         CodeMem(0x00, Code);
  1262.         break;
  1263.       case ModImm:
  1264.         CodeLen = 3;
  1265.         BAsmCode[0] = Code;
  1266.         memcpy(BAsmCode + 1, AdrVals, AdrCnt);
  1267.         break;
  1268.     }
  1269.   }
  1270. }
  1271.  
  1272. static void DecodeCALLV(Word Code)
  1273. {
  1274.   UNUSED(Code);
  1275.  
  1276.   if (ChkArgCnt(1, 1))
  1277.   {
  1278.     Boolean OK;
  1279.     Byte HVal = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
  1280.     if (OK)
  1281.     {
  1282.       CodeLen = 1;
  1283.       BAsmCode[0] = 0x70 | (HVal & 15);
  1284.     }
  1285.   }
  1286. }
  1287.  
  1288. /*--------------------------------------------------------------------------*/
  1289.  
  1290. static void AddFixed(const char *NName, Word NCode)
  1291. {
  1292.   AddInstTable(InstTable, NName, NCode, DecodeFixed);
  1293. }
  1294.  
  1295. static void AddCond(const char *NName, Word NCode)
  1296. {
  1297.   order_array_rsv_end(Conditions, CondRec);
  1298.   Conditions[InstrZ].Name = NName;
  1299.   Conditions[InstrZ++].Code = NCode;
  1300. }
  1301.  
  1302. static void AddReg(const char *NName, Word NCode)
  1303. {
  1304.   AddInstTable(InstTable, NName, NCode, DecodeReg);
  1305. }
  1306.  
  1307. static void AddReg16(const char *NName, Word NCode)
  1308. {
  1309.   AddInstTable(InstTable, NName, NCode, DecodeReg16);
  1310. }
  1311.  
  1312. static void InitFields(void)
  1313. {
  1314.   InstTable = CreateInstTable(203);
  1315.  
  1316.   add_null_pseudo(InstTable);
  1317.  
  1318.   AddInstTable(InstTable, "LD", 0, DecodeLD);
  1319.   AddInstTable(InstTable, "LDW", 0, DecodeLDW);
  1320.   AddInstTable(InstTable, "PUSH", 0, DecodePUSH_POP);
  1321.   AddInstTable(InstTable, "POP", 1, DecodePUSH_POP);
  1322.   AddInstTable(InstTable, "XCH", 0, DecodeXCH);
  1323.   AddInstTable(InstTable, "INC", 0, DecodeINC_DEC);
  1324.   AddInstTable(InstTable, "DEC", 8, DecodeINC_DEC);
  1325.   AddInstTable(InstTable, "MUL", 0, DecodeMUL);
  1326.   AddInstTable(InstTable, "DIV", 0, DecodeDIV);
  1327.   AddInstTable(InstTable, "NEG", 0, DecodeNEG);
  1328.   AddInstTable(InstTable, "ROLD", 0xf6, DecodeROLD_RORD);
  1329.   AddInstTable(InstTable, "RORD", 0xf7, DecodeROLD_RORD);
  1330.   AddInstTable(InstTable, "CLR", 0xfac8, DecodeTEST_CPL_SET_CLR);
  1331.   AddInstTable(InstTable, "TEST", 0xfc58, DecodeTEST_CPL_SET_CLR);
  1332.   AddInstTable(InstTable, "CPL", 0xfbe0, DecodeTEST_CPL_SET_CLR);
  1333.   AddInstTable(InstTable, "SET", 0xf2c0, DecodeTEST_CPL_SET_CLR);
  1334.   AddInstTable(InstTable, "JR", 0, DecodeJR);
  1335.   AddInstTable(InstTable, "JRS", 0, DecodeJRS);
  1336.   AddInstTable(InstTable, "JP", 0xfe, DecodeJP_CALL);
  1337.   AddInstTable(InstTable, "J", 0, DecodeJ);
  1338.   AddInstTable(InstTable, "CALL", 0xfd, DecodeJP_CALL);
  1339.   AddInstTable(InstTable, "CALLV", 0, DecodeCALLV);
  1340.  
  1341.   AddFixed("DI"  , 0xc83a);
  1342.   AddFixed("EI"  , 0xc03a);
  1343.   AddFixed("RET" , 0x00fa);
  1344.   AddFixed("RETI", 0x00fb);
  1345.   AddFixed("RETN", 0xe8fb);
  1346.   AddFixed("SWI" , 0x00ff);
  1347.   AddFixed("NOP" , 0x0000);
  1348.  
  1349.   InstrZ = 0;
  1350.   AddCond("EQ" , 0x00d8); AddCond("Z"  , 0x00d8);
  1351.   AddCond("NE" , 0x00d9); AddCond("NZ" , 0x00d9);
  1352.   AddCond("CS" , 0x00da); AddCond("LT" , 0x00da);
  1353.   AddCond("CC" , 0x00db); AddCond("GE" , 0x00db);
  1354.   AddCond("LE" , 0x00dc); AddCond("GT" , 0x00dd);
  1355.   AddCond("M"  , 0xe8d0); AddCond("P"  , 0xe8d1);
  1356.   AddCond("SLT", 0xe8d2); AddCond("SGE", 0xe8d3);
  1357.   AddCond("SLE", 0xe8d4); AddCond("SGT", 0xe8d5);
  1358.   AddCond("VS" , 0xe8d6); AddCond("VC" , 0xe8d7);
  1359.   AddCond("T"  , COND_CODE_TRUE); AddCond("F"  , 0x00df);
  1360.   AddCond(NULL , 0);
  1361.  
  1362.   AddReg("DAA" , 0xdae8);  AddReg("DAS" , 0xdbe8);
  1363.   AddReg("SHLC", 0xf4e8);  AddReg("SHRC", 0xf5e8);
  1364.   AddReg("ROLC", 0xf6e8);  AddReg("RORC", 0xf7e8);
  1365.   AddReg("SWAP", 0xffe8);
  1366.  
  1367.   AddReg16("SHLCA", 0xf0e8); AddReg16("SHRCA", 0xf1e8);
  1368.  
  1369.   InstrZ = 0;
  1370.   AddInstTable(InstTable, "ADDC", InstrZ++, DecodeALU);
  1371.   AddInstTable(InstTable, "ADD" , InstrZ++, DecodeALU);
  1372.   AddInstTable(InstTable, "SUBB", InstrZ++, DecodeALU);
  1373.   AddInstTable(InstTable, "SUB" , InstrZ++, DecodeALU);
  1374.   AddInstTable(InstTable, "AND" , InstrZ++, DecodeALU);
  1375.   AddInstTable(InstTable, "XOR" , InstrZ++, DecodeALU);
  1376.   AddInstTable(InstTable, "OR"  , InstrZ++, DecodeALU);
  1377.   AddInstTable(InstTable, "CMP" , InstrZ++, DecodeALU);
  1378.  
  1379.   AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
  1380. }
  1381.  
  1382. static void DeinitFields(void)
  1383. {
  1384.   DestroyInstTable(InstTable);
  1385.  
  1386.   order_array_free(Conditions);
  1387. }
  1388.  
  1389. /*--------------------------------------------------------------------------*/
  1390.  
  1391. static void MakeCode_870C(void)
  1392. {
  1393.   OpSize = eSymbolSizeUnknown;
  1394.  
  1395.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  1396.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  1397. }
  1398.  
  1399. static Boolean IsDef_870C(void)
  1400. {
  1401.   return False;
  1402. }
  1403.  
  1404. static void SwitchFrom_870C(void)
  1405. {
  1406.   DeinitFields();
  1407. }
  1408.  
  1409. static Boolean TrueFnc(void)
  1410. {
  1411.   return True;
  1412. }
  1413.  
  1414. static void SwitchTo_870C(void)
  1415. {
  1416.   const TFamilyDescr *FoundDescr;
  1417.  
  1418.   FoundDescr = FindFamilyByName("TLCS-870/C");
  1419.  
  1420.   TurnWords = False;
  1421.   SetIntConstMode(eIntConstModeIntel);
  1422.   SetIsOccupiedFnc = TrueFnc;
  1423.  
  1424.   PCSymbol = "$";
  1425.   HeaderID = FoundDescr->Id;
  1426.   NOPCode = 0x00;
  1427.   DivideChars = ",";
  1428.   HasAttrs = False;
  1429.  
  1430.   ValidSegs = 1 << SegCode;
  1431.   Grans[SegCode] = 1;
  1432.   ListGrans[SegCode] = 1;
  1433.   SegInits[SegCode] = 0;
  1434.   SegLimits[SegCode] = 0xffff;
  1435.  
  1436.   MakeCode = MakeCode_870C;
  1437.   IsDef = IsDef_870C;
  1438.   SwitchFrom = SwitchFrom_870C;
  1439.   InitFields();
  1440. }
  1441.  
  1442. void code870c_init(void)
  1443. {
  1444.   CPU870C = AddCPU("TLCS-870/C", SwitchTo_870C);
  1445. }
  1446.