Subversion Repositories pentevo

Rev

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

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