Subversion Repositories pentevo

Rev

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

  1. /* codekenbak.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS                                                                        */
  6. /*                                                                           */
  7. /* Code Generator KENBAK(-1)                                                 */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12.  
  13. #include <string.h>
  14. #include "stdinc.h"
  15. #include "strutil.h"
  16. #include "intformat.h"
  17. #include "asmdef.h"
  18. #include "asmsub.h"
  19. #include "asmpars.h"
  20. #include "asmallg.h"
  21. #include "asmstructs.h"
  22. #include "headids.h"
  23.  
  24. #include "asmitree.h"
  25. #include "codevars.h"
  26. #include "codepseudo.h"
  27. #include "intpseudo.h"
  28.  
  29. #include "codekenbak.h"
  30.  
  31. /*---------------------------------------------------------------------------*/
  32.  
  33. /* do not change enum values, they match the machine codings: */
  34.  
  35. enum
  36. {
  37.   ModNone = 0,
  38.   ModImm = 3,
  39.   ModMemory = 4,
  40.   ModIndirect = 5,
  41.   ModIndexed = 6,
  42.   ModIndirectIndexed = 7
  43. };
  44.  
  45. #define MModImm (1 << ModImm)
  46. #define MModMemory (1 << ModMemory)
  47. #define MModIndirect (1 << ModIndirect)
  48. #define MModIndexed (1 << ModIndexed)
  49. #define MModIndirectIndexed (1 << ModIndirectIndexed)
  50.  
  51. #define MModAll (MModImm | MModMemory | MModIndirect | MModIndexed | MModIndirectIndexed)
  52.  
  53. typedef struct
  54. {
  55.   Byte Mode, Val;
  56. } tAdrData;
  57.  
  58. static const char Regs[5] = "ABXP";
  59.  
  60. /*---------------------------------------------------------------------------*/
  61.  
  62. /*!------------------------------------------------------------------------
  63.  * \fn     DecodeRegCore(const char *pArg, Byte *pResult)
  64.  * \brief  check whether argument describes a CPU register
  65.  * \param  pArg argument
  66.  * \param  pValue resulting register # if yes
  67.  * \return true if argument is a register
  68.  * ------------------------------------------------------------------------ */
  69.  
  70. static Boolean DecodeRegCore(const char *pArg, Byte *pResult)
  71. {
  72.   const char *pPos;
  73.  
  74.   if (strlen(pArg) != 1)
  75.     return False;
  76.   pPos = strchr(Regs, as_toupper(*pArg));
  77.   if (pPos)
  78.     *pResult = pPos - Regs;
  79.   return !!pPos;
  80. }
  81.  
  82. /*!------------------------------------------------------------------------
  83.  * \fn     DissectReg_KENBAK(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  84.  * \brief  dissect register symbols - KENBAK variant
  85.  * \param  pDest destination buffer
  86.  * \param  DestSize destination buffer size
  87.  * \param  Value numeric register value
  88.  * \param  InpSize register size
  89.  * ------------------------------------------------------------------------ */
  90.  
  91. static void DissectReg_KENBAK(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
  92. {
  93.   switch (InpSize)
  94.   {
  95.     case eSymbolSize8Bit:
  96.       if (Value <= 3)
  97.       {
  98.         as_snprintf(pDest, DestSize, "%c", Regs[Value]);
  99.         break;
  100.       }
  101.       /* else fall-thru */
  102.     default:
  103.       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
  104.   }
  105. }
  106.  
  107. /*!------------------------------------------------------------------------
  108.  * \fn     DecodeReg(const tStrComp *pArg, Byte *pResult, Word RegMask, Boolean MustBeReg)
  109.  * \brief  check whether argument is CPU register, including register aliases
  110.  * \param  pArg source code argument
  111.  * \param  pResult register # if it's a register
  112.  * \param  RegMask bit mask of allowed registers
  113.  * \param  MustBeReg expecting register anyway
  114.  * \return eval result
  115.  * ------------------------------------------------------------------------ */
  116.  
  117. static tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pResult, Word RegMask, Boolean MustBeReg)
  118. {
  119.   tRegDescr RegDescr;
  120.   tEvalResult EvalResult;
  121.   tRegEvalResult RegEvalResult;
  122.  
  123.   if (DecodeRegCore(pArg->str.p_str, pResult))
  124.     RegEvalResult = eIsReg;
  125.   else
  126.   {
  127.     RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize8Bit, MustBeReg);
  128.     *pResult = RegDescr.Reg;
  129.   }
  130.  
  131.   if ((RegEvalResult == eIsReg)
  132.    && !(1 & (RegMask >> *pResult)))
  133.   {
  134.     WrStrErrorPos(ErrNum_InvReg, pArg);
  135.     RegEvalResult = eRegAbort;
  136.   }
  137.  
  138.   return RegEvalResult;
  139. }
  140.  
  141. /*!------------------------------------------------------------------------
  142.  * \fn     DecodeRegWithMemOpt(const tStrComp *pArg, Byte *pResult, Word RegMask)
  143.  * \brief  check whether argument is CPU register, register alias, or memory location representing a register
  144.  * \param  pArg source code argument
  145.  * \param  pResult register # if it's a register
  146.  * \param  RegMask bit mask of allowed registers
  147.  * \return True if argument can be interpreted as register in some way
  148.  * ------------------------------------------------------------------------ */
  149.  
  150. static Boolean DecodeRegWithMemOpt(const tStrComp *pArg, Byte *pResult, Word RegMask)
  151. {
  152.   switch (DecodeReg(pArg, pResult, RegMask, False))
  153.   {
  154.     case eIsReg:
  155.       return True;
  156.     case eRegAbort:
  157.       return False;
  158.     default:
  159.     {
  160.       tEvalResult EvalResult;
  161.  
  162.       *pResult = EvalStrIntExpressionWithResult(pArg, UInt8, &EvalResult);
  163.       if (!EvalResult.OK)
  164.         return False;
  165.       if (!(1 & (RegMask >> *pResult)))
  166.       {
  167.         WrStrErrorPos(ErrNum_InvReg, pArg);
  168.         return False;
  169.       }
  170.       return True;
  171.     }
  172.   }
  173. }
  174.  
  175. /*!------------------------------------------------------------------------
  176.  * \fn     DecodeAdr(const tStrComp *pArg, tAdrData *pAdrData, Word ModeMask)
  177.  * \brief  decode address expression
  178.  * \param  pArg1 1st argument
  179.  * \param  pArg1 optional 2nd argument (may be NULL)
  180.  * \param  pAdrData result buffer
  181.  * \return true if successfully decoded
  182.  * ------------------------------------------------------------------------ */
  183.  
  184. static Boolean ChkMode(Word ModeMask, tAdrData *pAdrData)
  185. {
  186.   return !!((ModeMask >> pAdrData->Mode) & 1);
  187. }
  188.  
  189. static Boolean DecodeAdr(tStrComp *pArg1, tStrComp *pArg2, tAdrData *pAdrData, Word ModeMask)
  190. {
  191.   tStrComp Arg;
  192.  
  193.   pAdrData->Mode = 0;
  194.  
  195.   if (pArg2)
  196.   {
  197.     Byte IndexReg;
  198.  
  199.     if (DecodeReg(pArg2, &IndexReg, 4, True) != eIsReg)
  200.       return False;
  201.     pAdrData->Mode |= 2;
  202.   }
  203.   else
  204.   {
  205.     if (*pArg1->str.p_str == '#')
  206.     {
  207.       Boolean OK;
  208.  
  209.       pAdrData->Mode = 3;
  210.       pAdrData->Val = EvalStrIntExpressionOffs(pArg1, 1, Int8, &OK);
  211.       return OK && ChkMode(ModeMask, pAdrData);
  212.     }
  213.   }
  214.  
  215.   if ((ModeMask & (MModIndirect | MModIndirectIndexed)) && IsIndirect(pArg1->str.p_str))
  216.   {
  217.     StrCompShorten(pArg1, 1);
  218.     StrCompRefRight(&Arg, pArg1, 1);
  219.     pAdrData->Mode |= 1;
  220.   }
  221.   else
  222.     StrCompRefRight(&Arg, pArg1, 0);
  223.   switch (DecodeReg(&Arg, &pAdrData->Val, 15, False))
  224.   {
  225.     case eIsReg:
  226.       pAdrData->Mode |= 4;
  227.       return ChkMode(ModeMask, pAdrData);
  228.     case eRegAbort:
  229.       return False;
  230.     default:
  231.     {
  232.       Boolean OK;
  233.  
  234.       pAdrData->Val = EvalStrIntExpression(&Arg, UInt8, &OK);
  235.       pAdrData->Mode |= 4;
  236.       return OK && ChkMode(ModeMask, pAdrData);
  237.     }
  238.   }
  239. }
  240.  
  241. /*!------------------------------------------------------------------------
  242.  * \fn     DecodeAddrKeyword(const char *pKeyword, Byte *pMode)
  243.  * \brief  deduce addressing mode form key word
  244.  * \param  pKeyword keyword from source
  245.  * \param  pMode resulting mode if yes
  246.  * \return True if valid key word
  247.  * ------------------------------------------------------------------------ */
  248.  
  249. static Boolean DecodeAddrKeyword(const char *pKeyword, Byte *pMode)
  250. {
  251.   if (!as_strcasecmp(pKeyword, "Constant"))
  252.   {
  253.     *pMode = ModImm;
  254.     return True;
  255.   }
  256.   if (!as_strcasecmp(pKeyword, "Memory"))
  257.   {
  258.     *pMode = ModMemory;
  259.     return True;
  260.   }
  261.   if (!as_strcasecmp(pKeyword, "Indexed"))
  262.   {
  263.     *pMode = ModIndexed;
  264.     return True;
  265.   }
  266.   if (!as_strcasecmp(pKeyword, "Indirect"))
  267.   {
  268.     *pMode = ModIndirect;
  269.     return True;
  270.   }
  271.   if (!as_strcasecmp(pKeyword, "Indirect-Indexed"))
  272.   {
  273.     *pMode = ModIndirectIndexed;
  274.     return True;
  275.   }
  276.   return False;
  277. }
  278.  
  279. /*--------------------------------------------------------------------------*/
  280. /* Bit Symbol Handling */
  281.  
  282. /*
  283.  * Compact representation of bits in symbol table:
  284.  * Bits 10...3: Absolute Address
  285.  * Bits 0..2: Bit Position
  286.  */
  287.  
  288. /*!------------------------------------------------------------------------
  289.  * \fn     EvalBitPosition(const tStrComp *pArg, Boolean *pOK)
  290.  * \brief  evaluate bit position
  291.  * \param  bit position argument (with or without #)
  292.  * \param  pOK parsing OK?
  293.  * \return numeric bit position
  294.  * ------------------------------------------------------------------------ */
  295.  
  296. static LongWord EvalBitPosition(const tStrComp *pArg, Boolean *pOK)
  297. {
  298.   return EvalStrIntExpression(pArg, UInt3, pOK);
  299. }
  300.  
  301. /*!------------------------------------------------------------------------
  302.  * \fn     AssembleBitSymbol(Byte BitPos, LongWord Address)
  303.  * \brief  build the compact internal representation of a bit symbol
  304.  * \param  BitPos bit position in byte
  305.  * \param  Address register address
  306.  * \return compact representation
  307.  * ------------------------------------------------------------------------ */
  308.  
  309. static LongWord AssembleBitSymbol(Byte BitPos, Word Address)
  310. {
  311.   return
  312.     (Address << 3)
  313.   | (BitPos << 0);
  314. }
  315.  
  316. /*!------------------------------------------------------------------------
  317.  * \fn     DecodeBitArg2(LongWord *pResult, const tStrComp *pBitArg, tStrComp *pRegArg)
  318.  * \brief  encode a bit symbol, address & bit position separated
  319.  * \param  pResult resulting encoded bit
  320.  * \param  pRegArg register argument
  321.  * \param  pBitArg bit argument
  322.  * \return True if success
  323.  * ------------------------------------------------------------------------ */
  324.  
  325. static Boolean DecodeBitArg2(LongWord *pResult, const tStrComp *pBitArg, tStrComp *pRegArg)
  326. {
  327.   Boolean OK;
  328.   LongWord BitPos;
  329.   tAdrData AdrData;
  330.  
  331.   BitPos = EvalBitPosition(pBitArg, &OK);
  332.   if (!OK)
  333.     return False;
  334.  
  335.   if (!DecodeAdr(pRegArg, NULL, &AdrData, MModMemory))
  336.     return False;
  337.  
  338.   *pResult = AssembleBitSymbol(BitPos, AdrData.Val);
  339.   return True;
  340. }
  341.  
  342. /*!------------------------------------------------------------------------
  343.  * \fn     DecodeBitArg(LongWord *pResult, int Start, int Stop)
  344.  * \brief  encode a bit symbol from instruction argument(s)
  345.  * \param  pResult resulting encoded bit
  346.  * \param  Start first argument
  347.  * \param  Stop last argument
  348.  * \return True if success
  349.  * ------------------------------------------------------------------------ */
  350.  
  351. static Boolean DecodeBitArg(LongWord *pResult, int Start, int Stop)
  352. {
  353.   *pResult = 0;
  354.  
  355.   /* Just one argument -> parse as bit argument */
  356.  
  357.   if (Start == Stop)
  358.   {
  359.     tEvalResult EvalResult;
  360.  
  361.     *pResult = EvalStrIntExpressionWithResult(&ArgStr[Start], UInt32, &EvalResult);
  362.     if (EvalResult.OK)
  363.       ChkSpace(SegBData, EvalResult.AddrSpaceMask);
  364.     return EvalResult.OK;
  365.   }
  366.  
  367.   /* register & bit position are given as separate arguments */
  368.  
  369.   else if (Stop == Start + 1)
  370.     return DecodeBitArg2(pResult, &ArgStr[Start], &ArgStr[Stop]);
  371.  
  372.   /* other # of arguments not allowed */
  373.  
  374.   else
  375.   {
  376.     WrError(ErrNum_WrongArgCnt);
  377.     return False;
  378.   }
  379. }
  380.  
  381. /*!------------------------------------------------------------------------
  382.  * \fn     DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos)
  383.  * \brief  transform compact representation of bit (field) symbol into components
  384.  * \param  BitSymbol compact storage
  385.  * \param  pAddress register address
  386.  * \param  pBitPos bit position
  387.  * \return constant True
  388.  * ------------------------------------------------------------------------ */
  389.  
  390. static Boolean DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos)
  391. {
  392.   *pAddress = (BitSymbol >> 3) & 0xfful;
  393.   *pBitPos = BitSymbol & 7;
  394.   return True;
  395. }
  396.  
  397. /*!------------------------------------------------------------------------
  398.  * \fn     DissectBit_KENBAK(char *pDest, size_t DestSize, LargeWord Inp)
  399.  * \brief  dissect compact storage of bit (field) into readable form for listing
  400.  * \param  pDest destination for ASCII representation
  401.  * \param  DestSize destination buffer size
  402.  * \param  Inp compact storage
  403.  * ------------------------------------------------------------------------ */
  404.  
  405. static void DissectBit_KENBAK(char *pDest, size_t DestSize, LargeWord Inp)
  406. {
  407.   Byte BitPos;
  408.   Word Address;
  409.  
  410.   DissectBitSymbol(Inp, &Address, &BitPos);
  411.  
  412.   as_snprintf(pDest, DestSize, "%~02.*u%s,%u",
  413.               ListRadixBase, (unsigned)Address, GetIntConstIntelSuffix(ListRadixBase),
  414.               (unsigned)BitPos);
  415. }
  416.  
  417. /*!------------------------------------------------------------------------
  418.  * \fn     ExpandBit_KENBAK(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
  419.  * \brief  expands bit definition when a structure is instantiated
  420.  * \param  pVarName desired symbol name
  421.  * \param  pStructElem element definition
  422.  * \param  Base base address of instantiated structure
  423.  * ------------------------------------------------------------------------ */
  424.  
  425. static void ExpandBit_KENBAK(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
  426. {
  427.   LongWord Address = Base + pStructElem->Offset;
  428.  
  429.   if (pInnermostNamedStruct)
  430.   {
  431.     PStructElem pElem = CloneStructElem(pVarName, pStructElem);
  432.  
  433.     if (!pElem)
  434.       return;
  435.     pElem->Offset = Address;
  436.     AddStructElem(pInnermostNamedStruct->StructRec, pElem);
  437.   }
  438.   else
  439.   {
  440.     PushLocHandle(-1);
  441.     EnterIntSymbol(pVarName, AssembleBitSymbol(pStructElem->BitPos, Address), SegBData, False);
  442.     PopLocHandle();
  443.     /* TODO: MakeUseList? */
  444.   }
  445. }
  446.  
  447. /*---------------------------------------------------------------------------*/
  448.  
  449. /*!------------------------------------------------------------------------
  450.  * \fn     CodeGen(Word Code)
  451.  * \brief  decode generic 2-operand instructions
  452.  * \param  Code instruction code in 1st byte
  453.  * ------------------------------------------------------------------------ */
  454.  
  455. static void CodeGen(Word Code)
  456. {
  457.   if (ChkArgCnt(2, 3))
  458.   {
  459.     int RegArg;
  460.     Boolean AddrOK;
  461.     Byte Reg;
  462.     tAdrData AdrData;
  463.  
  464.     /* addressing mode is either given by keyword or by addressing syntax: */
  465.  
  466.     if ((ArgCnt == 3) && DecodeAddrKeyword(ArgStr[1].str.p_str, &AdrData.Mode))
  467.     {
  468.       AdrData.Val = EvalStrIntExpression(&ArgStr[3], Int8, &AddrOK);
  469.       RegArg = 2;
  470.     }
  471.     else
  472.     {
  473.       AddrOK = DecodeAdr(&ArgStr[2], (ArgCnt == 3) ? &ArgStr[3] : NULL, &AdrData, MModAll);
  474.       RegArg = 1;
  475.     }
  476.  
  477.     if (AddrOK && DecodeRegWithMemOpt(&ArgStr[RegArg], &Reg, Code & 0xc0 ? 1 : 7))
  478.     {
  479.       BAsmCode[CodeLen++] = (Reg << 6) | Code | AdrData.Mode;
  480.       BAsmCode[CodeLen++] = AdrData.Val;
  481.     }
  482.   }
  483. }
  484.  
  485. /*!------------------------------------------------------------------------
  486.  * \fn     CodeClear(Word Code)
  487.  * \brief  decode CLEAR instruction
  488.  * ------------------------------------------------------------------------ */
  489.  
  490. static void CodeClear(Word Code)
  491. {
  492.   Byte Reg;
  493.  
  494.   UNUSED(Code);
  495.  
  496.   if (ChkArgCnt(1, 1)
  497.    && DecodeRegWithMemOpt(&ArgStr[1], &Reg, 7))
  498.   {
  499.     /* SUB reg,reg */
  500.  
  501.     BAsmCode[CodeLen++] = (Reg << 6) | 0x0c;
  502.     BAsmCode[CodeLen++] = Reg;
  503.   }
  504. }
  505.  
  506. /*!------------------------------------------------------------------------
  507.  * \fn     CodeJump(Word Code)
  508.  * \brief  decode jump instructions (direct/indirect in mnemonic)
  509.  * \param  Code instruction code in 1st byte
  510.  * ------------------------------------------------------------------------ */
  511.  
  512. static void CodeJumpCommon(Word Code, const tAdrData *pAdrData)
  513. {
  514.   Byte Reg;
  515.   int Cond;
  516.   static const char ShortConds[5][4] = { "NZ", "Z", "N", "P", "PNZ" };
  517.   static const char *LongConds[5] = { "Non-zero", "Zero", "Negative", "Positive", "Positive-Non-zero" };
  518.  
  519.   if ((ArgCnt == 1) || !as_strcasecmp(ArgStr[1].str.p_str, "Unconditional"))
  520.     Reg = 3;
  521.   else if (!DecodeRegWithMemOpt(&ArgStr[1], &Reg, 7))
  522.     return;
  523.  
  524.   if (ArgCnt == 1)
  525.     Cond = 0;
  526.   else
  527.   {
  528.     for (Cond = 0; Cond < 5; Cond++)
  529.       if (!as_strcasecmp(ArgStr[ArgCnt - 1].str.p_str, ShortConds[Cond])
  530.        || !as_strcasecmp(ArgStr[ArgCnt - 1].str.p_str, LongConds[Cond]))
  531.         break;
  532.     if (Cond >= 5)
  533.     {
  534.       WrStrErrorPos(ErrNum_UndefCond, &ArgStr[ArgCnt - 1]);
  535.       return;
  536.     }
  537.   }
  538.   BAsmCode[CodeLen++] = (Reg << 6) | Code | (Cond + 3);
  539.   BAsmCode[CodeLen++] = pAdrData->Val;
  540. }
  541.  
  542. static void CodeJump(Word Code)
  543. {
  544.   tAdrData AdrData;
  545.  
  546.   if ((ArgCnt != 1) && (ArgCnt != 3))
  547.   {
  548.     WrError(ErrNum_WrongArgCnt);
  549.     return;
  550.   }
  551.   if (DecodeAdr(&ArgStr[ArgCnt], NULL, &AdrData, MModMemory))
  552.     CodeJumpCommon(Code, &AdrData);
  553. }
  554.  
  555. /*!------------------------------------------------------------------------
  556.  * \fn     CodeJumpGen(Word Code)
  557.  * \brief  decode jump instructions (direct/indirect in addressing mode argument)
  558.  * \param  Code instruction code in 1st byte
  559.  * ------------------------------------------------------------------------ */
  560.  
  561. static void CodeJumpGen(Word Code)
  562. {
  563.   tAdrData AdrData;
  564.  
  565.   if ((ArgCnt != 1) && (ArgCnt != 3))
  566.   {
  567.     WrError(ErrNum_WrongArgCnt);
  568.       return;
  569.   }
  570.  
  571.   /* transport the addressing mode's indirect bit (bit 0) to the
  572.      corresponding instruction code's bit (bit 3): */
  573.  
  574.   if (DecodeAdr(&ArgStr[ArgCnt], NULL, &AdrData, MModMemory | MModIndirect))
  575.     CodeJumpCommon(Code | ((AdrData.Mode & 1) << 3), &AdrData);
  576. }
  577.  
  578. /*!------------------------------------------------------------------------
  579.  * \fn     CodeSkip(Word Code)
  580.  * \brief  decode skip instructions
  581.  * \param  Code instruction code in 1st byte
  582.  * ------------------------------------------------------------------------ */
  583.  
  584. static void CodeSkipCore(Word Code, int ArgOffs)
  585. {
  586.   LongWord BitSpec;
  587.   tEvalResult DestEvalResult;
  588.   int HasDest;
  589.   Word Dest;
  590.  
  591.   /* For two operands, we do not know whether it's <addr>,<bit>
  592.      or <bitsym>,<dest>.  If the third op is from code segment, we
  593.      assume it's the second: */
  594.  
  595.   switch (ArgCnt - ArgOffs)
  596.   {
  597.     case 1:
  598.       HasDest = 0;
  599.       break;
  600.     case 3:
  601.       HasDest = 1;
  602.       Dest = EvalStrIntExpressionWithResult(&ArgStr[ArgOffs + 3], UInt8, &DestEvalResult);
  603.       if (!DestEvalResult.OK)
  604.         return;
  605.       break;
  606.     case 2:
  607.     {
  608.       Dest = EvalStrIntExpressionWithResult(&ArgStr[ArgOffs + 2], UInt8, &DestEvalResult);
  609.       if (!DestEvalResult.OK)
  610.         return;
  611.       HasDest = !!(DestEvalResult.AddrSpaceMask & (1 << SegCode));
  612.       break;
  613.     }
  614.     default:
  615.       (void)ChkArgCnt(1 + ArgOffs, 3 + ArgOffs);
  616.       return;
  617.   }
  618.  
  619.   if (DecodeBitArg(&BitSpec, 1 + ArgOffs, ArgCnt - HasDest))
  620.   {
  621.     Word Address;
  622.     Byte BitPos;
  623.  
  624.     DissectBitSymbol(BitSpec, &Address, &BitPos);
  625.  
  626.     if (HasDest)
  627.     {
  628.       if (!(DestEvalResult.Flags & (eSymbolFlag_FirstPassUnknown | eSymbolFlag_Questionable))
  629.        && (Dest != EProgCounter() + 4))
  630.       {
  631.         WrStrErrorPos(ErrNum_SkipTargetMismatch, &ArgStr[ArgCnt]);
  632.         return;
  633.       }
  634.     }
  635.     BAsmCode[CodeLen++] = Code | (BitPos << 3);
  636.     BAsmCode[CodeLen++] = Address;
  637.   }
  638. }
  639.  
  640. static void CodeSkip(Word Code)
  641. {
  642.   CodeSkipCore(Code, 0);
  643. }
  644.  
  645. static void CodeSkip2(Word Code)
  646. {
  647.   if (ChkArgCnt(2, 4))
  648.   {
  649.     Boolean OK;
  650.     Byte Value = EvalStrIntExpression(&ArgStr[1], UInt1, &OK);
  651.     if (OK)
  652.       CodeSkipCore(Code | (Value << 6), 1);
  653.   }
  654. }
  655.  
  656. /*!------------------------------------------------------------------------
  657.  * \fn     CodeReg(Word Code)
  658.  * \brief  decode shift/rotate instructions
  659.  * \param  Code instruction code in 1st byte
  660.  * ------------------------------------------------------------------------ */
  661.  
  662. static void CodeShiftCore(Word Code, int ArgOffs)
  663. {
  664.   Byte Reg;
  665.  
  666.   if (DecodeRegWithMemOpt(&ArgStr[ArgCnt], &Reg, 3))
  667.   {
  668.     Byte Count = 1;
  669.  
  670.     if (ArgCnt > ArgOffs)
  671.     {
  672.       tEvalResult EvalResult;
  673.  
  674.       Count = EvalStrIntExpressionWithResult(&ArgStr[ArgOffs], UInt3, &EvalResult);
  675.       if (!EvalResult.OK)
  676.         return;
  677.       if (mFirstPassUnknown(EvalResult.Flags))
  678.         Count = 1;
  679.       if ((Count < 1) || (Count > 4))
  680.       {
  681.         WrStrErrorPos(ErrNum_InvShiftArg, &ArgStr[ArgOffs]);
  682.         return;
  683.       }
  684.     }
  685.     BAsmCode[CodeLen++] = Code | (Reg << 5) | ((Count & 3) << 3);
  686.   }
  687. }
  688.  
  689. static void CodeShift(Word Code)
  690. {
  691.   if (ChkArgCnt(1, 2))
  692.     CodeShiftCore(Code, 1);
  693. }
  694.  
  695. static void CodeShift2(Word Code)
  696. {
  697.   if (ChkArgCnt(2, 3))
  698.   {
  699.     if (!as_strcasecmp(ArgStr[1].str.p_str, "LEFT"))
  700.       CodeShiftCore(Code | 0x80, 2);
  701.     else if (!as_strcasecmp(ArgStr[1].str.p_str, "RIGHT"))
  702.       CodeShiftCore(Code, 2);
  703.     else
  704.       WrStrErrorPos(ErrNum_InvShiftArg, &ArgStr[1]);
  705.   }
  706. }
  707.  
  708. /*!------------------------------------------------------------------------
  709.  * \fn     CodeBit(Word Code)
  710.  * \brief  decode bit instructions
  711.  * \param  Code instruction code in 1st byte
  712.  * ------------------------------------------------------------------------ */
  713.  
  714. static void CodeBitCore(Word Code, int BitArgStart)
  715. {
  716.   LongWord BitSpec;
  717.  
  718.   if (DecodeBitArg(&BitSpec, BitArgStart, ArgCnt))
  719.   {
  720.     Word Address;
  721.     Byte BitPos;
  722.  
  723.     DissectBitSymbol(BitSpec, &Address, &BitPos);
  724.     BAsmCode[CodeLen++] = Code | (BitPos << 3);
  725.     BAsmCode[CodeLen++] = Address;
  726.   }
  727. }
  728.  
  729. static void CodeBit(Word Code)
  730. {
  731.   if (ChkArgCnt(1, 2))
  732.     CodeBitCore(Code, 1);
  733. }
  734.  
  735. static void CodeBit2(Word Code)
  736. {
  737.   if (ChkArgCnt(2, 3))
  738.   {
  739.     Boolean OK;
  740.     Byte Value = EvalStrIntExpression(&ArgStr[1], UInt1, &OK);
  741.     if (OK)
  742.       CodeBitCore(Code | (Value << 6), 2);
  743.   }
  744. }
  745.  
  746. /*!------------------------------------------------------------------------
  747.  * \fn     CodeFixed(Word Code)
  748.  * \brief  decode instructions witohut argument
  749.  * \param  Code instruction code in 1st byte
  750.  * ------------------------------------------------------------------------ */
  751.  
  752. static void CodeFixed(Word Code)
  753. {
  754.   if (ChkArgCnt(0, 0))
  755.     BAsmCode[CodeLen++] = Code;
  756. }
  757.  
  758. /*!------------------------------------------------------------------------
  759.  * \fn     CodeBIT(Word Code)
  760.  * \brief  handle BIT instruction
  761.  * ------------------------------------------------------------------------ */
  762.  
  763. static void CodeBIT(Word Code)
  764. {
  765.   UNUSED(Code);
  766.  
  767.   /* if in structure definition, add special element to structure */
  768.  
  769.   if (ActPC == StructSeg)
  770.   {
  771.     Boolean OK;
  772.     Byte BitPos;
  773.     PStructElem pElement;
  774.  
  775.     if (!ChkArgCnt(2, 2))
  776.       return;
  777.     BitPos = EvalBitPosition(&ArgStr[1], &OK);
  778.     if (!OK)
  779.       return;
  780.     pElement = CreateStructElem(&LabPart);
  781.     if (!pElement)
  782.       return;
  783.     pElement->pRefElemName = as_strdup(ArgStr[2].str.p_str);
  784.     pElement->OpSize = eSymbolSize8Bit;
  785.     pElement->BitPos = BitPos;
  786.     pElement->ExpandFnc = ExpandBit_KENBAK;
  787.     AddStructElem(pInnermostNamedStruct->StructRec, pElement);
  788.   }
  789.   else
  790.   {
  791.     LongWord BitSpec;
  792.  
  793.     if (DecodeBitArg(&BitSpec, 1, ArgCnt))
  794.     {
  795.       *ListLine = '=';
  796.       DissectBit_KENBAK(ListLine + 1, STRINGSIZE - 3, BitSpec);
  797.       PushLocHandle(-1);
  798.       EnterIntSymbol(&LabPart, BitSpec, SegBData, False);
  799.       PopLocHandle();
  800.       /* TODO: MakeUseList? */
  801.     }
  802.   }
  803. }
  804.  
  805. /*---------------------------------------------------------------------------*/
  806.  
  807. /*!------------------------------------------------------------------------
  808.  * \fn     InitFields(void)
  809.  * \brief  fill instruction hash table
  810.  * ------------------------------------------------------------------------ */
  811.  
  812. static void InitFields(void)
  813. {
  814.   InstTable = CreateInstTable(51);
  815.  
  816.   AddInstTable(InstTable, "ADD"  , 0 << 3, CodeGen);
  817.   AddInstTable(InstTable, "SUB"  , 1 << 3, CodeGen);
  818.   AddInstTable(InstTable, "LOAD" , 2 << 3, CodeGen);
  819.   AddInstTable(InstTable, "STORE", 3 << 3, CodeGen);
  820.  
  821.   AddInstTable(InstTable, "AND"  , 0xd0, CodeGen);
  822.   AddInstTable(InstTable, "OR"   , 0xc0, CodeGen);
  823.   AddInstTable(InstTable, "LNEG" , 0xd8, CodeGen);
  824.  
  825.   AddInstTable(InstTable, "JPD"  , 0x20, CodeJump);
  826.   AddInstTable(InstTable, "JPI"  , 0x28, CodeJump);
  827.   AddInstTable(InstTable, "JMD"  , 0x30, CodeJump);
  828.   AddInstTable(InstTable, "JMI"  , 0x38, CodeJump);
  829.  
  830.   AddInstTable(InstTable, "JP"   , 0x20, CodeJumpGen);
  831.   AddInstTable(InstTable, "JM"   , 0x30, CodeJumpGen);
  832.  
  833.   AddInstTable(InstTable, "SKP0" , 0x82, CodeSkip);
  834.   AddInstTable(InstTable, "SKP1" , 0xc2, CodeSkip);
  835.   AddInstTable(InstTable, "SKP"  , 0x82, CodeSkip2);
  836.   AddInstTable(InstTable, "SKIP" , 0x82, CodeSkip2);
  837.  
  838.   AddInstTable(InstTable, "SET0" , 0x02, CodeBit);
  839.   AddInstTable(InstTable, "SET1" , 0x42, CodeBit);
  840.   AddInstTable(InstTable, "SET"  , 0x02, CodeBit2);
  841.  
  842.   AddInstTable(InstTable, "SFTL"  , 0x81, CodeShift);
  843.   AddInstTable(InstTable, "SFTR"  , 0x01, CodeShift);
  844.   AddInstTable(InstTable, "ROTL"  , 0xc1, CodeShift);
  845.   AddInstTable(InstTable, "ROTR"  , 0x41, CodeShift);
  846.   AddInstTable(InstTable, "SHIFT" , 0x01, CodeShift2);
  847.   AddInstTable(InstTable, "ROTATE", 0x41, CodeShift2);
  848.  
  849.   AddInstTable(InstTable, "CLEAR" , 0x00, CodeClear);
  850.  
  851.   AddInstTable(InstTable, "NOOP" , 0x80, CodeFixed);
  852.   AddInstTable(InstTable, "HALT" , 0x00, CodeFixed);
  853.  
  854.   AddInstTable(InstTable, "REG"  , 0   , CodeREG);
  855.   AddInstTable(InstTable, "BIT"  , 0   , CodeBIT);
  856. }
  857.  
  858. static void DeinitFields(void)
  859. {
  860.   DestroyInstTable(InstTable);
  861. }
  862.  
  863. /*---------------------------------------------------------------------------*/
  864.  
  865. static void MakeCode_KENBAK(void)
  866. {
  867.   CodeLen = 0; DontPrint = False;
  868.  
  869.   /* to be ignored */
  870.  
  871.   if (Memo("")) return;
  872.  
  873.   /* Pseudo Instructions */
  874.  
  875.   if (DecodeIntelPseudo(False)) return;
  876.  
  877.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  878.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  879. }
  880.  
  881. static void InternSymbol_KENBAK(char *pArg, TempResult *pResult)
  882. {
  883.   Byte RegNum;
  884.  
  885.   if (DecodeRegCore(pArg, &RegNum))
  886.   {
  887.     pResult->Typ = TempReg;
  888.     pResult->DataSize = eSymbolSize8Bit;
  889.     pResult->Contents.RegDescr.Reg = RegNum;
  890.     pResult->Contents.RegDescr.Dissect = DissectReg_KENBAK;
  891.     pResult->Contents.RegDescr.compare = NULL;
  892.   }
  893. }
  894.  
  895. static Boolean IsDef_KENBAK(void)
  896. {
  897.   return Memo("REG")
  898.       || Memo("BIT");
  899. }
  900.  
  901. static void SwitchFrom_KENBAK(void)
  902. {
  903.   DeinitFields();
  904. }
  905.  
  906. static Boolean TrueFnc(void)
  907. {
  908.   return True;
  909. }
  910.  
  911. /*!------------------------------------------------------------------------
  912.  * \fn     SwitchTo_KENBAK(void)
  913.  * \brief  initialize for KENBAK as target
  914.  * ------------------------------------------------------------------------ */
  915.  
  916. static void SwitchTo_KENBAK(void)
  917. {
  918.   const TFamilyDescr *Descr;
  919.  
  920.   TurnWords = False;
  921.   SetIntConstMode(eIntConstModeIntel);
  922.  
  923.   Descr = FindFamilyByName("KENBAK");
  924.   PCSymbol = "$";
  925.   HeaderID = Descr->Id;
  926.   NOPCode = 0x80;
  927.   DivideChars = ",";
  928.   HasAttrs = False;
  929.   SetIsOccupiedFnc = TrueFnc;
  930.   ShiftIsOccupied = True;
  931.  
  932.   ValidSegs = (1 << SegCode);
  933.   Grans[SegCode] = 1;
  934.   ListGrans[SegCode] = 1;
  935.   SegLimits[SegCode] = 0xff;
  936.   SegInits[SegCode] = 0;
  937.  
  938.   MakeCode = MakeCode_KENBAK;
  939.   IsDef = IsDef_KENBAK;
  940.   DissectReg = DissectReg_KENBAK;
  941.   DissectBit = DissectBit_KENBAK;
  942.   SwitchFrom = SwitchFrom_KENBAK;
  943.   InternSymbol = InternSymbol_KENBAK;
  944.   InitFields();
  945. }
  946.  
  947. void codekenbak_init(void)
  948. {
  949.   (void)AddCPU("KENBAK", SwitchTo_KENBAK);
  950. }
  951.