Subversion Repositories pentevo

Rev

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

  1. /* code48.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegeneratormodul MCS-48-Familie                                         */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include "bpemu.h"
  13. #include <string.h>
  14. #include <ctype.h>
  15.  
  16. #include "nls.h"
  17. #include "strutil.h"
  18. #include "stringlists.h"
  19. #include "asmdef.h"
  20. #include "asmsub.h"
  21. #include "asmpars.h"
  22. #include "asmallg.h"
  23. #include "asmitree.h"
  24. #include "codepseudo.h"
  25. #include "intpseudo.h"
  26. #include "codevars.h"
  27. #include "errmsg.h"
  28.  
  29. #include "code48.h"
  30.  
  31. typedef struct
  32. {
  33.   const char *Name;
  34.   Byte Code;
  35. } SelOrder;
  36.  
  37. typedef enum
  38. {
  39.   ModImm = 0,
  40.   ModReg = 1,
  41.   ModInd = 2,
  42.   ModAcc = 3,
  43.   ModNone = -1
  44. } tAdrMode;
  45.  
  46. #define MModImm (1 << ModImm)
  47. #define MModReg (1 << ModReg)
  48. #define MModInd (1 << ModInd)
  49. #define MModAcc (1 << ModAcc)
  50.  
  51. #define eCPUFlagCMOS (1ul << 0)
  52. #define eCPUFlagSiemens (1ul << 1)
  53. #define eCPUFlagDEC_DJNZ_IREG (1ul << 2)
  54. #define eCPUFlagXMem (1ul << 3)
  55. #define eCPUFlagUPIPort (1ul << 4)
  56. #define eCPUFlagPort0 (1ul << 5)
  57. #define eCPUFlagPort1 (1ul << 6)
  58. #define eCPUFlagPort2 (1ul << 7)
  59. #define eCPUFlagIOExpander (1ul << 8)
  60. #define eCPUFlagUserFlags (1ul << 9)
  61. #define eCPUFlagT0 (1ul << 10)
  62. #define eCPUFlagT0CLK (1ul << 11)
  63. #define eCPUFlagCondBitJmp (1ul << 12)
  64. #define eCPUFlagTransferA_PSW (1ul << 13)
  65. #define eCPUFlagBUS (1ul << 14)
  66. #define eCPUFlagRegBanks (1ul << 15)
  67. #define eCPUFlagADConv (1ul << 16)
  68. #define eCPUFlagLogToPort (1ul << 17)
  69. #define eCPUFlagDEC_REG (1ul << 18)
  70. #define eCPUFlagMOVP3 (1ul << 19)
  71. #define eCPUFlagINTLogic (1ul << 20)
  72. #define eCPUFlagOKI (1ul << 21)
  73. #define eCPUFlagSerial (1ul << 22)
  74. #define eCPUFlag84xx (1ul << 23)
  75.  
  76. #define MB_NOTHING 0xff
  77.  
  78. typedef struct
  79. {
  80.   const char *pName;
  81.   Word CodeSize;
  82.   LongWord Flags;
  83. } tCPUProps;
  84.  
  85. typedef struct
  86. {
  87.   const char *p_val;
  88.   Byte code;
  89. } clr_cpl_t;
  90.  
  91. static const tCPUProps *pCurrCPUProps;
  92. static tAdrMode AdrMode;
  93. static Byte AdrVal;
  94. clr_cpl_t *clr_cpl_args;
  95. static SelOrder *SelOrders;
  96. static LongInt Reg_MB;
  97.  
  98. /****************************************************************************/
  99.  
  100. /*!------------------------------------------------------------------------
  101.  * \fn     DecodeRegCore(const char *pAsc, tRegInt *pValue, tSymbolSize *pSize)
  102.  * \brief  check whether argument describes a CPU register
  103.  * \param  pAsc argument
  104.  * \param  pValue resulting register # if yes
  105.  * \param  pSize resulting register size if yes
  106.  * \return true if yes
  107.  * ------------------------------------------------------------------------ */
  108.  
  109. static Boolean DecodeRegCore(const char *pAsc, tRegInt *pValue, tSymbolSize *pSize)
  110. {
  111.   if ((strlen(pAsc) != 2)
  112.    || (as_toupper(pAsc[0]) != 'R')
  113.    || (!isdigit(pAsc[1])))
  114.     return False;
  115.  
  116.   *pValue = pAsc[1] - '0';
  117.   *pSize = eSymbolSize8Bit;
  118.   return (*pValue <= 7);
  119. }
  120.  
  121. /*!------------------------------------------------------------------------
  122.  * \fn     DissectReg_48(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  123.  * \brief  dissect register symbols - 8048 variant
  124.  * \param  pDest destination buffer
  125.  * \param  DestSize destination buffer size
  126.  * \param  Value numeric register value
  127.  * \param  InpSize register size
  128.  * ------------------------------------------------------------------------ */
  129.  
  130. static void DissectReg_48(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  131. {
  132.   switch (InpSize)
  133.   {
  134.     case eSymbolSize8Bit:
  135.       as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
  136.       break;
  137.     default:
  138.       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
  139.   }
  140. }
  141.  
  142. /*!------------------------------------------------------------------------
  143.  * \fn     DecodeReg(const tStrComp *pArg, Byte *pValue, Boolean MustBeReg)
  144.  * \brief  check whether argument is a CPU register or user-defined register alias
  145.  * \param  pArg argument
  146.  * \param  pValue resulting register # if yes
  147.  * \param  MustBeReg expect register at this arg?
  148.  * \return eIsReg/eIsNoReg/eRegAbort
  149.  * ------------------------------------------------------------------------ */
  150.  
  151. static tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pValue, Boolean MustBeReg)
  152. {
  153.   tSymbolSize Size;
  154.   tRegDescr RegDescr;
  155.   tEvalResult EvalResult;
  156.   tRegEvalResult RegEvalResult;
  157.  
  158.   if (DecodeRegCore(pArg->str.p_str, &RegDescr.Reg, &Size))
  159.   {
  160.     *pValue = RegDescr.Reg;
  161.     return eIsReg;
  162.   }
  163.  
  164.   RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
  165.   *pValue = RegDescr.Reg;
  166.   return RegEvalResult;
  167. }
  168.  
  169. static Boolean IsPort(const char *pArg, Word PortMask, Byte *pPortNum)
  170. {
  171.   if (!as_strcasecmp(pArg, "BUS"))
  172.     *pPortNum = 8;
  173.   else if ((strlen(pArg) == 2)
  174.         && (as_toupper(pArg[0]) == 'P')
  175.         && isdigit(pArg[1]))
  176.     *pPortNum = pArg[1] - '0';
  177.   else
  178.     return False;
  179.  
  180.   return !!(PortMask & (1 << *pPortNum));
  181. }
  182.  
  183. static Boolean IsSerialPort(const char *pArg, Word PortMask, Byte *pPortNum)
  184. {
  185.   if ((strlen(pArg) == 2)
  186.    && (as_toupper(pArg[0]) == 'S')
  187.    && isdigit(pArg[1]))
  188.     *pPortNum = pArg[1] - '0';
  189.   else
  190.     return False;
  191.  
  192.   return !!(PortMask & (1 << *pPortNum));
  193. }
  194.  
  195. static tAdrMode DecodeAdr(const tStrComp *pArg, unsigned Mask)
  196. {
  197.   Boolean OK;
  198.  
  199.   AdrMode = ModNone;
  200.  
  201.   if (*pArg->str.p_str == '\0') return ModNone;
  202.  
  203.   if (!as_strcasecmp(pArg->str.p_str, "A"))
  204.   {
  205.     AdrMode = ModAcc;
  206.     goto found;
  207.   }
  208.  
  209.   if (*pArg->str.p_str == '#')
  210.   {
  211.     AdrVal = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK);
  212.     if (OK)
  213.     {
  214.       AdrMode = ModImm;
  215.       BAsmCode[1] = AdrVal;
  216.       goto found;
  217.     }
  218.   }
  219.  
  220.   switch (DecodeReg(pArg, &AdrVal, False))
  221.   {
  222.     case eIsReg:
  223.       AdrMode = ModReg;
  224.       goto found;
  225.     case eRegAbort:
  226.       return ModNone;
  227.     default:
  228.       break;
  229.   }
  230.  
  231.   if (*pArg->str.p_str == '@')
  232.   {
  233.     tStrComp Arg;
  234.  
  235.     StrCompRefRight(&Arg, pArg, 1);
  236.     if (!DecodeReg(&Arg, &AdrVal, True))
  237.       return ModNone;
  238.     if (AdrVal > 1)
  239.     {
  240.       WrStrErrorPos(ErrNum_InvReg, &Arg);
  241.       return ModNone;
  242.     }
  243.     AdrMode = ModInd;
  244.     goto found;
  245.   }
  246.  
  247.   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  248.  
  249. found:
  250.   if ((AdrMode != ModNone) && !(Mask & (1 << AdrMode)))
  251.   {
  252.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  253.      AdrMode= ModNone;
  254.   }
  255.   return AdrMode;
  256. }
  257.  
  258. static Boolean ChkCPUFlags(LongWord CPUFlags)
  259. {
  260.   if (pCurrCPUProps->Flags & CPUFlags)
  261.     return True;
  262.   WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
  263.   return False;
  264. }
  265.  
  266. static Boolean AChkCPUFlags(LongWord CPUFlags, const tStrComp *pArg)
  267. {
  268.   if (pCurrCPUProps->Flags & CPUFlags)
  269.     return True;
  270.   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  271.   return False;
  272. }
  273.  
  274. static void ChkPx(Byte PortNum, const tStrComp *pArg)
  275. {
  276.   if (!(pCurrCPUProps->Flags & (eCPUFlagPort0 << PortNum)))
  277.   {
  278.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  279.     CodeLen = 0;
  280.   }
  281. }
  282.  
  283. static Boolean IsIReg3(const tStrComp *pArg)
  284. {
  285.   tStrComp Arg;
  286.   Byte RegNum;
  287.  
  288.   if (*pArg->str.p_str != '@')
  289.     return False;
  290.   StrCompRefRight(&Arg, pArg, 1);
  291.   if (!DecodeReg(&Arg, &RegNum, True))
  292.     return False;
  293.   if (RegNum != 3)
  294.   {
  295.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  296.     return False;
  297.   }
  298.   return True;
  299. }
  300.  
  301. /****************************************************************************/
  302.  
  303. static void DecodeADD_ADDC(Word Code)
  304. {
  305.   if (!ChkArgCnt(2, 2));
  306.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  307.   else
  308.   {
  309.     switch (DecodeAdr(&ArgStr[2], MModImm | MModReg | MModInd))
  310.     {
  311.       case ModImm:
  312.         CodeLen = 2;
  313.         BAsmCode[0] = Code + 0x03;
  314.         break;
  315.       case ModReg:
  316.         CodeLen = 1;
  317.         BAsmCode[0] = Code + 0x68 + AdrVal;
  318.         break;
  319.       case ModInd:
  320.         CodeLen = 1;
  321.         BAsmCode[0] = Code + 0x60 + AdrVal;
  322.         break;
  323.       default:
  324.         break;
  325.     }
  326.   }
  327. }
  328.  
  329. static void DecodeANL_ORL_XRL(Word Code)
  330. {
  331.   Byte PortNum;
  332.   Word PortMask = 0x06;
  333.  
  334.   if (pCurrCPUProps->Flags & eCPUFlagBUS)
  335.     PortMask |= 0x100;
  336.   if (pCurrCPUProps->Flags & eCPUFlag84xx)
  337.     PortMask |= 0x01;
  338.  
  339.   if (!ChkArgCnt(2, 2));
  340.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
  341.   {
  342.     switch (DecodeAdr(&ArgStr[2], MModImm | MModReg | MModInd))
  343.     {
  344.       case ModImm:
  345.         CodeLen = 2;
  346.         BAsmCode[0] = Code + 0x43;
  347.         break;
  348.       case ModReg:
  349.         CodeLen = 1;
  350.         BAsmCode[0] = Code + 0x48 + AdrVal;
  351.         break;
  352.       case ModInd:
  353.         CodeLen = 1;
  354.         BAsmCode[0] = Code + 0x40 + AdrVal;
  355.         break;
  356.       default:
  357.         break;
  358.     }
  359.   }
  360.   else if (IsPort(ArgStr[1].str.p_str, PortMask, &PortNum))
  361.   {
  362.     if (Code == 0x90) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]); /* no XRL to ports */
  363.     else if (AChkCPUFlags(eCPUFlagLogToPort, &ArgStr[1]))
  364.     {
  365.       if (DecodeAdr(&ArgStr[2], MModImm) == ModImm)
  366.       {
  367.         CodeLen = 2;
  368.         BAsmCode[0] = Code + 0x88 + (PortNum & 3);
  369.         if (PortNum)
  370.           ChkPx(PortNum, &ArgStr[1]);
  371.       }
  372.     }
  373.   }
  374.   else
  375.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  376. }
  377.  
  378. static void DecodeCALL_JMP(Word Code)
  379. {
  380.   if (!ChkArgCnt(1, 1));
  381.   else if ((EProgCounter() & 0x7fe) == 0x7fe) WrError(ErrNum_NotOnThisAddress);
  382.   else
  383.   {
  384.     tEvalResult EvalResult;
  385.     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
  386.  
  387.     if (EvalResult.OK)
  388.     {
  389.       if (AdrWord > SegLimits[SegCode]) WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
  390.       else
  391.       {
  392.         Word DestBank = (AdrWord >> 11) & 3,
  393.              CurrBank = (EProgCounter() >> 11) & 3;
  394.  
  395.         if (Reg_MB == MB_NOTHING)
  396.         {
  397.           if (CurrBank != DestBank)
  398.           {
  399.             BAsmCode[0] = SelOrders[DestBank].Code;
  400.             CodeLen = 1;
  401.           }
  402.         }
  403.         else if ((DestBank != Reg_MB) && !mFirstPassUnknownOrQuestionable(EvalResult.Flags))
  404.           WrStrErrorPos(ErrNum_InAccPage, &ArgStr[1]);
  405.         BAsmCode[CodeLen + 1] = AdrWord & 0xff;
  406.         BAsmCode[CodeLen] = Code + ((AdrWord & 0x700) >> 3);
  407.         CodeLen += 2;
  408.         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  409.       }
  410.     }
  411.   }
  412. }
  413.  
  414. static void DecodeCLR_CPL(Word Code)
  415. {
  416.   if (!ChkArgCnt(1, 1));
  417.   else
  418.   {
  419.     int z = 0;
  420.     Boolean OK = False;
  421.  
  422.     NLS_UpString(ArgStr[1].str.p_str);
  423.     do
  424.     {
  425.       if (!strcmp(clr_cpl_args[z].p_val, ArgStr[1].str.p_str))
  426.       {
  427.         if ((*ArgStr[1].str.p_str == 'F') && !(pCurrCPUProps->Flags & eCPUFlagUserFlags)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  428.         else
  429.         {
  430.           CodeLen = 1;
  431.           BAsmCode[0] = clr_cpl_args[z].code;
  432.           OK = True;
  433.         }
  434.       }
  435.       z++;
  436.     }
  437.     while ((clr_cpl_args[z].p_val) && (CodeLen != 1));
  438.     if (!OK)
  439.       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  440.     else
  441.       BAsmCode[0] += Code;
  442.   }
  443. }
  444.  
  445. static void DecodeAcc(Word Code)
  446. {
  447.   if (!ChkArgCnt(1, 1));
  448.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  449.   else
  450.   {
  451.     CodeLen = 1;
  452.     BAsmCode[0] = Code;
  453.   }
  454. }
  455.  
  456. static void DecodeDEC(Word Code)
  457. {
  458.   UNUSED(Code);
  459.  
  460.   if (!ChkArgCnt(1, 1));
  461.   else
  462.   {
  463.     switch (DecodeAdr(&ArgStr[1], MModAcc | MModReg | MModInd))
  464.     {
  465.       case ModAcc:
  466.         CodeLen = 1;
  467.         BAsmCode[0] = 0x07;
  468.         break;
  469.       case ModReg:
  470.         if (AChkCPUFlags(eCPUFlagDEC_REG, &ArgStr[1]))
  471.         {
  472.           CodeLen = 1;
  473.           BAsmCode[0] = 0xc8 + AdrVal;
  474.         }
  475.         break;
  476.       case ModInd:
  477.         if (AChkCPUFlags(eCPUFlagDEC_DJNZ_IREG, &ArgStr[1]))
  478.         {
  479.           CodeLen = 1;
  480.           BAsmCode[0] = 0xc0 | AdrVal;
  481.         }
  482.         break;
  483.       default:
  484.         break;
  485.     }
  486.   }
  487. }
  488.  
  489. static void DecodeDIS_EN(Word Code)
  490. {
  491.   if (ChkArgCnt(1, 1))
  492.   {
  493.     NLS_UpString(ArgStr[1].str.p_str);
  494.     if (!strcmp(ArgStr[1].str.p_str, "I"))
  495.     {
  496.       if (AChkCPUFlags(eCPUFlagINTLogic, &ArgStr[1]))
  497.       {
  498.         CodeLen = 1;
  499.         BAsmCode[0] = Code + 0x05;
  500.       }
  501.     }
  502.     else if (!strcmp(ArgStr[1].str.p_str, "TCNTI"))
  503.     {
  504.       if (AChkCPUFlags(eCPUFlagINTLogic, &ArgStr[1]))
  505.       {
  506.         CodeLen = 1;
  507.         BAsmCode[0] = Code + 0x25;
  508.       }
  509.     }
  510.     else if (!strcmp(ArgStr[1].str.p_str, "SI"))
  511.     {
  512.       if (AChkCPUFlags(eCPUFlagSerial, &ArgStr[1]))
  513.       {
  514.         CodeLen = 1;
  515.         BAsmCode[0] = Code + 0x85;
  516.       }
  517.     }
  518.     else if (!Code && !strcmp(ArgStr[1].str.p_str, "DMA"))
  519.     {
  520.       if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
  521.       {
  522.         BAsmCode[0] = 0xe5;
  523.         CodeLen = 1;
  524.       }
  525.     }
  526.     else if (!Code && !strcmp(ArgStr[1].str.p_str, "FLAGS"))
  527.     {
  528.       if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
  529.       {
  530.         BAsmCode[0] = 0xf5;
  531.         CodeLen = 1;
  532.       }
  533.     }
  534.     else
  535.       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  536.   }
  537. }
  538.  
  539. static void DecodeDJNZ(Word Code)
  540. {
  541.   UNUSED(Code);
  542.  
  543.   if (!ChkArgCnt(2, 2));
  544.   else
  545.   {
  546.     switch (DecodeAdr(&ArgStr[1], MModReg | MModInd))
  547.     {
  548.       case ModReg:
  549.         CodeLen = 1;
  550.         BAsmCode[0] = 0xe8 + AdrVal;
  551.         break;
  552.       case ModInd:
  553.         if (AChkCPUFlags(eCPUFlagDEC_DJNZ_IREG, &ArgStr[1]))
  554.         {
  555.           CodeLen = 1;
  556.           BAsmCode[0] = 0xe0 + AdrVal;
  557.         }
  558.         break;
  559.       default:
  560.         break;
  561.     }
  562.     if (CodeLen > 0)
  563.     {
  564.       Boolean OK;
  565.       Word AdrWord;
  566.       tSymbolFlags Flags;
  567.  
  568.       AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], Int16, &OK, &Flags);
  569.       if (OK)
  570.       {
  571.         if (ChkSamePage(EProgCounter() + CodeLen, AdrWord, 8, Flags))
  572.           BAsmCode[CodeLen++] = AdrWord & 0xff;
  573.       }
  574.     }
  575.   }
  576. }
  577.  
  578. static void DecodeENT0(Word Code)
  579. {
  580.   UNUSED(Code);
  581.  
  582.   if (ChkArgCnt(1, 1) && ChkCPUFlags(eCPUFlagT0CLK))
  583.   {
  584.     if (as_strcasecmp(ArgStr[1].str.p_str, "CLK")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  585.     else
  586.     {
  587.       CodeLen = 1;
  588.       BAsmCode[0] = 0x75;
  589.     }
  590.   }
  591. }
  592.  
  593. static void DecodeINC(Word Code)
  594. {
  595.   UNUSED(Code);
  596.  
  597.   if (!ChkArgCnt(1, 1));
  598.   else
  599.   {
  600.     switch (DecodeAdr(&ArgStr[1], MModAcc | MModReg | MModInd))
  601.     {
  602.       case ModAcc:
  603.         CodeLen = 1;
  604.         BAsmCode[0] = 0x17;
  605.         break;
  606.       case ModReg:
  607.         CodeLen = 1;
  608.         BAsmCode[0] = 0x18 + AdrVal;
  609.         break;
  610.       case ModInd:
  611.         CodeLen = 1;
  612.         BAsmCode[0] = 0x10 + AdrVal;
  613.         break;
  614.       default:
  615.         break;
  616.     }
  617.   }
  618. }
  619.  
  620. static void DecodeIN(Word Code)
  621. {
  622.   Byte PortNum;
  623.  
  624.   UNUSED(Code);
  625.  
  626.   if (!ChkArgCnt(2, 2));
  627.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  628.   else if (!as_strcasecmp(ArgStr[2].str.p_str, "DBB"))
  629.   {
  630.     if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[2]))
  631.     {
  632.       CodeLen = 1;
  633.       BAsmCode[0] = 0x22;
  634.     }
  635.   }
  636.   else if (!IsPort(ArgStr[2].str.p_str, 0x07, &PortNum)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  637.   else
  638.   {
  639.     CodeLen = 1;
  640.     BAsmCode[0] = 0x08 + PortNum;
  641.     ChkPx(PortNum, &ArgStr[2]);
  642.   }
  643. }
  644.  
  645. static void DecodeINS(Word Code)
  646. {
  647.   UNUSED(Code);
  648.  
  649.   if (!ChkArgCnt(2, 2));
  650.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  651.   else if (as_strcasecmp(ArgStr[2].str.p_str, "BUS")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  652.   else if (AChkCPUFlags(eCPUFlagBUS, &ArgStr[2]))
  653.   {
  654.     CodeLen = 1;
  655.     BAsmCode[0] = 0x08;
  656.   }
  657. }
  658.  
  659. static void DecodeJMPP(Word Code)
  660. {
  661.   UNUSED(Code);
  662.  
  663.   if (!ChkArgCnt(1, 1));
  664.   else if (as_strcasecmp(ArgStr[1].str.p_str, "@A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  665.   else
  666.   {
  667.     CodeLen = 1;
  668.     BAsmCode[0] = 0xb3;
  669.   }
  670. }
  671.  
  672. static void DecodeCond(Word Code)
  673. {
  674.   if (ChkArgCnt(1, 1))
  675.   {
  676.     tEvalResult EvalResult;
  677.     Word AdrWord;
  678.  
  679.     AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt12, &EvalResult);
  680.     if (EvalResult.OK && ChkSamePage(EProgCounter() + 1, AdrWord, 8, EvalResult.Flags))
  681.     {
  682.       CodeLen = 2;
  683.       BAsmCode[0] = Code;
  684.       BAsmCode[1] = AdrWord & 0xff;
  685.       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  686.     }
  687.   }
  688. }
  689.  
  690. static void DecodeJB(Word Code)
  691. {
  692.   UNUSED(Code);
  693.  
  694.   if (ChkArgCnt(2, 2) && ChkCPUFlags(eCPUFlagCondBitJmp))
  695.   {
  696.     Boolean OK;
  697.     AdrVal = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
  698.     if (OK)
  699.     {
  700.       Word AdrWord;
  701.       tSymbolFlags Flags;
  702.  
  703.       AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt12, &OK, &Flags);
  704.       if (OK && ChkSamePage(EProgCounter() + 1, AdrWord, 8, Flags))
  705.       {
  706.         CodeLen = 2;
  707.         BAsmCode[0] = 0x12 + (AdrVal << 5);
  708.         BAsmCode[1] = AdrWord & 0xff;
  709.       }
  710.     }
  711.   }
  712. }
  713.  
  714. static void DecodeMOV(Word Code)
  715. {
  716.   Byte PortNum;
  717.  
  718.   UNUSED(Code);
  719.  
  720.   if (!ChkArgCnt(2, 2));
  721.   else if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
  722.   {
  723.     if (!as_strcasecmp(ArgStr[2].str.p_str, "T"))
  724.     {
  725.       CodeLen = 1;
  726.       BAsmCode[0] = 0x42;
  727.     }
  728.     else if (IsPort(ArgStr[2].str.p_str, 0x06, &PortNum))
  729.     {
  730.       if (AChkCPUFlags(eCPUFlagOKI, &ArgStr[2]))
  731.       {
  732.         CodeLen = 1;
  733.         BAsmCode[0] = 0x53 + (PortNum << 4);
  734.       }
  735.     }
  736.     else if (!as_strcasecmp(ArgStr[2].str.p_str, "PSW"))
  737.     {
  738.       if (AChkCPUFlags(eCPUFlagTransferA_PSW, &ArgStr[2]))
  739.       {
  740.         CodeLen = 1;
  741.         BAsmCode[0] = 0xc7;
  742.       }
  743.     }
  744.     else if (IsSerialPort(ArgStr[2].str.p_str, 0x03, &PortNum))
  745.     {
  746.       if (AChkCPUFlags(eCPUFlagSerial, &ArgStr[2]))
  747.       {
  748.         CodeLen = 1;
  749.         BAsmCode[0] = 0x0c + PortNum;
  750.       }
  751.     }
  752.     else
  753.     {
  754.        switch (DecodeAdr(&ArgStr[2], MModReg | MModInd | MModImm))
  755.        {
  756.          case ModReg:
  757.            CodeLen = 1;
  758.            BAsmCode[0] = 0xf8 + AdrVal;
  759.            break;
  760.          case ModInd:
  761.            CodeLen = 1;
  762.            BAsmCode[0] = 0xf0 + AdrVal;
  763.            break;
  764.          case ModImm:
  765.            CodeLen = 2;
  766.            BAsmCode[0] = 0x23;
  767.            break;
  768.          default:
  769.            break;
  770.        }
  771.     }
  772.   }
  773.   else if (IsPort(ArgStr[1].str.p_str, 0x02, &PortNum))
  774.   {
  775.     if (IsIReg3(&ArgStr[2]))
  776.     {
  777.       if (AChkCPUFlags(eCPUFlagOKI, &ArgStr[1]))
  778.       {
  779.         CodeLen = 1;
  780.         BAsmCode[0] = 0xe3 | (PortNum << 4);
  781.       }
  782.     }
  783.   }
  784.   else if (IsSerialPort(ArgStr[1].str.p_str, 0x07, &PortNum))
  785.   {
  786.     if (AChkCPUFlags(eCPUFlagSerial, &ArgStr[1]))
  787.     {
  788.       switch (DecodeAdr(&ArgStr[2], MModAcc | MModImm))
  789.       {
  790.         case ModAcc:
  791.           CodeLen = 1;
  792.           BAsmCode[0] = 0x3c + PortNum;
  793.           break;
  794.         case ModImm:
  795.           CodeLen = 2;
  796.           BAsmCode[0] = 0x9c + PortNum;
  797.           break;
  798.         default:
  799.           break;
  800.       }
  801.     }
  802.   }
  803.   else if (!as_strcasecmp(ArgStr[2].str.p_str, "A"))
  804.   {
  805.     if (!as_strcasecmp(ArgStr[1].str.p_str, "STS"))
  806.     {
  807.       if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
  808.       {
  809.         CodeLen = 1;
  810.         BAsmCode[0] = 0x90;
  811.       }
  812.     }
  813.     else if (!as_strcasecmp(ArgStr[1].str.p_str, "T"))
  814.     {
  815.       CodeLen = 1;
  816.       BAsmCode[0] = 0x62;
  817.     }
  818.     else if (!as_strcasecmp(ArgStr[1].str.p_str, "PSW"))
  819.     {
  820.       if (AChkCPUFlags(eCPUFlagTransferA_PSW, &ArgStr[1]))
  821.       {
  822.         CodeLen = 1;
  823.         BAsmCode[0] = 0xd7;
  824.       }
  825.     }
  826.     else
  827.     {
  828.       switch (DecodeAdr(&ArgStr[1], MModReg | MModInd))
  829.       {
  830.         case ModReg:
  831.           CodeLen = 1;
  832.           BAsmCode[0] = 0xa8 + AdrVal;
  833.           break;
  834.         case ModInd:
  835.           CodeLen = 1;
  836.           BAsmCode[0] = 0xa0 + AdrVal;
  837.           break;
  838.         default:
  839.           break;
  840.       }
  841.     }
  842.   }
  843.   else if (*ArgStr[2].str.p_str == '#')
  844.   {
  845.     Boolean OK;
  846.     Word AdrWord = EvalStrIntExpressionOffs(&ArgStr[2], 1, Int8, &OK);
  847.     if (OK)
  848.     {
  849.       switch (DecodeAdr(&ArgStr[1], MModReg | MModInd))
  850.       {
  851.         case ModReg:
  852.           CodeLen = 2;
  853.           BAsmCode[0] = 0xb8 + AdrVal;
  854.           BAsmCode[1] = AdrWord;
  855.           break;
  856.         case ModInd:
  857.           CodeLen = 2;
  858.           BAsmCode[0] = 0xb0 + AdrVal;
  859.           BAsmCode[1] = AdrWord;
  860.           break;
  861.         default:
  862.           break;
  863.       }
  864.     }
  865.   }
  866.   else
  867.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  868. }
  869.  
  870. static void DecodeANLD_ORLD_MOVD(Word Code)
  871. {
  872.   Byte PortNum;
  873.  
  874.   if (ChkArgCnt(2, 2) && ChkCPUFlags(eCPUFlagIOExpander))
  875.   {
  876.     const tStrComp *pArg1 = &ArgStr[1],
  877.                    *pArg2 = &ArgStr[2];
  878.  
  879.     if ((Code == 0x3c) && (!as_strcasecmp(ArgStr[1].str.p_str, "A"))) /* MOVD */
  880.     {
  881.       pArg1 = &ArgStr[2];
  882.       pArg2 = &ArgStr[1];
  883.       Code = 0x0c;
  884.     }
  885.     if (as_strcasecmp(pArg2->str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
  886.     else if (!IsPort(pArg1->str.p_str, 0xf0, &PortNum)) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  887.     else
  888.     {
  889.       PortNum -= 4;
  890.  
  891.       if ((PortNum == 3) && (pCurrCPUProps->Flags & eCPUFlagSiemens)) WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
  892.       else
  893.       {
  894.         CodeLen = 1;
  895.         BAsmCode[0] = Code + PortNum;
  896.       }
  897.     }
  898.   }
  899. }
  900.  
  901. static void DecodeMOVP_MOVP3(Word Code)
  902. {
  903.   if (!ChkArgCnt(2, 2));
  904.   else if ((Code == 0xe3) && !ChkCPUFlags(eCPUFlagMOVP3));
  905.   else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  906.   else if (as_strcasecmp(ArgStr[2].str.p_str, "@A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  907.   else
  908.   {
  909.     CodeLen = 1;
  910.     BAsmCode[0] = Code;
  911.   }
  912. }
  913.  
  914. static void DecodeMOVP1(Word Code)
  915. {
  916.   UNUSED(Code);
  917.  
  918.   if (!ChkArgCnt(2, 2));
  919.   else if (!ChkCPUFlags(eCPUFlagOKI));
  920.   else if (as_strcasecmp(ArgStr[1].str.p_str, "P")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  921.   else if (IsIReg3(&ArgStr[2]))
  922.   {
  923.     CodeLen = 1;
  924.     BAsmCode[0] = 0xc3;
  925.   }
  926. }
  927.  
  928. static void DecodeMOVX(Word Code)
  929. {
  930.   UNUSED(Code);
  931.  
  932.   if (ChkArgCnt(2, 2)
  933.    && ChkCPUFlags(eCPUFlagXMem))
  934.   {
  935.     const tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
  936.     Byte Code = 0x80;
  937.  
  938.     if (!as_strcasecmp(pArg2->str.p_str, "A"))
  939.     {
  940.       pArg2 = &ArgStr[1];
  941.       pArg1 = &ArgStr[2];
  942.       Code += 0x10;
  943.     }
  944.     if (as_strcasecmp(pArg1->str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  945.     else
  946.     {
  947.       if (DecodeAdr(pArg2, MModInd) == ModInd)
  948.       {
  949.         CodeLen = 1;
  950.         BAsmCode[0] = Code + AdrVal;
  951.       }
  952.     }
  953.   }
  954. }
  955.  
  956. static void DecodeNOP(Word Code)
  957. {
  958.   UNUSED(Code);
  959.  
  960.   if (!ChkArgCnt(0, 0));
  961.   else
  962.   {
  963.     CodeLen = 1;
  964.     BAsmCode[0] = 0x00;
  965.   }
  966. }
  967.  
  968. static void DecodeOUT(Word Code)
  969. {
  970.   UNUSED(Code);
  971.  
  972.   if (!ChkArgCnt(2, 2));
  973.   else if (as_strcasecmp(ArgStr[1].str.p_str, "DBB")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  974.   else if (as_strcasecmp(ArgStr[2].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  975.   else if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
  976.   {
  977.     BAsmCode[0] = 0x02;
  978.     CodeLen = 1;
  979.   }
  980. }
  981.  
  982. static void DecodeOUTL(Word Code)
  983. {
  984.   UNUSED(Code);
  985.  
  986.   NLS_UpString(ArgStr[1].str.p_str);
  987.   if (!ChkArgCnt(2, 2));
  988.   else
  989.   {
  990.     Word PortMask = 0x07;
  991.     Byte PortNum;
  992.  
  993.     if (pCurrCPUProps->Flags & eCPUFlagBUS)
  994.       PortMask |= 0x100;
  995.     if (as_strcasecmp(ArgStr[2].str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  996.     else if (!IsPort(ArgStr[1].str.p_str, PortMask, &PortNum)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  997.     else if (PortNum == 8)
  998.     {
  999.       CodeLen = 1;
  1000.       BAsmCode[0] = 0x02;
  1001.     }
  1002.     else
  1003.     {
  1004.       CodeLen = 1;
  1005.       BAsmCode[0] = PortNum ? (0x38 + PortNum) : 0x90;
  1006.       ChkPx(PortNum, &ArgStr[1]);
  1007.     }
  1008.   }
  1009. }
  1010.  
  1011. static void DecodeRET_RETR(Word Code)
  1012. {
  1013.   if (ChkArgCnt(0, 0))
  1014.   {
  1015.     /* RETR not present if no interrupts at all (8021), or replaced by RETI (8022) */
  1016.     if ((Code == 0x93) && (!(pCurrCPUProps->Flags & eCPUFlagINTLogic) || (pCurrCPUProps->Flags & eCPUFlagADConv))) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
  1017.     else
  1018.     {
  1019.       CodeLen = 1;
  1020.       BAsmCode[0] = Code;
  1021.     }
  1022.   }
  1023. }
  1024.  
  1025. static void DecodeSEL(Word Code)
  1026. {
  1027.   UNUSED(Code);
  1028.  
  1029.   if (ChkArgCnt(1, 1))
  1030.   {
  1031.     Boolean OK = False;
  1032.     int z;
  1033.  
  1034.     NLS_UpString(ArgStr[1].str.p_str);
  1035.     for (z = 0; SelOrders[z].Name; z++)
  1036.       if (!strcmp(ArgStr[1].str.p_str, SelOrders[z].Name))
  1037.       {
  1038.         /* SEL MBx not allowed if program memory cannot be larger than 2K.
  1039.            Similar is true for the Philips-specific MB2/MB3 arguments if
  1040.            less than 6K/8K ROM is present: */
  1041.  
  1042.         if (!strncmp(SelOrders[z].Name, "MB", 2) && (pCurrCPUProps->CodeSize <= 0x7ff));
  1043.         else if (!strcmp(SelOrders[z].Name, "MB2") && (pCurrCPUProps->CodeSize <= 0xfff));
  1044.         else if (!strcmp(SelOrders[z].Name, "MB32") && (pCurrCPUProps->CodeSize <= 0x17ff));
  1045.  
  1046.         else if (!strncmp(SelOrders[z].Name, "RB", 2) && !(pCurrCPUProps->Flags & eCPUFlagRegBanks));
  1047.  
  1048.         else if (!strncmp(SelOrders[z].Name, "AN", 2) && !(pCurrCPUProps->Flags & eCPUFlagADConv));
  1049.  
  1050.         else
  1051.         {
  1052.           CodeLen = 1;
  1053.           BAsmCode[0] = SelOrders[z].Code;
  1054.           OK = True;
  1055.         }
  1056.       }
  1057.     if (!OK)
  1058.       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1059.   }
  1060. }
  1061.  
  1062. static void DecodeSTOP(Word Code)
  1063. {
  1064.   UNUSED(Code);
  1065.  
  1066.   if (!ChkArgCnt(1, 1));
  1067.   else if (as_strcasecmp(ArgStr[1].str.p_str, "TCNT")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1068.   else
  1069.   {
  1070.     CodeLen = 1;
  1071.     BAsmCode[0] = 0x65;
  1072.   }
  1073. }
  1074.  
  1075. static void DecodeSTRT(Word Code)
  1076. {
  1077.   UNUSED(Code);
  1078.  
  1079.   if (!ChkArgCnt(1, 1));
  1080.   else
  1081.   {
  1082.     NLS_UpString(ArgStr[1].str.p_str);
  1083.     if (!strcmp(ArgStr[1].str.p_str, "CNT"))
  1084.     {
  1085.       CodeLen = 1;
  1086.       BAsmCode[0] = 0x45;
  1087.     }
  1088.     else if (!strcmp(ArgStr[1].str.p_str, "T"))
  1089.     {
  1090.       CodeLen = 1;
  1091.       BAsmCode[0] = 0x55;
  1092.     }
  1093.     else
  1094.       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  1095.   }
  1096. }
  1097.  
  1098. static void DecodeXCH(Word Code)
  1099. {
  1100.   UNUSED(Code);
  1101.  
  1102.   if (!ChkArgCnt(2, 2));
  1103.   else
  1104.   {
  1105.     const tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
  1106.  
  1107.     if (!as_strcasecmp(pArg2->str.p_str, "A"))
  1108.     {
  1109.       pArg2 = &ArgStr[1];
  1110.       pArg1 = &ArgStr[2];
  1111.     }
  1112.     if (as_strcasecmp(pArg1->str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  1113.     else
  1114.     {
  1115.       switch (DecodeAdr(pArg2, MModReg | MModInd))
  1116.       {
  1117.         case ModReg:
  1118.           CodeLen = 1;
  1119.           BAsmCode[0] = 0x28 + AdrVal;
  1120.           break;
  1121.         case ModInd:
  1122.           CodeLen = 1;
  1123.           BAsmCode[0] = 0x20 + AdrVal;
  1124.           break;
  1125.         default:
  1126.           break;
  1127.       }
  1128.     }
  1129.   }
  1130. }
  1131.  
  1132. static void DecodeXCHD(Word Code)
  1133. {
  1134.   UNUSED(Code);
  1135.  
  1136.   if (!ChkArgCnt(2, 2));
  1137.   else
  1138.   {
  1139.     const tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
  1140.  
  1141.     if (!as_strcasecmp(pArg2->str.p_str, "A"))
  1142.     {
  1143.       pArg2 = &ArgStr[1];
  1144.       pArg1 = &ArgStr[2];
  1145.     }
  1146.     if (as_strcasecmp(pArg1->str.p_str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
  1147.     else
  1148.     {
  1149.       if (DecodeAdr(pArg2, MModInd) == ModInd)
  1150.       {
  1151.         CodeLen = 1;
  1152.         BAsmCode[0] = 0x30 + AdrVal;
  1153.       }
  1154.     }
  1155.   }
  1156. }
  1157.  
  1158. static void DecodeRAD(Word Code)
  1159. {
  1160.   UNUSED(Code);
  1161.  
  1162.   if (ChkArgCnt(0, 0) && ChkCPUFlags(eCPUFlagADConv))
  1163.   {
  1164.     CodeLen = 1;
  1165.     BAsmCode[0] = 0x80;
  1166.   }
  1167. }
  1168.  
  1169. static void DecodeRETI(Word Code)
  1170. {
  1171.   UNUSED(Code);
  1172.  
  1173.   if (ChkArgCnt(0, 0) && ChkCPUFlags(eCPUFlagADConv)) /* check for 8022 */
  1174.   {
  1175.     CodeLen = 1;
  1176.     BAsmCode[0] = 0x93;
  1177.   }
  1178. }
  1179.  
  1180. static void DecodeIDL_HALT(Word Code)
  1181. {
  1182.   UNUSED(Code);
  1183.  
  1184.   if (ChkArgCnt(0, 0)
  1185.    && ChkCPUFlags(eCPUFlagCMOS))
  1186.   {
  1187.     CodeLen = 1;
  1188.     BAsmCode[0] = (pCurrCPUProps->Flags & eCPUFlagSiemens) ? 0xf3 : 0x01;
  1189.   }
  1190. }
  1191.  
  1192. static void DecodeOKIFixed(Word Code)
  1193. {
  1194.   if (ChkArgCnt(0, 0) && ChkCPUFlags(eCPUFlagOKI))
  1195.   {
  1196.     CodeLen = 1;
  1197.     BAsmCode[0] = Code;
  1198.   }
  1199. }
  1200.  
  1201. /****************************************************************************/
  1202.  
  1203. static void AddAcc(const char *Name, Byte Code)
  1204. {
  1205.   AddInstTable(InstTable, Name, Code, DecodeAcc);
  1206. }
  1207.  
  1208. static void AddCond(const char *Name, Byte Code)
  1209. {
  1210.   AddInstTable(InstTable, Name, Code, DecodeCond);
  1211. }
  1212.  
  1213. static void AddSel(const char *Name, Byte Code)
  1214. {
  1215.   order_array_rsv_end(SelOrders, SelOrder);
  1216.   SelOrders[InstrZ].Name = Name;
  1217.   SelOrders[InstrZ].Code = Code;
  1218.   InstrZ++;
  1219. }
  1220.  
  1221. static void add_clr_cpl(const char *p_name, Byte code)
  1222. {
  1223.   order_array_rsv_end(clr_cpl_args, clr_cpl_t);
  1224.   clr_cpl_args[InstrZ].p_val = p_name;
  1225.   clr_cpl_args[InstrZ].code = code;
  1226.   InstrZ++;
  1227. }
  1228.  
  1229. static void InitFields(void)
  1230. {
  1231.   InstTable = CreateInstTable(203);
  1232.  
  1233.   add_null_pseudo(InstTable);
  1234.  
  1235.   AddInstTable(InstTable, "ADD", 0x00, DecodeADD_ADDC);
  1236.   AddInstTable(InstTable, "ADDC", 0x10, DecodeADD_ADDC);
  1237.   AddInstTable(InstTable, "ORL", 0x00, DecodeANL_ORL_XRL);
  1238.   AddInstTable(InstTable, "ANL", 0x10, DecodeANL_ORL_XRL);
  1239.   AddInstTable(InstTable, "XRL", 0x90, DecodeANL_ORL_XRL);
  1240.   AddInstTable(InstTable, "CALL", 0x14, DecodeCALL_JMP);
  1241.   AddInstTable(InstTable, "JMP", 0x04, DecodeCALL_JMP);
  1242.   AddInstTable(InstTable, "CLR", 0x00, DecodeCLR_CPL);
  1243.   AddInstTable(InstTable, "CPL", 0x10, DecodeCLR_CPL);
  1244.   AddInstTable(InstTable, "DEC", 0, DecodeDEC);
  1245.   AddInstTable(InstTable, "DIS", 0x10, DecodeDIS_EN);
  1246.   AddInstTable(InstTable, "EN", 0x00, DecodeDIS_EN);
  1247.   AddInstTable(InstTable, "DJNZ", 0x00, DecodeDJNZ);
  1248.   AddInstTable(InstTable, "ENT0", 0x00, DecodeENT0);
  1249.   AddInstTable(InstTable, "INC", 0x00, DecodeINC);
  1250.   AddInstTable(InstTable, "IN", 0x00, DecodeIN);
  1251.   AddInstTable(InstTable, "INS", 0x00, DecodeINS);
  1252.   AddInstTable(InstTable, "JMPP", 0x00, DecodeJMPP);
  1253.   AddInstTable(InstTable, "JB", 0x00, DecodeJB);
  1254.   AddInstTable(InstTable, "MOV", 0x00, DecodeMOV);
  1255.   AddInstTable(InstTable, "ANLD", 0x9c, DecodeANLD_ORLD_MOVD);
  1256.   AddInstTable(InstTable, "ORLD", 0x8c, DecodeANLD_ORLD_MOVD);
  1257.   AddInstTable(InstTable, "MOVD", 0x3c, DecodeANLD_ORLD_MOVD);
  1258.   AddInstTable(InstTable, "MOVP", 0xa3, DecodeMOVP_MOVP3);
  1259.   AddInstTable(InstTable, "MOVP3", 0xe3, DecodeMOVP_MOVP3);
  1260.   AddInstTable(InstTable, "MOVP1", 0x00, DecodeMOVP1);
  1261.   AddInstTable(InstTable, "MOVX", 0x00, DecodeMOVX);
  1262.   AddInstTable(InstTable, "NOP", 0x00, DecodeNOP);
  1263.   AddInstTable(InstTable, "OUT", 0x00, DecodeOUT);
  1264.   AddInstTable(InstTable, "OUTL", 0x00, DecodeOUTL);
  1265.   AddInstTable(InstTable, "RET", 0x83, DecodeRET_RETR);
  1266.   AddInstTable(InstTable, "RETR", 0x93, DecodeRET_RETR);
  1267.   AddInstTable(InstTable, "SEL", 0x00, DecodeSEL);
  1268.   AddInstTable(InstTable, "STOP", 0x00, DecodeSTOP);
  1269.   AddInstTable(InstTable, "STRT", 0x00, DecodeSTRT);
  1270.   AddInstTable(InstTable, "XCH", 0x00, DecodeXCH);
  1271.   AddInstTable(InstTable, "XCHD", 0x00, DecodeXCHD);
  1272.   AddInstTable(InstTable, "RAD", 0x00, DecodeRAD);
  1273.   AddInstTable(InstTable, "RETI", 0x00, DecodeRETI);
  1274.   AddInstTable(InstTable, "IDL", 0x00, DecodeIDL_HALT);
  1275.   AddInstTable(InstTable, "HALT", 0x00, DecodeIDL_HALT);
  1276.   AddInstTable(InstTable, "HLTS", 0x82, DecodeOKIFixed);
  1277.   AddInstTable(InstTable, "FLT", 0xa2, DecodeOKIFixed);
  1278.   AddInstTable(InstTable, "FLTT", 0xc2, DecodeOKIFixed);
  1279.   AddInstTable(InstTable, "FRES", 0xe2, DecodeOKIFixed);
  1280.  
  1281.   InstrZ = 0;
  1282.   add_clr_cpl("A", 0x27);
  1283.   add_clr_cpl("C", 0x97);
  1284.   add_clr_cpl("F0", 0x85);
  1285.   add_clr_cpl("F1", 0xa5);
  1286.  
  1287.   AddCond("JTF"  , 0x16);
  1288.   AddCond("JC"   , 0xf6);
  1289.   AddCond("JNC"  , 0xe6);
  1290.   AddCond("JZ"   , 0xc6);
  1291.   AddCond("JNZ"  , 0x96);
  1292.   if (pCurrCPUProps->Flags & eCPUFlagT0)
  1293.   {
  1294.     AddCond("JT0"  , 0x36);
  1295.     AddCond("JNT0" , 0x26);
  1296.   }
  1297.   AddCond("JT1"  , 0x56);
  1298.   AddCond("JNT1" , 0x46);
  1299.   if (pCurrCPUProps->Flags & eCPUFlagUserFlags)
  1300.   {
  1301.     AddCond("JF0"  , 0xb6);
  1302.     AddCond("JF1"  , 0x76);
  1303.   }
  1304.   if (pCurrCPUProps->Flags & eCPUFlagUPIPort)
  1305.   {
  1306.     AddCond("JNIBF", 0xd6);
  1307.     AddCond("JOBF" , 0x86);
  1308.   }
  1309.   else
  1310.     AddCond("JNI"  , (pCurrCPUProps->Flags & eCPUFlagSiemens) ? 0x66 : 0x86);
  1311.   if (pCurrCPUProps->Flags & eCPUFlagCondBitJmp)
  1312.   {
  1313.     AddCond("JB0"  , 0x12);
  1314.     AddCond("JB1"  , 0x32);
  1315.     AddCond("JB2"  , 0x52);
  1316.     AddCond("JB3"  , 0x72);
  1317.     AddCond("JB4"  , 0x92);
  1318.     AddCond("JB5"  , 0xb2);
  1319.     AddCond("JB6"  , 0xd2);
  1320.     AddCond("JB7"  , 0xf2);
  1321.   }
  1322.   if (pCurrCPUProps->Flags & eCPUFlag84xx)
  1323.     AddCond("JNTF", 0x06);
  1324.  
  1325.   AddAcc("DA"  , 0x57);
  1326.   AddAcc("RL"  , 0xe7);
  1327.   AddAcc("RLC" , 0xf7);
  1328.   AddAcc("RR"  , 0x77);
  1329.   AddAcc("RRC" , 0x67);
  1330.   AddAcc("SWAP", 0x47);
  1331.  
  1332.   /* Leave MBx first, used by CALL/JMP! */
  1333.  
  1334.   InstrZ = 0;
  1335.   AddSel("MB0" , 0xe5);
  1336.   AddSel("MB1" , 0xf5);
  1337.   AddSel("MB2" , 0xa5);
  1338.   AddSel("MB3" , 0xb5);
  1339.   AddSel("RB0" , 0xc5);
  1340.   AddSel("RB1" , 0xd5);
  1341.   AddSel("AN0" , 0x95);
  1342.   AddSel("AN1" , 0x85);
  1343.   AddSel(NULL  , 0);
  1344.  
  1345.   AddInstTable(InstTable, "REG", 0, CodeREG);
  1346.   AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
  1347. }
  1348.  
  1349. static void DeinitFields(void)
  1350. {
  1351.   DestroyInstTable(InstTable);
  1352.   order_array_free(clr_cpl_args);
  1353.   order_array_free(SelOrders);
  1354. }
  1355.  
  1356. static void MakeCode_48(void)
  1357. {
  1358.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  1359.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  1360. }
  1361.  
  1362. static Boolean IsDef_48(void)
  1363. {
  1364.   return Memo("REG");
  1365. }
  1366.  
  1367. /*!------------------------------------------------------------------------
  1368.  * \fn     InternSymbol_48(char *pArg, TempResult *pResult)
  1369.  * \brief  handle built-in symbols on MCS-48
  1370.  * \param  pArg source argument
  1371.  * \param  pResult result buffer
  1372.  * ------------------------------------------------------------------------ */
  1373.  
  1374. static void InternSymbol_48(char *pArg, TempResult *pResult)
  1375. {
  1376.   tRegInt Erg;
  1377.   tSymbolSize Size;
  1378.  
  1379.   if (DecodeRegCore(pArg, &Erg, &Size))
  1380.   {
  1381.     pResult->Typ = TempReg;
  1382.     pResult->DataSize = Size;
  1383.     pResult->Contents.RegDescr.Reg = Erg;
  1384.     pResult->Contents.RegDescr.Dissect = DissectReg_48;
  1385.     pResult->Contents.RegDescr.compare = NULL;
  1386.   }
  1387. }
  1388.  
  1389. static void SwitchFrom_48(void)
  1390. {
  1391.   DeinitFields();
  1392. }
  1393.  
  1394. static void InitCode_48(void)
  1395. {
  1396.   Reg_MB = MB_NOTHING;
  1397. }
  1398.  
  1399. static void SwitchTo_48(void *pUser)
  1400. {
  1401. #define ASSUME48Count (sizeof(ASSUME48s) / sizeof(*ASSUME48s))
  1402.   static ASSUMERec ASSUME48s[] =
  1403.   {
  1404.     { "MB"   , &Reg_MB   , 0,  1, MB_NOTHING, NULL },
  1405.   };
  1406.  
  1407.   pCurrCPUProps = (const tCPUProps*)pUser;
  1408.   ASSUME48s[0].Max = (pCurrCPUProps->CodeSize >> 11) & 3;
  1409.  
  1410.   TurnWords = False;
  1411.   SetIntConstMode(eIntConstModeIntel);
  1412.  
  1413.   PCSymbol = "$";
  1414.   HeaderID = 0x21;
  1415.   NOPCode = 0x00;
  1416.   DivideChars = ",";
  1417.   HasAttrs = False;
  1418.  
  1419.   /* limit code segement size only vor variants known to have no
  1420.      external program memory */
  1421.  
  1422.   ValidSegs = (1 << SegCode) | (1 << SegIData);
  1423.   Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
  1424.   SegLimits[SegCode] = pCurrCPUProps->CodeSize;
  1425.   Grans[SegIData] = 1; ListGrans[SegIData] = 1; SegInits[SegIData] = 0x20;
  1426.   SegLimits[SegIData] = 0xff;
  1427.   if (pCurrCPUProps->Flags & eCPUFlagXMem)
  1428.   {
  1429.     ValidSegs |= (1 << SegXData);
  1430.     Grans[SegXData] = 1; ListGrans[SegXData] = 1; SegInits[SegXData] = 0;
  1431.     SegLimits[SegXData] = 0xff;
  1432.   }
  1433.  
  1434.   MakeCode = MakeCode_48;
  1435.   IsDef = IsDef_48;
  1436.   InternSymbol = InternSymbol_48;
  1437.   DissectReg = DissectReg_48;
  1438.   SwitchFrom = SwitchFrom_48;
  1439.   InitFields();
  1440.  
  1441.   pASSUMERecs = ASSUME48s;
  1442.   ASSUMERecCnt = ASSUME48Count;
  1443. }
  1444.  
  1445. /* Limit code segment size only for variants known to have no
  1446.    external program memory: */
  1447.  
  1448. static tCPUProps CPUProps[] =
  1449. {
  1450.   { "8021"     , 0x3ff, eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 },
  1451.   { "8022"     , 0x7ff, eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagBUS | eCPUFlagADConv | eCPUFlagINTLogic },
  1452.   { "8401"     , 0x1fff,eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
  1453.   { "8421"     , 0x7ff, eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
  1454.   { "8441"     , 0xfff, eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
  1455.   { "8461"     , 0x17ff,eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
  1456.   { "8039"     , 0xfff, eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1457.   { "8048"     , 0xfff, eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1458.   { "80C39"    , 0xfff, eCPUFlagCMOS | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1459.   { "80C48"    , 0xfff, eCPUFlagCMOS | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1460.   { "8041"     , 0x3ff, eCPUFlagUPIPort | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1461.   { "8042"     , 0x7ff, eCPUFlagUPIPort | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1462.   { "80C382"   , 0xfff, eCPUFlagCMOS | eCPUFlagSiemens | eCPUFlagDEC_DJNZ_IREG | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagIOExpander | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
  1463.   { "MSM80C39" , 0xfff, eCPUFlagCMOS | eCPUFlagDEC_DJNZ_IREG | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic | eCPUFlagOKI },
  1464.   { "MSM80C48" , 0xfff, eCPUFlagCMOS | eCPUFlagDEC_DJNZ_IREG | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic | eCPUFlagOKI },
  1465.   { NULL, 0, 0 }
  1466. };
  1467.  
  1468. void code48_init(void)
  1469. {
  1470.   tCPUProps *pProp;
  1471.  
  1472.   for (pProp = CPUProps; pProp->pName; pProp++)
  1473.     (void)AddCPUUser(pProp->pName, SwitchTo_48, (void*)pProp, NULL);
  1474.  
  1475.   AddInitPassProc(InitCode_48);
  1476. }
  1477.