Subversion Repositories pentevo

Rev

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

  1. /* codekcp3.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator Xilinx kcpsm3                                               */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15.  
  16. #include "nls.h"
  17. #include "strutil.h"
  18. #include "bpemu.h"
  19. #include "asmdef.h"
  20. #include "asmsub.h"
  21. #include "asmpars.h"
  22. #include "asmitree.h"
  23. #include "asmallg.h"
  24. #include "intpseudo.h"
  25. #include "codevars.h"
  26. #include "headids.h"
  27. #include "errmsg.h"
  28. #include "codepseudo.h"
  29.  
  30. #include "codekcp3.h"
  31.  
  32. typedef struct
  33. {
  34.   LongWord Code;
  35. } FixedOrder;
  36.  
  37. static FixedOrder *RegOrders, *ALUOrders;
  38.  
  39. static CPUVar CPUKCPSM3;
  40.  
  41. /*--------------------------------------------------------------------------
  42.  * Address Expression Parsing
  43.  *--------------------------------------------------------------------------*/
  44.  
  45. /*!------------------------------------------------------------------------
  46.  * \fn     IsWRegCore(const char *pArg, LongWord *pResult)
  47.  * \brief  is argument a built-in register?
  48.  * \param  pArg argument
  49.  * \param  pResult register number if yes
  50.  * \return true if yes
  51.  * ------------------------------------------------------------------------ */
  52.  
  53. static Boolean IsWRegCore(const char *pArg, LongWord *pResult)
  54. {
  55.   Boolean OK;
  56.  
  57.   if ((strlen(pArg) < 2) || (as_toupper(*pArg) != 'S'))
  58.     return False;
  59.  
  60.   *pResult = ConstLongInt(pArg + 1, &OK, 16);
  61.   if (!OK)
  62.     return False;
  63.  
  64.   return (*pResult < 16);
  65. }
  66.  
  67. /*!------------------------------------------------------------------------
  68.  * \fn     DissectReg_KCPSM3(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  69.  * \brief  dissect register symbols - KCPSM3 variant
  70.  * \param  pDest destination buffer
  71.  * \param  DestSize destination buffer size
  72.  * \param  Value numeric register value
  73.  * \param  InpSize register size
  74.  * ------------------------------------------------------------------------ */
  75.  
  76. static void DissectReg_KCPSM3(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  77. {
  78.   switch (InpSize)
  79.   {
  80.     case eSymbolSize8Bit:
  81.       as_snprintf(pDest, DestSize, "S%x", (unsigned)Value);
  82.       pDest[1] = as_toupper(pDest[1]);
  83.       break;
  84.     default:
  85.       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
  86.   }
  87. }
  88.  
  89. /*!------------------------------------------------------------------------
  90.  * \fn     IsWReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
  91.  * \brief  is argument a built-in register or register alias?
  92.  * \param  pArg argument
  93.  * \param  pResult register number if yes
  94.  * \param  MustBeReg expect register arg?
  95.  * \return reg evel result
  96.  * ------------------------------------------------------------------------ */
  97.  
  98. static tRegEvalResult IsWReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
  99. {
  100.   tRegDescr RegDescr;
  101.   tEvalResult EvalResult;
  102.   tRegEvalResult RegEvalResult;
  103.  
  104.   if (IsWRegCore(pArg->str.p_str, pResult))
  105.     return eIsReg;
  106.  
  107.   RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize8Bit, MustBeReg);
  108.   *pResult = RegDescr.Reg;
  109.   return RegEvalResult;
  110. }
  111.  
  112. /*!------------------------------------------------------------------------
  113.  * \fn     IsIWReg(const tStrComp *pArg, LongWord *pResult)
  114.  * \brief  is argument an indirect register expression?
  115.  * \param  pArg argument
  116.  * \param  pResult register number if yes
  117.  * \return true if yes
  118.  * ------------------------------------------------------------------------ */
  119.  
  120. static tRegEvalResult IsIWReg(const tStrComp *pArg, LongWord *pResult)
  121. {
  122.   char Tmp[10];
  123.   tStrComp TmpComp;
  124.   int l = strlen(pArg->str.p_str);
  125.  
  126.   if ((l < 3) || (pArg->str.p_str[0] != '(') || (pArg->str.p_str[l - 1] != ')'))
  127.     return eIsNoReg;
  128.  
  129.   StrCompMkTemp(&TmpComp, Tmp, sizeof(Tmp));
  130.   StrCompCopySub(&TmpComp, pArg, 1, l - 2);
  131.   return IsWReg(&TmpComp, pResult, False);
  132. }
  133.  
  134. static Boolean IsCond(int OtherArgCnt, LongWord *pErg)
  135. {
  136.   static const char Conds[4][3] = { "Z", "NZ", "C", "NC" };
  137.  
  138.   if (ArgCnt <= OtherArgCnt)
  139.   {
  140.     *pErg = 0;
  141.     return True;
  142.   }
  143.  
  144.   for (*pErg = 0; *pErg < (sizeof(Conds) / sizeof(*Conds)); (*pErg)++)
  145.     if (!as_strcasecmp(Conds[*pErg], ArgStr[1].str.p_str))
  146.     {
  147.       *pErg |= 4;
  148.       return True;
  149.     }
  150.  
  151.   return False;
  152. }
  153.  
  154. /*--------------------------------------------------------------------------
  155.  * Code Handlers
  156.  *--------------------------------------------------------------------------*/
  157.  
  158. static void DecodePort(Word Index)
  159. {
  160.   UNUSED(Index);
  161.  
  162.   CodeEquate(SegIO, 0, SegLimits[SegIO]);
  163. }
  164.  
  165. static void DecodeConstant(Word Index)
  166. {
  167.   UNUSED(Index);
  168.  
  169.   if (ChkArgCnt(2, 2))
  170.   {
  171.     TempResult t;
  172.     Boolean OK;
  173.  
  174.     as_tempres_ini(&t);
  175.     as_tempres_set_int(&t, EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &OK, &t.Flags));
  176.     if (OK && !mFirstPassUnknown(t.Flags))
  177.     {
  178.       SetListLineVal(&t);
  179.       PushLocHandle(-1);
  180.       EnterIntSymbol(&ArgStr[1], t.Contents.Int, SegNone, False);
  181.       PopLocHandle();
  182.     }
  183.     as_tempres_free(&t);
  184.   }
  185. }
  186.  
  187. static void DecodeOneReg(Word Index)
  188. {
  189.   FixedOrder *pOrder = RegOrders + Index;
  190.   LongWord Reg;
  191.  
  192.   if (ChkArgCnt(1, 1)
  193.    && IsWReg(&ArgStr[1], &Reg, True))
  194.   {
  195.     DAsmCode[0] = pOrder->Code | (Reg << 8);
  196.     CodeLen = 1;
  197.   }
  198. }
  199.  
  200. static void DecodeALU(Word Index)
  201. {
  202.   FixedOrder *pOrder = ALUOrders + Index;
  203.   LongWord Src, DReg;
  204.   Boolean OK;
  205.  
  206.   if (ChkArgCnt(2, 2)
  207.    && IsWReg(&ArgStr[1], &DReg, True))
  208.     switch (IsWReg(&ArgStr[2], &Src, False))
  209.     {
  210.       case eIsReg:
  211.         DAsmCode[0] = pOrder->Code | 0x1000 | (DReg << 8) | (Src << 4);
  212.         CodeLen = 1;
  213.         break;
  214.       case eIsNoReg:
  215.         Src = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  216.         if (OK)
  217.         {
  218.           DAsmCode[0] = pOrder->Code | (DReg << 8) | (Src & 0xff);
  219.           CodeLen = 1;
  220.         }
  221.         break;
  222.       case eRegAbort:
  223.         break;
  224.     }
  225. }
  226.  
  227. static void DecodeJmp(Word Index)
  228. {
  229.   LongWord Cond;
  230.  
  231.   if (ChkArgCnt(1, 2)
  232.    && IsCond(1, &Cond))
  233.   {
  234.     tEvalResult EvalResult;
  235.     LongWord Addr = EvalStrIntExpressionWithResult(&ArgStr[ArgCnt], UInt10, &EvalResult);
  236.  
  237.     if (EvalResult.OK)
  238.     {
  239.       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  240.       DAsmCode[0] = 0x30000 | Index | (Cond << 10) | (Addr & 0x3ff);
  241.       CodeLen = 1;
  242.     }
  243.   }
  244. }
  245.  
  246. static void DecodeRet(Word Index)
  247. {
  248.   LongWord Cond;
  249.  
  250.   UNUSED(Index);
  251.  
  252.   if (ChkArgCnt(0, 1)
  253.    && IsCond(0, &Cond))
  254.   {
  255.     DAsmCode[0] = 0x2a000 | (Cond << 10);
  256.     CodeLen = 1;
  257.   }
  258. }
  259.  
  260. static void DecodeReti(Word Index)
  261. {
  262.   UNUSED(Index);
  263.  
  264.   if (ChkArgCnt(1, 1))
  265.   {
  266.     if (!as_strcasecmp(ArgStr[1].str.p_str, "DISABLE"))
  267.     {
  268.       DAsmCode[0] = 0x38000;
  269.       CodeLen = 1;
  270.     }
  271.     else if (!as_strcasecmp(ArgStr[1].str.p_str, "ENABLE"))
  272.     {
  273.       DAsmCode[0] = 0x38001;
  274.       CodeLen = 1;
  275.     }
  276.     else
  277.       WrError(ErrNum_InvAddrMode);
  278.   }
  279. }
  280.  
  281. static void DecodeInt(Word Index)
  282. {
  283.   if (ChkArgCnt(1, 1))
  284.   {
  285.     if (as_strcasecmp(ArgStr[1].str.p_str, "INTERRUPT")) WrError(ErrNum_InvAddrMode);
  286.     else
  287.     {
  288.       DAsmCode[0] = 0x3c000 | Index;
  289.       CodeLen = 1;
  290.     }
  291.   }
  292. }
  293.  
  294. static void DecodeMem(Word Index)
  295. {
  296.   LongWord Reg, Addr;
  297.  
  298.   if (ChkArgCnt(2, 2)
  299.    && IsWReg(&ArgStr[1], &Reg, True))
  300.   {
  301.     DAsmCode[0] = (((LongWord)Index) << 13) | (Reg << 8);
  302.     switch (IsIWReg(&ArgStr[2], &Addr))
  303.     {
  304.       case eIsReg:
  305.         DAsmCode[0] |= 0x01000 | (Addr << 4);
  306.         CodeLen = 1;
  307.         break;
  308.       case eIsNoReg:
  309.       {
  310.         tEvalResult EvalResult;
  311.  
  312.         Addr = EvalStrIntExpressionWithResult(&ArgStr[2], UInt6, &EvalResult);
  313.         if (EvalResult.OK)
  314.         {
  315.           ChkSpace(SegData, EvalResult.AddrSpaceMask);
  316.           DAsmCode[0] |= Addr & 0x3f;
  317.           CodeLen = 1;
  318.         }
  319.         break;
  320.       }
  321.       case eRegAbort:
  322.         break;
  323.     }
  324.   }
  325. }
  326.  
  327. static void DecodeIO(Word Index)
  328. {
  329.   LongWord Reg, Addr;
  330.  
  331.   if (ChkArgCnt(2, 2)
  332.    && IsWReg(&ArgStr[1], &Reg, True))
  333.   {
  334.     DAsmCode[0] = (((LongWord)Index) << 13) | (Reg << 8);
  335.     switch (IsIWReg(&ArgStr[2], &Addr))
  336.     {
  337.       case eIsReg:
  338.         DAsmCode[0] |= 0x01000 | (Addr << 4);
  339.         CodeLen = 1;
  340.         break;
  341.       case eIsNoReg:
  342.       {
  343.         tEvalResult EvalResult;
  344.  
  345.         Addr = EvalStrIntExpressionWithResult(&ArgStr[2], UInt8, &EvalResult);
  346.         if (EvalResult.OK)
  347.         {
  348.           ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  349.           DAsmCode[0] |= Addr & 0xff;
  350.           CodeLen = 1;
  351.         }
  352.         break;
  353.       }
  354.       case eRegAbort:
  355.         break;
  356.     }
  357.   }
  358. }
  359.  
  360. static void DecodeNop(Word Index)
  361. {
  362.   UNUSED (Index);
  363.  
  364.   if (ChkArgCnt(0, 0))
  365.   {
  366.     DAsmCode[0] = NOPCode;
  367.     CodeLen = 1;
  368.   }
  369. }
  370.  
  371. /*--------------------------------------------------------------------------
  372.  * Instruction Table Handling
  373.  *--------------------------------------------------------------------------*/
  374.  
  375. static void AddReg(const char *NName, LongWord NCode)
  376. {
  377.   order_array_rsv_end(RegOrders, FixedOrder);
  378.   RegOrders[InstrZ].Code = NCode;
  379.   AddInstTable(InstTable, NName, InstrZ++, DecodeOneReg);
  380. }
  381.  
  382. static void AddALU(const char *NName, LongWord NCode)
  383. {
  384.   order_array_rsv_end(ALUOrders, FixedOrder);
  385.   ALUOrders[InstrZ].Code = NCode;
  386.   AddInstTable(InstTable, NName, InstrZ++, DecodeALU);
  387. }
  388.  
  389. static void InitFields(void)
  390. {
  391.   InstTable = CreateInstTable(97);
  392.  
  393.   InstrZ = 0;
  394.   AddReg("RL" , 0x20002);
  395.   AddReg("RR" , 0x2000c);
  396.   AddReg("SL0", 0x20006);
  397.   AddReg("SL1", 0x20007);
  398.   AddReg("SLA", 0x20000);
  399.   AddReg("SLX", 0x20004);
  400.   AddReg("SR0", 0x2000e);
  401.   AddReg("SR1", 0x2000f);
  402.   AddReg("SRA", 0x20008);
  403.   AddReg("SRX", 0x2000a);
  404.  
  405.   InstrZ = 0;
  406.   AddALU("ADD"    , 0x18000);
  407.   AddALU("ADDCY"  , 0x1a000);
  408.   AddALU("AND"    , 0x0a000);
  409.   AddALU("COMPARE", 0x14000);
  410.   AddALU("LOAD"   , 0x00000);
  411.   AddALU("OR"     , 0x0c000);
  412.   AddALU("SUB"    , 0x1c000);
  413.   AddALU("SUBCY"  , 0x1e000);
  414.   AddALU("TEST"   , 0x12000);
  415.   AddALU("XOR"    , 0x0e000);
  416.  
  417.   AddInstTable(InstTable, "CALL", 0x0000, DecodeJmp);
  418.   AddInstTable(InstTable, "JUMP", 0x4000, DecodeJmp);
  419.   AddInstTable(InstTable, "RETURN", 0, DecodeRet);
  420.   AddInstTable(InstTable, "RETURNI", 0, DecodeReti);
  421.   AddInstTable(InstTable, "ENABLE", 1, DecodeInt);
  422.   AddInstTable(InstTable, "DISABLE", 0, DecodeInt);
  423.   AddInstTable(InstTable, "FETCH", 0x03, DecodeMem);
  424.   AddInstTable(InstTable, "STORE", 0x17, DecodeMem);
  425.   AddInstTable(InstTable, "INPUT", 0x02, DecodeIO);
  426.   AddInstTable(InstTable, "OUTPUT", 0x16, DecodeIO);
  427.  
  428.   AddInstTable(InstTable, "PORT", 0, DecodePort);
  429.   AddInstTable(InstTable, "REG", 0, CodeREG);
  430.   AddInstTable(InstTable, "NAMEREG", 0, CodeNAMEREG);
  431.   AddInstTable(InstTable, "CONSTANT", 0, DecodeConstant);
  432.  
  433.   AddInstTable(InstTable, "NOP", 0, DecodeNop);
  434. }
  435.  
  436. static void DeinitFields(void)
  437. {
  438.   DestroyInstTable(InstTable);
  439.   order_array_free(RegOrders);
  440.   order_array_free(ALUOrders);
  441. }
  442.  
  443. /*--------------------------------------------------------------------------
  444.  * Semipublic Functions
  445.  *--------------------------------------------------------------------------*/
  446.  
  447. /*!------------------------------------------------------------------------
  448.  * \fn     InternSymbol_KCPSM3(char *pArg, TempResult *pResult)
  449.  * \brief  handle built-in (register) symbols for KCPSM3
  450.  * \param  pArg source argument
  451.  * \param  pResult result buffer
  452.  * ------------------------------------------------------------------------ */
  453.  
  454. static void InternSymbol_KCPSM3(char *pArg, TempResult *pResult)
  455. {
  456.   LongWord RegNum;
  457.  
  458.   if (IsWRegCore(pArg, &RegNum))
  459.   {
  460.     pResult->Typ = TempReg;
  461.     pResult->DataSize = eSymbolSize8Bit;
  462.     pResult->Contents.RegDescr.Reg = RegNum;
  463.     pResult->Contents.RegDescr.Dissect = DissectReg_KCPSM3;
  464.     pResult->Contents.RegDescr.compare = NULL;
  465.   }
  466. }
  467.  
  468. static Boolean IsDef_KCPSM3(void)
  469. {
  470.    return (Memo("REG")) || (Memo("PORT"));
  471. }
  472.  
  473. static void SwitchFrom_KCPSM3(void)
  474. {
  475.    DeinitFields();
  476. }
  477.  
  478. static void MakeCode_KCPSM3(void)
  479. {
  480.   CodeLen = 0; DontPrint = False;
  481.  
  482.   /* zu ignorierendes */
  483.  
  484.    if (Memo("")) return;
  485.  
  486.    /* Pseudoanweisungen */
  487.  
  488.    if (DecodeIntelPseudo(True)) return;
  489.  
  490.    if (!LookupInstTable(InstTable, OpPart.str.p_str))
  491.      WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  492. }
  493.  
  494. static void SwitchTo_KCPSM3(void)
  495. {
  496.    const TFamilyDescr *FoundDescr;
  497.  
  498.    FoundDescr = FindFamilyByName("KCPSM3");
  499.  
  500.    TurnWords = True;
  501.    SetIntConstMode(eIntConstModeIntel);
  502.  
  503.    PCSymbol = "$"; HeaderID = FoundDescr->Id;
  504.  
  505.    /* NOP = load s0,s0 */
  506.  
  507.    NOPCode = 0x01000;
  508.    DivideChars = ","; HasAttrs = False;
  509.  
  510.    ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
  511.    Grans[SegCode] = 4; ListGrans[SegCode] = 4; SegInits[SegCode] = 0;
  512.    SegLimits[SegCode] = 0x3ff;
  513.    Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0;
  514.    SegLimits[SegData] = 0x3f;
  515.    Grans[SegIO] = 1; ListGrans[SegIO] = 1; SegInits[SegIO] = 0;
  516.    SegLimits[SegIO] = 0xff;
  517.  
  518.    MakeCode = MakeCode_KCPSM3;
  519.    IsDef = IsDef_KCPSM3;
  520.    InternSymbol = InternSymbol_KCPSM3;
  521.    DissectReg = DissectReg_KCPSM3;
  522.    SwitchFrom = SwitchFrom_KCPSM3; InitFields();
  523. }
  524.  
  525. /*--------------------------------------------------------------------------
  526.  * Initialization
  527.  *--------------------------------------------------------------------------*/
  528.  
  529. void codekcpsm3_init(void)
  530. {
  531.    CPUKCPSM3 = AddCPU("KCPSM3", SwitchTo_KCPSM3);
  532. }
  533.