Subversion Repositories pentevo

Rev

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

  1. /* code2650.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator Signetics 2650                                              */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "nls.h"
  16. #include "chunks.h"
  17. #include "bpemu.h"
  18. #include "strutil.h"
  19.  
  20. #include "asmdef.h"
  21. #include "asmsub.h"
  22. #include "asmpars.h"
  23. #include "asmitree.h"
  24. #include "codevars.h"
  25. #include "headids.h"
  26. #include "intpseudo.h"
  27. #include "errmsg.h"
  28. #include "onoff_common.h"
  29.  
  30. #include "code2650.h"
  31.  
  32. #define ADDR_INT UInt15
  33.  
  34. /*--------------------------------------------------------------------------*/
  35. /* Local Variables */
  36.  
  37. static CPUVar CPU2650;
  38.  
  39. /*--------------------------------------------------------------------------*/
  40. /* Expression Parsers */
  41.  
  42. static Boolean DecodeReg(const char *pAsc, Byte *pRes)
  43. {
  44.   Boolean Result;
  45.  
  46.   Result = ((strlen(pAsc) == 2) && (as_toupper(pAsc[0]) == 'R') && (pAsc[1] >= '0') && (pAsc[1] <= '3'));
  47.   if (Result)
  48.     *pRes = pAsc[1] - '0';
  49.   return Result;
  50. }
  51.  
  52. /*!------------------------------------------------------------------------
  53.  * \fn     DecodeCondition(const tStrComp *p_arg, Byte *p_ret)
  54.  * \brief  decode condition code
  55.  * \param  p_arg source argument
  56.  * \param  p_ret binary encoded argument
  57.  * \return true if success
  58.  * ------------------------------------------------------------------------ */
  59.  
  60. static Boolean DecodeCondition(const tStrComp *p_arg, Byte *p_ret)
  61. {
  62.   const char *p_asc = p_arg->str.p_str;
  63.  
  64.   if (!as_strcasecmp(p_asc, "EQ") || !as_strcasecmp(p_asc, "Z"))
  65.   {
  66.     *p_ret = 0;
  67.     return True;
  68.   }
  69.   else if (!as_strcasecmp(p_asc, "GT") || !as_strcasecmp(p_asc, "P"))
  70.   {
  71.     *p_ret = 1;
  72.     return True;
  73.   }
  74.   else if (!as_strcasecmp(p_asc, "LT") || !as_strcasecmp(p_asc, "N"))
  75.   {
  76.     *p_ret = 2;
  77.     return True;
  78.   }
  79.   else if ((!as_strcasecmp(p_asc, "ALWAYS")) || (!as_strcasecmp(p_asc, "UN")))
  80.   {
  81.     *p_ret = 3;
  82.     return True;
  83.   }
  84.   else
  85.   {
  86.     Boolean ok;
  87.  
  88.     *p_ret = EvalStrIntExpression(p_arg, UInt2, &ok);
  89.     return ok;
  90.   }
  91. }
  92.  
  93. /*!------------------------------------------------------------------------
  94.  * \fn     page_rel_ok(Word dest, Word src, tSymbolFlags flags, Word *p_dist, Boolean is_branch)
  95.  * \brief  check whether relative addressing in same 8K page is possible
  96.  * \param  dest target address
  97.  * \param  src current (source) address
  98.  * \param  flags expression evaluation flags
  99.  * \param  p_dist resulting distance
  100.  * \param  is_branch code or data access?
  101.  * \return True if distance is in range
  102.  * ------------------------------------------------------------------------ */
  103.  
  104. #define PAGE_MASK 0x1fff
  105.  
  106. static Boolean page_rel_ok(Word dest, Word src, tSymbolFlags flags, Word *p_dist, Boolean is_branch)
  107. {
  108.   if (((src & ~PAGE_MASK) != (dest & ~PAGE_MASK)) && !mSymbolQuestionable(flags))
  109.   {
  110.     WrError(is_branch ? ErrNum_JmpTargOnDiffPage : ErrNum_TargOnDiffPage);
  111.     return False;
  112.   }
  113.  
  114.   *p_dist = (dest - src) & PAGE_MASK;
  115.   if (((*p_dist < 0x1fc0) && (*p_dist > 0x3f)) && !mSymbolQuestionable(flags))
  116.   {
  117.     WrError(is_branch ? ErrNum_JmpDistTooBig : ErrNum_DistTooBig);
  118.     return False;
  119.   }
  120.  
  121.   return True;
  122. }
  123.  
  124. /*!------------------------------------------------------------------------
  125.  * \fn     Boolean page_abs_ok(Word dest, Word src, tSymbolFlags flags, Word *p_dest, Boolean is_branch)
  126.  * \brief  check whether absolute address is in same 8K page
  127.  * \param  dest target address
  128.  * \param  src current (source) address
  129.  * \param  flags expression evaluation flags
  130.  * \param  p_dest resulting address in machine instruction
  131.  * \param  is_branch code or data access?
  132.  * \return True if distance is in range
  133.  * ------------------------------------------------------------------------ */
  134.  
  135. static Boolean page_abs_ok(Word dest, Word src, tSymbolFlags flags, Word *p_dest, Boolean is_branch)
  136. {
  137.   if (((src & ~PAGE_MASK) != (dest & ~PAGE_MASK)) && !mSymbolQuestionable(flags))
  138.   {
  139.     WrError(is_branch ? ErrNum_JmpTargOnDiffPage : ErrNum_TargOnDiffPage);
  140.     return False;
  141.   }
  142.  
  143.   *p_dest = dest & PAGE_MASK;
  144.   return True;
  145. }
  146.  
  147. /*--------------------------------------------------------------------------*/
  148. /* Instruction Decoders */
  149.  
  150. static void DecodeFixed(Word Index)
  151. {
  152.   if (ChkArgCnt(0, 0))
  153.   {
  154.     BAsmCode[0] = Index; CodeLen = 1;
  155.   }
  156. }
  157.  
  158. /*!------------------------------------------------------------------------
  159.  * \fn     DecodeOneReg(Word Index)
  160.  * \brief  decode instructions taking a single register as argument
  161.  * \param  Index machine code of instruction when register 0 is used
  162.  * ------------------------------------------------------------------------ */
  163.  
  164. static void DecodeOneReg(Word Index)
  165. {
  166.   Byte Reg;
  167.  
  168.   if (!ChkArgCnt(1, 1));
  169.   else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  170.   else
  171.   {
  172.     BAsmCode[0] = Index | Reg;
  173.     CodeLen = 1;
  174.   }
  175. }
  176.  
  177. /*!------------------------------------------------------------------------
  178.  * \fn     DecodeOneReg_NoZero(Word Index)
  179.  * \brief  decode instructions taking a single register except R0 as argument
  180.  * \param  Index machine code of instruction register # is added to
  181.  * ------------------------------------------------------------------------ */
  182.  
  183.  
  184. static void DecodeOneReg_NoZero(Word Index)
  185. {
  186.   Byte Reg;
  187.  
  188.   if (!ChkArgCnt(1, 1));
  189.   else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  190.   else if (!Reg) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  191.   else
  192.   {
  193.     BAsmCode[0] = Index | Reg;
  194.     CodeLen = 1;
  195.   }
  196. }
  197.  
  198. /*!------------------------------------------------------------------------
  199.  * \fn     DecodeLODZ(Word Index)
  200.  * \brief  decode LODZ instruction
  201.  * \param  Index machine code of instruction when register 0 is used
  202.  * ------------------------------------------------------------------------ */
  203.  
  204. static void DecodeLODZ(Word Index)
  205. {
  206.   Byte Reg;
  207.  
  208.   if (!ChkArgCnt(1, 1));
  209.   else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  210.   else
  211.   {
  212.     /* LODZ R0 shall be encoded as IORZ R0 */
  213.     BAsmCode[0] = Reg ? (Index | Reg) : 0x60;
  214.     CodeLen = 1;
  215.   }
  216. }
  217.  
  218. static void DecodeImm(Word Index)
  219. {
  220.   Boolean OK;
  221.  
  222.   if (ChkArgCnt(1, 1))
  223.   {
  224.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
  225.     if (OK)
  226.     {
  227.       BAsmCode[0] = Index; CodeLen = 2;
  228.     }
  229.   }
  230. }
  231.  
  232. static void DecodeRegImm(Word Index)
  233. {
  234.   Byte Reg;
  235.   Boolean OK;
  236.  
  237.   if (!ChkArgCnt(2, 2));
  238.   else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  239.   else
  240.   {
  241.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  242.     if (OK)
  243.     {
  244.       BAsmCode[0] = Index | Reg; CodeLen = 2;
  245.     }
  246.   }
  247. }
  248.  
  249. /*!------------------------------------------------------------------------
  250.  * \fn     void DecodeRegAbs(Word code)
  251.  * \brief  handle instruction with register & absolute address
  252.  * \param  code instruction machine code
  253.  * ------------------------------------------------------------------------ */
  254.  
  255. static void DecodeRegAbs(Word code)
  256. {
  257.   Byte dest_reg;
  258.  
  259.   if (!ChkArgCnt(2, 4));
  260.   else if (!DecodeReg(ArgStr[1].str.p_str, &dest_reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  261.   else
  262.   {
  263.     Boolean ok, ind_flag = *ArgStr[2].str.p_str == '*';
  264.     Word abs_val;
  265.     tSymbolFlags flags;
  266.     Byte index_reg;
  267.  
  268.     abs_val = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], ind_flag, ADDR_INT, &ok, &flags);
  269.     if (ok && page_abs_ok(abs_val, EProgCounter() + 3, flags, &abs_val, False))
  270.     {
  271.       BAsmCode[0] = code;
  272.       BAsmCode[1] = Hi(abs_val);
  273.       BAsmCode[2] = Lo(abs_val);
  274.       if (ind_flag)
  275.         BAsmCode[1] |= 0x80;
  276.       if (ArgCnt == 2)
  277.       {
  278.         BAsmCode[0] |= dest_reg;
  279.         CodeLen = 3;
  280.       }
  281.       else
  282.       {
  283.         if (!DecodeReg(ArgStr[3].str.p_str, &index_reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[3]);
  284.         else if (dest_reg != 0) WrError(ErrNum_InvAddrMode);
  285.         else
  286.         {
  287.           BAsmCode[0] |= index_reg;
  288.           if (ArgCnt == 3)
  289.           {
  290.             BAsmCode[1] |= 0x60;
  291.             CodeLen = 3;
  292.           }
  293.           else if (!strcmp(ArgStr[4].str.p_str, "-"))
  294.           {
  295.             BAsmCode[1] |= 0x40;
  296.             CodeLen = 3;
  297.           }
  298.           else if (!strcmp(ArgStr[4].str.p_str, "+"))
  299.           {
  300.             BAsmCode[1] |= 0x20;
  301.             CodeLen = 3;
  302.           }
  303.           else
  304.             WrError(ErrNum_InvAddrMode);
  305.         }
  306.       }
  307.     }
  308.   }
  309. }
  310.  
  311. /*!------------------------------------------------------------------------
  312.  * \fn     DecodeRegRel(Word code)
  313.  * \brief  handle instructions with register & relative argument
  314.  * \param  code instruction machine code
  315.  * ------------------------------------------------------------------------ */
  316.  
  317. static void DecodeRegRel(Word code)
  318. {
  319.   Byte reg;
  320.  
  321.   if (!ChkArgCnt(2, 2));
  322.   else if (!DecodeReg(ArgStr[1].str.p_str, &reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  323.   else
  324.   {
  325.     Word dest, dist;
  326.     tSymbolFlags flags;
  327.     Boolean ind_flag, ok;
  328.  
  329.     BAsmCode[0] = code | reg;
  330.     ind_flag = *ArgStr[2].str.p_str == '*';
  331.     dest = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], ind_flag, ADDR_INT, &ok, &flags);
  332.     if (ok && page_rel_ok(dest, EProgCounter() + 2, flags, &dist, False))
  333.     {
  334.       BAsmCode[1] = dist & 0x7f;
  335.       if (ind_flag)
  336.         BAsmCode[1] |= 0x80;
  337.       CodeLen = 2;
  338.     }
  339.   }
  340. }
  341.  
  342. static void DecodeCondAbs(Word Index)
  343. {
  344.   Byte Cond;
  345.   Word Address;
  346.   Boolean OK, IndFlag;
  347.  
  348.   if (ChkArgCnt(2, 2)
  349.    && DecodeCondition(&ArgStr[1], &Cond))
  350.   {
  351.     IndFlag = *ArgStr[2].str.p_str == '*';
  352.     Address = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, ADDR_INT, &OK);
  353.     if (OK)
  354.     {
  355.       BAsmCode[0] = Index | Cond;
  356.       BAsmCode[1] = Hi(Address);
  357.       if (IndFlag)
  358.         BAsmCode[1] |= 0x80;
  359.       BAsmCode[2] = Lo(Address);
  360.       CodeLen = 3;
  361.     }
  362.   }
  363. }
  364.  
  365. /*!------------------------------------------------------------------------
  366.  * \fn     DecodeCondRel(Word code)
  367.  * \brief  decode relative branches
  368.  * \param  code machine code
  369.  * ------------------------------------------------------------------------ */
  370.  
  371. static void DecodeCondRel(Word code)
  372. {
  373.   Byte cond;
  374.  
  375.   if (ChkArgCnt(2, 2)
  376.    && DecodeCondition(&ArgStr[1], &cond))
  377.   {
  378.     Boolean ind_flag, ok;
  379.     tSymbolFlags flags;
  380.     Word dist, dest;
  381.  
  382.     BAsmCode[0] = code | cond;
  383.     ind_flag = *ArgStr[2].str.p_str == '*';
  384.     dest = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], ind_flag, ADDR_INT, &ok, &flags);
  385.     if (ok && page_rel_ok(dest, EProgCounter() + 2, flags, &dist, True))
  386.     {
  387.       BAsmCode[1] = dist & 0x7f;
  388.       if (ind_flag)
  389.         BAsmCode[1] |= 0x80;
  390.       CodeLen = 2;
  391.     }
  392.   }
  393. }
  394.  
  395. static void DecodeRegAbs2(Word Index)
  396. {
  397.   Byte Reg;
  398.   Word AbsVal;
  399.   Boolean IndFlag, OK;
  400.  
  401.   if (!ChkArgCnt(2, 2));
  402.   else if (!DecodeReg(ArgStr[1].str.p_str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  403.   else
  404.   {
  405.     BAsmCode[0] = Index | Reg;
  406.     IndFlag = *ArgStr[2].str.p_str == '*';
  407.     AbsVal = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, ADDR_INT, &OK);
  408.     if (OK)
  409.     {
  410.       BAsmCode[1] = Hi(AbsVal);
  411.       if (IndFlag)
  412.         BAsmCode[1] |= 0x80;
  413.       BAsmCode[2] = Lo(AbsVal);
  414.       CodeLen = 3;
  415.     }
  416.   }
  417. }
  418.  
  419. static void DecodeBrAbs(Word Index)
  420. {
  421.   Byte Reg = 3;
  422.   Word AbsVal;
  423.   Boolean IndFlag, OK;
  424.  
  425.   if (!ChkArgCnt(1, 2));
  426.   else if ((ArgCnt == 2) && (!DecodeReg(ArgStr[2].str.p_str, &Reg))) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
  427.   else if (Reg != 3) WrError(ErrNum_InvAddrMode);
  428.   else
  429.   {
  430.     BAsmCode[0] = Index | Reg;
  431.     IndFlag = *ArgStr[1].str.p_str == '*';
  432.     AbsVal = EvalStrIntExpressionOffs(&ArgStr[1], IndFlag, ADDR_INT, &OK);
  433.     if (OK)
  434.     {
  435.       BAsmCode[1] = Hi(AbsVal);
  436.       if (IndFlag)
  437.         BAsmCode[1] |= 0x80;
  438.       BAsmCode[2] = Lo(AbsVal);
  439.       CodeLen = 3;
  440.     }
  441.   }
  442. }
  443.  
  444. static void DecodeCond(Word Index)
  445. {
  446.   Byte Cond;
  447.  
  448.   if (ChkArgCnt(1, 1)
  449.    && DecodeCondition(&ArgStr[1], &Cond))
  450.   {
  451.     BAsmCode[0] = Index | Cond;
  452.     CodeLen = 1;
  453.   }
  454. }
  455.  
  456. /*!------------------------------------------------------------------------
  457.  * \fn     DecodeZero(Word code)
  458.  * \brief  decode zero page branch instructions
  459.  * \param  code machine code
  460.  * ------------------------------------------------------------------------ */
  461.  
  462. static void DecodeZero(Word code)
  463. {
  464.   if (ChkArgCnt(1, 1))
  465.   {
  466.     Boolean ind_flag, ok;
  467.     tSymbolFlags flags;
  468.     Word dest, dist;
  469.  
  470.     BAsmCode[0] = code;
  471.     ind_flag = *ArgStr[1].str.p_str == '*';
  472.     dest = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], ind_flag, ADDR_INT, &ok, &flags);
  473.     if (ok && page_rel_ok(dest, 0x0000, flags, &dist, True))
  474.     {
  475.       BAsmCode[1] = dist & 0x7f;
  476.       if (ind_flag)
  477.         BAsmCode[1] |= 0x80;
  478.       CodeLen = 2;
  479.     }
  480.   }
  481. }
  482.  
  483. /*--------------------------------------------------------------------------*/
  484. /* Code Table Handling */
  485.  
  486. static void AddFixed(const char *pName, Word Code)
  487. {
  488.   AddInstTable(InstTable, pName, Code, DecodeFixed);
  489. }
  490.  
  491. static void AddOneReg(const char *pName, Word Code)
  492. {
  493.   AddInstTable(InstTable, pName, Code, DecodeOneReg);
  494. }
  495.  
  496. static void AddImm(const char *pName, Word Code)
  497. {
  498.   AddInstTable(InstTable, pName, Code, DecodeImm);
  499. }
  500.  
  501. static void AddRegImm(const char *pName, Word Code)
  502. {
  503.   AddInstTable(InstTable, pName, Code, DecodeRegImm);
  504. }
  505.  
  506. static void AddRegAbs(const char *pName, Word Code)
  507. {
  508.   AddInstTable(InstTable, pName, Code, DecodeRegAbs);
  509. }
  510.  
  511. static void AddRegRel(const char *pName, Word Code)
  512. {
  513.   AddInstTable(InstTable, pName, Code, DecodeRegRel);
  514. }
  515.  
  516. static void AddCondAbs(const char *pName, Word Code)
  517. {
  518.   AddInstTable(InstTable, pName, Code, DecodeCondAbs);
  519. }
  520.  
  521. static void AddCondRel(const char *pName, Word Code)
  522. {
  523.   AddInstTable(InstTable, pName, Code, DecodeCondRel);
  524. }
  525.  
  526. static void AddRegAbs2(const char *pName, Word Code)
  527. {
  528.   AddInstTable(InstTable, pName, Code, DecodeRegAbs2);
  529. }
  530.  
  531. static void AddBrAbs(const char *pName, Word Code)
  532. {
  533.   AddInstTable(InstTable, pName, Code, DecodeBrAbs);
  534. }
  535.  
  536. static void AddCond(const char *pName, Word Code)
  537. {
  538.   AddInstTable(InstTable, pName, Code, DecodeCond);
  539. }
  540.  
  541. static void AddZero(const char *pName, Word Code)
  542. {
  543.   AddInstTable(InstTable, pName, Code, DecodeZero);
  544. }
  545.  
  546. static void InitFields(void)
  547. {
  548.   InstTable = CreateInstTable(203);
  549.  
  550.   AddFixed("NOP", 0xc0);
  551.   AddFixed("HALT", 0x40);
  552.   AddFixed("LPSL", 0x93);
  553.   AddFixed("LPSU", 0x92);
  554.   AddFixed("SPSL", 0x13);
  555.   AddFixed("SPSU", 0x12);
  556.  
  557.   AddOneReg("ADDZ", 0x80);
  558.   /* ANDZ R0 is not allowed and decodes as HALT */
  559.   AddInstTable(InstTable, "ANDZ", 0x40, DecodeOneReg_NoZero);
  560.   AddOneReg("COMZ", 0xe0);
  561.   AddOneReg("DAR", 0x94);
  562.   AddOneReg("EORZ", 0x20);
  563.   AddOneReg("IORZ", 0x60);
  564.   AddInstTable(InstTable, "LODZ", 0x00, DecodeLODZ);
  565.   AddOneReg("REDC", 0x30);
  566.   AddOneReg("REDD", 0x70);
  567.   AddOneReg("RRL", 0xd0);
  568.   AddOneReg("RRR", 0x50);
  569.   /* STRZ R0 is not allowed and decodes as NOP */
  570.   AddInstTable(InstTable, "STRZ", 0xc0, DecodeOneReg_NoZero);
  571.   AddOneReg("SUBZ", 0xa0);
  572.   AddOneReg("WRTC", 0xb0);
  573.   AddOneReg("WRTD", 0xf0);
  574.  
  575.   AddImm("CPSL", 0x75);
  576.   AddImm("CPSU", 0x74);
  577.   AddImm("PPSL", 0x77);
  578.   AddImm("PPSU", 0x76);
  579.   AddImm("TPSL", 0xb5);
  580.   AddImm("TPSU", 0xb4);
  581.  
  582.   AddRegImm("ADDI", 0x84);
  583.   AddRegImm("ANDI", 0x44);
  584.   AddRegImm("COMI", 0xe4);
  585.   AddRegImm("EORI", 0x24);
  586.   AddRegImm("IORI", 0x64);
  587.   AddRegImm("LODI", 0x04);
  588.   AddRegImm("REDE", 0x54);
  589.   AddRegImm("SUBI", 0xa4);
  590.   AddRegImm("TMI", 0xf4);
  591.   AddRegImm("WRTE", 0xd4);
  592.  
  593.   AddRegAbs("ADDA", 0x8c);
  594.   AddRegAbs("ANDA", 0x4c);
  595.   AddRegAbs("COMA", 0xec);
  596.   AddRegAbs("EORA", 0x2c);
  597.   AddRegAbs("IORA", 0x6c);
  598.   AddRegAbs("LODA", 0x0c);
  599.   AddRegAbs("STRA", 0xcc);
  600.   AddRegAbs("SUBA", 0xac);
  601.  
  602.   AddRegRel("ADDR", 0x88);
  603.   AddRegRel("ANDR", 0x48);
  604.   AddRegRel("BDRR", 0xf8);
  605.   AddRegRel("BIRR", 0xd8);
  606.   AddRegRel("BRNR", 0x58);
  607.   AddRegRel("BSNR", 0x78);
  608.   AddRegRel("COMR", 0xe8);
  609.   AddRegRel("EORR", 0x28);
  610.   AddRegRel("IORR", 0x68);
  611.   AddRegRel("LODR", 0x08);
  612.   AddRegRel("STRR", 0xc8);
  613.   AddRegRel("SUBR", 0xa8);
  614.  
  615.   AddCondAbs("BCFA", 0x9c);
  616.   AddCondAbs("BCTA", 0x1c);
  617.   AddCondAbs("BSFA", 0xbc);
  618.   AddCondAbs("BSTA", 0x3c);
  619.  
  620.   AddCondRel("BCFR", 0x98);
  621.   AddCondRel("BCTR", 0x18);
  622.   AddCondRel("BSFR", 0xb8);
  623.   AddCondRel("BSTR", 0x38);
  624.  
  625.   AddRegAbs2("BDRA", 0xfc);
  626.   AddRegAbs2("BIRA", 0xdc);
  627.   AddRegAbs2("BRNA", 0x5c);
  628.   AddRegAbs2("BSNA", 0x7c);
  629.  
  630.   AddBrAbs("BSXA", 0xbf);
  631.   AddBrAbs("BXA", 0x9f);
  632.  
  633.   AddCond("RETC", 0x14);
  634.   AddCond("RETE", 0x34);
  635.  
  636.   AddZero("ZBRR", 0x9b);
  637.   AddZero("ZBSR", 0xbb);
  638.  
  639.   AddInstTable(InstTable, "RES", 1, DecodeIntelDS);
  640.   AddInstTable(InstTable, "ACON", eIntPseudoFlag_BigEndian | eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString, DecodeIntelDW);
  641. }
  642.  
  643. static void DeinitFields(void)
  644. {
  645.   DestroyInstTable(InstTable);
  646. }
  647.  
  648. /*--------------------------------------------------------------------------*/
  649. /* Callbacks */
  650.  
  651. static void MakeCode_2650(void)
  652. {
  653.   char *pPos;
  654.  
  655.   CodeLen = 0;
  656.  
  657.   DontPrint = False;
  658.  
  659.   /* Nullanweisung */
  660.  
  661.   if ((*OpPart.str.p_str == '\0') && (ArgCnt == 0))
  662.     return;
  663.  
  664.   /* Pseudoanweisungen */
  665.  
  666.   if (DecodeIntelPseudo(TargetBigEndian)) return;
  667.  
  668.   /* try to split off first (register) operand from instruction */
  669.  
  670.   pPos = strchr(OpPart.str.p_str, ',');
  671.   if (pPos)
  672.   {
  673.     InsertArg(1, strlen(OpPart.str.p_str));
  674.     StrCompSplitRight(&OpPart, &ArgStr[1], pPos);
  675.   }
  676.  
  677.   /* alles aus der Tabelle */
  678.  
  679.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  680.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  681. }
  682.  
  683. static Boolean IsDef_2650(void)
  684. {
  685.   return FALSE;
  686. }
  687.  
  688. static void SwitchFrom_2650(void)
  689. {
  690.   DeinitFields();
  691. }
  692.  
  693. static void SwitchTo_2650(void)
  694. {
  695.   const TFamilyDescr *pDescr;
  696.  
  697.   TurnWords = False;
  698.   SetIntConstMode(eIntConstModeMoto);
  699.  
  700.   pDescr = FindFamilyByName("2650");
  701.   PCSymbol = "$"; HeaderID = pDescr->Id; NOPCode = 0xc0;
  702.   DivideChars = ","; HasAttrs = False;
  703.  
  704.   ValidSegs = (1 << SegCode);
  705.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  706.   SegLimits[SegCode] = IntTypeDefs[ADDR_INT].Max;
  707.  
  708.   MakeCode = MakeCode_2650; IsDef = IsDef_2650;
  709.   SwitchFrom = SwitchFrom_2650; InitFields();
  710.  
  711.   onoff_bigendian_add();
  712. }
  713.  
  714. /*--------------------------------------------------------------------------*/
  715. /* Initialisierung */
  716.  
  717. void code2650_init(void)
  718. {
  719.   CPU2650 = AddCPU("2650", SwitchTo_2650);
  720. }
  721.