Subversion Repositories pentevo

Rev

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

  1. /* code8008.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Codegenerator Intel 8008                                                  */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <ctype.h>
  13. #include <string.h>
  14.  
  15. #include "bpemu.h"
  16. #include "strutil.h"
  17. #include "asmdef.h"
  18. #include "asmsub.h"
  19. #include "asmpars.h"
  20. #include "asmitree.h"
  21. #include "headids.h"
  22. #include "codevars.h"
  23. #include "codepseudo.h"
  24. #include "intpseudo.h"
  25. #include "errmsg.h"
  26.  
  27. #include "code8008.h"
  28.  
  29. /*---------------------------------------------------------------------------*/
  30. /* Types */
  31.  
  32. typedef enum
  33. {
  34.   eModNone = 0,
  35.   eModReg8 = 1,
  36.   eModIHL = 2,
  37.   eModImm = 3,
  38.   eModReg16 = 4
  39. } tAdrMode;
  40.  
  41. #define AccReg 0
  42.  
  43. #define MModReg8 (1 << eModReg8)
  44. #define MModReg16 (1 << eModReg16)
  45. #define MModImm (1 << eModImm)
  46. #define MModIHL (1 << eModIHL)
  47. #define MModReg16 (1 << eModReg16)
  48.  
  49. typedef struct
  50. {
  51.   tAdrMode Mode;
  52.   Byte Val;
  53. } tAdrVals;
  54.  
  55. /*---------------------------------------------------------------------------*/
  56. /* Variablen */
  57.  
  58. static CPUVar CPU8008, CPU8008New;
  59.  
  60. static const char RegNames[] = "ABCDEHLM";
  61.  
  62. /*---------------------------------------------------------------------------*/
  63. /* Parser */
  64.  
  65. static Boolean DecodeReg(char *Asc, tZ80Syntax Syntax, Byte *pErg)
  66. {
  67.   const char *p;
  68.  
  69.   if (strlen(Asc) != 1)
  70.     return False;
  71.  
  72.   p = strchr(RegNames, as_toupper(*Asc));
  73.   if (!p)
  74.     return False;
  75.  
  76.   *pErg = p - RegNames;
  77.   if ((!(Syntax & eSyntax808x)) && (*pErg == 7))
  78.     return False;
  79.   return True;
  80. }
  81.  
  82. static Boolean DecodeReg16(char *Asc, Byte *pErg)
  83. {
  84.   if (strlen(Asc) != 2)
  85.     return False;
  86.  
  87.   for (*pErg = 1; *pErg < 7; *pErg += 2)
  88.     if ((as_toupper(Asc[0]) == RegNames[*pErg])
  89.      && (as_toupper(Asc[1]) == RegNames[*pErg + 1]))
  90.     {
  91.       *pErg /= 2;
  92.       return True;
  93.     }
  94.  
  95.   return False;
  96. }
  97.  
  98. /*!------------------------------------------------------------------------
  99.  * \fn     DecodeCondition_Z80(const char *pAsc, Byte *pResult)
  100.  * \brief  decode Z80-style conditions for JP CALL RET
  101.  * \param  pAsc source argument
  102.  * \param  dest buffer
  103.  * \return True if success
  104.  * ------------------------------------------------------------------------ */
  105.  
  106. static const char Conditions[][4] =
  107. {
  108.   "NC", "NZ", "P", "PO", "C", "Z", "M", "PE"
  109. };
  110.  
  111. static Boolean DecodeCondition_Z80(const char *pAsc, Byte *pResult)
  112. {
  113.   for (*pResult = 0; *pResult < sizeof(Conditions) / sizeof(*Conditions); (*pResult)++)
  114.     if (!as_strcasecmp(pAsc, Conditions[*pResult]))
  115.     {
  116.       *pResult = *pResult << 3;
  117.       return True;
  118.     }
  119.   return False;
  120. }
  121.  
  122. /*!------------------------------------------------------------------------
  123.  * \fn     DecodeAdr_Z80(const tStrComp *pArg, Word Mask, tAdrVals *pVals)
  124.  * \brief  decode address expression in Z80 style syntax
  125.  * \param  pArg source argument
  126.  * \param  Mask bit mask of allowed addressig modes
  127.  * \param  pVals dest buffer
  128.  * \return resulting addressing mode
  129.  * ------------------------------------------------------------------------ */
  130.  
  131. static void ResetAdrVals(tAdrVals *pVals)
  132. {
  133.   pVals->Mode = eModNone;
  134.   pVals->Val = 0;
  135. }
  136.  
  137. static tAdrMode DecodeAdr_Z80(const tStrComp *pArg, Word Mask, tAdrVals *pVals)
  138. {
  139.   Boolean OK;
  140.  
  141.   ResetAdrVals(pVals);
  142.  
  143.   if (DecodeReg(pArg->str.p_str, eSyntaxZ80, &pVals->Val))
  144.   {
  145.     pVals->Mode = eModReg8;
  146.     goto AdrFound;
  147.   }
  148.  
  149.   if (DecodeReg16(pArg->str.p_str, &pVals->Val))
  150.   {
  151.     pVals->Mode = eModReg16;
  152.     goto AdrFound;
  153.   }
  154.  
  155.   if (!as_strcasecmp(pArg->str.p_str, "(HL)"))
  156.   {
  157.     pVals->Mode = eModIHL;
  158.     goto AdrFound;
  159.   }
  160.  
  161.   pVals->Val = EvalStrIntExpression(pArg, Int8, &OK);
  162.   if (OK)
  163.     pVals->Mode = eModImm;
  164.  
  165. AdrFound:
  166.  
  167.   if ((pVals->Mode != eModNone) && (!(Mask & (1 << pVals->Mode))))
  168.   {
  169.     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
  170.     ResetAdrVals(pVals);
  171.   }
  172.   return pVals->Mode;
  173. }
  174.  
  175. /*!------------------------------------------------------------------------
  176.  * \fn     CheckAcc_Z80(const tStrComp *pArg)
  177.  * \brief  check whether (optional first) argument is accumulator
  178.  * \param  pArg source argument
  179.  * \return True if it is
  180.  * ------------------------------------------------------------------------ */
  181.  
  182. static Boolean CheckAcc_Z80(const tStrComp *pArg)
  183. {
  184.   tAdrVals AdrVals;
  185.  
  186.   switch (DecodeAdr_Z80(pArg, MModReg8, &AdrVals))
  187.   {
  188.     case eModReg8:
  189.       if (AdrVals.Val != AccReg)
  190.       {
  191.         WrStrErrorPos(ErrNum_InvReg, pArg);
  192.         return False;
  193.       }
  194.       break;
  195.     default:
  196.       return False;
  197.   }
  198.   return True;
  199. }
  200.  
  201. /*---------------------------------------------------------------------------*/
  202. /* Instruction Decoders */
  203.  
  204. /*!------------------------------------------------------------------------
  205.  * \fn     DecodeFixed(Word Code)
  206.  * \brief  handle instructions without argument
  207.  * \param  Word instruction code & syntax flag
  208.  * ------------------------------------------------------------------------ */
  209.  
  210. static void DecodeFixed(Word Code)
  211. {
  212.   if (ChkArgCnt(0, 0)
  213.    && ChkZ80Syntax((tZ80Syntax)Hi(Code)))
  214.   {
  215.     BAsmCode[0] = Lo(Code);
  216.     CodeLen = 1;
  217.   }
  218. }
  219.  
  220. /*!------------------------------------------------------------------------
  221.  * \fn     DecodeFixed(Word Code)
  222.  * \brief  handle instructions with one (8 bit) immediate argument
  223.  * \param  Index machine code
  224.  * ------------------------------------------------------------------------ */
  225.  
  226. static void DecodeImm(Word Code)
  227. {
  228.   if (ChkArgCnt(1, 1)
  229.    && ChkZ80Syntax((tZ80Syntax)Hi(Code)))
  230.   {
  231.     Boolean OK;
  232.  
  233.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
  234.     if (OK)
  235.     {
  236.       BAsmCode[0] = Lo(Code);
  237.       CodeLen = 2;
  238.     }
  239.   }
  240. }
  241.  
  242. /*!------------------------------------------------------------------------
  243.  * \fn     DecodeJmp(Word Index)
  244.  * \brief  decode jump/call instructions taking one address argument
  245.  * \param  Index machine code
  246.  * ------------------------------------------------------------------------ */
  247.  
  248. static void DecodeJmpCore(Byte Code)
  249. {
  250.   tEvalResult EvalResult;
  251.   Word AdrWord;
  252.  
  253.   AdrWord = EvalStrIntExpressionWithResult(&ArgStr[ArgCnt], UInt14, &EvalResult);
  254.   if (EvalResult.OK)
  255.   {
  256.     BAsmCode[0] = Code;
  257.     BAsmCode[1] = Lo(AdrWord);
  258.     BAsmCode[2] = Hi(AdrWord) & 0x3f;
  259.     CodeLen = 3;
  260.     ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  261.   }
  262. }
  263.  
  264. static void DecodeJmp(Word Index)
  265. {
  266.   if (ChkArgCnt(1, 1)
  267.    && ChkZ80Syntax(eSyntax808x))
  268.     DecodeJmpCore(Lo(Index));
  269. }
  270.  
  271. /*!------------------------------------------------------------------------
  272.  * \fn     DecodeJP(Word Code)
  273.  * \brief  decode JP instruction
  274.  * ------------------------------------------------------------------------ */
  275.  
  276. static void DecodeJP(Word Code)
  277. {
  278.   UNUSED(Code);
  279.  
  280.   /* one argument, new 8008 insn set & not exclusively Z80: -> jump on positive or parity even */
  281.  
  282.   if ((CurrZ80Syntax != eSyntaxZ80) && (ArgCnt == 1))
  283.   {
  284.     DecodeJmp((MomCPU == CPU8008New) ? 0x50 : 0x78);
  285.     return;
  286.   }
  287.  
  288.   /* for all other stuff, Z80 syntax must be enabled */
  289.  
  290.   if (!ChkArgCnt(1, 2)
  291.    || !ChkZ80Syntax(eSyntaxZ80))
  292.     return;
  293.  
  294.   if (ArgCnt == 2)
  295.   {
  296.     Byte Cond;
  297.  
  298.     if (DecodeCondition_Z80(ArgStr[1].str.p_str, &Cond))
  299.       DecodeJmpCore(0x40 | Cond);
  300.   }
  301.   else
  302.     DecodeJmpCore(0x44);
  303. }
  304.  
  305. /*!------------------------------------------------------------------------
  306.  * \fn     DecodeCALL(Word Code)
  307.  * \brief  decode CALL instruction
  308.  * ------------------------------------------------------------------------ */
  309.  
  310. static void DecodeCALL(Word Code)
  311. {
  312.   UNUSED(Code);
  313.  
  314.   /* single-arg CALL is only NOT allowed on old 8008 in pure  808x mode : */
  315.  
  316.   if ((CurrZ80Syntax != eSyntaxZ80) && (ArgCnt == 1) && (MomCPU == CPU8008New))
  317.   {
  318.     DecodeJmp(0x46);
  319.     return;
  320.   }
  321.  
  322.   if (!ChkArgCnt(1, 2)
  323.    || !ChkZ80Syntax(eSyntaxZ80))
  324.     return;
  325.  
  326.   if (ArgCnt == 2)
  327.   {
  328.     Byte Cond;
  329.  
  330.     if (DecodeCondition_Z80(ArgStr[1].str.p_str, &Cond))
  331.       DecodeJmpCore(0x42 | Cond);
  332.   }
  333.   else
  334.     DecodeJmpCore(0x46);
  335. }
  336.  
  337. /*!------------------------------------------------------------------------
  338.  * \fn     DecodeRET(Word Code)
  339.  * \brief  handle RET instruction
  340.  * ------------------------------------------------------------------------ */
  341.  
  342. static void DecodeRET(Word Code)
  343. {
  344.   UNUSED(Code);
  345.  
  346.   if (ChkArgCnt(0, (CurrZ80Syntax != eSyntax808x) ? 1 : 0))
  347.   {
  348.     if (1 == ArgCnt)
  349.     {
  350.       Byte Cond;
  351.  
  352.       if (DecodeCondition_Z80(ArgStr[1].str.p_str, &Cond))
  353.         BAsmCode[CodeLen++] = 0x03 | Cond;
  354.     }
  355.     else
  356.       BAsmCode[CodeLen++] = 0x07;
  357.   }
  358. }
  359.  
  360. /*!------------------------------------------------------------------------
  361.  * \fn     DecodeRST(Word Index)
  362.  * \brief  handle RST instruction
  363.  * ------------------------------------------------------------------------ */
  364.  
  365. static void DecodeRST(Word Index)
  366. {
  367.   UNUSED(Index);
  368.  
  369.   if (ChkArgCnt(1, 1))
  370.   {
  371.     Word AdrWord;
  372.     tEvalResult EvalResult;
  373.  
  374.     AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt14, &EvalResult);
  375.     if (mFirstPassUnknown(EvalResult.Flags)) AdrWord &= 0x38;
  376.     if (EvalResult.OK)
  377.     {
  378.       if (ChkRange(AdrWord, 0, 0x38))
  379.       {
  380.         if (AdrWord < 8)
  381.         {
  382.           BAsmCode[0] = 0x05 | (AdrWord << 3);
  383.           CodeLen = 1;
  384.           ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  385.         }
  386.         else if ((AdrWord & 7) != 0) WrError(ErrNum_NotAligned);
  387.         else
  388.         {
  389.           BAsmCode[0] = AdrWord + 0x05;
  390.           CodeLen = 1;
  391.           ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  392.         }
  393.       }
  394.     }
  395.   }
  396. }
  397.  
  398. /*!------------------------------------------------------------------------
  399.  * \fn     DecodeINP_OUT(Word Index)
  400.  * \brief  Handle IN(P)/OUT Instructions
  401.  * \param  IsIN True if IN
  402.  * ------------------------------------------------------------------------ */
  403.  
  404. static void DecodeINP_OUT(Word IsIN)
  405. {
  406.   tEvalResult EvalResult;
  407.   Byte Addr, AddrArgIdx;
  408.  
  409.   if (Memo("INP") && !ChkZ80Syntax(eSyntax808x))
  410.     return;
  411.   if (Memo("IN") && (MomCPU == CPU8008) && !ChkZ80Syntax(eSyntaxZ80))
  412.     return;
  413.  
  414.   if (!ChkArgCnt((CurrZ80Syntax & eSyntax808x) ? 1 : 2, (CurrZ80Syntax & eSyntaxZ80) ? 2 : 1))
  415.     return;
  416.  
  417.   if ((ArgCnt == 2) /* Z80-style with A */
  418.    && !CheckAcc_Z80(&ArgStr[IsIN ? 1 : 2]))
  419.     return;
  420.  
  421.   AddrArgIdx = ((ArgCnt == 2) && IsIN) ? 2 : 1;
  422.   if (IsIN)
  423.     Addr = EvalStrIntExpressionWithResult(&ArgStr[AddrArgIdx], UInt3, &EvalResult);
  424.   else
  425.   {
  426.     Addr = EvalStrIntExpressionWithResult(&ArgStr[AddrArgIdx], UInt5, &EvalResult);
  427.     if (mFirstPassUnknown(EvalResult.Flags))
  428.       Addr |= 0x08;
  429.     if ((EvalResult.OK) && (Addr < 8))
  430.     {
  431.       WrStrErrorPos(ErrNum_UnderRange, &ArgStr[AddrArgIdx]);
  432.       EvalResult.OK = False;
  433.     }
  434.   }
  435.  
  436.   if (EvalResult.OK)
  437.   {
  438.     BAsmCode[0] = 0x41 | (Addr << 1);
  439.     CodeLen = 1;
  440.     ChkSpace(SegIO, EvalResult.AddrSpaceMask);
  441.   }
  442. }
  443.  
  444. /*!------------------------------------------------------------------------
  445.  * \fn     DecodeMOV(Word Index)
  446.  * \brief  handle MOV instruction
  447.  * ------------------------------------------------------------------------ */
  448.  
  449. static void DecodeMOV(Word Index)
  450. {
  451.   Byte SReg, DReg;
  452.  
  453.   UNUSED(Index);
  454.  
  455.   if (!ChkArgCnt(2, 2));
  456.   else if (!ChkZ80Syntax(eSyntax808x));
  457.   else if (!DecodeReg(ArgStr[1].str.p_str, eSyntax808x, &DReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  458.   else if (!DecodeReg(ArgStr[2].str.p_str, eSyntax808x, &SReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
  459.   else if ((DReg == 7) && (SReg == 7)) WrError(ErrNum_InvRegPair); /* MOV M,M not allowed - asame opcode as HLT */
  460.   else
  461.   {
  462.     BAsmCode[0] = 0xc0 | (DReg << 3) | SReg;
  463.     CodeLen = 1;
  464.   }
  465. }
  466.  
  467. /*!------------------------------------------------------------------------
  468.  * \fn     DecodeMVI(Word Index)
  469.  * \brief  handle MVI instruction
  470.  * ------------------------------------------------------------------------ */
  471.  
  472. static void DecodeMVI(Word Index)
  473. {
  474.   Byte DReg;
  475.  
  476.   UNUSED(Index);
  477.  
  478.   if (!ChkArgCnt(2, 2));
  479.   else if (!ChkZ80Syntax(eSyntax808x));
  480.   else if (!DecodeReg(ArgStr[1].str.p_str, eSyntax808x, &DReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  481.   else
  482.   {
  483.     Boolean OK;
  484.  
  485.     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
  486.     if (OK)
  487.     {
  488.       BAsmCode[0] = 0x06 | (DReg << 3);
  489.       CodeLen = 2;
  490.     }
  491.   }
  492. }
  493.  
  494. /*!------------------------------------------------------------------------
  495.  * \fn     DecodeLXI(Word Index)
  496.  * \brief  handle (pseudo) LXI instruction
  497.  * ------------------------------------------------------------------------ */
  498.  
  499. static void BuildLXI(Byte DReg, Word Val)
  500. {
  501.   BAsmCode[2] = 0x06 | ((DReg + 1) << 3);
  502.   BAsmCode[3] = Lo(Val);
  503.   BAsmCode[0] = 0x06 | (DReg << 3);
  504.   BAsmCode[1] = Hi(Val);
  505.   CodeLen = 4;
  506. }
  507.  
  508. static void DecodeLXI(Word Index)
  509. {
  510.   Byte DReg;
  511.  
  512.   UNUSED(Index);
  513.  
  514.   if (!ChkArgCnt(2, 2));
  515.   else if (!ChkZ80Syntax(eSyntax808x));
  516.   else if (!DecodeReg(ArgStr[1].str.p_str, eSyntax808x, &DReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  517.   else if ((DReg != 1) && (DReg != 3) && (DReg != 5)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  518.   else
  519.   {
  520.     Boolean OK;
  521.     Word Val;
  522.  
  523.     Val = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
  524.     if (OK)
  525.       BuildLXI(DReg, Val);
  526.   }
  527. }
  528.  
  529. /*!------------------------------------------------------------------------
  530.  * \fn     DecodeLD(Word Index)
  531.  * \brief  handle LD instruction
  532.  * ------------------------------------------------------------------------ */
  533.  
  534. static void DecodeLD(Word Index)
  535. {
  536.   UNUSED(Index);
  537.   if (ChkArgCnt(2, 2)
  538.    && ChkZ80Syntax(eSyntaxZ80))
  539.   {
  540.     tAdrVals DestAdrVals, SrcAdrVals;
  541.  
  542.     switch (DecodeAdr_Z80(&ArgStr[1], MModReg8 | MModReg16 | MModIHL, &DestAdrVals))
  543.     {
  544.       case eModReg8:
  545.         switch (DecodeAdr_Z80(&ArgStr[2], MModReg8 | MModReg16 | MModIHL | MModImm, &SrcAdrVals))
  546.         {
  547.           case eModReg8:
  548.             BAsmCode[CodeLen++] = 0xc0 | (DestAdrVals.Val << 3) | SrcAdrVals.Val;
  549.             break;
  550.           case eModIHL:
  551.             BAsmCode[CodeLen++] = 0xc7 | (DestAdrVals.Val << 3);
  552.             break;
  553.           case eModImm:
  554.             BAsmCode[CodeLen++] = 0x06 | (DestAdrVals.Val << 3);
  555.             BAsmCode[CodeLen++] = SrcAdrVals.Val;
  556.             break;
  557.           default:
  558.             break;
  559.         }
  560.         break;
  561.       case eModReg16:
  562.       {
  563.         Boolean OK;
  564.         Word Arg = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
  565.  
  566.         if (OK)
  567.           BuildLXI((DestAdrVals.Val << 1) + 1, Arg);
  568.         break;
  569.       }
  570.       case eModIHL:
  571.         switch (DecodeAdr_Z80(&ArgStr[2], MModReg8 | MModImm, &SrcAdrVals))
  572.         {
  573.           case eModReg8:
  574.             BAsmCode[CodeLen++] = 0xf8 | SrcAdrVals.Val;
  575.             break;
  576.           case eModImm:
  577.             BAsmCode[CodeLen++] = 0x3e;
  578.             BAsmCode[CodeLen++] = SrcAdrVals.Val;
  579.             break;
  580.           default:
  581.             break;
  582.         }
  583.         break;
  584.       default:
  585.         break;
  586.     }
  587.   }
  588. }
  589.  
  590. /*!------------------------------------------------------------------------
  591.  * \fn     DecodeADD(Word Code)
  592.  * \brief  handle ADD instruction
  593.  * \param  Code machine code
  594.  * ------------------------------------------------------------------------ */
  595.  
  596. static void DecodeADD(Word Code)
  597. {
  598.   int MinArgCnt = (CurrZ80Syntax & eSyntax808x) ? ((MomCPU == CPU8008New) ? 1 : 0) : 2,
  599.       MaxArgCnt = (CurrZ80Syntax & eSyntaxZ80) ? 2 : ((MomCPU == CPU8008New) ? 1 : 0);
  600.  
  601.   if (!ChkArgCnt(MinArgCnt, MaxArgCnt))
  602.     return;
  603.  
  604.   switch (ArgCnt)
  605.   {
  606.     case 0: /* 8008 old style - src is implicit D, dst is implicitly ACC */
  607.       BAsmCode[CodeLen++] = Code | 0x03;
  608.       break;
  609.     case 1: /* 8008 (new) style - 8 bit register src only, dst is implicitly ACC */
  610.       if (MomCPU == CPU8008) (void)ChkArgCnt(0, 0);
  611.       else
  612.       {
  613.         Byte Reg;
  614.  
  615.         if (!DecodeReg(ArgStr[1].str.p_str, eSyntax808x, &Reg)) WrStrErrorPos(ErrNum_InvRegName, &ArgStr[1]);
  616.           else
  617.         BAsmCode[CodeLen++] = Code | Reg;
  618.       }
  619.       break;
  620.     case 2: /* Z80 style - dst must be A and is first arg */
  621.     {
  622.       tAdrVals SrcAdrVals;
  623.  
  624.       if (!CheckAcc_Z80(&ArgStr[1]))
  625.         return;
  626.       switch (DecodeAdr_Z80(&ArgStr[2], MModReg8 | MModIHL | MModImm, &SrcAdrVals))
  627.       {
  628.         case eModReg8:
  629.           BAsmCode[CodeLen++] = Code | SrcAdrVals.Val;
  630.           break;
  631.         case eModIHL:
  632.           BAsmCode[CodeLen++] = Code | 0x07;
  633.           break;
  634.         case eModImm:
  635.           BAsmCode[CodeLen++] = 0x04;
  636.           BAsmCode[CodeLen++] = SrcAdrVals.Val;
  637.           break;
  638.         default:
  639.           break;
  640.       }
  641.     }
  642.   }
  643. }
  644.  
  645. /*!------------------------------------------------------------------------
  646.  * \fn     DecodeADC(Word Code)
  647.  * \brief  handle ADC instruction
  648.  * \param  Code machine code
  649.  * ------------------------------------------------------------------------ */
  650.  
  651. static void DecodeADC(Word Code)
  652. {
  653.   int MinArgCnt = (CurrZ80Syntax & eSyntax808x) ? ((MomCPU == CPU8008New) ? 1 : 0) : 2,
  654.       MaxArgCnt = (CurrZ80Syntax & eSyntaxZ80) ? 2 : ((MomCPU == CPU8008New) ? 1 : 0);
  655.  
  656.   if (!ChkArgCnt(MinArgCnt, MaxArgCnt))
  657.     return;
  658.  
  659.   switch (ArgCnt)
  660.   {
  661.     case 0: /* 8008 add(!) old style - src is implicit C, dst is implicitly ACC */
  662.       BAsmCode[CodeLen++] = 0x82;
  663.       break;
  664.     case 1: /* 8008 (new) style - 8 bit register src only, dst is implicitly ACC */
  665.     {
  666.       Byte Reg;
  667.  
  668.       if (!DecodeReg(ArgStr[1].str.p_str, eSyntax808x, &Reg)) WrStrErrorPos(ErrNum_InvRegName, &ArgStr[1]);
  669.         else
  670.       BAsmCode[CodeLen++] = Code | Reg;
  671.       break;
  672.     }
  673.     case 2: /* Z80 style - dst must be A and is first arg */
  674.     {
  675.       tAdrVals SrcAdrVals;
  676.  
  677.       if (!CheckAcc_Z80(&ArgStr[1]))
  678.         return;
  679.       switch (DecodeAdr_Z80(&ArgStr[2], MModReg8 | MModIHL | MModImm, &SrcAdrVals))
  680.       {
  681.         case eModReg8:
  682.           BAsmCode[CodeLen++] = Code | SrcAdrVals.Val;
  683.           break;
  684.         case eModIHL:
  685.           BAsmCode[CodeLen++] = Code | 0x07;
  686.           break;
  687.         case eModImm:
  688.           BAsmCode[CodeLen++] = 0x0c;
  689.           BAsmCode[CodeLen++] = SrcAdrVals.Val;
  690.           break;
  691.         default:
  692.           break;
  693.       }
  694.       break;
  695.     }
  696.   }
  697. }
  698.  
  699. /*!------------------------------------------------------------------------
  700.  * \fn     DecodeSUB(Word Code)
  701.  * \brief  handle SUB instruction
  702.  * \param  Code machine code
  703.  * ------------------------------------------------------------------------ */
  704.  
  705. static void DecodeSUB(Word Code)
  706. {
  707.   Byte Reg;
  708.   int MinArgCnt, MaxArgCnt;
  709.   tAdrVals SrcAdrVals;
  710.  
  711.   if (CurrZ80Syntax & eSyntaxZ80)
  712.     MaxArgCnt = 2;
  713.   else
  714.     MaxArgCnt = (MomCPU == CPU8008New) ? 1 : 0;
  715.  
  716.   /* dest operand is always A and also optional for Z80 mode, so min arg cnt is
  717.      also 1 for pure Z80 mode: */
  718.  
  719.   if ((CurrZ80Syntax & eSyntax808x) && (MomCPU == CPU8008))
  720.     MinArgCnt = 0;
  721.   else
  722.     MinArgCnt = 1;
  723.   if (!ChkArgCnt(MinArgCnt, MaxArgCnt))
  724.     return;
  725.  
  726.   /* For Z80, optionally allow A as dest */
  727.  
  728.   if ((ArgCnt == 2) && !CheckAcc_Z80(&ArgStr[1]))
  729.     return;
  730.  
  731.   /* no arg (SUB -> B register) */
  732.  
  733.   if (!ArgCnt)
  734.   {
  735.     BAsmCode[CodeLen++] = Code | 0x01;
  736.     return;
  737.   }
  738.  
  739.   /* 8 bit register as source
  740.      808x style incl. M, Z80 style excl. (HL) */
  741.  
  742.   if (DecodeReg(ArgStr[ArgCnt].str.p_str, CurrZ80Syntax, &Reg)) /* 808x style incl. M, Z80 style excl. (HL) */
  743.   {
  744.     BAsmCode[CodeLen++] = Code | Reg;
  745.     return;
  746.   }
  747.  
  748.   /* rest is Z80 style ( (HL) or immediate) */
  749.  
  750.   if (!(CurrZ80Syntax & eSyntaxZ80))
  751.   {
  752.     WrError(ErrNum_InvAddrMode);
  753.     return;
  754.   }
  755.  
  756.   switch (DecodeAdr_Z80(&ArgStr[ArgCnt], MModImm | MModIHL, &SrcAdrVals))
  757.   {
  758.     case eModIHL:
  759.       BAsmCode[CodeLen++] = Code | 0x07;
  760.       break;
  761.     case eModImm:
  762.       BAsmCode[CodeLen++] = 0x14;
  763.       BAsmCode[CodeLen++] = SrcAdrVals.Val;
  764.       break;
  765.     default:
  766.       break;
  767.   }
  768. }
  769.  
  770. /*!------------------------------------------------------------------------
  771.  * \fn     DecodeSBC(Word Code)
  772.  * \brief  handle SBC instruction
  773.  * \param  Code machine code
  774.  * ------------------------------------------------------------------------ */
  775.  
  776. static void DecodeSBC(Word Code)
  777. {
  778.   tAdrVals SrcAdrVals;
  779.  
  780.   /* special case of 8008 SBC: */
  781.  
  782.   if ((CurrZ80Syntax & eSyntax808x) && (ArgCnt == 0) && (MomCPU == CPU8008))
  783.   {
  784.     BAsmCode[CodeLen++] = Code | 0x02;
  785.     return;
  786.   }
  787.  
  788.   /* everything else is Z80-specific: */
  789.  
  790.   if (!ChkArgCnt(1, 2) || !ChkZ80Syntax(eSyntaxZ80))
  791.     return;
  792.  
  793.   /* dest operand is always A and also optional, since 8008 can only SUB from A: */
  794.  
  795.   if ((ArgCnt == 2) && !CheckAcc_Z80(&ArgStr[1]))
  796.     return;
  797.  
  798.   switch (DecodeAdr_Z80(&ArgStr[ArgCnt], MModImm | MModReg8 | MModIHL, &SrcAdrVals))
  799.   {
  800.     case eModReg8:
  801.       BAsmCode[CodeLen++] = Code | SrcAdrVals.Val;
  802.       break;
  803.     case eModIHL:
  804.       BAsmCode[CodeLen++] = Code | 0x07;
  805.       break;
  806.     case eModImm:
  807.       BAsmCode[CodeLen++] = 0x1c;
  808.       BAsmCode[CodeLen++] = SrcAdrVals.Val;
  809.       break;
  810.     default:
  811.       break;
  812.   }
  813. }
  814.  
  815. /*!------------------------------------------------------------------------
  816.  * \fn     DecodeALU8_Z80(Word Code)
  817.  * \brief  arithmetic instructions only available in Z80 style
  818.  * \param  Code machine code
  819.  * ------------------------------------------------------------------------ */
  820.  
  821. static void DecodeALU8_Z80(Word Code)
  822. {
  823.   tAdrVals SrcAdrVals;
  824.  
  825.   if (!ChkZ80Syntax(eSyntaxZ80)
  826.    || !ChkArgCnt(1, 2))
  827.     return;
  828.  
  829.   if ((ArgCnt == 2) /* A as dest */
  830.    && !CheckAcc_Z80(&ArgStr[1]))
  831.     return;
  832.  
  833.   switch (DecodeAdr_Z80(&ArgStr[ArgCnt], MModImm | MModIHL | MModReg8, &SrcAdrVals))
  834.   {
  835.     case eModReg8:
  836.       BAsmCode[CodeLen++] = Lo(Code) | SrcAdrVals.Val;
  837.       break;
  838.     case eModIHL:
  839.       BAsmCode[CodeLen++] = Lo(Code) | 0x07;
  840.       break;
  841.     case eModImm:
  842.       BAsmCode[CodeLen++] = Hi(Code);
  843.       BAsmCode[CodeLen++] = SrcAdrVals.Val;
  844.       break;
  845.     default:
  846.       break;
  847.   }
  848. }
  849.  
  850. /*!------------------------------------------------------------------------
  851.  * \fn     DecodeCP(Word Code)
  852.  * \brief  handle CP instruction
  853.  * ------------------------------------------------------------------------ */
  854.  
  855. static void DecodeCP(Word Code)
  856. {
  857.   tAdrVals SrcAdrVals;
  858.   Boolean IsCall;
  859.  
  860.   UNUSED(Code);
  861.  
  862.   if (!ChkArgCnt(1, (CurrZ80Syntax & eSyntaxZ80) ? 2 : 1))
  863.     return;
  864.  
  865.   /* 2 arguments -> check for A as dest, and compare is meant
  866.      (syntax is either Z80 or Z80+808x implicitly due to previous check) */
  867.  
  868.   if (ArgCnt == 2) /* A as dest */
  869.   {
  870.     if (!CheckAcc_Z80(&ArgStr[1]))
  871.       return;
  872.     IsCall = False;
  873.   }
  874.  
  875.   /* 1 argument -> must be compare anyway in pure Z80 syntax mode, otherwise assume 808x call-on-positive */
  876.  
  877.   else
  878.     IsCall = CurrZ80Syntax != eSyntaxZ80;
  879.  
  880.   if (IsCall)
  881.   {
  882.     DecodeJmpCore((MomCPU == CPU8008New) ? 0x52 : 0x7a);
  883.     return;
  884.   }
  885.  
  886.   switch (DecodeAdr_Z80(&ArgStr[ArgCnt], MModImm | MModIHL | MModReg8, &SrcAdrVals))
  887.   {
  888.     case eModReg8:
  889.       BAsmCode[CodeLen++] = 0xb8 | SrcAdrVals.Val;
  890.       break;
  891.     case eModIHL:
  892.       BAsmCode[CodeLen++] = 0xbf;
  893.       break;
  894.     case eModImm:
  895.       BAsmCode[CodeLen++] = 0x3c;
  896.       BAsmCode[CodeLen++] = SrcAdrVals.Val;
  897.       break;
  898.     default:
  899.       break;
  900.   }
  901. }
  902.  
  903. /*!------------------------------------------------------------------------
  904.  * \fn     DecodeINCDEC(Word Code)
  905.  * \brief  handle (Z80 style) INC/DEC
  906.  * \param  Code machine code
  907.  * ------------------------------------------------------------------------ */
  908.  
  909. static void DecodeINCDEC(Word Code)
  910. {
  911.   /* INC aka INC C on old 8008: */
  912.  
  913.   if ((MomCPU == CPU8008) && (CurrZ80Syntax & eSyntax808x) && (!ArgCnt) && !Code)
  914.   {
  915.     BAsmCode[CodeLen++] = Code | (0x02 << 3);
  916.     return;
  917.   }
  918.  
  919.   if (ChkZ80Syntax(eSyntaxZ80)
  920.    && ChkArgCnt(1, 1))
  921.   {
  922.     tAdrVals AdrVals;
  923.  
  924.     switch (DecodeAdr_Z80(&ArgStr[1], MModReg8, &AdrVals))
  925.     {
  926.       case eModReg8:
  927.         if (AdrVals.Val == AccReg) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  928.         else
  929.           BAsmCode[CodeLen++] = Code | (AdrVals.Val << 3);
  930.         break;
  931.       default:
  932.         break;
  933.     }
  934.   }
  935. }
  936.  
  937. /*!------------------------------------------------------------------------
  938.  * \fn     DecodeSingleReg(Word Index)
  939.  * \brief  handle instructions taking a single register as argument
  940.  * \param  Index machine code
  941.  * ------------------------------------------------------------------------ */
  942.  
  943. static void DecodeSingleReg(Word Index)
  944. {
  945.   Byte Reg, Opcode = Lo(Index), Shift = Hi(Index) & 7;
  946.   Boolean NoAM = (Index & 0x8000) || False;
  947.  
  948.   if (!ChkArgCnt(1, 1));
  949.   else if (!ChkZ80Syntax(eSyntax808x));
  950.   else if (!DecodeReg(ArgStr[1].str.p_str, eSyntax808x, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  951.   else if (NoAM && ((Reg == 0) || (Reg == 7))) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
  952.   else
  953.   {
  954.     BAsmCode[0] = Opcode | (Reg << Shift);
  955.     CodeLen = 1;
  956.   }
  957. }
  958.  
  959. /*!------------------------------------------------------------------------
  960.  * \fn     DecodePORT(Word Index)
  961.  * \brief  handle PORT instruction
  962.  * ------------------------------------------------------------------------ */
  963.  
  964. static void DecodePORT(Word Index)
  965. {
  966.   UNUSED(Index);
  967.  
  968.   CodeEquate(SegIO, 0, 0x7);
  969. }
  970.  
  971. /*---------------------------------------------------------------------------*/
  972. /* Codetabellenverwaltung */
  973.  
  974. static const char FlagNames[] = "CZSP";
  975.  
  976. static void AddFixed(const char *NName, Byte NCode, Word SyntaxMask)
  977. {
  978.   AddInstTable(InstTable, NName, (SyntaxMask << 8) | NCode, DecodeFixed);
  979. }
  980.  
  981. static void AddFixeds(const char *NName, Byte NCode, int Shift, Byte RegMask)
  982. {
  983.   char Memo[10], *p;
  984.   int Reg;
  985.  
  986.   strcpy(Memo, NName); p = strchr(Memo, '*');
  987.   for (Reg = 0; Reg < 8; Reg++)
  988.     if ((1 << Reg) & RegMask)
  989.     {
  990.       *p = RegNames[Reg];
  991.       AddFixed(Memo, NCode + (Reg << Shift), eSyntax808x);
  992.     }
  993. }
  994.  
  995. static void AddImm(const char *NName, Byte NCode, Word SyntaxMask)
  996. {
  997.   AddInstTable(InstTable, NName, (SyntaxMask << 8) | NCode, DecodeImm);
  998. }
  999.  
  1000. static void AddImms(const char *NName, Byte NCode, int Pos)
  1001. {
  1002.   char Memo[10], *p;
  1003.   int z;
  1004.  
  1005.   strcpy(Memo, NName); p = strchr(Memo, '*');
  1006.   for (z = 0; z < 8; z++)
  1007.   {
  1008.     *p = RegNames[z];
  1009.     AddImm(Memo, NCode + (z << Pos), eSyntax808x);
  1010.   }
  1011. }
  1012.  
  1013. static void AddJmp(const char *NName, Byte NCode)
  1014. {
  1015.   AddInstTable(InstTable, NName, NCode, DecodeJmp);
  1016. }
  1017.  
  1018. static void AddJmps(const char *NName, Byte NCode, int Pos)
  1019. {
  1020.   char Memo[10], *p;
  1021.   int z;
  1022.  
  1023.   strcpy(Memo, NName); p = strchr(Memo, '*');
  1024.   for (z = 0; z < 4; z++)
  1025.   {
  1026.     *p = FlagNames[z];
  1027.     AddJmp(Memo, NCode + (z << Pos));
  1028.   }
  1029. }
  1030.  
  1031. static void InitFields(void)
  1032. {
  1033.   Boolean New = (MomCPU == CPU8008New);
  1034.  
  1035.   SetDynamicInstTable(InstTable = CreateInstTable(503));
  1036.  
  1037.   AddFixed("HLT" , 0x00, eSyntax808x);
  1038.   AddFixed("HALT", 0x00, eSyntaxZ80);
  1039.   AddFixed("NOP" , 0xc0, eSyntaxBoth); /* = MOV A,A */
  1040.  
  1041.   if (!New)
  1042.     AddInstTable(InstTable, "INP", True, DecodeINP_OUT);
  1043.   AddInstTable(InstTable, "IN" , True , DecodeINP_OUT);
  1044.   AddInstTable(InstTable, "OUT", False, DecodeINP_OUT);
  1045.  
  1046.   AddInstTable(InstTable, "JP", 0, DecodeJP);
  1047.   AddJmp ("JMP", 0x44);
  1048.   if (New)
  1049.   {
  1050.     AddJmp("JNC", 0x40);
  1051.     AddJmp("JNZ", 0x48);
  1052.     AddJmp("JPO", 0x58);
  1053.     AddJmp("JM" , 0x70);
  1054.     AddJmp("JPE", 0x78);
  1055.   }
  1056.   else
  1057.   {
  1058.     AddJmp("JS" , 0x70);
  1059.     AddJmps("JF*", 0x40, 3);
  1060.     AddJmps("JT*", 0x60, 3);
  1061.   }
  1062.   AddJmp("JC" , 0x60);
  1063.   AddJmp("JZ" , 0x68);
  1064.  
  1065.   AddInstTable(InstTable, "CALL", 0, DecodeCALL);
  1066.   AddInstTable(InstTable, "CP", 0, DecodeCP);
  1067.   if (New)
  1068.   {
  1069.     AddJmp("CNC", 0x42);
  1070.     AddJmp("CNZ", 0x4a);
  1071.     AddJmp("CPO", 0x5a);
  1072.     AddJmp("CM" , 0x72);
  1073.     AddJmp("CPE", 0x7a);
  1074.   }
  1075.   else
  1076.   {
  1077.     AddJmp("CAL", 0x46);
  1078.     AddJmp("CS" , 0x72);
  1079.     AddJmps("CF*", 0x42, 3);
  1080.     AddJmps("CT*", 0x62, 3);
  1081.   }
  1082.   AddJmp ("CC" , 0x62);
  1083.   AddJmp ("CZ" , 0x6a);
  1084.  
  1085.   AddInstTable(InstTable, "RET", 0x07, DecodeRET);
  1086.   if (New)
  1087.   {
  1088.     AddFixed("RNC", 0x03, eSyntax808x);
  1089.     AddFixed("RNZ", 0x0b, eSyntax808x);
  1090.     AddFixed("RP" , 0x13, eSyntax808x);
  1091.     AddFixed("RPO", 0x1b, eSyntax808x);
  1092.     AddFixed("RM" , 0x33, eSyntax808x);
  1093.     AddFixed("RPE", 0x3b, eSyntax808x);
  1094.   }
  1095.   else
  1096.   {
  1097.     AddFixed("RFC", 0x03, eSyntax808x);
  1098.     AddFixed("RFZ", 0x0b, eSyntax808x);
  1099.     AddFixed("RFS", 0x13, eSyntax808x);
  1100.     AddFixed("RFP", 0x1b, eSyntax808x);
  1101.     AddFixed("RS" , 0x33, eSyntax808x);
  1102.     AddFixed("RP" , 0x3b, eSyntax808x);
  1103.     AddFixed("RTC", 0x23, eSyntax808x);
  1104.     AddFixed("RTZ", 0x2b, eSyntax808x);
  1105.     AddFixed("RTS", 0x33, eSyntax808x);
  1106.     AddFixed("RTP", 0x3b, eSyntax808x);
  1107.   }
  1108.   AddFixed("RC" , 0x23, eSyntax808x);
  1109.   AddFixed("RZ" , 0x2b, eSyntax808x);
  1110.  
  1111.   AddInstTable(InstTable, "RST", 0, DecodeRST); /* TODO: Z80 */
  1112.  
  1113.   if (New)
  1114.     AddInstTable(InstTable, "MOV", 0, DecodeMOV);
  1115.   else
  1116.   {
  1117.     AddFixeds("L*A", 0xc0, 3, 0xff);
  1118.     AddFixeds("L*B", 0xc1, 3, 0xff);
  1119.     AddFixeds("L*C", 0xc2, 3, 0xff);
  1120.     AddFixeds("L*D", 0xc3, 3, 0xff);
  1121.     AddFixeds("L*E", 0xc4, 3, 0xff);
  1122.     AddFixeds("L*H", 0xc5, 3, 0xff);
  1123.     AddFixeds("L*L", 0xc6, 3, 0xff);
  1124.     AddFixeds("L*M", 0xc7, 3, 0x7f); /* forbid LMM - would be opcode for HLT */
  1125.   }
  1126.  
  1127.   if (New)
  1128.   {
  1129.     AddInstTable(InstTable, "MVI", 0, DecodeMVI);
  1130.     AddInstTable(InstTable, "LXI", 0, DecodeLXI);
  1131.   }
  1132.   else
  1133.     AddImms("L*I", 0x06, 3);
  1134.  
  1135.   AddInstTable(InstTable, "LD", 0, DecodeLD);
  1136.  
  1137.   AddInstTable(InstTable, "ADD", 0x0080, DecodeADD);
  1138.   AddInstTable(InstTable, "ADC", 0x0088, DecodeADC);
  1139.   AddInstTable(InstTable, "SUB", 0x0090, DecodeSUB);
  1140.   AddInstTable(InstTable, "SBC", 0x0098, DecodeSBC);
  1141.   AddInstTable(InstTable, "AND", 0x24a0, DecodeALU8_Z80);
  1142.   AddInstTable(InstTable, "XOR", 0x2ca8, DecodeALU8_Z80);
  1143.   AddInstTable(InstTable, "OR" , 0x34b0, DecodeALU8_Z80);
  1144.   AddInstTable(InstTable, "INC", 0x00, DecodeINCDEC);
  1145.   AddInstTable(InstTable, "DEC", 0x01, DecodeINCDEC);
  1146.   if (New)
  1147.   {
  1148.     AddInstTable(InstTable, "SBB", 0x0098, DecodeSingleReg);
  1149.     AddInstTable(InstTable, "ANA", 0x00a0, DecodeSingleReg);
  1150.     AddInstTable(InstTable, "XRA", 0x00a8, DecodeSingleReg);
  1151.     AddInstTable(InstTable, "ORA", 0x00b0, DecodeSingleReg);
  1152.     AddInstTable(InstTable, "CMP", 0x00b8, DecodeSingleReg);
  1153.     AddInstTable(InstTable, "INR", 0x8300, DecodeSingleReg);
  1154.     AddInstTable(InstTable, "DCR", 0x8301, DecodeSingleReg);
  1155.   }
  1156.   else
  1157.   {
  1158.     AddFixeds("AD*", 0x80, 0, 0xf3); /* ADC/ADD handled separately */
  1159.     AddFixeds("AC*", 0x88, 0, 0xff);
  1160.     AddFixeds("SU*", 0x90, 0, 0xfd); /* SUB handled separately */
  1161.     AddFixeds("SB*", 0x98, 0, 0xfb); /* SBC handled separately */
  1162.     AddFixeds("NR*", 0xa0, 0, 0xff);
  1163.     AddFixeds("ND*", 0xa0, 0, 0xff);
  1164.     AddFixeds("XR*", 0xa8, 0, 0xff);
  1165.     AddFixeds("OR*", 0xb0, 0, 0xff);
  1166.     AddFixeds("CP*", 0xb8, 0, 0xff);
  1167.     AddFixeds("IN*", 0x00, 3, 0x7a); /* no INA/INM, INC handled separately */
  1168.     AddFixeds("DC*", 0x01, 3, 0x7e); /* no DCA/DCM */
  1169.   }
  1170.  
  1171.   AddImm ("ADI", 0x04, eSyntax808x);
  1172.   AddImm ("ACI", 0x0c, eSyntax808x);
  1173.   AddImm ("SUI", 0x14, eSyntax808x);
  1174.   AddImm ("SBI", 0x1c, eSyntax808x);
  1175.   AddImm (New ? "ANI" : "NDI", 0x24, eSyntax808x);
  1176.   AddImm ("XRI", 0x2c, eSyntax808x);
  1177.   AddImm ("ORI", 0x34, eSyntax808x);
  1178.   AddImm ("CPI", 0x3c, eSyntax808x);
  1179.  
  1180.   AddFixed ("RLC" , 0x02, eSyntax808x);
  1181.   AddFixed ("RLCA", 0x02, eSyntaxZ80);
  1182.   AddFixed ("RRC" , 0x0a, eSyntax808x);
  1183.   AddFixed ("RRCA", 0x0a, eSyntaxZ80);
  1184.   AddFixed ("RAL" , 0x12, eSyntax808x);
  1185.   AddFixed ("RLA" , 0x12, eSyntaxZ80);
  1186.   AddFixed ("RAR" , 0x1a, eSyntax808x);
  1187.   AddFixed ("RRA" , 0x1a, eSyntaxZ80);
  1188.  
  1189.   AddInstTable(InstTable, "PORT", 0, DecodePORT);
  1190.   AddZ80Syntax(InstTable);
  1191. }
  1192.  
  1193. static void DeinitFields(void)
  1194. {
  1195.   DestroyInstTable(InstTable);
  1196. }
  1197.  
  1198. /*---------------------------------------------------------------------------*/
  1199. /* Callbacks */
  1200.  
  1201. static void MakeCode_8008(void)
  1202. {
  1203.   CodeLen = 0; DontPrint = False;
  1204.  
  1205.   /* zu ignorierendes */
  1206.  
  1207.   if (Memo("")) return;
  1208.  
  1209.   /* Pseudoanweisungen */
  1210.  
  1211.   if (DecodeIntelPseudo(False)) return;
  1212.  
  1213.   /* der Rest */
  1214.  
  1215.   if (!LookupInstTable(InstTable, OpPart.str.p_str))
  1216.     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
  1217. }
  1218.  
  1219. static Boolean IsDef_8008(void)
  1220. {
  1221.   return Memo("PORT");
  1222. }
  1223.  
  1224. static void SwitchFrom_8008(void)
  1225. {
  1226.   DeinitFields();
  1227. }
  1228.  
  1229. static void SwitchTo_8008(void)
  1230. {
  1231.   const TFamilyDescr *FoundDescr;
  1232.  
  1233.   FoundDescr = FindFamilyByName("8008");
  1234.  
  1235.   TurnWords = False;
  1236.   SetIntConstMode(eIntConstModeIntel);
  1237.  
  1238.   PCSymbol = "$"; HeaderID = FoundDescr->Id; NOPCode = 0xc0;
  1239.   DivideChars = ","; HasAttrs = False;
  1240.  
  1241.   ValidSegs = (1 << SegCode) | (1 << SegIO);
  1242.   Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
  1243.   SegLimits[SegCode] = 0x3fff;
  1244.   Grans[SegIO   ] = 1; ListGrans[SegIO   ] = 1; SegInits[SegIO   ] = 0;
  1245.   SegLimits[SegIO] = 7;
  1246.  
  1247.   MakeCode = MakeCode_8008;
  1248.   IsDef = IsDef_8008;
  1249.   SwitchFrom = SwitchFrom_8008;
  1250.  
  1251.   InitFields();
  1252. }
  1253.  
  1254. /*---------------------------------------------------------------------------*/
  1255. /* Initialisierung */
  1256.  
  1257. void code8008_init(void)
  1258. {
  1259.   CPU8008    = AddCPU("8008"   , SwitchTo_8008);
  1260.   CPU8008New = AddCPU("8008NEW", SwitchTo_8008);
  1261. }
  1262.