Subversion Repositories pentevo

Rev

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

  1. /* code53c8xx.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* Makroassembler AS                                                         */
  6. /*                                                                           */
  7. /* Codegenerator SYM53C8xx                                                   */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "asmdef.h"
  16. #include "asmsub.h"
  17. #include "asmpars.h"
  18. #include "asmitree.h"
  19. #include "headids.h"
  20. #include "strutil.h"
  21. #include "codevars.h"
  22. #include "codepseudo.h"
  23. #include "intpseudo.h"
  24. #include "errmsg.h"
  25.  
  26. #include "code53c8xx.h"
  27.  
  28. /*---------------------------------------------------------------------------*/
  29.  
  30. typedef struct
  31. {
  32.   const char *Name;
  33.   LongWord Code;
  34.   Word Mask;
  35. } TReg, *PReg;
  36.  
  37. static CPUVar CPU53C810, CPU53C860, CPU53C815, CPU53C825, CPU53C875,
  38.               CPU53C895;
  39.  
  40. #define M_53C810 0x0001
  41. #define M_53C860 0x0002
  42. #define M_53C815 0x0004
  43. #define M_53C825 0x0008
  44. #define M_53C875 0x0010
  45. #define M_53C895 0x0020
  46.  
  47. static PReg Regs;
  48.  
  49. /*---------------------------------------------------------------------------*/
  50.  
  51. static Boolean IsInToken(char Inp)
  52. {
  53.   return ((Inp == '_') || (isalnum(((usint) Inp) & 0xff)));
  54. }
  55.  
  56. static void GetToken(tStrComp *pSrc, tStrComp *pDest)
  57. {
  58.   char *p;
  59.  
  60.   /* search token start, by skipping spaces */
  61.  
  62.   for (p = pSrc->str.p_str; as_isspace(*p); p++)
  63.     if (*p == '\0') break;
  64.   StrCompCutLeft(pSrc, p - pSrc->str.p_str);
  65.   if (*p == '\0')
  66.   {
  67.     StrCompReset(pDest);
  68.     return;
  69.   }
  70.   pDest->Pos.StartCol = pSrc->Pos.StartCol;
  71.  
  72.   /* geklammerter Ausdruck ? */
  73.  
  74.   if (*pSrc->str.p_str == '(')
  75.   {
  76.     p = QuotPos(pSrc->str.p_str, ')');
  77.  
  78.     /* no closing ) -> copy all up to end */
  79.  
  80.     if (!p)
  81.     {
  82.       StrCompCopy(pDest, pSrc);
  83.       StrCompCutLeft(pSrc, strlen(pSrc->str.p_str));
  84.     }
  85.  
  86.     /* otherwise, copy (...) */
  87.  
  88.     else
  89.     {
  90.       pDest->Pos.Len = strmemcpy(pDest->str.p_str, STRINGSIZE, pSrc->str.p_str, p + 1 - pSrc->str.p_str);
  91.       StrCompCutLeft(pSrc, p + 1 - pSrc->str.p_str);
  92.     }
  93.   }
  94.  
  95.   /* Spezialtoken ? */
  96.  
  97.   else if (!IsInToken(*pSrc->str.p_str))
  98.   {
  99.     pDest->str.p_str[0] = *pSrc->str.p_str;
  100.     pDest->str.p_str[1] = '\0';
  101.     pDest->Pos.Len = 1;
  102.     StrCompCutLeft(pSrc, 1);
  103.   }
  104.  
  105.   /* Wort ? */
  106.  
  107.   else
  108.   {
  109.     for (; IsInToken(*p); p++)
  110.       if (*p == '\0')
  111.         break;
  112.     pDest->Pos.Len = strmemcpy(pDest->str.p_str, STRINGSIZE, pSrc->str.p_str, p - pSrc->str.p_str);
  113.     StrCompCutLeft(pSrc, p - pSrc->str.p_str);
  114.   }
  115. }
  116.  
  117.  
  118. static Boolean DecodePhase(char *Name, LongWord *Result)
  119. {
  120.   *Result = 8;
  121.   if (!as_strcasecmp(Name, "DATA_OUT")) *Result = 0;
  122.   else if (!as_strcasecmp(Name, "DATA_IN")) *Result = 1;
  123.   else if (!as_strcasecmp(Name, "CMD")) *Result = 2;
  124.   else if (!as_strcasecmp(Name, "COMMAND")) *Result = 2;
  125.   else if (!as_strcasecmp(Name, "STATUS")) *Result = 3;
  126.   else if (!as_strcasecmp(Name, "RES4")) *Result = 4;
  127.   else if (!as_strcasecmp(Name, "RES5")) *Result = 5;
  128.   else if (!as_strcasecmp(Name, "MSG_OUT")) *Result = 6;
  129.   else if (!as_strcasecmp(Name, "MSG_IN")) *Result = 7;
  130.   else if (!as_strcasecmp(Name, "MESSAGE_OUT")) *Result = 6;
  131.   else if (!as_strcasecmp(Name, "MESSAGE_IN")) *Result = 7;
  132.   return (*Result < 8);
  133. }
  134.  
  135. static Boolean DecodeReg(char *Name, LongWord *Result)
  136. {
  137.   Integer Mask = 1 << (MomCPU - CPU53C810);
  138.   PReg Reg;
  139.  
  140.   for (Reg = Regs; Reg->Name; Reg++)
  141.     if (!(as_strcasecmp(Reg->Name, Name)) && (Mask & Reg->Mask))
  142.     {
  143.       *Result = Reg->Code;
  144.       return True;
  145.     }
  146.  
  147.   return False;
  148. }
  149.  
  150. static Boolean Err(tErrorNum Num, const char *Msg)
  151. {
  152.   WrXError(Num, Msg);
  153.   return False;
  154. }
  155.  
  156. static Boolean DecodeCond(tStrComp *pSrc, LongWord *Dest)
  157. {
  158.   String TokStr;
  159.   tStrComp Tok;
  160.   Boolean PhaseATNUsed, DataUsed, CarryUsed, MaskUsed;
  161.   LongWord Tmp;
  162.   Boolean OK;
  163.  
  164.   /* IF/WHEN/Nix-Unterscheidung - TRUE fuer Nix setzen */
  165.  
  166.   StrCompMkTemp(&Tok, TokStr, sizeof(TokStr));
  167.   GetToken(pSrc, &Tok);
  168.   if (*Tok.str.p_str == '\0')
  169.   {
  170.     *Dest |= 0x00080000;
  171.     return True;
  172.   }
  173.  
  174.   if (as_strcasecmp(Tok.str.p_str, "WHEN") == 0)
  175.     *Dest |= 0x00010000;
  176.   else if (as_strcasecmp(Tok.str.p_str, "IF") != 0)
  177.     return Err(ErrNum_OpTypeMismatch, Tok.str.p_str);
  178.  
  179.   /* Negierung? */
  180.  
  181.   GetToken(pSrc, &Tok);
  182.   if (as_strcasecmp(Tok.str.p_str, "NOT") == 0)
  183.     GetToken(pSrc, &Tok);
  184.   else
  185.     *Dest |= 0x00080000;
  186.  
  187.   /* Bedingungen durchgehen */
  188.  
  189.   PhaseATNUsed = DataUsed = MaskUsed = CarryUsed = False;
  190.   do
  191.   {
  192.     if (!as_strcasecmp(Tok.str.p_str, "ATN"))
  193.     {
  194.       if (PhaseATNUsed)
  195.         return Err(ErrNum_InvAddrMode, "2 x ATN/Phase");
  196.       if (CarryUsed)
  197.         return Err(ErrNum_InvAddrMode, "Carry + ATN/Phase");
  198.       if ((*Dest & 0x00010000) != 0)
  199.         return Err(ErrNum_InvAddrMode, "WHEN + ATN");
  200.       PhaseATNUsed = True;
  201.       *Dest |= 0x00020000;
  202.     }
  203.     else if (DecodePhase(Tok.str.p_str, &Tmp))
  204.     {
  205.       if (PhaseATNUsed)
  206.         return Err(ErrNum_InvAddrMode, "2 x ATN/Phase");
  207.       if (CarryUsed)
  208.         return Err(ErrNum_InvAddrMode, "Carry + ATN/Phase");
  209.       PhaseATNUsed = True;
  210.       *Dest |= 0x00020000 + (Tmp << 24);
  211.     }
  212.     else if (!as_strcasecmp(Tok.str.p_str, "CARRY"))
  213.     {
  214.       if (CarryUsed)
  215.         return Err(ErrNum_InvAddrMode, "2 x Carry");
  216.       if ((PhaseATNUsed) || (DataUsed))
  217.         return Err(ErrNum_InvAddrMode, "Carry + ...");
  218.       CarryUsed = True;
  219.       *Dest |= 0x00200000;
  220.     }
  221.     else if (!as_strcasecmp(Tok.str.p_str, "MASK"))
  222.     {
  223.       if (CarryUsed)
  224.         return Err(ErrNum_InvAddrMode, "Carry + Data");
  225.       if (MaskUsed)
  226.         return Err(ErrNum_InvAddrMode, "2 x Mask");
  227.       if (!DataUsed)
  228.         return Err(ErrNum_InvAddrMode, "Mask + !Data");
  229.       GetToken(pSrc, &Tok);
  230.       Tmp = EvalStrIntExpression(&Tok, UInt8, &OK);
  231.       if (!OK)
  232.         return False;
  233.       MaskUsed = True;
  234.       *Dest |= (Tmp << 8);
  235.     }
  236.     else
  237.     {
  238.       if (CarryUsed)
  239.         return Err(ErrNum_InvAddrMode, "Carry + Data");
  240.       if (DataUsed)
  241.         return Err(ErrNum_InvAddrMode, "2 x Data");
  242.       Tmp = EvalStrIntExpression(&Tok, UInt8, &OK);
  243.       if (!OK)
  244.         return False;
  245.       DataUsed = True;
  246.       *Dest |= 0x00040000 + Tmp;
  247.     }
  248.     GetToken(pSrc, &Tok);
  249.     if (*Tok.str.p_str != '\0')
  250.     {
  251.       if (as_strcasecmp(Tok.str.p_str, "AND"))
  252.         return Err(ErrNum_InvAddrMode, Tok.str.p_str);
  253.       GetToken(pSrc, &Tok);
  254.     }
  255.   }
  256.   while (*Tok.str.p_str != '\0');
  257.  
  258.   return True;
  259. }
  260.  
  261. typedef enum
  262. {
  263.   NONE, SFBR, REGISTER, IMM8
  264. } CompType;
  265.  
  266. static CompType DecodeComp(const tStrComp *pInp, LongWord *Outp)
  267. {
  268.   Boolean OK;
  269.  
  270.   if (!as_strcasecmp(pInp->str.p_str, "SFBR"))
  271.     return SFBR;
  272.   else if (DecodeReg(pInp->str.p_str, Outp))
  273.     return REGISTER;
  274.   else
  275.   {
  276.     *Outp = EvalStrIntExpression(pInp, Int8, &OK) & 0xff;
  277.     return (OK) ?  IMM8 : NONE;
  278.   }
  279. }
  280.  
  281. /*---------------------------------------------------------------------------*/
  282.  
  283. static void DecodeFixed(Word Index)
  284. {
  285.   if (ChkArgCnt(0, 0))
  286.   {
  287.     DAsmCode[0] = ((LongWord) Index) << 24;
  288.     DAsmCode[1] = 0x00000000;
  289.     CodeLen = 8;
  290.   }
  291. }
  292.  
  293. static void DecodeJmps(Word Index)
  294. {
  295.   LongWord Buf;
  296.   LongInt Adr;
  297.   int l;
  298.   Boolean OK;
  299.   tSymbolFlags Flags;
  300.  
  301.   if (ArgCnt == 0)
  302.   {
  303.     if (Memo("INTFLY"))
  304.     {
  305.       ArgCnt = 1;
  306.       strcpy(ArgStr[1].str.p_str, "0");
  307.     }
  308.     else if (Memo("RETURN"))
  309.     {
  310.       ArgCnt = 1;
  311.       *ArgStr[1].str.p_str = '\0';
  312.     }
  313.   }
  314.   if (ChkArgCnt(1, 2))
  315.   {
  316.     if (ArgCnt == 1)
  317.     {
  318.       if (Memo("RETURN"))
  319.         StrCompCopy(&ArgStr[2], &ArgStr[1]);
  320.       else
  321.         StrCompReset(&ArgStr[2]);
  322.     }
  323.     Buf = 0;
  324.     if (Memo("RETURN"))
  325.     {
  326.       Adr = 0;
  327.       OK = True;
  328.     }
  329.     else
  330.     {
  331.       l = strlen(ArgStr[1].str.p_str);
  332.       if ((!as_strncasecmp(ArgStr[1].str.p_str, "REL(", 4)) && (ArgStr[1].str.p_str[l - 1] == ')'))
  333.       {
  334.         if (*OpPart.str.p_str == 'I')
  335.         {
  336.           WrError(ErrNum_InvAddrMode);
  337.           OK = False;
  338.         }
  339.         Buf |= 0x00800000;
  340.         strmov(ArgStr[1].str.p_str, ArgStr[1].str.p_str + 4);
  341.         ArgStr[1].str.p_str[l - 5] = '\0';
  342.       }
  343.       Adr = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags);
  344.       if ((OK) && (Buf != 0))
  345.       {
  346.         Adr -= EProgCounter() + 8;
  347.         if (!mSymbolQuestionable(Flags) && ((Adr > 0x7fffff) || (Adr < -0x800000)))
  348.         {
  349.           WrError(ErrNum_JmpDistTooBig);
  350.           OK = False;
  351.         }
  352.       }
  353.     }
  354.     if ((OK) && (DecodeCond(&ArgStr[2], &Buf)))
  355.     {
  356.       DAsmCode[0] = 0x80000000 + (((LongWord) Index) << 27) + Buf;
  357.       if (Memo("INTFLY")) DAsmCode[0] |= 0x00100000;
  358.       DAsmCode[1] = Adr;
  359.       CodeLen = 8;
  360.     }
  361.   }
  362. }
  363.  
  364. static void DecodeCHMOV(Word Index)
  365. {
  366.   String TokenStr;
  367.   tStrComp Token, *pAdrArg = NULL;
  368.   LongWord Phase;
  369.   Boolean OK;
  370.  
  371.   UNUSED(Index);
  372.   StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
  373.  
  374.   if ((ChkExactCPUList(ErrNum_InstructionNotSupported, CPU53C825, CPU53C875, CPU53C895, CPUNone) >= 0)
  375.    && ChkArgCnt(2, 3))
  376.   {
  377.     GetToken(&ArgStr[ArgCnt], &Token);
  378.     if (!as_strcasecmp(Token.str.p_str, "WITH"))
  379.       DAsmCode[0] = 0x08000000;
  380.     else if (!as_strcasecmp(Token.str.p_str, "WHEN"))
  381.       DAsmCode[0] = 0x00000000;
  382.     else
  383.     {
  384.       WrStrErrorPos(ErrNum_InvAddrMode, &Token);
  385.       return;
  386.     }
  387.     KillPrefBlanksStrComp(&ArgStr[ArgCnt]);
  388.     KillPostBlanksStrComp(&ArgStr[ArgCnt]);
  389.     if (!DecodePhase(ArgStr[ArgCnt].str.p_str, &Phase)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[ArgCnt]);
  390.     else
  391.     {
  392.       DAsmCode[0] |= Phase << 24;
  393.       OK = False;
  394.       if (ArgCnt == 2)
  395.       {
  396.         GetToken(&ArgStr[1], &Token);
  397.         if (as_strcasecmp(Token.str.p_str, "FROM")) WrError(ErrNum_InvAddrMode);
  398.         else
  399.         {
  400.           pAdrArg = &ArgStr[1];
  401.           DAsmCode[0] |= 0x10000000;
  402.           OK = True;
  403.         }
  404.       }
  405.       else
  406.       {
  407.         Phase = EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
  408.         if (OK)
  409.         {
  410.           DAsmCode[0] |= Phase;
  411.           if (!as_strncasecmp(ArgStr[2].str.p_str,"PTR", 3))
  412.           {
  413.             StrCompCutLeft(&ArgStr[2], 4);
  414.             DAsmCode[0] |= 0x20000000;
  415.           }
  416.           pAdrArg = &ArgStr[2];
  417.         }
  418.       }
  419.       if (OK)
  420.       {
  421.         KillPrefBlanksStrComp(pAdrArg);
  422.         DAsmCode[1] = EvalStrIntExpression(pAdrArg, UInt32, &OK);
  423.         if (OK)
  424.           CodeLen = 8;
  425.       }
  426.     }
  427.   }
  428. }
  429.  
  430. static Boolean TrueFnc(void)
  431. {
  432.   return True;
  433. }
  434.  
  435. static void DecodeFlags(Word Index)
  436. {
  437.   Boolean OK;
  438.   String TokenStr;
  439.   tStrComp Token;
  440.  
  441.   StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
  442.   if (ChkArgCnt(1, 1))
  443.   {
  444.     OK = True;
  445.     DAsmCode[0] = ((LongWord) Index) << 24;
  446.     DAsmCode[1] = 0;
  447.     while ((OK) && (*ArgStr[1].str.p_str != '\0'))
  448.     {
  449.       GetToken(&ArgStr[1], &Token);
  450.       if (!as_strcasecmp(Token.str.p_str, "ACK"))
  451.         DAsmCode[0] |= 0x00000040;
  452.       else if (!as_strcasecmp(Token.str.p_str, "ATN"))
  453.         DAsmCode[0] |= 0x00000008;
  454.       else if (!as_strcasecmp(Token.str.p_str, "TARGET"))
  455.         DAsmCode[0] |= 0x00000200;
  456.       else if (!as_strcasecmp(Token.str.p_str, "CARRY"))
  457.         DAsmCode[0] |= 0x00000400;
  458.       else
  459.       {
  460.         OK = False;
  461.         WrStrErrorPos(ErrNum_InvAddrMode, &Token);
  462.       }
  463.       if (OK && (*ArgStr[1].str.p_str != '\0'))
  464.       {
  465.         GetToken(&ArgStr[1], &Token);
  466.         if (as_strcasecmp(Token.str.p_str, "AND"))
  467.         {
  468.           OK = False;
  469.           WrStrErrorPos(ErrNum_InvAddrMode, &Token);
  470.         }
  471.       }
  472.     }
  473.     if (OK)
  474.       CodeLen = 8;
  475.   }
  476. }
  477.  
  478. static void DecodeRegTrans(Word Index)
  479. {
  480.   LongWord Reg, Cnt;
  481.   Boolean OK;
  482.  
  483.   if (!ChkArgCnt(3, 3));
  484.   else if (!ChkExcludeCPU(CPU53C815));
  485.   else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  486.   else
  487.   {
  488.     tSymbolFlags Flags;
  489.  
  490.     Cnt = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt3, &OK, &Flags);
  491.     if (mFirstPassUnknown(Flags))
  492.       Cnt = 1;
  493.     if ((OK) && (ChkRange(Cnt, 1, 4)))
  494.     {
  495.       int l = strlen(ArgStr[3].str.p_str);
  496.       DAsmCode[0] = 0xe0000000 + (((LongInt) Index) << 24) + (Reg << 16) + Cnt;
  497.       if ((!as_strncasecmp(ArgStr[3].str.p_str, "DSAREL(", 7))
  498.        && (ArgStr[3].str.p_str[l - 1] == ')'))
  499.       {
  500.         ArgStr[3].str.p_str[--l] = '\0';
  501.         DAsmCode[0] |= 0x10000000;
  502.         DAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[3], 6, SInt24, &OK) & 0xffffff;
  503.       }
  504.       else
  505.         DAsmCode[1] = EvalStrIntExpression(&ArgStr[3], UInt32, &OK);
  506.       if (OK)
  507.         CodeLen = 8;
  508.     }
  509.   }
  510. }
  511.  
  512. static void DecodeMOVE(Word Index)
  513. {
  514. #define MAXPARTS 8
  515.   Boolean WithCarry;
  516.   String TokenStr;
  517.   tStrComp Token;
  518.   LongWord Tmp, DReg , AriOp = 0xff, ImmVal = 0x100;
  519.   Boolean OK;
  520.   int z;
  521.   Word BigCPUMask = (1 << (CPU53C825 - CPU53C810))
  522.                   | (1 << (CPU53C875 - CPU53C810))
  523.                   | (1 << (CPU53C895 - CPU53C810));
  524.  
  525.   UNUSED(Index);
  526.   StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
  527.  
  528.   if (!ChkArgCnt(1, 3));
  529.   else if (ArgCnt == 1) /* MOVE Register */
  530.   {
  531.     String PartStr[MAXPARTS];
  532.     tStrComp Parts[MAXPARTS];
  533.     int PartCnt = 0;
  534.  
  535.     for (z = 0; z < MAXPARTS; z++)
  536.       StrCompMkTemp(&Parts[z], PartStr[z], sizeof(PartStr[z]));
  537.     do
  538.     {
  539.       GetToken(&ArgStr[1], &Parts[PartCnt++]);
  540.     }
  541.     while ((*ArgStr[1].str.p_str != '\0') && (PartCnt < MAXPARTS));
  542.     if ((PartCnt > 1) && (!as_strcasecmp(Parts[PartCnt - 1].str.p_str, "CARRY")) && (!as_strcasecmp(Parts[PartCnt - 1].str.p_str, "TO")))
  543.     {
  544.       WithCarry = True;
  545.       PartCnt -= 2;
  546.     }
  547.     else
  548.       WithCarry = False;
  549.     DAsmCode[0] = 0x40000000;
  550.     DAsmCode[1] = 0;
  551.     if (PartCnt == 3)
  552.     {
  553.       if (WithCarry) WrError(ErrNum_InvAddrMode);
  554.       else if (!as_strcasecmp(Parts[1].str.p_str, "TO")) /* MOVE */
  555.       {
  556.         switch (DecodeComp(&Parts[0], &ImmVal))
  557.         {
  558.           case SFBR:
  559.             switch (DecodeComp(&Parts[2], &ImmVal))
  560.             {
  561.               case SFBR:
  562.                 ImmVal = 8;
  563.                 /* fall-through */
  564.               case REGISTER: /* --> 0x00 OR SFBR to reg */
  565.                 DAsmCode[0] += 0x2a000000 + (ImmVal << 16);
  566.                 CodeLen = 8;
  567.                 break;
  568.               default:
  569.                 WrError(ErrNum_InvAddrMode);
  570.             }
  571.             break;
  572.           case REGISTER:
  573.             DReg = ImmVal;
  574.             switch (DecodeComp(&Parts[2], &ImmVal))
  575.             {
  576.               case SFBR: /* --> 0x00 OR reg to SFBR */
  577.                 DAsmCode[0] += 0x32000000 + (DReg << 16);
  578.                 CodeLen = 8;
  579.                 break;
  580.               case REGISTER:
  581.                 if (ImmVal != DReg) WrError(ErrNum_InvAddrMode);
  582.                 else
  583.                 {
  584.                   DAsmCode[0] += 0x3a000000 + (DReg << 16);
  585.                   CodeLen = 8;
  586.                 }
  587.                 break;
  588.               default:
  589.                 WrError(ErrNum_InvAddrMode);
  590.             }
  591.             break;
  592.           case IMM8:
  593.             switch (DecodeComp(&Parts[2], &DReg))
  594.             {
  595.               case SFBR:
  596.                 DReg = 8;
  597.                 /* fall-through */
  598.               case REGISTER: /* --> imm to reg */
  599.                 DAsmCode[0] += 0x38000000 + (DReg << 16) + (ImmVal << 8);
  600.                 CodeLen = 8;
  601.                 break;
  602.               default:
  603.                 WrError(ErrNum_InvAddrMode);
  604.             }
  605.             break;
  606.           default:
  607.             WrError(ErrNum_InvAddrMode);
  608.             break;
  609.         }
  610.       } /* ... TO ... */
  611.       else if ((!as_strcasecmp(Parts[1].str.p_str, "SHL")) || (!as_strcasecmp(Parts[1].str.p_str, "SHR")))
  612.       {
  613.         AriOp = 1 + (Ord(as_toupper(Parts[1].str.p_str[2]) == 'R') << 2);
  614.         switch (DecodeComp(&Parts[0], &DReg))
  615.         {
  616.            case SFBR:
  617.              switch (DecodeComp(&Parts[2], &DReg))
  618.              {
  619.                case SFBR:
  620.                  DReg = 8;
  621.                  /* fall-through */
  622.                case REGISTER:
  623.                  DAsmCode[0] += 0x28000000 + (AriOp << 24) + (DReg << 16);
  624.                  CodeLen = 8;
  625.                  break;
  626.                default:
  627.                  WrError(ErrNum_InvAddrMode);
  628.              }
  629.              break;
  630.            case REGISTER:
  631.              ImmVal = DReg;
  632.              switch (DecodeComp(&Parts[2], &DReg))
  633.              {
  634.                case SFBR:
  635.                  DAsmCode[0] += 0x30000000 + (AriOp << 24) + (ImmVal << 16);
  636.                  CodeLen = 8;
  637.                  break;
  638.                case REGISTER:
  639.                  if (DReg != ImmVal) WrError(ErrNum_InvAddrMode);
  640.                  else
  641.                  {
  642.                    DAsmCode[0] += 0x38000000 + (AriOp << 24) + (ImmVal << 16);
  643.                    CodeLen = 8;
  644.                  }
  645.                  break;
  646.                default:
  647.                  WrError(ErrNum_InvAddrMode);
  648.              }
  649.              break;
  650.           default:
  651.             WrError(ErrNum_InvAddrMode);
  652.         }
  653.       } /* ... SHx ... */
  654.     } /* PartCnt == 3 */
  655.     else if (PartCnt == 5)
  656.     {
  657.       if (as_strcasecmp(Parts[3].str.p_str, "TO")) WrError(ErrNum_InvAddrMode);
  658.       else
  659.       {
  660.         if ((!as_strcasecmp(Parts[1].str.p_str, "XOR"))
  661.          || (!as_strcasecmp(Parts[1].str.p_str, "^")))
  662.           AriOp = 3;
  663.         else if ((!as_strcasecmp(Parts[1].str.p_str, "OR"))
  664.               || (!as_strcasecmp(Parts[1].str.p_str, "|")))
  665.           AriOp = 2;
  666.         else if ((!as_strcasecmp(Parts[1].str.p_str, "AND"))
  667.               || (!as_strcasecmp(Parts[1].str.p_str, "&")))
  668.           AriOp = 4;
  669.         else if (!strcmp(Parts[1].str.p_str, "+"))
  670.           AriOp = 6;
  671.         if (WithCarry)
  672.           AriOp = (AriOp == 6) ? 7 : 0xff;
  673.         if (AriOp == 0xff) WrError(ErrNum_InvAddrMode);
  674.         else
  675.         {
  676.           DAsmCode[0] |= (AriOp << 24);
  677.           switch (DecodeComp(&Parts[0], &ImmVal))
  678.           {
  679.             case SFBR:
  680.               switch (DecodeComp(&Parts[2], &ImmVal))
  681.               {
  682.                 case SFBR:
  683.                   switch (DecodeComp(&Parts[4], &ImmVal))
  684.                   {
  685.                     case SFBR:
  686.                       ImmVal = 8;
  687.                       /* fall-through */
  688.                     case REGISTER:
  689.                       if (ChkExactCPUMask(BigCPUMask, CPU53C810) >= 0)
  690.                       {
  691.                         DAsmCode[0] |= 0x28800000 + (ImmVal << 16);
  692.                         CodeLen = 8;
  693.                       }
  694.                       break;
  695.                     default:
  696.                       WrError(ErrNum_InvAddrMode);
  697.                   }
  698.                   break;
  699.                 case IMM8:
  700.                   switch (DecodeComp(&Parts[4], &DReg))
  701.                   {
  702.                     case SFBR:
  703.                       DReg = 8;
  704.                       /* fall-through */
  705.                     case REGISTER:
  706.                       DAsmCode[0] |= 0x28000000 + (DReg << 16) + (ImmVal << 8);
  707.                       CodeLen = 8;
  708.                       break;
  709.                     default:
  710.                       WrError(ErrNum_InvAddrMode);
  711.                   }
  712.                   break;
  713.                 default:
  714.                   WrError(ErrNum_InvAddrMode);
  715.               }
  716.               break;
  717.             case REGISTER:
  718.               DAsmCode[0] |= ImmVal << 16;
  719.               DReg = ImmVal;
  720.               switch (DecodeComp(&Parts[2], &ImmVal))
  721.               {
  722.                 case SFBR:
  723.                   switch (DecodeComp(&Parts[4], &ImmVal))
  724.                   {
  725.                     case SFBR:
  726.                       if (ChkExactCPUMask(BigCPUMask, CPU53C810) >= 0)
  727.                       {
  728.                         DAsmCode[0] |= 0x30800000;
  729.                         CodeLen = 8;
  730.                       }
  731.                       break;
  732.                     case REGISTER:
  733.                       if (DReg != ImmVal) WrError(ErrNum_InvAddrMode);
  734.                       else if (ChkExactCPUMask(BigCPUMask, CPU53C810) >= 0)
  735.                       {
  736.                         DAsmCode[0] |= 0x38800000;
  737.                         CodeLen = 8;
  738.                       }
  739.                       break;
  740.                     default:
  741.                       WrError(ErrNum_InvAddrMode);
  742.                   }
  743.                   break;
  744.                 case IMM8:
  745.                   DAsmCode[0] |= (ImmVal << 8);
  746.                   switch (DecodeComp(&Parts[4], &Tmp))
  747.                   {
  748.                     case SFBR:
  749.                       DAsmCode[0] |= 0x30000000;
  750.                       CodeLen = 8;
  751.                       break;
  752.                     case REGISTER:
  753.                       if (DReg != Tmp) WrError(ErrNum_InvAddrMode);
  754.                       else
  755.                       {
  756.                         DAsmCode[0] |= 0x38000000;
  757.                         CodeLen = 8;
  758.                       }
  759.                       break;
  760.                     default:
  761.                       WrError(ErrNum_InvAddrMode);
  762.                   }
  763.                   break;
  764.                 default:
  765.                   WrError(ErrNum_InvAddrMode);
  766.               }
  767.               break;
  768.             default:
  769.               WrError(ErrNum_InvAddrMode);
  770.           }
  771.         }
  772.       }
  773.     }  /* PartCnt == 5 */
  774.     else
  775.       WrError(ErrNum_InvAddrMode);
  776.   }
  777.   else if (ArgCnt == 2)
  778.   {
  779.     GetToken(&ArgStr[1], &Token);
  780.     if (as_strcasecmp(Token.str.p_str, "FROM")) WrError(ErrNum_InvAddrMode);
  781.     else
  782.     {
  783.       DAsmCode[0] = 0x00000000;
  784.       DAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int32, &OK);
  785.       if (OK)
  786.       {
  787.         GetToken(&ArgStr[2], &Token);
  788.         OK = True;
  789.         if (!as_strcasecmp(Token.str.p_str, "WHEN"))
  790.           DAsmCode[0] |= 0x08000000;
  791.         else if (as_strcasecmp(Token.str.p_str, "WITH"))
  792.           OK = False;
  793.         if (!OK) WrError(ErrNum_InvAddrMode);
  794.         else
  795.         {
  796.           KillPrefBlanksStrComp(&ArgStr[2]);
  797.           KillPostBlanksStrComp(&ArgStr[2]);
  798.           if (!DecodePhase(ArgStr[2].str.p_str, &ImmVal)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
  799.           else
  800.           {
  801.             DAsmCode[0] |= ImmVal << 24;
  802.             CodeLen = 8;
  803.           }
  804.         }
  805.       }
  806.     }
  807.   }
  808.   else if (ArgCnt == 3)
  809.   {
  810.     if (!as_strncasecmp(ArgStr[1].str.p_str, "MEMORY", 6))
  811.     {
  812.       StrCompCutLeft(&ArgStr[1], 7);
  813.       if (!as_strncasecmp(ArgStr[1].str.p_str, "NO FLUSH", 8))
  814.       {
  815.         DAsmCode[0] = 0xc1000000;
  816.         StrCompCutLeft(&ArgStr[1], 9);
  817.       }
  818.       else DAsmCode[0] = 0xc0000000;
  819.       DAsmCode[0] |= EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
  820.       if (OK)
  821.       {
  822.         DAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int32, &OK);
  823.         if (OK)
  824.         {
  825.           DAsmCode[2] = EvalStrIntExpression(&ArgStr[3], Int32, &OK);
  826.           if (OK) CodeLen = 12;
  827.         }
  828.       }
  829.     }
  830.     else
  831.     {
  832.       DAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
  833.       if (OK)
  834.       {
  835.         GetToken(&ArgStr[3], &Token);
  836.         OK = True;
  837.         if (!as_strcasecmp(Token.str.p_str, "WHEN")) DAsmCode[0] |= 0x08000000;
  838.         else if (as_strcasecmp(Token.str.p_str, "WITH")) OK = False;
  839.         if (!OK) WrError(ErrNum_InvAddrMode);
  840.         else
  841.         {
  842.           KillPrefBlanksStrComp(&ArgStr[3]);
  843.           KillPostBlanksStrComp(&ArgStr[3]);
  844.           if (!DecodePhase(ArgStr[3].str.p_str, &ImmVal)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[3]);
  845.           else
  846.           {
  847.             DAsmCode[0] |= ImmVal << 24;
  848.             if (!as_strncasecmp(ArgStr[2].str.p_str, "PTR", 3))
  849.             {
  850.               StrCompCutLeft(&ArgStr[2], 4);
  851.               DAsmCode[0] |= 0x20000000;
  852.             }
  853.             DAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt32, &OK);
  854.             if (OK) CodeLen = 8;
  855.           }
  856.         }
  857.       }
  858.     }
  859.   }
  860. }
  861.  
  862. static void DecodeSELECT(Word MayATN)
  863. {
  864.   Boolean OK;
  865.   LongInt Dist;
  866.   tSymbolFlags Flags;
  867.   int l;
  868.  
  869.   if (ChkArgCnt(2, 2))
  870.   {
  871.     DAsmCode[0] = 0x40000000;
  872.     OK = True;
  873.     if (!as_strncasecmp(ArgStr[1].str.p_str, "ATN ", 4))
  874.     {
  875.       strmov(ArgStr[1].str.p_str, ArgStr[1].str.p_str + 4);
  876.       ArgStr[1].Pos.StartCol += 4;
  877.       ArgStr[1].Pos.Len -= 4;
  878.       KillPrefBlanksStrComp(&ArgStr[1]);
  879.       if (!MayATN)
  880.         OK = False;
  881.       else
  882.         DAsmCode[0] |= 0x01000000;
  883.     }
  884.     if (!OK) WrError(ErrNum_InvAddrMode);
  885.     else
  886.     {
  887.       if (!as_strncasecmp(ArgStr[1].str.p_str, "FROM ", 5))
  888.       {
  889.         strmov(ArgStr[1].str.p_str, ArgStr[1].str.p_str + 5);
  890.         ArgStr[1].Pos.StartCol += 5;
  891.         ArgStr[1].Pos.Len -= 5;
  892.         KillPrefBlanksStrComp(&ArgStr[1]);
  893.         DAsmCode[0] |= 0x02000000 + EvalStrIntExpression(&ArgStr[1], UInt24, &OK);
  894.       }
  895.       else
  896.         DAsmCode[0] |= EvalStrIntExpression(&ArgStr[1], UInt4, &OK) << 16;
  897.       if (OK)
  898.       {
  899.         l = strlen(ArgStr[2].str.p_str);
  900.         if ((!as_strncasecmp(ArgStr[2].str.p_str, "REL(", 4)) && (ArgStr[2].str.p_str[l - 1] == ')'))
  901.         {
  902.           DAsmCode[0] |= 0x04000000;
  903.           ArgStr[2].str.p_str[l - 1] = '\0';
  904.           Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], 4, UInt32, &OK, &Flags) - (EProgCounter() + 8);
  905.           if (OK)
  906.           {
  907.             if (!mSymbolQuestionable(Flags) && ((Dist > 0x7fffff) || (Dist < -0x800000))) WrError(ErrNum_JmpDistTooBig);
  908.             else DAsmCode[1] = Dist & 0xffffff;
  909.           }
  910.         }
  911.         else DAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt32, &OK);
  912.         if (OK) CodeLen = 8;
  913.       }
  914.     }
  915.   }
  916. }
  917.  
  918. static void DecodeWAIT(Word Index)
  919. {
  920.   String TokenStr;
  921.   tStrComp Token;
  922.   Boolean OK;
  923.   LongInt Dist;
  924.   tSymbolFlags Flags;
  925.  
  926.   UNUSED(Index);
  927.   StrCompMkTemp(&Token, TokenStr, sizeof(TokenStr));
  928.  
  929.   if (ChkArgCnt(1, 1))
  930.   {
  931.     GetToken(&ArgStr[1], &Token);
  932.     KillPrefBlanksStrComp(&ArgStr[1]);
  933.     if (!as_strcasecmp(Token.str.p_str, "DISCONNECT"))
  934.     {
  935.       if (*ArgStr[1].str.p_str != '\0') WrError(ErrNum_InvAddrMode);
  936.       else
  937.       {
  938.         DAsmCode[0] = 0x48000000;
  939.         DAsmCode[1] = 0;
  940.         CodeLen = 8;
  941.       }
  942.     }
  943.     else if ((!as_strcasecmp(Token.str.p_str, "RESELECT")) || (!as_strcasecmp(Token.str.p_str, "SELECT")))
  944.     {
  945.       if ((!as_strncasecmp(ArgStr[1].str.p_str, "REL(", 4)) && (ArgStr[1].str.p_str[strlen(ArgStr[1].str.p_str) - 1] == ')'))
  946.       {
  947.         StrCompShorten(&ArgStr[1], 1);
  948.         DAsmCode[0] = 0x54000000;
  949.         Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 4, UInt32, &OK, &Flags) - (EProgCounter() + 8);
  950.         if (OK)
  951.         {
  952.           if (mSymbolQuestionable(Flags) && ((Dist > 0x7fffff) || (Dist < -0x800000))) WrError(ErrNum_JmpDistTooBig);
  953.           else
  954.             DAsmCode[1] = Dist & 0xffffff;
  955.         }
  956.       }
  957.       else
  958.       {
  959.         DAsmCode[0] = 0x50000000;
  960.         DAsmCode[1] = EvalStrIntExpression(&ArgStr[1], UInt32, &OK);
  961.       }
  962.       if (OK)
  963.       {
  964.         if (as_toupper(*Token.str.p_str) == 'S')
  965.           DAsmCode[0] |= 0x00000200;
  966.         CodeLen = 8;
  967.       }
  968.     }
  969.   }
  970. }
  971.  
  972. /*---------------------------------------------------------------------------*/
  973.  
  974. static void AddReg(const char *NName, LargeWord Adr, Word Mask)
  975. {
  976.   order_array_rsv_end(Regs, TReg);
  977.   Regs[InstrZ].Name = NName;
  978.   Regs[InstrZ].Code = Adr;
  979.   Regs[InstrZ++].Mask = Mask;
  980. }
  981.  
  982. static void InitFields(void)
  983. {
  984.   InstTable = CreateInstTable(51);
  985.  
  986.   add_null_pseudo(InstTable);
  987.  
  988.   AddInstTable(InstTable, "NOP"     , 0x80, DecodeFixed);
  989.   AddInstTable(InstTable, "DISCONNECT" , 0x48, DecodeFixed);
  990.   AddInstTable(InstTable, "JUMP"    , 0,    DecodeJmps);
  991.   AddInstTable(InstTable, "CALL"    , 1,    DecodeJmps);
  992.   AddInstTable(InstTable, "RETURN"  , 2,    DecodeJmps);
  993.   AddInstTable(InstTable, "INT"     , 3,    DecodeJmps);
  994.   AddInstTable(InstTable, "INTFLY"  , 3,    DecodeJmps);
  995.   AddInstTable(InstTable, "CHMOV"   , 0,    DecodeCHMOV);
  996.   AddInstTable(InstTable, "CLEAR"   , 0x60, DecodeFlags);
  997.   AddInstTable(InstTable, "SET"     , 0x58, DecodeFlags);
  998.   AddInstTable(InstTable, "LOAD"    , 1,    DecodeRegTrans);
  999.   AddInstTable(InstTable, "STORE"   , 0,    DecodeRegTrans);
  1000.   AddInstTable(InstTable, "MOVE"    , 0,    DecodeMOVE);
  1001.   AddInstTable(InstTable, "RESELECT", 0,    DecodeSELECT);
  1002.   AddInstTable(InstTable, "SELECT"  , 1,    DecodeSELECT);
  1003.   AddInstTable(InstTable, "WAIT"    , 0,    DecodeWAIT);
  1004.  
  1005.   InstrZ = 0;
  1006.   AddReg("SCNTL0"   , 0x00, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1007.   AddReg("SCNTL1"   , 0x01, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1008.   AddReg("SCNTL2"   , 0x02, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1009.   AddReg("SCNTL3"   , 0x03, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1010.   AddReg("SCID"     , 0x04, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1011.   AddReg("SXFER"    , 0x05, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1012.   AddReg("SDID"     , 0x06, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1013.   AddReg("GPREG"    , 0x07, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1014.   AddReg("SFBR"     , 0x08, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1015.   AddReg("SOCL"     , 0x09, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1016.   AddReg("SSID"     , 0x0a, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1017.   AddReg("SBCL"     , 0x0b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1018.   AddReg("DSTAT"    , 0x0c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1019.   AddReg("SSTAT0"   , 0x0d, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1020.   AddReg("SSTAT1"   , 0x0e, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1021.   AddReg("SSTAT2"   , 0x0f, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1022.   AddReg("DSA"      , 0x10, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1023.   AddReg("ISTAT"    , 0x14, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1024.   AddReg("CTEST0"   , 0x18, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1025.   AddReg("CTEST1"   , 0x19, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1026.   AddReg("CTEST2"   , 0x1a, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1027.   AddReg("CTEST3"   , 0x1b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1028.   AddReg("TEMP"     , 0x1c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1029.   AddReg("DFIFO"    , 0x20, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1030.   AddReg("CTEST4"   , 0x21, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1031.   AddReg("CTEST5"   , 0x22, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1032.   AddReg("CTEST6"   , 0x23, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1033.   AddReg("DBC"      , 0x24, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1034.   AddReg("DCMD"     , 0x27, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1035.   AddReg("DNAD"     , 0x28, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1036.   AddReg("DSP"      , 0x2c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1037.   AddReg("DSPS"     , 0x30, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1038.   AddReg("SCRATCHA" , 0x34, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1039.   AddReg("DMODE"    , 0x38, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1040.   AddReg("DIEN"     , 0x39, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1041.   AddReg("SBR"      , 0x3a, M_53C810                       + M_53C860 + M_53C875 + M_53C895);
  1042.   AddReg("DWT"      , 0x3a,            M_53C815                                            );
  1043.   AddReg("DCNTL"    , 0x3b, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1044.   AddReg("ADDER"    , 0x3c, M_53C810            + M_53C825 + M_53C860            + M_53C895);
  1045.   AddReg("SIEN0"    , 0x40, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1046.   AddReg("SIEN1"    , 0x41, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1047.   AddReg("SIST0"    , 0x42, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1048.   AddReg("SIST1"    , 0x43, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1049.   AddReg("SLPAR"    , 0x44, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1050.   AddReg("SWIDE"    , 0x45,                       M_53C825            + M_53C875 + M_53C895);
  1051.   AddReg("MACNTL"   , 0x46, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1052.   AddReg("GPCNTL"   , 0x47, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1053.   AddReg("STIME0"   , 0x48, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1054.   AddReg("STIME1"   , 0x49, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1055.   AddReg("RESPID"   , 0x4a, M_53C810 + M_53C815 + M_53C825 + M_53C860                      );
  1056.   AddReg("RESPID0"  , 0x4a,                                             M_53C875 + M_53C895);
  1057.   AddReg("RESPID1"  , 0x4b,                                             M_53C875 + M_53C895);
  1058.   AddReg("STEST0"   , 0x4c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1059.   AddReg("STEST1"   , 0x4d, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1060.   AddReg("STEST2"   , 0x4e, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1061.   AddReg("STEST3"   , 0x4f, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1062.   AddReg("SIDL"     , 0x50, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1063.   AddReg("STEST4"   , 0x52,                                                      + M_53C895);
  1064.   AddReg("SODL"     , 0x54, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1065.   AddReg("SBDL"     , 0x58, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1066.   AddReg("SCRATCHB" , 0x5c, M_53C810 + M_53C815 + M_53C825 + M_53C860 + M_53C875 + M_53C895);
  1067.   AddReg("SCRATCHC" , 0x60,                                             M_53C875 + M_53C895);
  1068.   AddReg("SCRATCHD" , 0x64,                                             M_53C875 + M_53C895);
  1069.   AddReg("SCRATCHE" , 0x68,                                             M_53C875 + M_53C895);
  1070.   AddReg("SCRATCHF" , 0x6c,                                             M_53C875 + M_53C895);
  1071.   AddReg("SCRATCHG" , 0x70,                                             M_53C875 + M_53C895);
  1072.   AddReg("SCRATCHH" , 0x74,                                             M_53C875 + M_53C895);
  1073.   AddReg("SCRATCHI" , 0x78,                                             M_53C875 + M_53C895);
  1074.   AddReg("SCRATCHJ" , 0x7c,                                             M_53C875 + M_53C895);
  1075.   AddReg(NULL       , 0x00, 0);
  1076.  
  1077.   AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
  1078. }
  1079.  
  1080. static void DeinitFields(void)
  1081. {
  1082.   DestroyInstTable(InstTable);
  1083.   order_array_free(Regs);
  1084. }
  1085.  
  1086. /*---------------------------------------------------------------------------*/
  1087.  
  1088. static void MakeCode_53c8xx(void)
  1089. {
  1090.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  1091.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  1092. }
  1093.  
  1094. static Boolean IsDef_53c8xx(void)
  1095. {
  1096.   return False;
  1097. }
  1098.  
  1099. static void SwitchFrom_53c8xx(void)
  1100. {
  1101.   DeinitFields();
  1102. }
  1103.  
  1104. static void SwitchTo_53c8xx(void)
  1105. {
  1106.   const TFamilyDescr *FoundDescr;
  1107.  
  1108.   FoundDescr = FindFamilyByName("SYM53C8xx");
  1109.  
  1110.   TurnWords = False;
  1111.   SetIntConstMode(eIntConstModeC);
  1112.   SetIsOccupiedFnc = TrueFnc;
  1113.   PCSymbol="$";
  1114.   HeaderID = FoundDescr->Id;
  1115.   NOPCode = 0;
  1116.   DivideChars = ",";
  1117.   HasAttrs = False;
  1118.  
  1119.   ValidSegs = (1 << SegCode);
  1120.   Grans[SegCode ] = 1; ListGrans[SegCode ] = 4; SegInits[SegCode ] = 0;
  1121.   SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
  1122.  
  1123.   MakeCode = MakeCode_53c8xx;
  1124.   IsDef = IsDef_53c8xx;
  1125.   SwitchFrom = SwitchFrom_53c8xx;
  1126.  
  1127.   InitFields();
  1128. }
  1129.  
  1130. /*---------------------------------------------------------------------------*/
  1131.  
  1132. void code53c8xx_init(void)
  1133. {
  1134.   CPU53C810 = AddCPU("SYM53C810", SwitchTo_53c8xx);
  1135.   CPU53C860 = AddCPU("SYM53C860", SwitchTo_53c8xx);
  1136.   CPU53C815 = AddCPU("SYM53C815", SwitchTo_53c8xx);
  1137.   CPU53C825 = AddCPU("SYM53C825", SwitchTo_53c8xx);
  1138.   CPU53C875 = AddCPU("SYM53C875", SwitchTo_53c8xx);
  1139.   CPU53C895 = AddCPU("SYM53C895", SwitchTo_53c8xx);
  1140. }
  1141.