Subversion Repositories pentevo

Rev

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

  1. /* codekcpsm.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator Xilinx kcpsm                                                */
  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.  
  29. #include "codekcpsm.h"
  30.  
  31. #undef DEBUG_PRINTF
  32.  
  33. typedef struct
  34. {
  35.   const char *Name;
  36.   Word Code;
  37. } Condition;
  38.  
  39.  
  40. #define WorkOfs 0xe0
  41.  
  42. #define COND_CODE_TRUE 0
  43.  
  44. #define IOopCnt 2
  45.  
  46. #define ModNone  (-1)
  47. #define ModWReg   0
  48. #define MModWReg   (1 << ModWReg)
  49. #define ModAbs    1
  50. #define MModAbs    (1 << ModAbs)
  51. #define ModImm    4
  52. #define MModImm    (1 << ModImm)
  53. #define ModIRReg  6
  54. #define MModIRReg  (1 << ModIRReg)
  55. #define ModInd    7
  56. #define MModInd    (1 << ModInd)
  57.  
  58. static ShortInt AdrType;
  59. static Word AdrMode,AdrIndex;
  60.  
  61. static Condition *Conditions;
  62.  
  63. static CPUVar CPUKCPSM;
  64.  
  65. /*--------------------------------------------------------------------------*/
  66. /* Code Helpers */
  67.  
  68. /*!------------------------------------------------------------------------
  69.  * \fn     IsWRegCore(const char *pArg, Word *pResult)
  70.  * \brief  check whether argument is CPU register
  71.  * \param  pArg argument
  72.  * \param  pResult register number if it is
  73.  * \return True if it is
  74.  * ------------------------------------------------------------------------ */
  75.  
  76. static Boolean IsWRegCore(const char *pArg, Word *pResult)
  77. {
  78.   Boolean retValue;
  79.  
  80.   if ((strlen(pArg) < 2) || (as_toupper(*pArg) != 'S'))
  81.     retValue = False;
  82.   else
  83.   {
  84.     Boolean OK;
  85.  
  86.     *pResult = ConstLongInt(pArg + 1, &OK, 10);
  87.     if (!OK)
  88.       retValue = False;
  89.     else
  90.       retValue = (*pResult <= 15);
  91.   }
  92. #ifdef DEBUG_PRINTF
  93.   fprintf( stderr, "IsWRegCore: %s %d\n", Asc, retValue );
  94. #endif
  95.   return retValue;
  96. }
  97.  
  98. /*!------------------------------------------------------------------------
  99.  * \fn     DissectReg_KCPSM(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  100.  * \brief  dissect register symbols - KCPSM3 variant
  101.  * \param  pDest destination buffer
  102.  * \param  DestSize destination buffer size
  103.  * \param  Value numeric register value
  104.  * \param  InpSize register size
  105.  * ------------------------------------------------------------------------ */
  106.  
  107. static void DissectReg_KCPSM(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  108. {
  109.   switch (InpSize)
  110.   {
  111.     case eSymbolSize8Bit:
  112.       as_snprintf(pDest, DestSize, "S%x", (unsigned)Value);
  113.       pDest[1] = as_toupper(pDest[1]);
  114.       break;
  115.     default:
  116.       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
  117.   }
  118. }
  119.  
  120. /*!------------------------------------------------------------------------
  121.  * \fn     IsWReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
  122.  * \brief  check whether argument is CPU register, including register aliases
  123.  * \param  pArg argument
  124.  * \param  pResult register number if it is
  125.  * \param  MustBeReg expecting register as arg?
  126.  * \return reg eval result
  127.  * ------------------------------------------------------------------------ */
  128.  
  129. static tRegEvalResult IsWReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
  130. {
  131.   tRegDescr RegDescr;
  132.   tEvalResult EvalResult;
  133.   tRegEvalResult RegEvalResult;
  134.  
  135.   if (IsWRegCore(pArg->str.p_str, pResult))
  136.     return eIsReg;
  137.  
  138.   RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize8Bit, MustBeReg);
  139.   *pResult = RegDescr.Reg;
  140.   return RegEvalResult;
  141. }
  142.  
  143. static void DecodeAdr(const tStrComp *pArg, Byte Mask, int Segment)
  144. {
  145.   tEvalResult EvalResult;
  146.   char *p;
  147.   int ArgLen;
  148.  
  149.   AdrType = ModNone;
  150.  
  151.   /* immediate ? */
  152.  
  153.   if (*pArg->str.p_str == '#')
  154.   {
  155.     AdrMode = EvalStrIntExpressionOffsWithResult(pArg, 1, UInt8, &EvalResult);
  156.     if (EvalResult.OK)
  157.       AdrType = ModImm;
  158.     goto chk;
  159.   }
  160.  
  161.   /* Register ? */
  162.  
  163.   switch (IsWReg(pArg, &AdrMode, False))
  164.   {
  165.     case eIsReg:
  166.       AdrType = ModWReg;
  167.       goto chk;
  168.     case eIsNoReg:
  169.       break;
  170.     case eRegAbort:
  171.       return;
  172.   }
  173.  
  174.   /* indiziert ? */
  175.  
  176.   ArgLen = strlen(pArg->str.p_str);
  177.   if ((ArgLen >= 4) && (pArg->str.p_str[ArgLen - 1] == ')'))
  178.   {
  179.     p = pArg->str.p_str + ArgLen - 1;
  180.     while ((p >= pArg->str.p_str) && (*p != '('))
  181.       p--;
  182.     if (*p != '(') WrError(ErrNum_BrackErr);
  183.     else
  184.     {
  185.       tStrComp RegComp, DispComp;
  186.  
  187.       StrCompSplitRef(&DispComp, &RegComp, pArg, p);
  188.       StrCompShorten(&RegComp, 1);
  189.       if (IsWReg(&RegComp, &AdrMode, True) == eIsReg)
  190.       {
  191.         AdrIndex = EvalStrIntExpressionWithResult(&DispComp, UInt8, &EvalResult);
  192.         if (EvalResult.OK)
  193.         {
  194.           AdrType = ModInd;
  195.           ChkSpace(SegData, EvalResult.AddrSpaceMask);
  196.         }
  197.         goto chk;
  198.       }
  199.     }
  200.   }
  201.  
  202.   /* einfache direkte Adresse ? */
  203.  
  204.   AdrMode = EvalStrIntExpressionWithResult(pArg, UInt8, &EvalResult);
  205.   if (EvalResult.OK)
  206.   {
  207.     AdrType = ModAbs;
  208.     if (Segment != SegNone)
  209.       ChkSpace(Segment, EvalResult.AddrSpaceMask);
  210.     goto chk;
  211.   }
  212.  
  213. chk:
  214.   if ((AdrType != ModNone) && ((Mask & (1 << AdrType)) == 0))
  215.   {
  216.     WrError(ErrNum_InvAddrMode);
  217.     AdrType = ModNone;
  218.   }
  219. }
  220.  
  221. static Boolean DecodeCond(char *Asc, Word *p_code)
  222. {
  223.   int Cond;
  224.  
  225.    for (Cond = 0; Conditions[Cond].Name; Cond++)
  226.      if (!strcmp(Conditions[Cond].Name, Asc))
  227.      {
  228.        *p_code = Conditions[Cond].Code;
  229.        return True;
  230.      }
  231.   return False;
  232. }
  233.  
  234. /*--------------------------------------------------------------------------*/
  235. /* Instruction Decoders */
  236.  
  237. static void DecodeFixed(Word Code)
  238. {
  239.   if (ChkArgCnt(0, 0))
  240.   {
  241.     CodeLen = 1;
  242.     WAsmCode[0] = Code;
  243.   }
  244. }
  245.  
  246. static void DecodeLOAD(Word Code)
  247. {
  248.   UNUSED(Code);
  249.  
  250.   if (ChkArgCnt(2, 2))
  251.   {
  252.     DecodeAdr(&ArgStr[1], MModWReg, SegNone);
  253.     switch (AdrType)
  254.     {
  255.       case ModWReg:
  256.       {
  257.         Word Save = AdrMode;
  258.         DecodeAdr(&ArgStr[2], MModWReg | MModAbs | MModImm, SegNone);
  259.         switch (AdrType)
  260.         {
  261.           case ModWReg:
  262. #ifdef DEBUG_PRINTF
  263.             fprintf( stderr, "LOAD-->ModWReg %d %d\n", AdrMode, Save );
  264. #endif
  265.             WAsmCode[0] = 0xc000 | (Save << 8) | ( AdrMode << 4 );
  266.             CodeLen = 1;
  267.             break;
  268.           case ModAbs:
  269. #ifdef DEBUG_PRINTF
  270.             fprintf( stderr, "LOAD-->ModAbs %d %d\n", AdrMode, Save );
  271. #endif
  272.             WAsmCode[0] = 0xc000 | (Save << 8) | ( AdrMode << 4 );
  273.             CodeLen = 1;
  274.             break;
  275.           case ModImm:
  276. #ifdef DEBUG_PRINTF
  277.             fprintf( stderr, "LOAD-->ModImm %d %d\n", AdrMode, Save );
  278. #endif
  279.             WAsmCode[0] = (Save << 8) | AdrMode;
  280.             CodeLen = 1;
  281.             break;
  282.         }
  283.         break;
  284.       }
  285.     }
  286.   }
  287. }
  288.  
  289. static void DecodeALU2(Word Code)
  290. {
  291.   if (ChkArgCnt(2, 2))
  292.   {
  293.     DecodeAdr(&ArgStr[1], MModWReg, SegNone);
  294.     switch (AdrType)
  295.     {
  296.       case ModWReg:
  297.       {
  298.         Word Save = AdrMode;
  299.         DecodeAdr(&ArgStr[2], MModAbs | MModWReg | MModImm, SegNone);
  300.         switch (AdrType)
  301.         {
  302.           case ModWReg:
  303.             WAsmCode[0] = 0xc000 | (Save << 8) | ( AdrMode << 4 ) | Code;
  304.             CodeLen = 1;
  305.             break;
  306.           case ModImm:
  307.           case ModAbs:
  308.             WAsmCode[0] = (Code << 12 ) | (Save << 8) | AdrMode;
  309.             CodeLen = 1;
  310.             break;
  311.         }
  312.         break;
  313.       }
  314.     }
  315.   }
  316. }
  317.  
  318. static void DecodeALU1(Word Code)
  319. {
  320.   if (ChkArgCnt(1, 1))
  321.   {
  322.     DecodeAdr(&ArgStr[1], MModWReg, SegNone);
  323.     switch (AdrType)
  324.     {
  325.       case ModWReg:
  326.         WAsmCode[0] = 0xd000 | (AdrMode << 8) | Code;
  327.         CodeLen = 1;
  328.         break;
  329.     }
  330.   }
  331. }
  332.  
  333. static void DecodeCALL(Word Code)
  334. {
  335.   UNUSED(Code);
  336.  
  337.   if (ChkArgCnt(1, 2))
  338.   {
  339.     Word cond_code;
  340.  
  341.     if (ArgCnt == 1)
  342.       cond_code = COND_CODE_TRUE;
  343.     else if (!DecodeCond(ArgStr[1].str.p_str, &cond_code))
  344.     {
  345.       WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  346.       return;
  347.     }
  348.  
  349.     DecodeAdr(&ArgStr[ArgCnt], MModAbs | ModImm, SegCode);
  350.     switch (AdrType)
  351.     {
  352.       case ModAbs:
  353.       case ModImm:
  354.         WAsmCode[0] = 0x8300 | (cond_code << 10) | Lo(AdrMode);
  355.         CodeLen = 1;
  356.         break;
  357.     }
  358.   }
  359. }
  360.  
  361. static void DecodeJUMP(Word Code)
  362. {
  363.   UNUSED(Code);
  364.  
  365.   if (ChkArgCnt(1, 2))
  366.   {
  367.     Word cond_code;
  368.  
  369.     if (ArgCnt == 1)
  370.        cond_code= COND_CODE_TRUE;
  371.     else if (!DecodeCond(ArgStr[1].str.p_str, &cond_code))
  372.     {
  373.       WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  374.       return;
  375.     }
  376.  
  377.     DecodeAdr(&ArgStr[ArgCnt], MModAbs | MModImm, SegCode);
  378.     switch (AdrType)
  379.     {
  380.       case ModAbs:
  381.       case ModImm:
  382.         WAsmCode[0] = 0x8100 | (cond_code << 10) | Lo(AdrMode);
  383.         CodeLen = 1;
  384.         break;
  385.     }
  386.   }
  387. }
  388.  
  389. static void DecodeRETURN(Word Code)
  390. {
  391.   UNUSED(Code);
  392.  
  393.   if (ChkArgCnt(0, 1))
  394.   {
  395.     Word cond_code;
  396.  
  397.     if (ArgCnt == 0)
  398.       cond_code = COND_CODE_TRUE;
  399.     else if (!DecodeCond(ArgStr[1].str.p_str, &cond_code))
  400.     {
  401.       WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
  402.       return ;
  403.     }
  404.  
  405.     WAsmCode[0] = 0x8080 | (cond_code << 10);
  406.     CodeLen = 1;
  407.   }
  408. }
  409.  
  410. static void DecodeIOop(Word Code)
  411. {
  412.   if (ChkArgCnt(2, 2))
  413.   {
  414.     DecodeAdr(&ArgStr[1], MModWReg, SegNone);
  415.     switch (AdrType)
  416.     {
  417.       case ModWReg:
  418.       {
  419.         Word Save = AdrMode;
  420.         DecodeAdr(&ArgStr[2], MModInd | MModImm | MModAbs, SegData);
  421.         switch (AdrType)
  422.         {
  423.           case ModInd:
  424.             WAsmCode[0] = 0x1000 | ((Code | Save) << 8) | ( AdrMode << 4);
  425.             CodeLen = 1;
  426.             break;
  427.           case ModImm:
  428.           case ModAbs:
  429.             WAsmCode[0] = ((Code | Save) << 8) | AdrMode;
  430.             CodeLen = 1;
  431.             break;
  432.         }
  433.         break;
  434.       }
  435.     }
  436.   }
  437. }
  438.  
  439. static void DecodeRETURNI(Word Code)
  440. {
  441.   UNUSED(Code);
  442.  
  443.   if (ChkArgCnt(1, 1))
  444.   {
  445.     NLS_UpString(ArgStr[1].str.p_str);
  446.     if (!strcmp(ArgStr[1].str.p_str, "ENABLE"))
  447.     {
  448.       WAsmCode[0] = 0x80f0;
  449.       CodeLen = 1;
  450.     }
  451.     else if (!strcmp(ArgStr[1].str.p_str, "DISABLE"))
  452.     {
  453.       WAsmCode[0] =  0x80d0;
  454.       CodeLen = 1;
  455.     }
  456.   }
  457. }
  458.  
  459. static void DecodeENABLE_DISABLE(Word Code)
  460. {
  461.   UNUSED(Code);
  462.  
  463.   if (ChkArgCnt(1, 1))
  464.   {
  465.     NLS_UpString(ArgStr[1].str.p_str);
  466.     if (!as_strcasecmp(ArgStr[1].str.p_str, "INTERRUPT"))
  467.     {
  468.       WAsmCode[0] = Code;
  469.       CodeLen = 1;
  470.     }
  471.   }
  472. }
  473.  
  474. static void DecodeCONSTANT(Word Code)
  475. {
  476.   UNUSED(Code);
  477.  
  478.   if (ChkArgCnt(2, 2))
  479.   {
  480.     TempResult t;
  481.     Boolean OK;
  482.  
  483.     as_tempres_ini(&t);
  484.     as_tempres_set_int(&t, EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &OK, &t.Flags));
  485.     if (OK && !mFirstPassUnknown(t.Flags))
  486.     {
  487.       SetListLineVal(&t);
  488.       PushLocHandle(-1);
  489.       EnterIntSymbol(&ArgStr[1], t.Contents.Int, SegNone, False);
  490.       PopLocHandle();
  491.     }
  492.     as_tempres_free(&t);
  493.   }
  494. }
  495.  
  496. /*--------------------------------------------------------------------------*/
  497. /* code table handling */
  498.  
  499. static void AddFixed(const char *NName, Word NCode)
  500. {
  501.   AddInstTable(InstTable, NName, NCode, DecodeFixed);
  502. }
  503.  
  504. static void AddALU2(const char *NName, Word NCode)
  505. {
  506.   AddInstTable(InstTable, NName, NCode, DecodeALU2);
  507. }
  508.  
  509. static void AddALU1(const char *NName, Word NCode)
  510. {
  511.   AddInstTable(InstTable, NName, NCode, DecodeALU1);
  512. }
  513.  
  514. static void AddIOop(const Char *NName, Word NCode)
  515. {
  516.   AddInstTable(InstTable, NName, NCode, DecodeIOop);
  517. }
  518.  
  519. static void AddCondition(const char *NName, Word NCode)
  520. {
  521.   order_array_rsv_end(Conditions, Condition);
  522.   Conditions[InstrZ].Name = NName;
  523.   Conditions[InstrZ++].Code = NCode;
  524. }
  525.  
  526. static void InitFields(void)
  527. {
  528.   InstTable = CreateInstTable(201);
  529.   AddInstTable(InstTable, "LOAD", 0, DecodeLOAD);
  530.   AddInstTable(InstTable, "CALL", 0, DecodeCALL);
  531.   AddInstTable(InstTable, "JUMP", 0, DecodeJUMP);
  532.   AddInstTable(InstTable, "RETURN", 0, DecodeRETURN);
  533.   AddInstTable(InstTable, "RETURNI", 0, DecodeRETURNI);
  534.   AddInstTable(InstTable, "ENABLE", 0x8030, DecodeENABLE_DISABLE);
  535.   AddInstTable(InstTable, "DISABLE", 0x8010, DecodeENABLE_DISABLE);
  536.   AddInstTable(InstTable, "REG", 0, CodeREG);
  537.   AddInstTable(InstTable, "NAMEREG", 0, CodeNAMEREG);
  538.   AddInstTable(InstTable, "CONSTANT", 0, DecodeCONSTANT);
  539.  
  540.   AddFixed("EI"     , 0x8030);  AddFixed("DI"     , 0x8010);
  541.   AddFixed("RETIE"  , 0x80f0);  AddFixed("RETID"  , 0x80d0);
  542.   AddFixed("NOP"    , 0xc000); /* fake */
  543.  
  544.   AddALU2("ADD"   , 0x04);
  545.   AddALU2("ADDCY" , 0x05);
  546.   AddALU2("SUB"   , 0x06);
  547.   AddALU2("SUBCY" , 0x07);
  548.   AddALU2("OR"    , 0x02);
  549.   AddALU2("AND"   , 0x01);
  550.   AddALU2("XOR"   , 0x03);
  551.  
  552.   AddALU1("SR0" , 0x0e);
  553.   AddALU1("SR1" , 0x0f);
  554.   AddALU1("SRX" , 0x0a);
  555.   AddALU1("SRA" , 0x08);
  556.   AddALU1("RR"  , 0x0c);
  557.   AddALU1("SL0" , 0x06);
  558.   AddALU1("SL1" , 0x07);
  559.   AddALU1("SLX" , 0x04);
  560.   AddALU1("SLA" , 0x00);
  561.   AddALU1("RL"  , 0x02);
  562.  
  563.   AddIOop("INPUT"  , 0xa0);
  564.   AddIOop("OUTPUT" , 0xe0);
  565.  
  566.   InstrZ = 0;
  567.   AddCondition("T"  , COND_CODE_TRUE);
  568.   AddCondition("C"  , 6); AddCondition("NC" , 7);
  569.   AddCondition("Z"  , 4); AddCondition("NZ" , 5);
  570.   AddCondition(NULL , 0);
  571. }
  572.  
  573. static void DeinitFields(void)
  574. {
  575.   DestroyInstTable(InstTable);
  576.   order_array_free(Conditions);
  577. }
  578.  
  579. /*---------------------------------------------------------------------*/
  580.  
  581. /*!------------------------------------------------------------------------
  582.  * \fn     InternSymbol_KCPSM(char *pArg, TempResult *pResult)
  583.  * \brief  handle built-in (register) symbols for KCPSM
  584.  * \param  pArg source argument
  585.  * \param  pResult result buffer
  586.  * ------------------------------------------------------------------------ */
  587.  
  588. static void InternSymbol_KCPSM(char *pArg, TempResult *pResult)
  589. {
  590.   Word RegNum;
  591.  
  592.   if (IsWRegCore(pArg, &RegNum))
  593.   {
  594.     pResult->Typ = TempReg;
  595.     pResult->DataSize = eSymbolSize8Bit;
  596.     pResult->Contents.RegDescr.Reg = RegNum;
  597.     pResult->Contents.RegDescr.Dissect = DissectReg_KCPSM;
  598.     pResult->Contents.RegDescr.compare = NULL;
  599.   }
  600. }
  601.  
  602. static void MakeCode_KCPSM(void)
  603. {
  604.   CodeLen = 0; DontPrint = False;
  605.  
  606.   /* zu ignorierendes */
  607.  
  608.   if (Memo("")) return;
  609.  
  610.   /* Pseudoanweisungen */
  611.  
  612.   if (DecodeIntelPseudo(True)) return;
  613.  
  614.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  615.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  616. }
  617.  
  618. static Boolean IsDef_KCPSM(void)
  619. {
  620.   return (Memo("REG"));
  621. }
  622.  
  623. static void SwitchFrom_KCPSM(void)
  624. {
  625.   DeinitFields();
  626. }
  627.  
  628. static void SwitchTo_KCPSM(void)
  629. {
  630.   const TFamilyDescr *FoundDescr;
  631.  
  632.   FoundDescr = FindFamilyByName("KCPSM");
  633.  
  634.   TurnWords = True;
  635.   SetIntConstMode(eIntConstModeIntel);
  636.  
  637.   PCSymbol = "$";
  638.   HeaderID = FoundDescr->Id;
  639.   NOPCode = 0xc0; /* nop = load s0,s0 */
  640.   DivideChars = ",";
  641.   HasAttrs = False;
  642.  
  643.   ValidSegs = (1 << SegCode) | (1 << SegData);
  644.   Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0; SegLimits[SegCode] = 0xff;
  645.   Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0; SegLimits[SegData] = 0xff;
  646.  
  647.   MakeCode = MakeCode_KCPSM;
  648.   IsDef = IsDef_KCPSM;
  649.   InternSymbol = InternSymbol_KCPSM;
  650.   DissectReg = DissectReg_KCPSM;
  651.   SwitchFrom = SwitchFrom_KCPSM;
  652.   InitFields();
  653. }
  654.  
  655. void codekcpsm_init(void)
  656. {
  657.   CPUKCPSM = AddCPU("KCPSM", SwitchTo_KCPSM);
  658.  
  659.   AddCopyright("XILINX KCPSM(Picoblaze)-Generator (C) 2003 Andreas Wassatsch");
  660. }
  661.