Subversion Repositories pentevo

Rev

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

  1. /* codecop4.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegeneratormodul COP4-Familie                                           */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include "bpemu.h"
  14. #include "asmdef.h"
  15. #include "asmpars.h"
  16. #include "asmsub.h"
  17. #include "asmitree.h"
  18. #include "headids.h"
  19. #include "codevars.h"
  20. #include "intpseudo.h"
  21. #include "natpseudo.h"
  22. #include "errmsg.h"
  23.  
  24. #include "codecop4.h"
  25.  
  26. #define FixedOrderCnt 44
  27. #define ImmOrderCnt 3
  28.  
  29. #define M_CPUCOP410 (1 << 0)
  30. #define M_CPUCOP420 (1 << 1)
  31. #define M_CPUCOP440 (1 << 2)
  32. #define M_CPUCOP444 (1 << 3)
  33.  
  34. typedef struct
  35. {
  36.   Word CPUMask;
  37.   Word Code;
  38. } FixedOrder;
  39.  
  40. static CPUVar CPUCOP410, CPUCOP420, CPUCOP440, CPUCOP444;
  41. static IntType AdrInt;
  42.  
  43. static FixedOrder *FixedOrders, *ImmOrders;
  44.  
  45. /*---------------------------------------------------------------------------*/
  46. /* Code Generators */
  47.  
  48. static void DecodeFixed(Word Index)
  49. {
  50.   FixedOrder *pOrder = FixedOrders + Index;
  51.  
  52.   if (ChkArgCnt(0, 0)
  53.    && (ChkExactCPUMask(pOrder->CPUMask, CPUCOP410) >= 0))
  54.   {
  55.     if (Hi(pOrder->Code))
  56.       BAsmCode[CodeLen++] = Hi(pOrder->Code);
  57.     BAsmCode[CodeLen++] = Lo(pOrder->Code);
  58.   }
  59. }
  60.  
  61. static void DecodeSK(Word Index)
  62. {
  63.   if (ChkArgCnt(1, 1))
  64.   {
  65.     Byte Bit;
  66.     Boolean OK;
  67.  
  68.     Bit = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  69.     if (OK)
  70.     {
  71.       if (Index)
  72.         BAsmCode[CodeLen++] = Index;
  73.       BAsmCode[CodeLen++] = 0x01 | ((Bit & 1) << 4) | (Bit & 2);
  74.     }
  75.   }
  76. }
  77.  
  78. static void DecodeImm(Word Index)
  79. {
  80.   FixedOrder *pOrder = ImmOrders + Index;
  81.  
  82.   if (ChkArgCnt(1, 1)
  83.    && (ChkExactCPUMask(pOrder->CPUMask, CPUCOP410) >= 0))
  84.   {
  85.     Byte Val;
  86.     Boolean OK;
  87.  
  88.     Val = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
  89.     if (OK)
  90.     {
  91.       if (Hi(pOrder->Code))
  92.         BAsmCode[CodeLen++] = Hi(pOrder->Code);
  93.       BAsmCode[CodeLen++] = Lo(pOrder->Code) | (Val & 0x0f);
  94.     }
  95.   }
  96. }
  97.  
  98. static void DecodeJmp(Word Index)
  99. {
  100.   if (ChkArgCnt(1, 1))
  101.   {
  102.     Word Addr;
  103.     Boolean OK;
  104.  
  105.     Addr = EvalStrIntExpression(&ArgStr[1], AdrInt, &OK);
  106.     if (OK)
  107.     {
  108.       BAsmCode[CodeLen++] = Index | Hi(Addr);
  109.       BAsmCode[CodeLen++] = Lo(Addr);
  110.     }
  111.   }
  112. }
  113.  
  114. static void DecodeReg(Word Index)
  115. {
  116.   if (ChkArgCnt(1, 1))
  117.   {
  118.     Byte Reg;
  119.     Boolean OK;
  120.  
  121.     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  122.     if (OK)
  123.     {
  124.       BAsmCode[CodeLen++] = Index | ((Reg & 3) << 4);;
  125.     }
  126.   }
  127. }
  128.  
  129. static void DecodeAISC(Word Index)
  130. {
  131.   UNUSED(Index);
  132.  
  133.   if (ChkArgCnt(1, 1))
  134.   {
  135.     Byte Val;
  136.     Boolean OK;
  137.     tSymbolFlags Flags;
  138.  
  139.     Val = EvalStrIntExpressionWithFlags(&ArgStr[1], Int4, &OK, &Flags);
  140.     if (mFirstPassUnknown(Flags))
  141.       Val = 1;
  142.     if (OK)
  143.     {
  144.       if (!Val) WrError(ErrNum_UnderRange);
  145.       else
  146.         BAsmCode[CodeLen++] = 0x50 | (Val & 0x0f);
  147.     }
  148.   }
  149. }
  150.  
  151. static void DecodeRMB(Word Index)
  152. {
  153.   UNUSED(Index);
  154.  
  155.   if (ChkArgCnt(1, 1))
  156.   {
  157.     Byte Reg;
  158.     Boolean OK;
  159.     static Byte Vals[4] = { 0x4c, 0x45, 0x42, 0x43 };
  160.  
  161.     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  162.     if (OK)
  163.     {
  164.       BAsmCode[CodeLen++] = Vals[Reg & 3];
  165.     }
  166.   }
  167. }
  168.  
  169. static void DecodeSMB(Word Index)
  170. {
  171.   UNUSED(Index);
  172.  
  173.   if (ChkArgCnt(1, 1))
  174.   {
  175.     Byte Reg;
  176.     Boolean OK;
  177.     static Byte Vals[4] = { 0x4d, 0x47, 0x46, 0x4b };
  178.  
  179.     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  180.     if (OK)
  181.     {
  182.       BAsmCode[CodeLen++] = Vals[Reg & 3];
  183.     }
  184.   }
  185. }
  186.  
  187. static void DecodeXAD(Word Index)
  188. {
  189.   UNUSED(Index);
  190.  
  191.   if (ChkArgCnt(2, 2))
  192.   {
  193.     Byte Reg1, Reg2;
  194.     Boolean OK;
  195.     tSymbolFlags Flags;
  196.  
  197.     Reg1 = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt2, &OK, &Flags);
  198.     if (mFirstPassUnknown(Flags) && (MomCPU < CPUCOP420))
  199.       Reg1 = 3;
  200.     if (OK)
  201.     {
  202.       Reg2 = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt4, &OK, &Flags);
  203.       if (mFirstPassUnknown(Flags) && (MomCPU < CPUCOP420))
  204.         Reg2 = 15;
  205.       if (OK)
  206.       {
  207.         if ((MomCPU < CPUCOP420) && ((Reg1 != 3) || (Reg2 != 15))) WrError(ErrNum_InvAddrMode);
  208.         else
  209.         {
  210.           BAsmCode[CodeLen++] = 0x23;
  211.           BAsmCode[CodeLen++] = 0x80 | (Reg1 << 4) | Reg2;
  212.         }
  213.       }
  214.     }
  215.   }
  216. }
  217.  
  218. static void DecodeLBI(Word Index)
  219. {
  220.   UNUSED(Index);
  221.  
  222.   if (ChkArgCnt(2, 2))
  223.   {
  224.     Byte Reg, Val;
  225.     Boolean OK;
  226.  
  227.     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  228.     if (OK)
  229.     {
  230.       tSymbolFlags Flags;
  231.  
  232.       Val = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt4, &OK, &Flags);
  233.       if (mFirstPassUnknown(Flags))
  234.         Val = 0;
  235.       if (OK)
  236.       {
  237.         if ((Val > 0) && (Val < 9))
  238.         {
  239.           if (ChkExactCPUMask(M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP440, CPUCOP410) >= 0)
  240.           {
  241.             BAsmCode[CodeLen++] = 0x33;
  242.             BAsmCode[CodeLen++] = 0x80 | (Reg << 4) | Val;
  243.           }
  244.         }
  245.         else
  246.         {
  247.           Val = (Val - 1) & 0x0f;
  248.           BAsmCode[CodeLen++] = (Reg << 4) | Val;
  249.         }
  250.       }
  251.     }
  252.   }
  253. }
  254.  
  255. static void DecodeLDD(Word Index)
  256. {
  257.   UNUSED(Index);
  258.  
  259.   if (ChkArgCnt(2, 2)
  260.    && (ChkExactCPUMask(M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP440, CPUCOP410) >= 0))
  261.   {
  262.     Byte Reg, Val;
  263.     Boolean OK;
  264.  
  265.     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
  266.     if (OK)
  267.     {
  268.       Val = EvalStrIntExpression(&ArgStr[2], UInt4, &OK);
  269.       if (OK)
  270.       {
  271.         BAsmCode[CodeLen++] = 0x23;
  272.         BAsmCode[CodeLen++] = (Reg << 4) | Val;
  273.       }
  274.     }
  275.   }
  276. }
  277.  
  278. static void DecodeJSRP(Word Index)
  279. {
  280.   UNUSED(Index);
  281.  
  282.   if (ChkArgCnt(1, 1))
  283.   {
  284.     Word Addr;
  285.     Boolean OK;
  286.     tSymbolFlags Flags;
  287.  
  288.     Addr = EvalStrIntExpressionWithFlags(&ArgStr[1], AdrInt, &OK, &Flags);
  289.     if (mFirstPassUnknown(Flags))
  290.       Addr = 2 << 6;
  291.     if (OK)
  292.     {
  293.       if (((Addr >> 6) != 2) || (Addr == 0xbf)) WrError(ErrNum_NotFromThisAddress);
  294.       else if ((EProgCounter() >> 7) == 1) WrError(ErrNum_NotOnThisAddress);
  295.       else
  296.         BAsmCode[CodeLen++] = 0x80 | (Addr & 0x3f);
  297.     }
  298.   }
  299. }
  300.  
  301. static void DecodeJP(Word Index)
  302. {
  303.   UNUSED(Index);
  304.  
  305.   if (ChkArgCnt(1, 1))
  306.   {
  307.     Word Addr, CurrPC;
  308.     Boolean OK;
  309.     tSymbolFlags Flags;
  310.  
  311.     Addr = EvalStrIntExpressionWithFlags(&ArgStr[1], AdrInt, &OK, &Flags);
  312.     if (mFirstPassUnknown(Flags))
  313.       Addr = EProgCounter() & (~0x1f);
  314.     if (OK)
  315.     {
  316.       CurrPC = EProgCounter();
  317.       if ((Addr & 0x3f) == 0x3f)
  318.         WrError(ErrNum_NotFromThisAddress);
  319.       if (((CurrPC >> 7) == 1) && ((Addr >> 7) == 1))
  320.         BAsmCode[CodeLen++] = 0x80 | (Addr & 0x7f);
  321.       else
  322.       {
  323.         Word PossPage;
  324.  
  325.         PossPage = CurrPC >> 6;
  326.         if ((CurrPC & 0x3f) == 0x3f)
  327.         {
  328.           PossPage++;
  329.           if (mFirstPassUnknown(Flags))
  330.             Addr += 0x40;
  331.         }
  332.  
  333.         if (PossPage == (Addr >> 6))
  334.           BAsmCode[CodeLen++] = 0xc0 | (Addr & 0x3f);
  335.         else
  336.           WrError(ErrNum_NotFromThisAddress);
  337.       }
  338.     }
  339.   }
  340. }
  341.  
  342. /*---------------------------------------------------------------------------*/
  343. /* Code Table Handling */
  344.  
  345. static void AddFixed(const char *NName, Word NCode, Word NMask)
  346. {
  347.   if (InstrZ >= FixedOrderCnt)
  348.     exit(0);
  349.   else
  350.   {
  351.     FixedOrders[InstrZ].Code = NCode;
  352.     FixedOrders[InstrZ].CPUMask = NMask;
  353.     AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
  354.   }
  355. }
  356.  
  357. static void AddImm(const char *NName, Word NCode, Word NMask)
  358. {
  359.   if (InstrZ >= ImmOrderCnt)
  360.     exit(0);
  361.   else
  362.   {
  363.     ImmOrders[InstrZ].Code = NCode;
  364.     ImmOrders[InstrZ].CPUMask = NMask;
  365.     AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
  366.   }
  367. }
  368.  
  369. static void InitFields(void)
  370. {
  371.   InstTable = CreateInstTable(173);
  372.  
  373.   FixedOrders = (FixedOrder*)malloc(sizeof(FixedOrder) * FixedOrderCnt);
  374.   InstrZ = 0;
  375.   AddFixed("ASC"  , 0x30,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  376.   AddFixed("ADD"  , 0x31,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  377.   AddFixed("CLRA" , 0x00,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  378.   AddFixed("COMP" , 0x40,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  379.   AddFixed("NOP"  , 0x44,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  380.   AddFixed("RC"   , 0x32,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  381.   AddFixed("SC"   , 0x22,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  382.   AddFixed("XOR"  , 0x02,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  383.   AddFixed("JID"  , 0xff,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  384.   AddFixed("RET"  , 0x48,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  385.   AddFixed("RETSK", 0x49,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  386.   AddFixed("CAMQ" , 0x333c, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  387.   AddFixed("CAME" , 0x331f,                             M_CPUCOP440              );
  388.   AddFixed("CAMT" , 0x333f,                             M_CPUCOP440 | M_CPUCOP444);
  389.   AddFixed("CAMR" , 0x333d,                             M_CPUCOP440              );
  390.   AddFixed("CEMA" , 0x330f,                             M_CPUCOP440              );
  391.   AddFixed("CTMA" , 0x332f,                             M_CPUCOP440 | M_CPUCOP444);
  392.   AddFixed("LQID" , 0xbf,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  393.   AddFixed("CAB"  , 0x50,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  394.   AddFixed("CBA"  , 0x4e,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  395.   AddFixed("SKC"  , 0x20,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  396.   AddFixed("SKE"  , 0x21,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  397.   AddFixed("SKGZ" , 0x3321, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  398.   AddFixed("SKSZ" , 0x331c,                             M_CPUCOP440 | M_CPUCOP444);
  399.   AddFixed("ING"  , 0x332a, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  400.   AddFixed("INH"  , 0x332b,                             M_CPUCOP440              );
  401.   AddFixed("INL"  , 0x332e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  402.   AddFixed("INR"  , 0x332d,                             M_CPUCOP440              );
  403.   AddFixed("OBD"  , 0x333e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  404.   AddFixed("OMG"  , 0x333a, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  405.   AddFixed("OMH"  , 0x333b,                             M_CPUCOP440              );
  406.   AddFixed("XAS"  , 0x4f,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  407.   AddFixed("ADT"  , 0x4a,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  408.   AddFixed("CASC" , 0x10,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  409.   AddFixed("CQMA" , 0x332c,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  410.   AddFixed("SKT"  , 0x41,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  411.   AddFixed("XABR" , 0x12,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  412.   AddFixed("ININ" , 0x3328,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  413.   AddFixed("INIL" , 0x3329,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  414.   AddFixed("OR"   , 0x331a,                             M_CPUCOP440              );
  415.   AddFixed("LID"  , 0x3319,                             M_CPUCOP440              );
  416.   AddFixed("XAN"  , 0x330b,                             M_CPUCOP440              );
  417.   AddFixed("HALT" , 0x3338,                                           M_CPUCOP444);
  418.   AddFixed("IT"   , 0x3339,                                           M_CPUCOP444);
  419.  
  420.   AddInstTable(InstTable, "SKGBZ", 0x33, DecodeSK);
  421.   AddInstTable(InstTable, "SKMBZ", 0x00, DecodeSK);
  422.  
  423.   ImmOrders = (FixedOrder*)malloc(sizeof(FixedOrder) * ImmOrderCnt);
  424.   InstrZ = 0;
  425.   AddImm("STII" , 0x70,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  426.   AddImm("LEI"  , 0x3360, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  427.   AddImm("OGI"  , 0x3350,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
  428.  
  429.   AddInstTable(InstTable, "JMP"  , 0x60, DecodeJmp);
  430.   AddInstTable(InstTable, "JSR"  , 0x68, DecodeJmp);
  431.  
  432.   AddInstTable(InstTable, "LD"   , 0x05, DecodeReg);
  433.   AddInstTable(InstTable, "X"    , 0x06, DecodeReg);
  434.   AddInstTable(InstTable, "XDS"  , 0x07, DecodeReg);
  435.   AddInstTable(InstTable, "XIS"  , 0x04, DecodeReg);
  436.  
  437.   AddInstTable(InstTable, "AISC" , 0x00, DecodeAISC);
  438.   AddInstTable(InstTable, "RMB"  , 0x00, DecodeRMB);
  439.   AddInstTable(InstTable, "SMB"  , 0x00, DecodeSMB);
  440.  
  441.   AddInstTable(InstTable, "XAD"  , 0x00, DecodeXAD);
  442.  
  443.   AddInstTable(InstTable, "LBI"  , 0x00, DecodeLBI);
  444.  
  445.   AddInstTable(InstTable, "LDD"  , 0x00, DecodeLDD);
  446.  
  447.   AddInstTable(InstTable, "JSRP"  , 0x00, DecodeJSRP);
  448.  
  449.   AddInstTable(InstTable, "JP"    , 0x00, DecodeJP);
  450. }
  451.  
  452. static void DeinitFields(void)
  453. {
  454.   free(FixedOrders);
  455.   free(ImmOrders);
  456.   DestroyInstTable(InstTable);
  457. }
  458.  
  459. /*---------------------------------------------------------------------------*/
  460.  
  461. static void MakeCode_COP4(void)
  462. {
  463.   CodeLen = 0; DontPrint = False;
  464.  
  465.   /* zu ignorierendes */
  466.  
  467.   if (*OpPart.str.p_str == '\0') return;
  468.  
  469.   /* pseudo instructions */
  470.  
  471.   if (DecodeNatPseudo()) return;
  472.   if (DecodeIntelPseudo(False)) return;
  473.  
  474.   /* machine instructions */
  475.  
  476.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  477.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  478. }
  479.  
  480. static void SwitchFrom_COP4(void)
  481. {
  482.   DeinitFields();
  483. }
  484.  
  485. static Boolean IsDef_COP4(void)
  486. {
  487.   return False;
  488. }
  489.  
  490. static void SwitchTo_COP4(void)
  491. {
  492.   const TFamilyDescr *pDescr;
  493.  
  494.   pDescr = FindFamilyByName("COP4");
  495.  
  496.   TurnWords = False;
  497.   SetIntConstMode(eIntConstModeC);
  498.  
  499.   PCSymbol = "."; HeaderID = pDescr->Id;
  500.   NOPCode = 0x44;
  501.   DivideChars = ","; HasAttrs = False;
  502.  
  503.   ValidSegs = (1 << SegCode);
  504.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
  505.   if (MomCPU >= CPUCOP440)
  506.   {
  507.     SegLimits[SegCode] = 0x7ff;
  508.     AdrInt = UInt11;
  509.   }
  510.   else if (MomCPU >= CPUCOP420)
  511.   {
  512.     SegLimits[SegCode] = 0x3ff;
  513.     AdrInt = UInt10;
  514.   }
  515.   else
  516.   {
  517.     SegLimits[SegCode] = 0x1ff;
  518.     AdrInt = UInt9;
  519.   }
  520.  
  521.   MakeCode = MakeCode_COP4; IsDef = IsDef_COP4;
  522.   SwitchFrom = SwitchFrom_COP4; InitFields();
  523. }
  524.  
  525. void codecop4_init(void)
  526. {
  527.   CPUCOP410 = AddCPU("COP410", SwitchTo_COP4);
  528.   CPUCOP420 = AddCPU("COP420", SwitchTo_COP4);
  529.   CPUCOP440 = AddCPU("COP440", SwitchTo_COP4);
  530.   CPUCOP444 = AddCPU("COP444", SwitchTo_COP4);
  531. }
  532.