Subversion Repositories pentevo

Rev

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

  1. /* code3201x.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator TMS3201x-Familie                                            */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "bpemu.h"
  16. #include "strutil.h"
  17. #include "chunks.h"
  18. #include "asmdef.h"
  19. #include "asmsub.h"
  20. #include "asmpars.h"
  21. #include "asmitree.h"
  22. #include "codepseudo.h"
  23. #include "fourpseudo.h"
  24. #include "codevars.h"
  25. #include "errmsg.h"
  26.  
  27. #include "code3201x.h"
  28.  
  29. typedef struct
  30. {
  31.   Word Code;
  32.   Word AllowShifts;
  33. } AdrShiftOrder;
  34.  
  35. typedef struct
  36. {
  37.   Word Code;
  38.   Integer Min, Max;
  39.   Word Mask;
  40. } ImmOrder;
  41.  
  42.  
  43. static Word AdrMode;
  44. static Boolean AdrOK;
  45.  
  46. static CPUVar CPU32010, CPU32015;
  47.  
  48. static AdrShiftOrder *AdrShiftOrders;
  49. static ImmOrder *ImmOrders;
  50.  
  51. /*----------------------------------------------------------------------------*/
  52.  
  53. static Word EvalARExpression(const tStrComp *pArg, Boolean *OK)
  54. {
  55.   *OK = True;
  56.   if (!as_strcasecmp(pArg->str.p_str, "AR0"))
  57.     return 0;
  58.   if (!as_strcasecmp(pArg->str.p_str, "AR1"))
  59.     return 1;
  60.   return EvalStrIntExpression(pArg, UInt1, OK);
  61. }
  62.  
  63. static void DecodeAdr(const tStrComp *pArg, int Aux, Boolean Must1)
  64. {
  65.   Byte h;
  66.   char *p;
  67.   char *Arg = pArg->str.p_str;
  68.  
  69.   AdrOK = False;
  70.  
  71.   if ((!strcmp(pArg->str.p_str, "*")) || (!strcmp(pArg->str.p_str, "*-")) || (!strcmp(pArg->str.p_str, "*+")))
  72.   {
  73.     AdrMode = 0x88;
  74.     if (strlen(Arg) == 2)
  75.       AdrMode += (pArg->str.p_str[1] == '+') ? 0x20 : 0x10;
  76.     if (Aux <= ArgCnt)
  77.     {
  78.       h = EvalARExpression(&ArgStr[Aux], &AdrOK);
  79.       if (AdrOK)
  80.       {
  81.         AdrMode &= 0xf7;
  82.         AdrMode += h;
  83.       }
  84.     }
  85.     else
  86.       AdrOK = True;
  87.   }
  88.   else if (ChkArgCnt(1, Aux - 1))
  89.   {
  90.     tEvalResult EvalResult;
  91.  
  92.     h = 0;
  93.     if ((strlen(pArg->str.p_str) > 3) && (!as_strncasecmp(pArg->str.p_str, "DAT", 3)))
  94.     {
  95.       AdrOK = True;
  96.       for (p = pArg->str.p_str + 3; *p != '\0'; p++)
  97.         if ((*p > '9') || (*p < '0'))
  98.           AdrOK = False;
  99.       if (AdrOK)
  100.       {
  101.         h = EvalStrIntExpressionOffsWithResult(pArg, 3, UInt8, &EvalResult);
  102.         AdrOK = EvalResult.OK;
  103.       }
  104.     }
  105.     if (!AdrOK)
  106.     {
  107.       h = EvalStrIntExpressionWithResult(pArg, Int8, &EvalResult);
  108.       AdrOK = EvalResult.OK;
  109.     }
  110.     if (AdrOK)
  111.     {
  112.       if (Must1 && (h < 0x80) && !mFirstPassUnknown(EvalResult.Flags))
  113.       {
  114.         WrError(ErrNum_UnderRange);
  115.         AdrOK = False;
  116.       }
  117.       else
  118.       {
  119.         AdrMode = h & 0x7f;
  120.         ChkSpace(SegData, EvalResult.AddrSpaceMask);
  121.       }
  122.     }
  123.   }
  124. }
  125.  
  126. /*----------------------------------------------------------------------------*/
  127.  
  128. /* kein Argument */
  129.  
  130. static void DecodeFixed(Word Code)
  131. {
  132.   if (ChkArgCnt(0, 0))
  133.   {
  134.     CodeLen = 1;
  135.     WAsmCode[0] = Code;
  136.   }
  137. }
  138.  
  139. /* Spruenge */
  140.  
  141. static void DecodeJmp(Word Code)
  142. {
  143.   if (ChkArgCnt(1, 1))
  144.   {
  145.     Boolean OK;
  146.  
  147.     WAsmCode[1] = EvalStrIntExpression(&ArgStr[1], UInt12, &OK);
  148.     if (OK)
  149.     {
  150.       CodeLen = 2;
  151.       WAsmCode[0] = Code;
  152.     }
  153.   }
  154. }
  155.  
  156. /* nur Adresse */
  157.  
  158. static void DecodeAdrInst(Word Code)
  159. {
  160.   if (ChkArgCnt(1, 2))
  161.   {
  162.     DecodeAdr(&ArgStr[1], 2, Code & 1);
  163.     if (AdrOK)
  164.     {
  165.       CodeLen = 1;
  166.       WAsmCode[0] = (Code & 0xfffe) + AdrMode;
  167.     }
  168.   }
  169. }
  170.  
  171. /* Adresse & schieben */
  172.  
  173. static void DecodeAdrShift(Word Index)
  174. {
  175.   Boolean HasSh;
  176.   int AuxArgIndex;
  177.   const AdrShiftOrder *pOrder = AdrShiftOrders + Index;
  178.  
  179.   if (ChkArgCnt(1, 3))
  180.   {
  181.     if (*ArgStr[1].str.p_str == '*')
  182.     {
  183.       switch (ArgCnt)
  184.       {
  185.         case 1:
  186.           HasSh = False;
  187.           AuxArgIndex = 3;
  188.           break;
  189.         case 2:
  190.           if (!as_strncasecmp(ArgStr[2].str.p_str, "AR", 2))
  191.           {
  192.             HasSh = False;
  193.             AuxArgIndex = 2;
  194.           }
  195.           else
  196.           {
  197.             HasSh = True;
  198.             AuxArgIndex = 3;
  199.           }
  200.           break;
  201.         default: /* 3 */
  202.           HasSh = True;
  203.           AuxArgIndex = 3;
  204.       }
  205.     }
  206.     else
  207.     {
  208.       AuxArgIndex = 3;
  209.       HasSh = (ArgCnt == 2);
  210.     }
  211.     DecodeAdr(&ArgStr[1], AuxArgIndex, False);
  212.     if (AdrOK)
  213.     {
  214.       Boolean OK;
  215.       Word AdrWord;
  216.  
  217.       if (!HasSh)
  218.       {
  219.         OK = True;
  220.         AdrWord = 0;
  221.       }
  222.       else
  223.       {
  224.         tSymbolFlags Flags;
  225.  
  226.         AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], Int4, &OK, &Flags);
  227.         if (OK && mFirstPassUnknown(Flags))
  228.           AdrWord = 0;
  229.       }
  230.       if (OK)
  231.       {
  232.         if ((pOrder->AllowShifts & (1 << AdrWord)) == 0) WrError(ErrNum_InvShiftArg);
  233.         else
  234.         {
  235.           CodeLen = 1;
  236.           WAsmCode[0] = pOrder->Code + AdrMode + (AdrWord << 8);
  237.         }
  238.       }
  239.     }
  240.   }
  241. }
  242.  
  243. /* Ein/Ausgabe */
  244.  
  245. static void DecodeIN_OUT(Word Code)
  246. {
  247.   if (ChkArgCnt(2, 3))
  248.   {
  249.     DecodeAdr(&ArgStr[1], 3, False);
  250.     if (AdrOK)
  251.     {
  252.       tEvalResult EvalResult;
  253.       Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[2], UInt3, &EvalResult);
  254.       if (EvalResult.OK)
  255.       {
  256.         ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  257.         CodeLen = 1;
  258.         WAsmCode[0] = Code + AdrMode + (AdrWord << 8);
  259.       }
  260.     }
  261.   }
  262. }
  263.  
  264. /* konstantes Argument */
  265.  
  266. static void DecodeImm(Word Index)
  267. {
  268.   const ImmOrder *pOrder = ImmOrders + Index;
  269.  
  270.   if (ChkArgCnt(1, 1))
  271.   {
  272.     Boolean OK;
  273.     tSymbolFlags Flags;
  274.     LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
  275.  
  276.     if (OK)
  277.     {
  278.       if (mFirstPassUnknown(Flags))
  279.         AdrLong &= pOrder->Mask;
  280.       if (AdrLong < pOrder->Min) WrError(ErrNum_UnderRange);
  281.       else if (AdrLong > pOrder->Max) WrError(ErrNum_OverRange);
  282.       else
  283.       {
  284.         CodeLen = 1;
  285.         WAsmCode[0] = pOrder->Code + (AdrLong & pOrder->Mask);
  286.       }
  287.     }
  288.   }
  289. }
  290.  
  291. /* mit Hilfsregistern */
  292.  
  293. static void DecodeLARP(Word Code)
  294. {
  295.   UNUSED(Code);
  296.  
  297.   if (ChkArgCnt(1, 1))
  298.   {
  299.     Boolean OK;
  300.     Word AdrWord = EvalARExpression(&ArgStr[1], &OK);
  301.     if (OK)
  302.     {
  303.       CodeLen = 1;
  304.       WAsmCode[0] = 0x6880 + AdrWord;
  305.     }
  306.   }
  307. }
  308.  
  309. static void DecodeLAR_SAR(Word Code)
  310. {
  311.   if (ChkArgCnt(2, 3))
  312.   {
  313.     Boolean OK;
  314.     Word AdrWord = EvalARExpression(&ArgStr[1], &OK);
  315.     if (OK)
  316.     {
  317.       DecodeAdr(&ArgStr[2], 3, False);
  318.       if (AdrOK)
  319.       {
  320.         CodeLen = 1;
  321.         WAsmCode[0] = Code + AdrMode + (AdrWord << 8);
  322.       }
  323.     }
  324.   }
  325. }
  326.  
  327. static void DecodeLARK(Word Code)
  328. {
  329.   UNUSED(Code);
  330.  
  331.   if (ChkArgCnt(2, 2))
  332.   {
  333.     Boolean OK;
  334.     Word AdrWord = EvalARExpression(&ArgStr[1], &OK);
  335.     if (OK)
  336.     {
  337.       WAsmCode[0] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  338.       if (OK)
  339.       {
  340.         CodeLen = 1;
  341.         WAsmCode[0] = Lo(WAsmCode[0]) + 0x7000 + (AdrWord << 8);
  342.       }
  343.     }
  344.   }
  345. }
  346.  
  347. static void DecodePORT(Word Code)
  348. {
  349.   UNUSED(Code);
  350.  
  351.   CodeEquate(SegIO, 0, 7);
  352. }
  353.  
  354. static void DecodeDATA_3201x(Word Code)
  355. {
  356.   UNUSED(Code);
  357.  
  358.   DecodeDATA(Int16, Int16);
  359. }
  360.  
  361. /*----------------------------------------------------------------------------*/
  362.  
  363. static void AddFixed(const char *NName, Word NCode)
  364. {
  365.   AddInstTable(InstTable, NName, NCode, DecodeFixed);
  366. }
  367.  
  368. static void AddJmp(const char *NName, Word NCode)
  369. {
  370.   AddInstTable(InstTable, NName, NCode, DecodeJmp);
  371. }
  372.  
  373. static void AddAdr(const char *NName, Word NCode, Word NMust1)
  374. {
  375.   AddInstTable(InstTable, NName, NCode | NMust1, DecodeAdrInst);
  376. }
  377.  
  378. static void AddAdrShift(const char *NName, Word NCode, Word NAllow)
  379. {
  380.   order_array_rsv_end(AdrShiftOrders, AdrShiftOrder);
  381.   AdrShiftOrders[InstrZ].Code = NCode;
  382.   AdrShiftOrders[InstrZ].AllowShifts = NAllow;
  383.   AddInstTable(InstTable, NName, InstrZ++, DecodeAdrShift);
  384. }
  385.  
  386. static void AddImm(const char *NName, Word NCode, Integer NMin, Integer NMax, Word NMask)
  387. {
  388.   order_array_rsv_end(ImmOrders, ImmOrder);
  389.   ImmOrders[InstrZ].Code = NCode;
  390.   ImmOrders[InstrZ].Min = NMin;
  391.   ImmOrders[InstrZ].Max = NMax;
  392.   ImmOrders[InstrZ].Mask = NMask;
  393.   AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
  394. }
  395.  
  396. static void InitFields(void)
  397. {
  398.   InstTable = CreateInstTable(203);
  399.   AddInstTable(InstTable, "IN", 0x4000, DecodeIN_OUT);
  400.   AddInstTable(InstTable, "OUT", 0x4800, DecodeIN_OUT);
  401.   AddInstTable(InstTable, "LARP", 0, DecodeLARP);
  402.   AddInstTable(InstTable, "LAR", 0x3800, DecodeLAR_SAR);
  403.   AddInstTable(InstTable, "SAR", 0x3000, DecodeLAR_SAR);
  404.   AddInstTable(InstTable, "LARK", 0, DecodeLARK);
  405.   AddInstTable(InstTable, "PORT", 0, DecodePORT);
  406.   AddInstTable(InstTable, "RES", 0, DecodeRES);
  407.   AddInstTable(InstTable, "DATA", 0, DecodeDATA_3201x);
  408.  
  409.   AddFixed("ABS"   , 0x7f88);  AddFixed("APAC"  , 0x7f8f);
  410.   AddFixed("CALA"  , 0x7f8c);  AddFixed("DINT"  , 0x7f81);
  411.   AddFixed("EINT"  , 0x7f82);  AddFixed("NOP"   , 0x7f80);
  412.   AddFixed("PAC"   , 0x7f8e);  AddFixed("POP"   , 0x7f9d);
  413.   AddFixed("PUSH"  , 0x7f9c);  AddFixed("RET"   , 0x7f8d);
  414.   AddFixed("ROVM"  , 0x7f8a);  AddFixed("SOVM"  , 0x7f8b);
  415.   AddFixed("SPAC"  , 0x7f90);  AddFixed("ZAC"   , 0x7f89);
  416.  
  417.   AddJmp("B"     , 0xf900);  AddJmp("BANZ"  , 0xf400);
  418.   AddJmp("BGEZ"  , 0xfd00);  AddJmp("BGZ"   , 0xfc00);
  419.   AddJmp("BIOZ"  , 0xf600);  AddJmp("BLEZ"  , 0xfb00);
  420.   AddJmp("BLZ"   , 0xfa00);  AddJmp("BNZ"   , 0xfe00);
  421.   AddJmp("BV"    , 0xf500);  AddJmp("BZ"    , 0xff00);
  422.   AddJmp("CALL"  , 0xf800);
  423.  
  424.   AddAdr("ADDH"  , 0x6000, False);  AddAdr("ADDS"  , 0x6100, False);
  425.   AddAdr("AND"   , 0x7900, False);  AddAdr("DMOV"  , 0x6900, False);
  426.   AddAdr("LDP"   , 0x6f00, False);  AddAdr("LST"   , 0x7b00, False);
  427.   AddAdr("LT"    , 0x6a00, False);  AddAdr("LTA"   , 0x6c00, False);
  428.   AddAdr("LTD"   , 0x6b00, False);  AddAdr("MAR"   , 0x6800, False);
  429.   AddAdr("MPY"   , 0x6d00, False);  AddAdr("OR"    , 0x7a00, False);
  430.   AddAdr("SST"   , 0x7c00, True );  AddAdr("SUBC"  , 0x6400, False);
  431.   AddAdr("SUBH"  , 0x6200, False);  AddAdr("SUBS"  , 0x6300, False);
  432.   AddAdr("TBLR"  , 0x6700, False);  AddAdr("TBLW"  , 0x7d00, False);
  433.   AddAdr("XOR"   , 0x7800, False);  AddAdr("ZALH"  , 0x6500, False);
  434.   AddAdr("ZALS"  , 0x6600, False);
  435.  
  436.   InstrZ = 0;
  437.   AddAdrShift("ADD"   , 0x0000, 0xffff);
  438.   AddAdrShift("LAC"   , 0x2000, 0xffff);
  439.   AddAdrShift("SACH"  , 0x5800, 0x0013);
  440.   AddAdrShift("SACL"  , 0x5000, 0x0001);
  441.   AddAdrShift("SUB"   , 0x1000, 0xffff);
  442.  
  443.   InstrZ = 0;
  444.   AddImm("LACK", 0x7e00,     0,  255,   0xff);
  445.   AddImm("LDPK", 0x6e00,     0,    1,    0x1);
  446.   AddImm("MPYK", 0x8000, -4096, 4095, 0x1fff);
  447. }
  448.  
  449. static void DeinitFields(void)
  450. {
  451.   DestroyInstTable(InstTable);
  452.  
  453.   order_array_free(AdrShiftOrders);
  454.   order_array_free(ImmOrders);
  455. }
  456.  
  457. /*----------------------------------------------------------------------------*/
  458.  
  459. /*!------------------------------------------------------------------------
  460.  * \fn     InternSymbol_3201X(char *pArg, TempResult *pResult)
  461.  * \brief  parse for built-in symbols
  462.  * \param  pArg source argument
  463.  * \param  pResult possible result
  464.  * ------------------------------------------------------------------------ */
  465.  
  466. static void InternSymbol_3201X(char *pArg, TempResult *pResult)
  467. {
  468.   if ((strlen(pArg) == 3)
  469.    && (as_toupper(pArg[0]) == 'P')
  470.    && (as_toupper(pArg[1]) == 'A')
  471.    && ((pArg[2] >= '0') && (pArg[2] <= '7')))
  472.   {
  473.     as_tempres_set_int(pResult, pArg[2] - '0');
  474.     pResult->AddrSpaceMask |= 1 << SegIO;
  475.   }
  476. }
  477.  
  478. static void MakeCode_3201X(void)
  479. {
  480.   CodeLen = 0;
  481.   DontPrint = False;
  482.  
  483.   /* zu ignorierendes */
  484.  
  485.   if (Memo(""))
  486.     return;
  487.  
  488.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  489.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  490. }
  491.  
  492. static Boolean IsDef_3201X(void)
  493. {
  494.   return (Memo("PORT"));
  495. }
  496.  
  497. static void SwitchFrom_3201X(void)
  498. {
  499.   DeinitFields();
  500. }
  501.  
  502. static void SwitchTo_3201X(void)
  503. {
  504.   TurnWords = False;
  505.   SetIntConstMode(eIntConstModeIntel);
  506.  
  507.   PCSymbol = "$";
  508.   HeaderID = 0x74;
  509.   NOPCode = 0x7f80;
  510.   DivideChars = ",";
  511.   HasAttrs = False;
  512.  
  513.   ValidSegs = (1 << SegCode)|(1 << SegData)|(1 << SegIO);
  514.   Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
  515.   SegLimits[SegCode] = 0xfff;
  516.   Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0;
  517.   SegLimits[SegData] = (MomCPU == CPU32010) ? 0x8f : 0xff;
  518.   Grans[SegIO  ] = 2; ListGrans[SegIO  ] = 2; SegInits[SegIO  ] = 0;
  519.   SegLimits[SegIO  ] = 7;
  520.  
  521.   MakeCode = MakeCode_3201X;
  522.   IsDef = IsDef_3201X;
  523.   InternSymbol = InternSymbol_3201X;
  524.   SwitchFrom = SwitchFrom_3201X;
  525.   InitFields();
  526. }
  527.  
  528. void code3201x_init(void)
  529. {
  530.   CPU32010 = AddCPU("32010", SwitchTo_3201X);
  531.   CPU32015 = AddCPU("32015", SwitchTo_3201X);
  532. }
  533.