Subversion Repositories pentevo

Rev

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

  1. /* codef8.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Code Generator Fairchild F8                                               */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include <string.h>
  14. #include <ctype.h>
  15.  
  16. #include "bpemu.h"
  17. #include "strutil.h"
  18. #include "chunks.h"
  19. #include "headids.h"
  20. #include "asmdef.h"
  21. #include "asmsub.h"
  22. #include "asmpars.h"
  23. #include "asmitree.h"
  24. #include "codepseudo.h"
  25. #include "intpseudo.h"
  26. #include "codevars.h"
  27. #include "errmsg.h"
  28.  
  29. #include "codef8.h"
  30.  
  31. #define Flg_IO (1 << 8)
  32. #define Flg_Code (1 << 9)
  33. #define Flg_CMOS (1 << 10)
  34.  
  35. static IntType CodeIntType;
  36. static Word MomCPUFlags;
  37.  
  38. /*---------------------------------------------------------------------------*/
  39.  
  40. static Boolean DecodeReg(const tStrComp *pArg, Byte *pResult)
  41. {
  42.   /* KU/KL/QU/QL are addressed via dedicated LR instructions! */
  43.   static const char RegNames[][3] = { "J", "HU", "HL", "S", "I", "D", "" };
  44.   int z;
  45.   Boolean OK;
  46.  
  47.   for (z = 0; *RegNames[z]; z++)
  48.     if (!as_strcasecmp(RegNames[z], pArg->str.p_str))
  49.     {
  50.       *pResult = z + 9;
  51.       return True;
  52.     }
  53.   *pResult = EvalStrIntExpression(pArg, UInt4, &OK);
  54.   return OK;
  55. }
  56.  
  57. static Boolean DecodeAux(const char *pArg, Byte *pResult)
  58. {
  59.   if (strlen(pArg) != 2)
  60.     return False;
  61.   *pResult = 0;
  62.  
  63.   if (toupper(pArg[0]) == 'Q')
  64.     *pResult |= 2;
  65.   else if (toupper(pArg[0]) != 'K')
  66.     return False;
  67.   if (toupper(pArg[1]) == 'L')
  68.     *pResult |= 1;
  69.   else if (toupper(pArg[1]) != 'U')
  70.     return False;
  71.   return True;
  72. }
  73.  
  74. static Boolean ArgPair(const char *pArg1, const char *pArg2)
  75. {
  76.   return !as_strcasecmp(ArgStr[1].str.p_str, pArg1) && !as_strcasecmp(ArgStr[2].str.p_str, pArg2);
  77. }
  78.  
  79. /*---------------------------------------------------------------------------*/
  80.  
  81. static void DecodeFixed(Word Code)
  82. {
  83.   if (!ChkArgCnt(0, 0));
  84.   else if ((Code & Flg_CMOS) && (!(MomCPUFlags & Flg_CMOS))) WrError(ErrNum_InstructionNotSupported);
  85.   else
  86.   {
  87.     BAsmCode[0] = Code;
  88.     CodeLen = 1;
  89.   }
  90. }
  91.  
  92. static void DecodeImm8(Word Code)
  93. {
  94.   Boolean IsIO = !!(Code & Flg_IO);
  95.  
  96.   if (ChkArgCnt(1, 1))
  97.   {
  98.     tEvalResult EvalResult;
  99.  
  100.     BAsmCode[1] = EvalStrIntExpressionWithResult(&ArgStr[1], IsIO ? UInt8 : Int8, &EvalResult);
  101.     if (EvalResult.OK)
  102.     {
  103.       if (IsIO)
  104.       {
  105.         ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  106.         if (BAsmCode[1] < 4)
  107.           WrStrErrorPos(ErrNum_NeedShortIO, &ArgStr[1]);
  108.       }
  109.       BAsmCode[0] = Lo(Code);
  110.       CodeLen = 2;
  111.     }
  112.   }
  113. }
  114.  
  115. static void DecodeImm4(Word Code)
  116. {
  117.   Boolean IsIO = !!(Code & Flg_IO);
  118.  
  119.   if (ChkArgCnt(1, 1))
  120.   {
  121.     tEvalResult EvalResult;
  122.  
  123.     BAsmCode[0] = Lo(Code) | EvalStrIntExpressionWithResult(&ArgStr[1], UInt4, &EvalResult);
  124.     if (EvalResult.OK)
  125.     {
  126.       CodeLen = 1;
  127.       if (IsIO)
  128.         ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  129.     }
  130.   }
  131. }
  132.  
  133. static void DecodeImm3(Word Code)
  134. {
  135.   if (ChkArgCnt(1, 1))
  136.   {
  137.     Boolean OK;
  138.  
  139.     BAsmCode[0] = Code | EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
  140.     if (OK)
  141.       CodeLen = 1;
  142.   }
  143. }
  144.  
  145. static void DecodeImm16(Word Code)
  146. {
  147.   Boolean IsCode = !!(Code & Flg_Code);
  148.  
  149.   if (ChkArgCnt(1, 1))
  150.   {
  151.     tEvalResult EvalResult;
  152.     Word Arg = EvalStrIntExpressionWithResult(&ArgStr[1], IsCode ? CodeIntType : Int16, &EvalResult);
  153.  
  154.     if (EvalResult.OK)
  155.     {
  156.       BAsmCode[0] = Code;
  157.       BAsmCode[1] = Hi(Arg);
  158.       BAsmCode[2] = Lo(Arg);
  159.       CodeLen = 3;
  160.       if (IsCode)
  161.         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  162.     }
  163.   }
  164. }
  165.  
  166. static void DecodeOneReg(Word Code)
  167. {
  168.   if (ChkArgCnt(1, 1) && DecodeReg(&ArgStr[1], &BAsmCode[0]))
  169.   {
  170.     BAsmCode[0] |= Code;
  171.     CodeLen = 1;
  172.   }
  173. }
  174.  
  175. static void DecodeBranchCore(const tStrComp *pArg, Word Code)
  176. {
  177.   Boolean OK;
  178.   LongInt Dist;
  179.   tSymbolFlags Flags;
  180.  
  181.   Dist = EvalStrIntExpressionWithFlags(pArg, UInt16, &OK, &Flags) - (EProgCounter() + 1);
  182.   if (OK)
  183.   {
  184.     if (!mSymbolQuestionable(Flags) && ((Dist < -128) || (Dist > 127))) WrStrErrorPos(ErrNum_JmpDistTooBig, pArg);
  185.     else
  186.     {
  187.       BAsmCode[0] = Code;
  188.       BAsmCode[1] = Dist & 0xff;
  189.       CodeLen = 2;
  190.     }
  191.   }
  192. }
  193.  
  194. static void DecodeBranch(Word Code)
  195. {
  196.   if (ChkArgCnt(1, 1))
  197.     DecodeBranchCore(&ArgStr[1], Code);
  198. }
  199.  
  200. static void DecodeGenBranch(Word Code)
  201. {
  202.   if (ChkArgCnt(2, 2))
  203.   {
  204.     Boolean OK;
  205.  
  206.     /* BT does not include OVF flag in its condition mask, only values 0..7! */
  207.  
  208.     Code |= EvalStrIntExpression(&ArgStr[1], (Code == 0x90) ? UInt4 : UInt3, &OK);
  209.     if (OK)
  210.       DecodeBranchCore(&ArgStr[2], Code);
  211.   }
  212. }
  213.  
  214. static void DecodeLR(Word Code)
  215. {
  216.   UNUSED(Code);
  217.  
  218.   if (!ChkArgCnt(2,2))
  219.     return;
  220.  
  221.   if (!as_strcasecmp(ArgStr[1].str.p_str, "A"))
  222.   {
  223.     if (DecodeAux(ArgStr[2].str.p_str, &BAsmCode[0]))
  224.     {
  225.       CodeLen = 1;
  226.     }
  227.     else if (!as_strcasecmp(ArgStr[2].str.p_str, "IS"))
  228.     {
  229.       BAsmCode[0] = 0x0a;
  230.       CodeLen = 1;
  231.     }
  232.     else if (DecodeReg(&ArgStr[2], &BAsmCode[0]))
  233.     {
  234.       BAsmCode[0] |= 0x40;
  235.       CodeLen = 1;
  236.     }
  237.   }
  238.   else if (!as_strcasecmp(ArgStr[2].str.p_str, "A"))
  239.   {
  240.     if (DecodeAux(ArgStr[1].str.p_str, &BAsmCode[0]))
  241.     {
  242.       BAsmCode[0] |= 4;
  243.       CodeLen = 1;
  244.     }
  245.     else if (!as_strcasecmp(ArgStr[1].str.p_str, "IS"))
  246.       BAsmCode[CodeLen++] = 0x0b;
  247.     else if (DecodeReg(&ArgStr[1], &BAsmCode[0]))
  248.     {
  249.       BAsmCode[0] |= 0x50;
  250.       CodeLen = 1;
  251.     }
  252.   }
  253.   else if (ArgPair("DC", "Q"))
  254.     BAsmCode[CodeLen++] = 0x0f;
  255.   else if (ArgPair("DC", "H"))
  256.     BAsmCode[CodeLen++] = 0x10;
  257.   else if (ArgPair("Q", "DC"))
  258.     BAsmCode[CodeLen++] = 0x0e;
  259.   else if (ArgPair("H", "DC"))
  260.     BAsmCode[CodeLen++] = 0x11;
  261.   else if (ArgPair("K", "P"))
  262.     BAsmCode[CodeLen++] = 0x08;
  263.   else if (ArgPair("P", "K"))
  264.     BAsmCode[CodeLen++] = 0x09;
  265.   else if (ArgPair("P0", "Q"))
  266.     BAsmCode[CodeLen++] = 0x0d;
  267.   else if (ArgPair("J", "W"))
  268.     BAsmCode[CodeLen++] = 0x1e;
  269.   else if (ArgPair("W", "J"))
  270.     BAsmCode[CodeLen++] = 0x1d;
  271.   else
  272.     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
  273. }
  274.  
  275. static void DecodeShift(Word Code)
  276. {
  277.   if (!ArgCnt)
  278.     BAsmCode[CodeLen++] = Code;
  279.   else if (ChkArgCnt(1,1))
  280.   {
  281.     Boolean OK;
  282.     Byte Cnt;
  283.     tSymbolFlags Flags;
  284.  
  285.     Cnt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt3, &OK, &Flags);
  286.     if (OK)
  287.     {
  288.       if (Cnt == 4)
  289.         BAsmCode[CodeLen++] = Code + 2;
  290.       else if (mFirstPassUnknown(Flags) || (Cnt == 1))
  291.         BAsmCode[CodeLen++] = Code;
  292.       else
  293.         WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
  294.     }
  295.   }
  296. }
  297.  
  298. static void DecodePORT(Word Code)
  299. {
  300.   UNUSED(Code);
  301.  
  302.   CodeEquate(SegIO, 0, 0xff);
  303. }
  304.  
  305. /*---------------------------------------------------------------------------*/
  306.  
  307. static void AddFixed(const char *NName, Word NCode)
  308. {
  309.   AddInstTable(InstTable, NName, NCode, DecodeFixed);
  310. }
  311.  
  312. static void AddImm8(const char *NName, Word NCode)
  313. {
  314.   AddInstTable(InstTable, NName, NCode, DecodeImm8);
  315. }
  316.  
  317. static void AddImm4(const char *NName, Word NCode)
  318. {
  319.   AddInstTable(InstTable, NName, NCode, DecodeImm4);
  320. }
  321.  
  322. static void AddImm3(const char *NName, Word NCode)
  323. {
  324.   AddInstTable(InstTable, NName, NCode, DecodeImm3);
  325. }
  326.  
  327. static void AddImm16(const char *NName, Word NCode)
  328. {
  329.   AddInstTable(InstTable, NName, NCode, DecodeImm16);
  330. }
  331.  
  332. static void AddOneReg(const char *NName, Word NCode)
  333. {
  334.   AddInstTable(InstTable, NName, NCode, DecodeOneReg);
  335. }
  336.  
  337. static void AddBranch(const char *NName, Word NCode)
  338. {
  339.   AddInstTable(InstTable, NName, NCode, DecodeBranch);
  340. }
  341.  
  342. static void AddGenBranch(const char *NName, Word NCode)
  343. {
  344.   AddInstTable(InstTable, NName, NCode, DecodeGenBranch);
  345. }
  346.  
  347. static void AddShift(const char *NName, Word NCode)
  348. {
  349.   AddInstTable(InstTable, NName, NCode, DecodeShift);
  350. }
  351.  
  352. static void InitFields(void)
  353. {
  354.   InstTable = CreateInstTable(101);
  355.  
  356.   AddFixed("ADC", 0x8e);
  357.   AddFixed("AM" , 0x88);
  358.   AddFixed("AMD", 0x89);
  359.   AddFixed("CLR", 0x70);
  360.   AddFixed("CM" , 0x8d);
  361.   AddFixed("COM", 0x18);
  362.   AddFixed("DI" , 0x1a);
  363.   AddFixed("EI" , 0x1b);
  364.   AddFixed("HET", Flg_CMOS | 0x2e); /* guess */
  365.   AddFixed("HAL", Flg_CMOS | 0x2f); /* guess */
  366.   AddFixed("INC", 0x1f);
  367.   AddFixed("LM" , 0x16);
  368.   AddFixed("LNK", 0x19);
  369.   AddFixed("NM" , 0x8a);
  370.   AddFixed("NOP", NOPCode);
  371.   AddFixed("OM" , 0x8b);
  372.   AddFixed("PK" , 0x0c);
  373.   AddFixed("POP", 0x1c);
  374.   AddFixed("ST" , 0x17);
  375.   AddFixed("XDC", 0x2c);
  376.   AddFixed("XM" , 0x8c);
  377.  
  378.   AddImm8("AI" , 0x24);
  379.   AddImm8("CI" , 0x25);
  380.   AddImm8("LI" , 0x20);
  381.   AddImm8("NI" , 0x21);
  382.   AddImm8("IN" , Flg_IO | 0x26);
  383.   AddImm8("OI" , 0x22);
  384.   AddImm8("OUT", Flg_IO | 0x27);
  385.   AddImm8("XI" , 0x23);
  386.  
  387.   AddImm4("LIS" , 0x70);
  388.   AddImm4("INS" , Flg_IO | 0xa0);
  389.   AddImm4("OUTS", Flg_IO | 0xb0);
  390.  
  391.   AddImm3("LISL", 0x68);
  392.   AddImm3("LISU", 0x60);
  393.  
  394.   AddImm16("DCI", 0x2a);
  395.   AddImm16("JMP", Flg_Code | 0x29);
  396.   AddImm16("PI" , Flg_Code | 0x28);
  397.  
  398.   AddOneReg("AS"  , 0xc0);
  399.   AddOneReg("ASD" , 0xd0);
  400.   AddOneReg("DS"  , 0x30);
  401.   AddOneReg("NS"  , 0xf0);
  402.   AddOneReg("XS"  , 0xe0);
  403.  
  404.   AddBranch("BC"  , 0x82);
  405.   AddBranch("BM"  , 0x91);
  406.   AddBranch("BNC" , 0x92);
  407.   AddBranch("BNO" , 0x98);
  408.   AddBranch("BNZ" , 0x94);
  409.   AddBranch("BP"  , 0x81);
  410.   AddBranch("BR"  , 0x90);
  411.   AddBranch("BR7" , 0x8f);
  412.   AddBranch("BZ"  , 0x84);
  413.   AddGenBranch("BF", 0x90);
  414.   AddGenBranch("BT", 0x80);
  415.  
  416.   AddShift("SL", 0x13);
  417.   AddShift("SR", 0x12);
  418.  
  419.   AddInstTable(InstTable, "LR", 0, DecodeLR);
  420.   AddInstTable(InstTable, "PORT", 0, DecodePORT);
  421. }
  422.  
  423. static void DeinitFields(void)
  424. {
  425.   DestroyInstTable(InstTable);
  426. }
  427.  
  428. /*---------------------------------------------------------------------------*/
  429.  
  430. static void MakeCode_F8(void)
  431. {
  432.   CodeLen = 0; DontPrint = False;
  433.  
  434.   /* zu ignorierendes */
  435.  
  436.   if (Memo("")) return;
  437.  
  438.   /* Pseudoanweisungen - DS is a machine instruction on F8 */
  439.  
  440.   if (!Memo("DS"))
  441.   {
  442.     if (DecodeIntelPseudo(True)) return;
  443.   }
  444.  
  445.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  446.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  447. }
  448.  
  449. static void SwitchFrom_F8(void)
  450. {
  451.   DeinitFields();
  452. }
  453.  
  454. static Boolean IsDef_F8(void)
  455. {
  456.   return Memo("PORT");
  457. }
  458.  
  459. static void SwitchTo_F8(void)
  460. {
  461.   const TFamilyDescr *Descr;
  462.  
  463.   TurnWords = False;
  464.   SetIntConstMode(eIntConstModeIntel);
  465.  
  466.   Descr = FindFamilyByName("F8");
  467.   PCSymbol = "$";
  468.   HeaderID = Descr->Id;
  469.   NOPCode = 0x2b;
  470.   DivideChars = ",";
  471.   HasAttrs = False;
  472.  
  473.   ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
  474.   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegLimits[SegCode] = IntTypeDefs[CodeIntType].Max;
  475.   Grans[SegData] = 1; ListGrans[SegData] = 1; SegLimits[SegData] = 0x3f;
  476.   Grans[SegIO  ] = 1; ListGrans[SegIO  ] = 1; SegLimits[SegIO  ] = 0xff;
  477.  
  478.   MakeCode = MakeCode_F8;
  479.   SwitchFrom = SwitchFrom_F8;
  480.   IsDef = IsDef_F8;
  481.   InitFields();
  482. }
  483.  
  484. static void SwitchTo_F8_12(void)
  485. {
  486.   CodeIntType = UInt12;
  487.   MomCPUFlags = 0;
  488.   SwitchTo_F8();
  489. }
  490.  
  491. static void SwitchTo_F8_16(void)
  492. {
  493.   CodeIntType = UInt16;
  494.   MomCPUFlags = 0;
  495.   SwitchTo_F8();
  496. }
  497.  
  498. static void SwitchTo_F8_12_CMOS(void)
  499. {
  500.   CodeIntType = UInt12;
  501.   MomCPUFlags = Flg_CMOS;
  502.   SwitchTo_F8();
  503. }
  504.  
  505. void codef8_init(void)
  506. {
  507.   (void)AddCPU("F3850"    , SwitchTo_F8_16);
  508.   (void)AddCPU("MK3850"   , SwitchTo_F8_16);
  509.   (void)AddCPU("MK3870"   , SwitchTo_F8_12);
  510.   (void)AddCPU("MK3870/10", SwitchTo_F8_12);
  511.   (void)AddCPU("MK3870/12", SwitchTo_F8_12);
  512.   (void)AddCPU("MK3870/20", SwitchTo_F8_12); /* == MK3870 */
  513.   (void)AddCPU("MK3870/22", SwitchTo_F8_12); /* == MK3876 */
  514.   (void)AddCPU("MK3870/30", SwitchTo_F8_12);
  515.   (void)AddCPU("MK3870/32", SwitchTo_F8_12);
  516.   (void)AddCPU("MK3870/40", SwitchTo_F8_12);
  517.   (void)AddCPU("MK3870/42", SwitchTo_F8_12); /* == MK3872 */
  518.   (void)AddCPU("MK3872"   , SwitchTo_F8_12);
  519.   (void)AddCPU("MK3873"   , SwitchTo_F8_12);
  520.   (void)AddCPU("MK3873/10", SwitchTo_F8_12);
  521.   (void)AddCPU("MK3873/12", SwitchTo_F8_12);
  522.   (void)AddCPU("MK3873/20", SwitchTo_F8_12); /* == MK3873 */
  523.   (void)AddCPU("MK3873/22", SwitchTo_F8_12);
  524.   (void)AddCPU("MK3874"   , SwitchTo_F8_12);
  525.   (void)AddCPU("MK3875"   , SwitchTo_F8_12);
  526.   (void)AddCPU("MK3875/22", SwitchTo_F8_12); /* == MK3876 with standby */
  527.   (void)AddCPU("MK3875/42", SwitchTo_F8_12); /* == MK3872 with standby */
  528.   (void)AddCPU("MK3876"   , SwitchTo_F8_12);
  529.   (void)AddCPU("MK38P70/02",SwitchTo_F8_12); /* == MK3874, MK974xx */
  530.   (void)AddCPU("MK38CP70/02", SwitchTo_F8_12_CMOS);
  531.   (void)AddCPU("MK38C70"  , SwitchTo_F8_12_CMOS);
  532.   (void)AddCPU("MK38C70/10",SwitchTo_F8_12);
  533.   (void)AddCPU("MK38C70/20",SwitchTo_F8_12); /* == MK38C70 */
  534.   (void)AddCPU("MK97400"  , SwitchTo_F8_12);
  535.   (void)AddCPU("MK97410"  , SwitchTo_F8_12);
  536.   (void)AddCPU("MK97500"  , SwitchTo_F8_16);
  537.   (void)AddCPU("MK97501"  , SwitchTo_F8_16);
  538.   (void)AddCPU("MK97503"  , SwitchTo_F8_16);
  539. }
  540.