?login_element?

Subversion Repositories NedoOS

Rev

Rev 129 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  
  3.   SjASMPlus Z80 Cross Compiler
  4.  
  5.   Copyright (c) 2004-2008 Aprisobal
  6.  
  7.   This software is provided 'as-is', without any express or implied warranty.
  8.   In no event will the authors be held liable for any damages arising from the
  9.   use of this software.
  10.  
  11.   Permission is granted to anyone to use this software for any purpose,
  12.   including commercial applications, and to alter it and redistribute it freely,
  13.   subject to the following restrictions:
  14.  
  15.   1. The origin of this software must not be misrepresented; you must not claim
  16.          that you wrote the original software. If you use this software in a product,
  17.          an acknowledgment in the product documentation would be appreciated but is
  18.          not required.
  19.  
  20.   2. Altered source versions must be plainly marked as such, and must not be
  21.          misrepresented as being the original software.
  22.  
  23.   3. This notice may not be removed or altered from any source distribution.
  24.  
  25. */
  26.  
  27. #include "sjdefs.h"
  28.  
  29. namespace Z80 {
  30.         enum Z80Reg { Z80_B = 0, Z80_C, Z80_D, Z80_E, Z80_H, Z80_L, Z80_MEM_HL, Z80_A, Z80_I, Z80_R, Z80_F,
  31.                 Z80_BC = 0x10, Z80_DE = 0x20, Z80_HL = 0x30, Z80_SP = 0x40, Z80_AF = 0x50,
  32.                 LR35902_MEM_HL_I = 0x22, LR35902_MEM_HL_D = 0x32,
  33.                 Z80_IX = 0xdd, Z80_IY = 0xfd, Z80_MEM_IX = Z80_IX|(Z80_MEM_HL<<8), Z80_MEM_IY = Z80_IY|(Z80_MEM_HL<<8),
  34.                 Z80_IXH = Z80_IX|(Z80_H<<8), Z80_IXL = Z80_IX|(Z80_L<<8),
  35.                 Z80_IYH = Z80_IY|(Z80_H<<8), Z80_IYL = Z80_IY|(Z80_L<<8), Z80_UNK = -1 };
  36.         enum Z80Cond {  // also used to calculate instruction opcode, so do not edit values
  37.                 Z80C_NZ = 0x00, Z80C_Z  = 0x08, Z80C_NC = 0x10, Z80C_C = 0x18,
  38.                 Z80C_PO = 0x20, Z80C_PE = 0x28, Z80C_P  = 0x30, Z80C_M = 0x38, Z80C_UNK };
  39.  
  40.         static CFunctionTable OpCodeTable;
  41.  
  42.         void GetOpCode() {
  43.                 char* n;
  44.                 bp = lp;
  45.                 if (!(n = getinstr(lp))) {
  46.                         Error("Unrecognized instruction", lp);
  47.                         return;
  48.                 }
  49.                 if (!OpCodeTable.zoek(n)) {
  50.                         Error("Unrecognized instruction", bp);
  51.                         SkipToEol(lp);
  52.                 }
  53.         }
  54.  
  55.         static byte GetByte(char*& p, bool signedCheck = false) {
  56.                 aint val;
  57.                 if (!ParseExpression(p, val)) {
  58.                         Error("Operand expected", nullptr, IF_FIRST); return 0;
  59.                 }
  60.                 if (signedCheck) check8o(val);
  61.                 else check8(val);
  62.                 return val & 255;
  63.         }
  64.  
  65.         static byte GetByteNoMem(char*& p, bool signedCheck = false) {
  66.                 if (0 == Options::syx.MemoryBrackets) return GetByte(p, signedCheck); // legacy behaviour => don't care
  67.                 aint val; char* const oldP = p;
  68.                 switch (ParseExpressionMemAccess(p, val)) {
  69.                 case 1:                                 // valid constant (not a memory access) => return value
  70.                         if (signedCheck) check8o(val);
  71.                         else check8(val);
  72.                         return val & 255;
  73.                 case 2:                                 // valid memory access => report error
  74.                         Error("Illegal instruction (can't access memory)", oldP);
  75.                         return 0;
  76.                 default:                                // parsing failed, report syntax error
  77.                         Error("Operand expected", oldP, IF_FIRST);
  78.                         return 0;
  79.                 }
  80.         }
  81.  
  82.         static word GetWord(char*& p) {
  83.                 aint val;
  84.                 if (!ParseExpression(p, val)) {
  85.                         Error("Operand expected", nullptr, IF_FIRST); return 0;
  86.                 }
  87.                 check16(val);
  88.                 return val & 65535;
  89.         }
  90.  
  91.         static word GetWordNoMem(char*& p) {
  92.                 if (0 == Options::syx.MemoryBrackets) return GetWord(p); // legacy behaviour => don't care
  93.                 aint val; char* const oldP = p;
  94.                 switch (ParseExpressionMemAccess(p, val)) {
  95.                 case 1:                                 // valid constant (not a memory access) => return value
  96.                         check16(val);
  97.                         return val & 65535;
  98.                 case 2:                                 // valid memory access => report error
  99.                         Error("Illegal instruction (can't access memory)", oldP);
  100.                         return 0;
  101.                 default:                                // parsing failed, report syntax error
  102.                         Error("Operand expected", oldP, IF_FIRST);
  103.                         return 0;
  104.                 }
  105.         }
  106.  
  107.         static byte z80GetIDxoffset(char*& p) {
  108.                 aint val;
  109.                 char* pp = p;
  110.                 SkipBlanks(pp);
  111.                 if (')' == *pp || ']' == *pp) return 0;
  112.                 if (!ParseExpression(p, val)) {
  113.                         Error("Operand expected", nullptr, IF_FIRST); return 0;
  114.                 }
  115.                 check8o(val);
  116.                 return val & 255;
  117.         }
  118.  
  119.         static int GetAddress(char*& p, aint& ad) {
  120.                 if (GetLocalLabelValue(p, ad) || ParseExpression(p, ad)) return 1;
  121.                 Error("Operand expected", nullptr, IF_FIRST);
  122.                 return (ad = 0);        // set "ad" to zero and return zero
  123.         }
  124.  
  125.         static Z80Cond getz80cond_Z80(char*& p) {
  126.                 if (SkipBlanks(p)) return Z80C_UNK;     // EOL detected
  127.                 char * const pp = p;
  128.                 const char p0 = 0x20|p[0];              // lowercase ASCII conversion
  129.                 if (!islabchar(p[1])) {                 // can be only single letter condition at most
  130.                         ++p;
  131.                         switch (p0) {
  132.                                 case 'z': return Z80C_Z;
  133.                                 case 'c': return Z80C_C;
  134.                                 case 'p': return Z80C_P;
  135.                                 case 'm': return Z80C_M;
  136.                                 case 's': return Z80C_M;
  137.                         }
  138.                         p = pp;
  139.                         return Z80C_UNK;
  140.                 }
  141.                 // ## p0 != 0 && p1 is label character
  142.                 if ((p[0]^p[1])&0x20) return Z80C_UNK;  // different case of the letters detected
  143.                 if (islabchar(p[2])) return Z80C_UNK;   // p2 is also label character = too many
  144.                 const char p1 = 0x20|p[1];              // lowercase ASCII conversion
  145.                 p += 2;
  146.                 if ('n' == p0) {
  147.                         switch (p1) {
  148.                                 case 'z': return Z80C_NZ;       // nz
  149.                                 case 'c': return Z80C_NC;       // nc
  150.                                 case 's': return Z80C_P;        // ns
  151.                         }
  152.                 } else if ('p' == p0) {
  153.                         switch (p1) {
  154.                                 case 'o': return Z80C_PO;       // po
  155.                                 case 'e': return Z80C_PE;       // pe
  156.                         }
  157.                 }
  158.                 p = pp;
  159.                 return Z80C_UNK;
  160.         }
  161.  
  162.         static Z80Cond getz80cond(char*& p) {
  163.                 if (!Options::IsLR35902) return getz80cond_Z80(p);
  164.                 // Sharp LR35902 has only nz|z|nc|c condition variants of ret|jp|jr|call
  165.                 char * const pp = p;
  166.                 Z80Cond cc = getz80cond_Z80(p);
  167.                 switch (cc) {
  168.                 case Z80C_NZ:   case Z80C_Z:
  169.                 case Z80C_NC:   case Z80C_C:
  170.                         return cc;
  171.                 default:
  172.                         p = pp;                 // restore source ptr
  173.                         return Z80C_UNK;
  174.                 }
  175.         }
  176.  
  177.         static Z80Reg GetRegister_r16High(const Z80Reg r16) {
  178.                 switch (r16) {
  179.                 case Z80_BC: return Z80_B;
  180.                 case Z80_DE: return Z80_D;
  181.                 case Z80_HL: return Z80_H;
  182.                 case Z80_AF: return Z80_A;
  183.                 case Z80_IX: return Z80_IXH;
  184.                 case Z80_IY: return Z80_IYH;
  185.                 default:
  186.                         return Z80_UNK;
  187.                 }
  188.         }
  189.  
  190.         static Z80Reg GetRegister_r16Low(const Z80Reg r16) {
  191.                 switch (r16) {
  192.                 case Z80_BC: return Z80_C;
  193.                 case Z80_DE: return Z80_E;
  194.                 case Z80_HL: return Z80_L;
  195.                 case Z80_AF: return Z80_F;
  196.                 case Z80_IX: return Z80_IXL;
  197.                 case Z80_IY: return Z80_IYL;
  198.                 default:
  199.                         return Z80_UNK;
  200.                 }
  201.         }
  202.  
  203.         static bool GetRegister_pair(char*& p, const char expect) {
  204.                 if (expect != p[0] || islabchar(p[1])) return false;
  205.                 ++p;
  206.                 return true;
  207.         }
  208.  
  209.         static int GetRegister_lastIxyD = 0;    //z80GetIDxoffset(lp)
  210.  
  211.         // fast lookup table for single letters 'a'..'r' ('gjkmnopq' will produce Z80_UNK instantly)
  212.         static Z80Reg r8[] {
  213.                 // a   b      c      d      e      f      g        h      i      j        k        l
  214.                 Z80_A, Z80_B, Z80_C, Z80_D, Z80_E, Z80_F, Z80_UNK, Z80_H, Z80_I, Z80_UNK, Z80_UNK, Z80_L,
  215.                 // m     n        o        p        q        r
  216.                 Z80_UNK, Z80_UNK, Z80_UNK, Z80_UNK, Z80_UNK, Z80_R
  217.         };
  218.  
  219.         static Z80Reg GetRegister(char*& p) {
  220.                 const bool nonZ80CPU = Options::IsI8080 || Options::IsLR35902;
  221.                 char* pp = p;
  222.                 SkipBlanks(p);
  223.                 // adjust the single letter look-up-table by current options (CPU modes and syntax modes)
  224.                 r8['m'-'a'] = Options::syx.Is_M_Memory ? Z80_MEM_HL : Z80_UNK;  // extra alias "M" for "(HL)" enabled?
  225.                 r8['i'-'a'] = nonZ80CPU ? Z80_UNK : Z80_I;      // i8080/LR35902 doesn't have I
  226.                 r8['r'-'a'] = nonZ80CPU ? Z80_UNK : Z80_R;      // i8080/LR35902 doesn't have R
  227.                 char oneLetter = p[0] | 0x20;           // force it lowercase, in case it's ASCII letter
  228.                 if ('a' <= oneLetter && oneLetter <= 'r' && !islabchar(p[1])) {
  229.                         const Z80Reg lutResult = r8[oneLetter - 'a'];
  230.                         if (Z80_UNK == lutResult) p = pp;       // not a register, restore "p"
  231.                         else ++p;       // reg8 found, advance pointer
  232.                         return lutResult;
  233.                 }
  234.                 // high/low operators can be used on register pair
  235.                 if (cmphstr(p, "high")) {
  236.                         const Z80Reg reg = GetRegister(p);
  237.                         if (Z80_UNK == reg) {
  238.                                 p = pp;
  239.                                 return Z80_UNK;
  240.                         }
  241.                         return GetRegister_r16High(reg);
  242.                 }
  243.                 if (cmphstr(p, "low")) {
  244.                         const Z80Reg reg = GetRegister(p);
  245.                         if (Z80_UNK == reg) {
  246.                                 p = pp;
  247.                                 return Z80_UNK;
  248.                         }
  249.                         return GetRegister_r16Low(reg);
  250.                 }
  251.                 // remaining two+ letter registers
  252.                 char memClose = 0;
  253.                 switch (*(p++)) {
  254.                 case 'a':
  255.                         if (GetRegister_pair(p, 'f')) return Z80_AF;
  256.                         break;
  257.                 case 'b':
  258.                         if (GetRegister_pair(p, 'c')) return Z80_BC;
  259.                         break;
  260.                 case 'd':
  261.                         if (GetRegister_pair(p, 'e')) return Z80_DE;
  262.                         break;
  263.                 case 'h':
  264.                         if (GetRegister_pair(p, 'l')) return Z80_HL;
  265.                         if (nonZ80CPU) break;
  266.                         if (GetRegister_pair(p, 'x')) return Z80_IXH;
  267.                         if (GetRegister_pair(p, 'y')) return Z80_IYH;
  268.                         break;
  269.                 case 'i':
  270.                         if (nonZ80CPU) break;
  271.                         if (*p == 'x') {
  272.                                 if (!islabchar(*(p + 1))) {
  273.                                         ++p;
  274.                                         return Z80_IX;
  275.                                 }
  276.                                 if (*(p + 1) == 'h' && !islabchar(*(p + 2))) {
  277.                                         p += 2;
  278.                                         return Z80_IXH;
  279.                                 }
  280.                                 if (*(p + 1) == 'l' && !islabchar(*(p + 2))) {
  281.                                         p += 2;
  282.                                         return Z80_IXL;
  283.                                 }
  284.                         }
  285.                         if (*p == 'y') {
  286.                                 if (!islabchar(*(p + 1))) {
  287.                                         ++p;
  288.                                         return Z80_IY;
  289.                                 }
  290.                                 if (*(p + 1) == 'h' && !islabchar(*(p + 2))) {
  291.                                         p += 2;
  292.                                         return Z80_IYH;
  293.                                 }
  294.                                 if (*(p + 1) == 'l' && !islabchar(*(p + 2))) {
  295.                                         p += 2;
  296.                                         return Z80_IYL;
  297.                                 }
  298.                         }
  299.                         break;
  300.                 case 'x':
  301.                         if (nonZ80CPU) break;
  302.                         if (GetRegister_pair(p, 'h')) return Z80_IXH;
  303.                         if (GetRegister_pair(p, 'l')) return Z80_IXL;
  304.                         break;
  305.                 case 'y':
  306.                         if (nonZ80CPU) break;
  307.                         if (GetRegister_pair(p, 'h')) return Z80_IYH;
  308.                         if (GetRegister_pair(p, 'l')) return Z80_IYL;
  309.                         break;
  310.                 case 'l':
  311.                         if (nonZ80CPU) break;
  312.                         if (GetRegister_pair(p, 'x')) return Z80_IXL;
  313.                         if (GetRegister_pair(p, 'y')) return Z80_IYL;
  314.                         break;
  315.                 case 's':
  316.                         if (GetRegister_pair(p, 'p')) return Z80_SP;
  317.                         break;
  318.                 case 'A':
  319.                         if (GetRegister_pair(p, 'F')) return Z80_AF;
  320.                         break;
  321.                 case 'B':
  322.                         if (GetRegister_pair(p, 'C')) return Z80_BC;
  323.                         break;
  324.                 case 'D':
  325.                         if (GetRegister_pair(p, 'E')) return Z80_DE;
  326.                         break;
  327.                 case 'H':
  328.                         if (GetRegister_pair(p, 'L')) return Z80_HL;
  329.                         if (nonZ80CPU) break;
  330.                         if (GetRegister_pair(p, 'X')) return Z80_IXH;
  331.                         if (GetRegister_pair(p, 'Y')) return Z80_IYH;
  332.                         break;
  333.                 case 'I':
  334.                         if (nonZ80CPU) break;
  335.                         if (*p == 'X') {
  336.                                 if (!islabchar(*(p + 1))) {
  337.                                         ++p; return Z80_IX;
  338.                                 }
  339.                                 if (*(p + 1) == 'H' && !islabchar(*(p + 2))) {
  340.                                         p += 2; return Z80_IXH;
  341.                                 }
  342.                                 if (*(p + 1) == 'L' && !islabchar(*(p + 2))) {
  343.                                         p += 2; return Z80_IXL;
  344.                                 }
  345.                         }
  346.                         if (*p == 'Y') {
  347.                                 if (!islabchar(*(p + 1))) {
  348.                                         ++p; return Z80_IY;
  349.                                 }
  350.                                 if (*(p + 1) == 'H' && !islabchar(*(p + 2))) {
  351.                                         p += 2; return Z80_IYH;
  352.                                 }
  353.                                 if (*(p + 1) == 'L' && !islabchar(*(p + 2))) {
  354.                                         p += 2; return Z80_IYL;
  355.                                 }
  356.                         }
  357.                         break;
  358.                 case 'X':
  359.                         if (nonZ80CPU) break;
  360.                         if (GetRegister_pair(p, 'H')) return Z80_IXH;
  361.                         if (GetRegister_pair(p, 'L')) return Z80_IXL;
  362.                         break;
  363.                 case 'Y':
  364.                         if (nonZ80CPU) break;
  365.                         if (GetRegister_pair(p, 'H')) return Z80_IYH;
  366.                         if (GetRegister_pair(p, 'L')) return Z80_IYL;
  367.                         break;
  368.                 case 'L':
  369.                         if (nonZ80CPU) break;
  370.                         if (GetRegister_pair(p, 'X')) return Z80_IXL;
  371.                         if (GetRegister_pair(p, 'Y')) return Z80_IYL;
  372.                         break;
  373.                 case 'S':
  374.                         if (GetRegister_pair(p, 'P')) return Z80_SP;
  375.                         break;
  376.                 case '(': memClose = (2 != Options::syx.MemoryBrackets) ? ')' : 0;      break;
  377.                 case '[': memClose = ']'; break;
  378.                 default:        break;
  379.                 }
  380.                 if (memClose) {
  381.                         Z80Reg memReg = GetRegister(p);
  382.                         if (Options::IsLR35902 && Z80_HL == memReg) {
  383.                                 if ('+' == *p) {
  384.                                         memReg = LR35902_MEM_HL_I;
  385.                                         ++p;
  386.                                 } else if ('-' == *p) {
  387.                                         memReg = LR35902_MEM_HL_D;
  388.                                         ++p;
  389.                                 }
  390.                         }
  391.                         if (Z80_IX == memReg || Z80_IY == memReg) GetRegister_lastIxyD = z80GetIDxoffset(p);
  392.                         SkipBlanks(p);
  393.                         if (memClose == *p++) {
  394.                                 switch (memReg) {
  395.                                 case Z80_HL:    return Z80_MEM_HL;
  396.                                 case Z80_IX:    return Z80_MEM_IX;
  397.                                 case Z80_IY:    return Z80_MEM_IY;
  398.                                 case LR35902_MEM_HL_I:
  399.                                 case LR35902_MEM_HL_D:
  400.                                         return memReg;
  401.                                 default:                break;
  402.                                 }
  403.                         }
  404.                 }
  405.                 p = pp;
  406.                 return Z80_UNK;
  407.         }
  408.  
  409.         static bool CommonAluOpcode(const int opcodeBase, int* e, bool hasNonRegA = false, bool nonMultiArgComma = true) {
  410.                 Z80Reg reg;
  411.                 char* oldLp = lp;
  412.                 switch (reg = GetRegister(lp)) {
  413.                 case Z80_BC:    case Z80_DE:    case Z80_HL:    case Z80_IX:    case Z80_IY:
  414.                         if (hasNonRegA) lp = oldLp;     // try to parse it one more time if non-A variants exist
  415.                         return !hasNonRegA;                     // invalid first register if only "A" is allowed
  416.                 case Z80_SP:
  417.                         if (Options::IsLR35902) lp = oldLp;
  418.                         return !Options::IsLR35902;     // LR35902 has "add sp,r8"
  419.                 case Z80_AF:    case Z80_I:             case Z80_R:             case Z80_F:
  420.                 case LR35902_MEM_HL_I:  case LR35902_MEM_HL_D:
  421.                         return true;                            // invalid first register
  422.                 case Z80_A:             // deal with optional shortened/prolonged form "add a" vs "and a,a", etc..
  423.                         if (nonMultiArgComma) { // "AND|SUB|... a,b" is possible only when multi-arg is not-comma
  424.                                 if (nonMaComma(lp)) reg = GetRegister(lp);
  425.                         } else {
  426.                                 if (comma(lp)) reg = GetRegister(lp);
  427.                         }
  428.                 default:
  429.                         // with optional "a," dealt with, do the argument recognition and machine code emitting
  430.                         switch (reg) {
  431.                         case Z80_IXH: case Z80_IXL: case Z80_IYH: case Z80_IYL: case Z80_MEM_IX: case Z80_MEM_IY:
  432.                                 *e++ = reg&0xFF;                // add prefix
  433.                                 reg = Z80Reg(reg>>8);   // convert reg into H, L or MEM_HL and continue
  434.                                 if (Z80_MEM_HL == reg) e[1] = GetRegister_lastIxyD;     // add "+d" byte for (ixy+d)
  435.                         case Z80_B: case Z80_C: case Z80_D: case Z80_E:
  436.                         case Z80_H: case Z80_L: case Z80_MEM_HL: case Z80_A:
  437.                                 e[0] = opcodeBase + reg;
  438.                                 return true;                    // successfully assembled
  439.                         case Z80_UNK:
  440.                                 e[0] = opcodeBase + 0x46; e[1] = GetByteNoMem(lp);      // imm8 variants
  441.                                 return true;
  442.                         default:
  443.                                 break;
  444.                         }
  445.                 }
  446.                 return true;
  447.         }
  448.  
  449.         // returns "Z80_A" when successfully finished, otherwise returns result of "GetRegister(lp)"
  450.         static Z80Reg OpCode_CbFamily(const int baseOpcode, int* e, bool canHaveDstRegForIxy = true) {
  451.                 Z80Reg reg;
  452.                 switch (reg = GetRegister(lp)) {
  453.                 case Z80_B: case Z80_C: case Z80_D: case Z80_E:
  454.                 case Z80_H: case Z80_L: case Z80_MEM_HL: case Z80_A:
  455.                         e[0] = 0xcb; e[1] = baseOpcode + reg;
  456.                         return Z80_A;
  457.                 case Z80_MEM_IX: case Z80_MEM_IY:
  458.                         e[0] = reg&0xFF; e[1] = 0xcb; e[2] = GetRegister_lastIxyD; e[3] = baseOpcode + (reg>>8);
  459.                         if (canHaveDstRegForIxy && comma(lp)) {
  460.                                 switch (reg = GetRegister(lp)) {
  461.                                 case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L: case Z80_A:
  462.                                         e[3] = baseOpcode + reg;
  463.                                         break;
  464.                                 default:
  465.                                         Error("Illegal destination register", line);
  466.                                 }
  467.                         }
  468.                         return Z80_A;
  469.                 default: break;
  470.                 }
  471.                 return reg;
  472.         }
  473.  
  474.         static void OpCode_ADC() {
  475.                 const bool nonZ80CPU = Options::IsI8080 || Options::IsLR35902;
  476.                 Z80Reg reg;
  477.                 do {
  478.                         int e[] { -1, -1, -1, -1 };
  479.                         if (!CommonAluOpcode(0x88, e, true, false)) {   // handle common 8-bit variants
  480.                                 if ((!nonZ80CPU) && (Z80_HL == GetRegister(lp))) {
  481.                                         if (!comma(lp)) {
  482.                                                 Error("[ADC] Comma expected");
  483.                                         } else {
  484.                                                 switch (reg = GetRegister(lp)) {
  485.                                                 case Z80_BC:    case Z80_DE:    case Z80_HL:    case Z80_SP:
  486.                                                         e[0] = 0xed; e[1] = 0x4a + reg - Z80_BC; break;
  487.                                                 default: break;
  488.                                                 }
  489.                                         }
  490.                                 }
  491.                         }
  492.                         EmitBytes(e);
  493.                 } while (Options::syx.MultiArg(lp));
  494.         }
  495.  
  496.         static void OpCode_ADD() {
  497.                 Z80Reg reg, reg2;
  498.                 do {
  499.                         int e[] { -1, -1, -1, -1, -1 };
  500.                         if (!CommonAluOpcode(0x80, e, true, false)) {   // handle common 8-bit variants
  501.                                 // add hl|ixy|bc|de|sp,... variants
  502.                                 reg = GetRegister(lp);  if (Z80_UNK == reg) break;
  503.                                 if (!comma(lp)) {
  504.                                         Error("[ADD] Comma expected");
  505.                                         break;
  506.                                 }
  507.                                 reg2 = GetRegister(lp);
  508.                                 switch (reg) {
  509.                                 case Z80_HL:
  510.                                         switch (reg2) {
  511.                                         case Z80_BC:    case Z80_DE:    case Z80_HL:    case Z80_SP:
  512.                                                 e[0] = 0x09 + reg2 - Z80_BC; break;
  513.                                         case Z80_A:
  514.                                                 if(!Options::syx.IsNextEnabled) break;
  515.                                                 e[0] = 0xED; e[1] = 0x31; break;
  516.                                         default:
  517.                                                 if(!Options::syx.IsNextEnabled) break;
  518.                                                 word b = GetWordNoMem(lp);
  519.                                                 e[0] = 0xED; e[1] = 0x34 ;
  520.                                                 e[2] = b & 255; e[3] = (b >> 8);
  521.                                                 break;
  522.                                         }
  523.                                         break;
  524.                                 case Z80_IX:
  525.                                 case Z80_IY:
  526.                                         switch (reg2) {
  527.                                         case Z80_BC:    case Z80_DE:    case Z80_SP:
  528.                                                 e[0] = reg; e[1] = 0x09 + reg2 - Z80_BC; break;
  529.                                         case Z80_IX:
  530.                                         case Z80_IY:
  531.                                                 if (reg != reg2) break;
  532.                                                 e[0] = reg; e[1] = 0x29; break;
  533.                                         default:
  534.                                                 break;
  535.                                         }
  536.                                         break;
  537.                                 case Z80_DE:
  538.                                 case Z80_BC:
  539.                                         if (!Options::syx.IsNextEnabled) break;   // DE|BC is valid first operand only for Z80N
  540.                                         if (Z80_A == reg2) {
  541.                                                 e[0] = 0xED; e[1] = 0x32 + (Z80_BC == reg);
  542.                                         } else if (Z80_UNK == reg2) {
  543.                                                 word b = GetWordNoMem(lp);
  544.                                                 e[0] = 0xED; e[1] = 0x35 + (Z80_BC == reg);
  545.                                                 e[2] = b & 255; e[3] = (b >> 8);
  546.                                         }
  547.                                         break;
  548.                                 case Z80_SP:                    // Sharp LR35902 "add sp,r8"
  549.                                         if (!Options::IsLR35902 || Z80_UNK != reg2) break;
  550.                                         e[0] = 0xE8;
  551.                                         e[1] = GetByteNoMem(lp, true);
  552.                                         break;
  553.                                 default:        break;          // unreachable (already validated by `CommonAluOpcode` call)
  554.                                 }
  555.                         }
  556.                         EmitBytes(e);
  557.                 } while (Options::syx.MultiArg(lp));
  558.         }
  559.  
  560.         static void OpCode_AND() {
  561.                 do {
  562.                         int e[] { -1, -1, -1, -1};
  563.                         CommonAluOpcode(0xa0, e);
  564.                         EmitBytes(e);
  565.                 } while (Options::syx.MultiArg(lp));
  566.         }
  567.  
  568.         static void OpCode_BIT() {
  569.                 do {
  570.                         int e[] { -1, -1, -1, -1, -1 };
  571.                         byte bit = GetByteNoMem(lp);
  572.                         if (comma(lp) && bit <= 7) OpCode_CbFamily(8 * bit + 0x40, e, false);
  573.                         EmitBytes(e);
  574.                 } while (Options::syx.MultiArg(lp));
  575.         }
  576.  
  577.         static void OpCode_Next_BREAK() {       // this is fake instruction for CSpect emulator, not for real Z80N
  578.                 if (Options::syx.IsNextEnabled < 2) {
  579.                         Error("[BREAK] fake instruction \"break\" must be specifically enabled by --zxnext=cspect option");
  580.                         return;
  581.                 }
  582.                 EmitByte(0xDD);
  583.                 EmitByte(0x01);
  584.         }
  585.  
  586.         // helper function for BRLC, BSLA, BSRA, BSRF, BSRL, as all need identical operand validation
  587.         static void OpCode_Z80N_BarrelShifts(int mainOpcode) {
  588.                 if (Options::syx.IsNextEnabled < 1) {
  589.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  590.                         return;
  591.                 }
  592.                 int e[] { -1, -1, -1 };
  593.                 // verify the operands are "de,b" (only valid ones)
  594.                 if (Z80_DE == GetRegister(lp) && comma(lp) && Z80_B == GetRegister(lp)) {
  595.                         e[0]=0xED;
  596.                         e[1]=mainOpcode;
  597.                 } else {
  598.                         Error("Z80N barrel shifts exist only with \"DE,B\" arguments", bp, SUPPRESS);
  599.                 }
  600.                 EmitBytes(e);
  601.         }
  602.  
  603.         static void OpCode_Next_BRLC() {
  604.                 OpCode_Z80N_BarrelShifts(0x2C);
  605.         }
  606.  
  607.         static void OpCode_Next_BSLA() {
  608.                 OpCode_Z80N_BarrelShifts(0x28);
  609.         }
  610.  
  611.         static void OpCode_Next_BSRA() {
  612.                 OpCode_Z80N_BarrelShifts(0x29);
  613.         }
  614.  
  615.         static void OpCode_Next_BSRF() {
  616.                 OpCode_Z80N_BarrelShifts(0x2B);
  617.         }
  618.  
  619.         static void OpCode_Next_BSRL() {
  620.                 OpCode_Z80N_BarrelShifts(0x2A);
  621.         }
  622.  
  623.         static void OpCode_CALL() {
  624.                 do {
  625.                         int e[] { -1, -1, -1, -1 };
  626.                         Z80Cond cc = getz80cond(lp);
  627.                         if (Z80C_UNK == cc) {
  628.                                 e[0] = 0xcd;
  629.                         } else if (comma(lp)) {
  630.                                 e[0] = 0xC4 + cc;
  631.                         } else {
  632.                                 Error("[CALL cc] Comma expected", bp);
  633.                         }
  634.                         // UNK != cc + no-comma leaves e[0] == -1 (invalid instruction)
  635.                         aint callad;
  636.                         GetAddress(lp, callad);
  637.                         check16(callad);
  638.                         e[1] = callad & 255; e[2] = (callad >> 8) & 255;
  639.                         EmitBytes(e);
  640.                 } while (Options::syx.MultiArg(lp));
  641.         }
  642.  
  643.         static void OpCode_CCF() {
  644.                 EmitByte(0x3f);
  645.         }
  646.  
  647.         static void OpCode_CP() {
  648.                 do {
  649.                         int e[] { -1, -1, -1, -1};
  650.                         CommonAluOpcode(0xb8, e);
  651.                         EmitBytes(e);
  652.                 } while (Options::syx.MultiArg(lp));
  653.         }
  654.  
  655.         static void OpCode_CPD() {
  656.                 EmitByte(0xED);
  657.                 EmitByte(0xA9);
  658.         }
  659.  
  660.         static void OpCode_CPDR() {
  661.                 EmitByte(0xED);
  662.                 EmitByte(0xB9);
  663.         }
  664.  
  665.         static void OpCode_CPI() {
  666.                 EmitByte(0xED);
  667.                 EmitByte(0xA1);
  668.         }
  669.  
  670.         static void OpCode_CPIR() {
  671.                 EmitByte(0xED);
  672.                 EmitByte(0xB1);
  673.         }
  674.  
  675.         static void OpCode_CPL() {
  676.                 EmitByte(0x2f);
  677.         }
  678.  
  679.         static void OpCode_DAA() {
  680.                 EmitByte(0x27);
  681.         }
  682.  
  683.         static void OpCode_DecInc(const int base8bOpcode, const int base16bOpcode, int* e) {
  684.                 Z80Reg reg;
  685.                 switch (reg = GetRegister(lp)) {
  686.                 case Z80_MEM_IX: case Z80_MEM_IY:
  687.                         e[2] = GetRegister_lastIxyD;    // set up the +d byte and fallthrough for other bytes
  688.                 case Z80_IXH: case Z80_IXL: case Z80_IYH: case Z80_IYL:
  689.                         *e++ = reg&0xFF;        reg = Z80Reg(reg>>8);
  690.                 case Z80_B: case Z80_C: case Z80_D: case Z80_E:
  691.                 case Z80_H: case Z80_L: case Z80_MEM_HL: case Z80_A:
  692.                         *e++ = base8bOpcode + 8 * reg;
  693.                         break;
  694.                 case Z80_IX: case Z80_IY:
  695.                         *e++ = reg;     reg = Z80_HL;
  696.                 case Z80_BC: case Z80_DE: case Z80_HL: case Z80_SP:
  697.                         *e++ = base16bOpcode + reg - Z80_BC;
  698.                         break;
  699.                 default:
  700.                         break;
  701.                 }
  702.         }
  703.  
  704.         static void OpCode_DEC() {
  705.                 do {
  706.                         int e[] { -1, -1, -1, -1 };
  707.                         OpCode_DecInc(0x05, 0x0B, e);
  708.                         EmitBytes(e);
  709.                 } while (Options::syx.MultiArg(lp));
  710.         }
  711.  
  712.         static void OpCode_DI() {
  713.                 EmitByte(0xf3);
  714.         }
  715.  
  716.         static void OpCode_DJNZ() {
  717.                 int jmp;
  718.                 aint nad;
  719.                 int e[3];
  720.                 do {
  721.                         e[0] = e[1] = e[2] = -1;
  722.                         if (!GetAddress(lp, nad)) {
  723.                                 nad = CurAddress + 2;
  724.                         }
  725.                         jmp = nad - CurAddress - 2;
  726.                         if (jmp < -128 || jmp > 127) {
  727.                                 char el[LINEMAX];
  728.                                 SPRINTF1(el, LINEMAX, "[DJNZ] Target out of range (%+i)", jmp);
  729.                                 Error(el); jmp = 0;
  730.                         }
  731.                         e[0] = 0x10; e[1] = jmp & 0xFF;
  732.                         EmitBytes(e);
  733.                 } while (Options::syx.MultiArg(lp));
  734.         }
  735.  
  736.         static void OpCode_EI() {
  737.                 EmitByte(0xfb);
  738.         }
  739.  
  740.         static void OpCode_EX() {
  741.                 int e[] { -1, -1, -1, -1 };
  742.                 Z80Reg reg = GetRegister(lp);
  743.                 switch (reg) {
  744.                 case Z80_AF:
  745.                         if (Options::IsI8080) break;
  746.                         if (comma(lp)) {
  747.                                 if (Z80_AF != GetRegister(lp)) break;
  748.                                 if (*lp == '\'') ++lp;
  749.                         }
  750.                         e[0] = 0x08;
  751.                         break;
  752.                 case Z80_DE:
  753.                 case Z80_HL:
  754.                         if (!comma(lp)) {
  755.                                 Error("[EX] Comma expected");
  756.                         } else {        // check for the other one: DE <-> HL
  757.                                 if (Z80Reg(reg ^ Z80_DE ^ Z80_HL) == GetRegister(lp)) e[0] = 0xeb;
  758.                         }
  759.                         break;
  760.                 default:
  761.                         if (BT_NONE == OpenBracket(lp) || Z80_SP != GetRegister(lp) || !CloseBracket(lp)) break;
  762.                         if (!comma(lp)) {
  763.                                 Error("[EX] Comma expected");
  764.                                 break;
  765.                         }
  766.                         switch (reg = GetRegister(lp)) {
  767.                         case Z80_HL:
  768.                                 e[0] = 0xe3; break;
  769.                         case Z80_IX:
  770.                         case Z80_IY:
  771.                                 e[0] = reg; e[1] = 0xe3; break;
  772.                         default:
  773.                                 ;
  774.                         }
  775.                 }
  776.                 EmitBytes(e);
  777.         }
  778.  
  779.         static void OpCode_EXA() {
  780.                 EmitByte(0x08);
  781.         }
  782.  
  783.         static void OpCode_EXD() {
  784.                 EmitByte(0xeb);
  785.         }
  786.  
  787.         static void OpCode_Next_EXIT() {        // this is fake instruction for CSpect emulator, not for real Z80N
  788.                 if (Options::syx.IsNextEnabled < 2) {
  789.                         Error("[EXIT] fake instruction \"exit\" must be specifically enabled by --zxnext=cspect option");
  790.                         return;
  791.                 }
  792.                 EmitByte(0xDD);
  793.                 EmitByte(0x00);
  794.         }
  795.  
  796.         static void OpCode_EXX() {
  797.                 EmitByte(0xd9);
  798.         }
  799.  
  800.         static void OpCode_HALT() {
  801.                 EmitByte(0x76);
  802.         }
  803.  
  804.         static void OpCode_IM() {
  805.                 int e[] { -1, -1, -1 }, machineCode[] { 0x46, 0x56, 0x5e };
  806.                 byte mode = GetByteNoMem(lp);
  807.                 if (mode <= 2) {
  808.                         e[0] = 0xed;
  809.                         e[1] = machineCode[mode];
  810.                 }
  811.                 EmitBytes(e);
  812.         }
  813.  
  814.         static void OpCode_IN() {
  815.                 do {
  816.                         int e[] { -1, -1, -1 };
  817.                         Z80Reg reg = GetRegister(lp);
  818.                         if (Z80_UNK == reg || comma(lp)) {
  819.                                 if (Z80_UNK == reg) reg = Z80_F;        // if there was no register, it may be "IN (C)"
  820.                                 if ((!Options::IsI8080) && NeedIoC()) {
  821.                                         e[0] = 0xed;
  822.                                         switch (reg) {
  823.                                                 case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L: case Z80_A:
  824.                                                         e[1] = 0x40 + reg*8;    // regular IN reg,(C)
  825.                                                         break;
  826.                                                 case Z80_F:
  827.                                                         e[1] = 0x70;                    // unofficial IN F,(C)
  828.                                                         break;
  829.                                                 default:
  830.                                                         e[0] = -1;                              // invalid combination
  831.                                                         break;
  832.                                         }
  833.                                 } else {
  834.                                         e[1] = GetByte(lp);
  835.                                         if (Z80_A == reg) e[0] = 0xdb;  // IN A,(n)
  836.                                 }
  837.                         }
  838.                         EmitBytes(e);
  839.                 } while (Options::syx.MultiArg(lp));
  840.         }
  841.  
  842.         static void OpCode_INC() {
  843.                 do {
  844.                         int e[] { -1, -1, -1, -1 };
  845.                         OpCode_DecInc(0x04, 0x03, e);
  846.                         EmitBytes(e);
  847.                 } while (Options::syx.MultiArg(lp));
  848.         }
  849.  
  850.         static void OpCode_IND() {
  851.                 EmitByte(0xED);
  852.                 EmitByte(0xAA);
  853.         }
  854.  
  855.         static void OpCode_INDR() {
  856.                 EmitByte(0xED);
  857.                 EmitByte(0xBA);
  858.         }
  859.  
  860.         static void OpCode_INI() {
  861.                 EmitByte(0xED);
  862.                 EmitByte(0xA2);
  863.         }
  864.  
  865.         static void OpCode_INIR() {
  866.                 EmitByte(0xED);
  867.                 EmitByte(0xB2);
  868.         }
  869.  
  870.         static void OpCode_INF() {
  871.                 EmitByte(0xED);
  872.                 EmitByte(0x70);
  873.         }
  874.  
  875.         static void OpCode_JP() {
  876.                 do {
  877.                         int e[] { -1, -1, -1, -1 };
  878.                         Z80Reg reg = Z80_UNK;
  879.                         Z80Cond cc = getz80cond(lp);
  880.                         if (Z80C_UNK == cc) {   // no condition, check for: jp (hl),... and Z80N jp (c)
  881.                                 char* expLp = lp;
  882.                                 if (Options::syx.IsNextEnabled && NeedIoC()) {
  883.                                         e[0] = 0xED; e[1] = 0x98;       // only "(C)" form with parentheses is legal syntax for Z80N "jp (C)"
  884.                                         reg = Z80_C;    // suppress "jp imm16" parser
  885.                                 } else {
  886.                                         EBracketType bt = OpenBracket(lp);
  887.                                         switch (reg = GetRegister(lp)) {
  888.                                         case Z80_HL: case Z80_IX: case Z80_IY:
  889.                                                 if (BT_NONE != bt && !CloseBracket(lp)) break;  // check [optional] brackets
  890.                                                 e[0] = reg;
  891.                                                 e[Z80_IX <= reg] = 0xe9;        // e[1] for IX/IY, e[0] overwritten for HL/MEM_HL
  892.                                                 break;
  893.                                         case Z80_MEM_HL: case Z80_MEM_IX: case Z80_MEM_IY:      // MEM_xx was handled manually, should NOT happen
  894.                                                 reg = Z80_UNK;                          // try to treat it like expression in following code
  895.                                         case Z80_UNK:
  896.                                                 if (BT_SQUARE == bt) break;     // "[" has no chance, report it
  897.                                                 if (BT_ROUND == bt) lp = expLp; // give "(" another chance to evaluate as expression
  898.                                                 e[0] = 0xc3;                            // jp imm16
  899.                                                 break;
  900.                                         default:                                                // any other register is illegal
  901.                                                 break;
  902.                                         }
  903.                                 }
  904.                         } else {        // if (Z80C_UNK == cc)
  905.                                 if (comma(lp)) e[0] = 0xC2 + cc;        // jp cc,imm16
  906.                                 else Error("[JP cc] Comma expected", bp);
  907.                         }
  908.                         // calculate the imm16 data
  909.                         if (Z80_UNK == reg) {
  910.                                 aint jpad;
  911.                                 GetAddress(lp, jpad);
  912.                                 check16(jpad);
  913.                                 e[1] = jpad & 255; e[2] = (jpad >> 8) & 255;
  914.                         }
  915.                         EmitBytes(e);
  916.                 } while (Options::syx.MultiArg(lp));
  917.         }
  918.  
  919.         static void OpCode_JR() {
  920.                 do {
  921.                         int e[] { -1, -1, -1, -1 };
  922.                         Z80Cond cc = getz80cond(lp);
  923.                         if (Z80C_UNK == cc) e[0] = 0x18;
  924.                         else if (cc <= Z80C_C) {
  925.                                 if (comma(lp)) e[0] = 0x20 + cc;
  926.                                 else Error("[JR cc] Comma expected", bp);
  927.                         } else {
  928.                                 Error("[JR] Illegal condition", bp);
  929.                                 SkipToEol(lp);
  930.                                 break;
  931.                         }
  932.                         aint jrad=0;
  933.                         if (GetAddress(lp, jrad)) jrad -= CurAddress + 2;
  934.                         if (jrad < -128 || jrad > 127) {
  935.                                 char el[LINEMAX];
  936.                                 SPRINTF1(el, LINEMAX, "[JR] Target out of range (%+i)", jrad);
  937.                                 Error(el);
  938.                                 jrad = 0;
  939.                         }
  940.                         e[1] = jrad & 0xFF;
  941.                         EmitBytes(e);
  942.                 } while (Options::syx.MultiArg(lp));
  943.         }
  944.  
  945.         static bool LD_simple_r_r(int* e, Z80Reg r1) {
  946.                 int prefix1 = 0, prefix2 = 0;
  947.                 bool eightBit = true;
  948.                 switch (r1) {
  949.                 case Z80_IXH:   case Z80_IXL:   case Z80_IYH:   case Z80_IYL:   case Z80_MEM_IX:        case Z80_MEM_IY:
  950.                         prefix1 = r1&0xFF;
  951.                         r1 = Z80Reg(r1>>8);
  952.                 case Z80_I:             case Z80_R:             case Z80_A:             case Z80_MEM_HL:
  953.                 case Z80_B:             case Z80_C:             case Z80_D:             case Z80_E:             case Z80_H:             case Z80_L:
  954.                 case LR35902_MEM_HL_I:  case LR35902_MEM_HL_D:
  955.                         break;
  956.                 case Z80_IY:    case Z80_IX:
  957.                         prefix1 = r1;
  958.                         r1 = Z80_HL;
  959.                 case Z80_BC:    case Z80_DE:    case Z80_HL:    case Z80_SP:
  960.                         eightBit = false;
  961.                         break;
  962.                 default:                // destination is not simple valid register
  963.                         return false;
  964.                 }
  965.                 if (!comma(lp)) return true;    // resolved as error
  966.                 char* olp = lp;
  967.                 Z80Reg r2 = GetRegister(lp);
  968.                 switch (r2) {
  969.                 case Z80_IXH:   case Z80_IXL:   case Z80_IYH:   case Z80_IYL:
  970.                         if (!eightBit || Z80_MEM_HL == r1) return true; // invalid combination
  971.                         prefix2 = r2&0xFF;
  972.                         r2 = Z80Reg(r2>>8);
  973.                         break;
  974.                 case Z80_I:             case Z80_R:             // resolve specials early
  975.                         if (Z80_A != r1) return true; // invalid combination
  976.                         *e++ = 0xED;    *e++ = Z80_I == r2 ? 0x57 : 0x5F;
  977.                         return true;
  978.                 case Z80_MEM_IX:        case Z80_MEM_IY:
  979.                         prefix2 = r2&0xFF;
  980.                         r2 = Z80Reg(r2>>8);                     // ,(ixy+d) has same logic as ,(hl) => fallthrough
  981.                 case Z80_MEM_HL:
  982.                         if (Z80_MEM_HL == r1 || prefix1) return true;   // (hl),(hl) is invalid, ixy,(hl) too
  983.                         if (Z80_BC == r1 || Z80_DE == r1 || (Z80_HL == r1 && prefix2)) {
  984.                                 lp = olp;
  985.                                 return false;   // ld bc|de,(hl) is possible fake ins., ld hl,(ixy) is possible fake
  986.                         }
  987.                 case Z80_A:
  988.                 case Z80_B:             case Z80_C:             case Z80_D:             case Z80_E:             case Z80_H:             case Z80_L:
  989.                         if (!eightBit) return true; // invalid combination
  990.                         if (LR35902_MEM_HL_I == r1 || LR35902_MEM_HL_D == r1) {
  991.                                 if (Z80_A == r2) *e = r1;       // `ld (hl+),a` or `ld (hl-),a`
  992.                                 return true;
  993.                         }
  994.                         break;
  995.                 case Z80_IY:    case Z80_IX:
  996.                         prefix2 = r2;
  997.                         r2 = Z80_HL;
  998.                 case Z80_BC:    case Z80_DE:
  999.                         if (!eightBit) break;           // ld r16, r16 -> resolve it
  1000.                         if (Z80_MEM_HL == r1) lp = olp; // ld (hl),bc|de are possible fake instructions
  1001.                         return (Z80_MEM_HL != r1);      // other 8b vs 16b are invalid combinations
  1002.                 case Z80_HL:
  1003.                         if (Z80_MEM_HL == r1 && prefix1) {
  1004.                                 lp = olp;
  1005.                                 return false;                   // ld (ixy),hl is possible fake instruction
  1006.                         }
  1007.                         if (!eightBit) break;           // ld r16, r16 -> resolve it
  1008.                 case Z80_SP:
  1009.                         if (Options::IsLR35902 && Z80_HL == r1) {
  1010.                                 lp = olp;
  1011.                                 return false;                   // LR35902 has "ld hl,sp+r8" syntax = check!
  1012.                         }
  1013.                         return true;                            // no other "ld r,SP" is valid (on other CPUs)
  1014.                 case Z80_AF: case Z80_F:
  1015.                         return true;                            // no simple "ld r,AF|F" (all invalid)
  1016.                 case LR35902_MEM_HL_I:  case LR35902_MEM_HL_D:
  1017.                         if (Z80_A == r1) *e = r2 + 0x08;
  1018.                         return true;
  1019.                 case Z80_UNK:           // source is not simple register
  1020.                         lp = olp;
  1021.                         return false;
  1022.                 }
  1023.                 //// r1 and r2 are now H/L/HL/MEM_HL for IXH/IXL/../IX/IY/MEM_IXY (only prefix1/prefix2 holds IXY info)
  1024.                 // resolve more specials early
  1025.                 if (Z80_I == r1 || Z80_R == r1) {       // ld i,a | ld r,a
  1026.                         if (Z80_A != r2) return true; // invalid combination
  1027.                         *e++ = 0xED;    *e++ = Z80_I == r1 ? 0x47 : 0x4F;
  1028.                         return true;
  1029.                 }
  1030.                 if (Z80_SP == r1) {                                     // ld sp,hl|ix|iy
  1031.                         if (Z80_HL == r2) {
  1032.                                 if (prefix2) *e++ = prefix2;
  1033.                                 *e++ = 0xF9;
  1034.                         }
  1035.                         return true;
  1036.                 }
  1037.                 if (!eightBit) {                                        // all possible ld r16,r16 (are fakes)
  1038.                         if (Options::noFakes()) return true;
  1039.                         // ld ix,iy | ld iy,ix | ld hl,ixy | ld ixy,hl => push + pop
  1040.                         if ((prefix1^prefix2) && (r1 == r2)) {
  1041.                                 if (prefix2) *e++ = prefix2;
  1042.                                 *e++ = 0xE5;
  1043.                                 if (prefix1) *e++ = prefix1;
  1044.                                 *e++ = 0xE1;
  1045.                                 return true;
  1046.                         }
  1047.                         // remaining standard "ld r16,r16"
  1048.                         if (prefix2) prefix1 = prefix2;         // any non-zero prefix is relevant here
  1049.                         if (prefix1) *e++ = prefix1;
  1050.                         *e++ = GetRegister_r16High(r2) + GetRegister_r16High(r1)*8 + 0x40;
  1051.                         if (prefix1) *e++ = prefix1;
  1052.                         *e++ = GetRegister_r16Low(r2) + GetRegister_r16Low(r1)*8 + 0x40;
  1053.                         return true;
  1054.                 }
  1055.                 // only eight bit simple "ld r8,r8" remains, but verify validity of IXY combinations
  1056.                 if ((prefix1 != prefix2) && (Z80_H == r1 || Z80_L == r1) && (Z80_H == r2 || Z80_L == r2)) {
  1057.                         return true;    // ld h|l|ixyhl,h|l|ixyhl is valid only when prefix1 == prefix2
  1058.                 }
  1059.                 if (prefix1|prefix2) {                                  // any non-zero prefix is relevant here
  1060.                         if (Z80_MEM_HL == r1 || Z80_MEM_HL == r2) e[2] = GetRegister_lastIxyD;  // "+d" byte
  1061.                         *e++ = prefix1|prefix2;
  1062.                 }
  1063.                 *e++ = r2 + r1*8 + 0x40;
  1064.                 return true;
  1065.         }
  1066.  
  1067.         static void LD_LR35902(int *e, const Z80Reg r2, const aint a16) {
  1068.                 // ld (a16),a|sp cases
  1069.                 e[1] = a16 & 255;                       // in any valid case this is correct
  1070.                 if (Z80_A == r2 && 0xFF00 <= a16 && a16 <= 0xFFFF) {    // "ldh a,(a8)" auto-magic detection
  1071.                         e[0] = 0xE0;
  1072.                         return;
  1073.                 }
  1074.                 e[2] = (a16 >> 8) & 255;        // in any remaining valid case this is correct
  1075.                 if (Z80_SP == r2) e[0] = 0x08;
  1076.                 else if (Z80_A == r2) e[0] = 0xEA;
  1077.         }
  1078.  
  1079.         static void OpCode_LD() {
  1080.                 aint b;
  1081.                 EBracketType bt;
  1082.                 do {
  1083.                         int e[] { -1, -1, -1, -1, -1, -1, -1 }, pemaRes;
  1084.                         Z80Reg reg2 = Z80_UNK, reg1 = GetRegister(lp);
  1085.                         // resolve all register to register cases or fixed memory literals
  1086.                         // "(hl)|(ixy+d)|(hl+)|(hl-)" (but not other memory or constant)
  1087.                         if (Z80_UNK != reg1 && LD_simple_r_r(e, reg1)) {
  1088.                                 EmitBytes(e);
  1089.                                 continue;
  1090.                         }
  1091.                         // memory, constant, fake instruction or syntax error is involved
  1092.                         // (!!! comma is already parsed for all destination=register cases)
  1093.                         switch (reg1) {
  1094.                         case Z80_A:
  1095.                                 if (BT_NONE != (bt = OpenBracket(lp))) {
  1096.                                         reg2 = GetRegister(lp);
  1097.                                         if ((Z80_BC == reg2 || Z80_DE == reg2) && CloseBracket(lp)) e[0] = reg2-6;
  1098.                                         else if (Z80_C == reg2 && Options::IsLR35902 && CloseBracket(lp)) {
  1099.                                                 e[0] = 0xF2;    // Sharp LR35902 `ld a,(c)` (targetting [$ff00+c])
  1100.                                         }
  1101.                                         if (Z80_UNK != reg2) break;     //"(register": emit instruction || bug
  1102.                                         // give non-register another chance to parse as value expression
  1103.                                         --lp;
  1104.                                 }
  1105.                                 switch (ParseExpressionMemAccess(lp, b)) {
  1106.                                         // LD a,imm8
  1107.                                         case 1: check8(b); e[0] = 0x06 + 8*reg1; e[1] = b & 255; break;
  1108.                                         // LD a,(mem8)
  1109.                                         case 2:
  1110.                                                 check16(b);
  1111.                                                 if (Options::IsLR35902) {
  1112.                                                         if (0xFF00 <= b && b <= 0xFFFF) {
  1113.                                                                 e[0] = 0xF0; e[1] = b & 255;
  1114.                                                         } else {
  1115.                                                                 e[0] = 0xFA; e[1] = b & 255; e[2] = (b >> 8) & 255;
  1116.                                                         }
  1117.                                                         break;
  1118.                                                 }
  1119.                                                 e[0] = 0x3a; e[1] = b & 255; e[2] = (b >> 8) & 255;
  1120.                                                 if (BT_ROUND == bt) checkLowMemory(e[2], e[1]);
  1121.                                                 break;
  1122.                                 }
  1123.                                 break;
  1124.  
  1125.                         case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1126.                                 e[0] = 0x06 + 8*reg1; e[1] = GetByteNoMem(lp);
  1127.                                 break;
  1128.  
  1129.                         case Z80_MEM_HL:
  1130.                                 switch (reg2 = GetRegister(lp)) {
  1131.                                 case Z80_BC: case Z80_DE:
  1132.                                         if (Options::noFakes()) break;
  1133.                                         e[0] = 0x70 + GetRegister_r16Low(reg2); e[1] = 0x23;
  1134.                                         e[2] = 0x70 + GetRegister_r16High(reg2); e[3] = 0x2b; break;
  1135.                                 case Z80_UNK:
  1136.                                         e[0] = 0x36; e[1] = GetByteNoMem(lp); break;
  1137.                                 default:
  1138.                                         break;
  1139.                                 }
  1140.                                 break;
  1141.  
  1142.                         case Z80_MEM_IX: case Z80_MEM_IY:
  1143.                                 e[2] = GetRegister_lastIxyD;
  1144.                                 switch (reg2 = GetRegister(lp)) {
  1145.                                 case Z80_BC: case Z80_DE: case Z80_HL:
  1146.                                         if (Options::noFakes()) break;          //fake LD (ixy+#),r16
  1147.                                         if (e[2] == 127) Error("Offset out of range", nullptr, IF_FIRST);
  1148.                                         e[0] = e[3] = reg1&0xFF; e[1] = 0x70+GetRegister_r16Low(reg2);
  1149.                                         e[4] = 0x70+GetRegister_r16High(reg2); e[5] = e[2] + 1;
  1150.                                         break;
  1151.                                 case Z80_UNK:
  1152.                                         e[0] = reg1&0xFF; e[1] = 0x36; e[3] = GetByteNoMem(lp); // LD (ixy+#),imm8
  1153.                                 default:
  1154.                                         break;
  1155.                                 }
  1156.                                 break;
  1157.  
  1158.                         case Z80_IXH: case Z80_IXL: case Z80_IYH: case Z80_IYL:
  1159.                                 e[0] = reg1&0xFF; e[1] = 0x06 + 8*(reg1>>8); e[2] = GetByteNoMem(lp);
  1160.                                 break;
  1161.  
  1162.                         case Z80_BC: case Z80_DE: case Z80_HL: case Z80_SP:
  1163.                                 switch (reg2 = GetRegister(lp)) {
  1164.                                 case Z80_MEM_HL:        // invalid combinations filtered already by LD_simple_r_r
  1165.                                         if (Options::noFakes()) break;
  1166.                                         e[0] = reg1+0x3e; e[1] = 0x23; e[2] = reg1+0x36; e[3] = 0x2b;
  1167.                                         break;
  1168.                                 case Z80_MEM_IX: case Z80_MEM_IY:       // invalid combinations NOT filtered -> validate
  1169.                                         if (Z80_SP == reg1 || Options::noFakes()) break;
  1170.                                         e[1] = reg1+0x3e; e[4] = reg1+0x36; e[2] = GetRegister_lastIxyD; e[5] = e[2]+1;
  1171.                                         if (e[2] == 127) Error("Offset out of range", nullptr, IF_FIRST);
  1172.                                         else e[0] = e[3] = reg2&0xFF;
  1173.                                         break;
  1174.                                 case Z80_SP:
  1175.                                         if (Options::IsLR35902 && Z80_HL == reg1) {             // "ld hl,sp+r8" syntax = "F8 r8"
  1176.                                                 b = 0;
  1177.                                                 // "sp" must be followed by + or - (or nothing: "ld hl,sp" = +0)
  1178.                                                 if (!SkipBlanks(lp) && ',' != *lp ) {           // comma is probably multi-arg
  1179.                                                         if ('+' != *lp && '-' != *lp) {
  1180.                                                                 Error("[LD] `ld hl,sp+r8` expects + or - after sp, found", lp);
  1181.                                                                 break;
  1182.                                                         }
  1183.                                                         b = GetByteNoMem(lp, true);
  1184.                                                 }
  1185.                                                 e[0] = 0xF8;
  1186.                                                 e[1] = b;
  1187.                                         }
  1188.                                         break;
  1189.                                 default:
  1190.                                         break;
  1191.                                 }
  1192.                                 if (Z80_UNK != reg2) break;     //"(register": emit instruction || bug
  1193.                                 switch (ParseExpressionMemAccess(lp, b)) {
  1194.                                         // ld bc|de|hl|sp,imm16
  1195.                                         case 1: check16(b); e[0] = reg1-0x0F; e[1] = b & 255; e[2] = (b >> 8) & 255; break;
  1196.                                         // LD r16,(mem16)
  1197.                                         case 2:
  1198.                                                 if (Options::IsLR35902) break;  // no "ld r16,(a16)" instruction on LR35902
  1199.                                                 check16(b);
  1200.                                                 if (Z80_HL == reg1) {           // ld hl,(mem16)
  1201.                                                         e[0] = 0x2a; e[1] = b & 255; e[2] = (b >> 8) & 255;
  1202.                                                 } else {                                        // ld bc|de|sp,(mem16)
  1203.                                                         if (Options::IsI8080) break;
  1204.                                                         e[0] = 0xed; e[1] = reg1+0x3b; e[2] = b & 255; e[3] = (b >> 8) & 255;
  1205.                                                 }
  1206.                                                 if (')' == lp[-1]) checkLowMemory(b>>8, b);
  1207.                                 }
  1208.                                 break;
  1209.  
  1210.                         case Z80_IX:
  1211.                         case Z80_IY:
  1212.                                 if (0 < (pemaRes = ParseExpressionMemAccess(lp, b))) {
  1213.                                         e[0] = reg1; e[1] = (1 == pemaRes) ? 0x21 : 0x2a;       // ld ix|iy,imm16  ||  ld ix|iy,(mem16)
  1214.                                         check16(b); e[2] = b & 255; e[3] = (b >> 8) & 255;
  1215.                                         if ((2 == pemaRes) && ')' == lp[-1]) checkLowMemory(e[3], e[2]);
  1216.                                 }
  1217.                                 break;
  1218.  
  1219.                         case Z80_UNK:
  1220.                                 if (BT_NONE == OpenBracket(lp)) break;
  1221.                                 reg1 = GetRegister(lp);
  1222.                                 if (Z80_UNK == reg1) b = GetWord(lp);
  1223.                                 if (!CloseBracket(lp) || !comma(lp)) break;
  1224.                                 reg2 = GetRegister(lp);
  1225.                                 switch (reg1) {
  1226.                                 case Z80_C:
  1227.                                         if (Options::IsLR35902 && Z80_A == reg2) {      // Sharp LR35902 `ld (c),a` (targetting [$ff00+c])
  1228.                                                 e[0] = 0xE2;
  1229.                                         }
  1230.                                         break;
  1231.                                 case Z80_BC:
  1232.                                 case Z80_DE:
  1233.                                         if (Z80_A == reg2) e[0] = reg1-14;      // LD (bc|de),a
  1234.                                         break;
  1235.                                 case Z80_UNK:
  1236.                                         if (Options::IsLR35902) {       // Sharp LR35902 has quite different opcodes for these
  1237.                                                 LD_LR35902(e, reg2, b);
  1238.                                                 break;
  1239.                                         }
  1240.                                         // Standard Z80 and i8080 opcodes for ld (nn),reg
  1241.                                         switch (reg2) {
  1242.                                         case Z80_A:             // LD (nnnn),a|hl
  1243.                                         case Z80_HL:
  1244.                                                 e[0] = (Z80_A == reg2) ? 0x32 : 0x22; e[1] = b & 255; e[2] = (b >> 8) & 255; break;
  1245.                                         case Z80_BC:    // LD (nnnn),bc|de|sp
  1246.                                         case Z80_DE:
  1247.                                         case Z80_SP:
  1248.                                                 if (Options::IsI8080) break;
  1249.                                                 e[0] = 0xed; e[1] = 0x33+reg2; e[2] = b & 255; e[3] = (b >> 8) & 255; break;
  1250.                                         case Z80_IX:    // LD (nnnn),ix|iy
  1251.                                         case Z80_IY:
  1252.                                                 e[0] = reg2; e[1] = 0x22; e[2] = b & 255; e[3] = (b >> 8) & 255; break;
  1253.                                         default:
  1254.                                                 break;
  1255.                                         }
  1256.                                         break;
  1257.                                 default:
  1258.                                         break;
  1259.                                 }
  1260.                                 break;
  1261.                         default:
  1262.                                 break;
  1263.                         }
  1264.                         EmitBytes(e);
  1265.                 } while (Options::syx.MultiArg(lp));
  1266.         }
  1267.  
  1268.         static void OpCode_LR35902_LDD() {
  1269.                 // ldd (hl),a = ld (hl-),a = 0x32
  1270.                 // ldd a,(hl) = ld a,(hl-) = 0x3A
  1271.                 do {
  1272.                         int e[] { -1, -1 };
  1273.                         const Z80Reg r1 = GetRegister(lp);
  1274.                         const bool comma_ok = comma(lp);
  1275.                         const Z80Reg r2 = comma_ok ? GetRegister(lp) : Z80_UNK;
  1276.                         if (Z80_MEM_HL == r1 && Z80_A == r2) e[0] = 0x32;
  1277.                         if (Z80_A == r1 && Z80_MEM_HL == r2) e[0] = 0x3A;
  1278.                         EmitBytes(e);
  1279.                 } while (Options::syx.MultiArg(lp));
  1280.         }
  1281.  
  1282.         static void OpCode_LDD() {
  1283.                 if (Options::noFakes(false)) {
  1284.                         EmitByte(0xED);
  1285.                         EmitByte(0xA8);
  1286.                         return;
  1287.                 }
  1288.  
  1289.                 // only when fakes are enabled (but they may be silent/warning enabled, so extra checks needed)
  1290.                 do {
  1291.                         int e[] { -1, -1, -1, -1, -1, -1, -1};
  1292.                         Z80Reg reg2 = Z80_UNK, reg = GetRegister(lp);
  1293.                         switch (reg) {
  1294.                         case Z80_A:
  1295.                                 if (!comma(lp)) break;
  1296.                                 if (BT_NONE == OpenBracket(lp)) break;
  1297.                                 Options::noFakes();             // to display warning if "-f"
  1298.                                 switch (reg = GetRegister(lp)) {
  1299.                                 case Z80_BC:    // 0x0A 0x0B
  1300.                                 case Z80_DE:    // 0x1A 0x1B
  1301.                                         e[1] = reg-5; if (CloseBracket(lp)) e[0] = reg-6;
  1302.                                         break;
  1303.                                 case Z80_HL:    // 0x7E 0x2B
  1304.                                         e[1] = 0x2b; if (CloseBracket(lp)) e[0] = 0x7e;
  1305.                                         break;
  1306.                                 case Z80_IX: case Z80_IY:
  1307.                                         e[1] = 0x7e; e[2] = z80GetIDxoffset(lp); e[4] = 0x2b;
  1308.                                         if (CloseBracket(lp)) e[0] = e[3] = reg;
  1309.                                         break;
  1310.                                 default:
  1311.                                         break;
  1312.                                 }
  1313.                                 break;
  1314.                         case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1315.                                 if (!comma(lp)) break;
  1316.                                 switch (reg2 = GetRegister(lp)) {
  1317.                                 case Z80_MEM_HL:
  1318.                                         Options::noFakes();             // to display warning if "-f"
  1319.                                         e[0] = 0x46 + reg * 8; e[1] = 0x2b;
  1320.                                         break;
  1321.                                 case Z80_MEM_IX: case Z80_MEM_IY:
  1322.                                         Options::noFakes();             // to display warning if "-f"
  1323.                                         e[0] = e[3] = reg2&0xFF; e[1] = 0x46 + reg * 8; e[2] = GetRegister_lastIxyD; e[4] = 0x2b;
  1324.                                         break;
  1325.                                 default:
  1326.                                         break;
  1327.                                 }
  1328.                                 break;
  1329.                         case Z80_MEM_HL:
  1330.                                 if (!comma(lp)) break;
  1331.                                 switch (reg = GetRegister(lp)) {
  1332.                                 case Z80_A: case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1333.                                         Options::noFakes();             // to display warning if "-f"
  1334.                                         e[0] = 0x70 + reg; e[1] = 0x2b; break;
  1335.                                 case Z80_UNK:
  1336.                                         Options::noFakes();             // to display warning if "-f"
  1337.                                         e[0] = 0x36; e[1] = GetByteNoMem(lp); e[2] = 0x2b; break;
  1338.                                 default:
  1339.                                         break;
  1340.                                 }
  1341.                                 break;
  1342.                         case Z80_MEM_IX: case Z80_MEM_IY:
  1343.                                 if (!comma(lp)) break;
  1344.                                 switch (reg2 = GetRegister(lp)) {
  1345.                                 case Z80_A: case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1346.                                         Options::noFakes();             // to display warning if "-f"
  1347.                                         e[0] = e[3] = reg&0xFF; e[2] = GetRegister_lastIxyD; e[1] = 0x70 + reg2; e[4] = 0x2b; break;
  1348.                                 case Z80_UNK:
  1349.                                         Options::noFakes();             // to display warning if "-f"
  1350.                                         e[0] = e[4] = reg&0xFF; e[1] = 0x36; e[2] = GetRegister_lastIxyD; e[3] = GetByteNoMem(lp); e[5] = 0x2b; break;
  1351.                                 default:
  1352.                                         break;
  1353.                                 }
  1354.                                 break;
  1355.                         default:
  1356.                                 if (BT_NONE != OpenBracket(lp)) {
  1357.                                         reg = GetRegister(lp);
  1358.                                         if (!CloseBracket(lp) || !comma(lp)) break;
  1359.                                         if ((Z80_BC != reg && Z80_DE != reg) || Z80_A != GetRegister(lp)) break;
  1360.                                         Options::noFakes();             // to display warning if "-f"
  1361.                                         e[0] = reg - 14; e[1] = reg - 5;        // LDD (bc|de),a
  1362.                                 } else {
  1363.                                         e[0] = 0xed; e[1] = 0xa8;                       // regular LDD
  1364.                                 }
  1365.                         }
  1366.                         EmitBytes(e);
  1367.                 } while (Options::syx.MultiArg(lp));
  1368.         }
  1369.  
  1370.         static void OpCode_LDDR() {
  1371.                 EmitByte(0xED);
  1372.                 EmitByte(0xB8);
  1373.         }
  1374.  
  1375.         static void OpCode_Next_LDDRX() {
  1376.                 if (Options::syx.IsNextEnabled < 1) {
  1377.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1378.                         return;
  1379.                 }
  1380.                 EmitByte(0xED);
  1381.                 EmitByte(0xBC);
  1382.         }
  1383.  
  1384.         static void OpCode_Next_LDDX() {
  1385.                 if (Options::syx.IsNextEnabled < 1) {
  1386.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1387.                         return;
  1388.                 }
  1389.                 EmitByte(0xED);
  1390.                 EmitByte(0xAC);
  1391.         }
  1392.  
  1393.         static void OpCode_LR35902_LDH() {
  1394.                 // ldh (a8),a = ld ($FF00+a8),a = "E0 a8"
  1395.                 // ldh a,(a8) = ld a,($FF00+a8) = "F0 a8"
  1396.                 do {
  1397.                         int e[] { -1, -1, -1 }, pemaRes = 0;
  1398.                         aint a8 = -1;
  1399.                         // parse two arguments, expected are "a,(n)" or "(n),a", others will fail in some stage
  1400.                         const Z80Reg r1 = GetRegister(lp);
  1401.                         if (Z80_UNK == r1) pemaRes = ParseExpressionMemAccess(lp, a8);
  1402.                         const bool comma_ok = (Z80_A == r1 || 0 < pemaRes) && comma(lp);
  1403.                         const Z80Reg r2 = comma_ok ? GetRegister(lp) : Z80_F;   // "F" as fail (UNK is legit result)
  1404.                         if (Z80_UNK == r2 && Z80_A == r1) pemaRes = ParseExpressionMemAccess(lp, a8);
  1405.                         else if (Z80_A != r2) pemaRes = 0;
  1406.                         // here pemaRes must be non-zero when valid combination was parsed
  1407.                         switch (pemaRes) {
  1408.                                 case 0:         // syntax error, or wrong registers combined with "ldh"
  1409.                                 case 1:         // immediate is also error, should have been memory
  1410.                                         Error("[LDH] only valid combinations: `ldh a,(a8)` or `ldh (a8),a`", lp, SUPPRESS);
  1411.                                         break;
  1412.                                 case 2:
  1413.                                         if (0xFF00 <= a8 && a8 <= 0xFFFF) a8 -= 0xFF00; // normalize a8 if "ldh a,($FFxx)" was used
  1414.                                         check8(a8);
  1415.                                         e[0] = (Z80_A == r2) ? 0xE0 : 0xF0;
  1416.                                         e[1] = a8 & 0xFF;
  1417.                                         break;
  1418.                         }
  1419.                         EmitBytes(e);
  1420.                 } while (Options::syx.MultiArg(lp));
  1421.         }
  1422.  
  1423.         static void OpCode_LR35902_LDI() {
  1424.                 // ldi (hl),a = ld (hl+),a = 0x22
  1425.                 // ldi a,(hl) = ld a,(hl+) = 0x2A
  1426.                 do {
  1427.                         int e[] { -1, -1 };
  1428.                         const Z80Reg r1 = GetRegister(lp);
  1429.                         const bool comma_ok = comma(lp);
  1430.                         const Z80Reg r2 = comma_ok ? GetRegister(lp) : Z80_UNK;
  1431.                         if (Z80_MEM_HL == r1 && Z80_A == r2) e[0] = 0x22;
  1432.                         if (Z80_A == r1 && Z80_MEM_HL == r2) e[0] = 0x2A;
  1433.                         EmitBytes(e);
  1434.                 } while (Options::syx.MultiArg(lp));
  1435.         }
  1436.  
  1437.         static void OpCode_LDI() {
  1438.                 if (Options::noFakes(false)) {
  1439.                         EmitByte(0xED);
  1440.                         EmitByte(0xA0);
  1441.                         return;
  1442.                 }
  1443.  
  1444.                 // only when fakes are enabled (but they may be silent/warning enabled, so extra checks needed)
  1445.                 do {
  1446.                         int e[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
  1447.                         Z80Reg reg2 = Z80_UNK, reg = GetRegister(lp);
  1448.                         switch (reg) {
  1449.                         case Z80_A:
  1450.                                 if (!comma(lp)) break;
  1451.                                 if (BT_NONE == OpenBracket(lp)) break;
  1452.                                 Options::noFakes();             // to display warning if "-f"
  1453.                                 switch (reg = GetRegister(lp)) {
  1454.                                 case Z80_BC:    // 0A 03
  1455.                                 case Z80_DE:    // 1A 13
  1456.                                         if (CloseBracket(lp)) e[0] = reg - Z80_BC + 0x0a;
  1457.                                         e[1] = reg - Z80_BC + 0x03;
  1458.                                         break;
  1459.                                 case Z80_HL:
  1460.                                         e[1] = 0x23; if (CloseBracket(lp)) e[0] = 0x7e;
  1461.                                         break;
  1462.                                 case Z80_IX:
  1463.                                 case Z80_IY:
  1464.                                         e[1] = 0x7e; e[4] = 0x23; e[2] = z80GetIDxoffset(lp);
  1465.                                         if (CloseBracket(lp)) e[0] = e[3] = reg;
  1466.                                         break;
  1467.                                 default:
  1468.                                         break;
  1469.                                 }
  1470.                                 break;
  1471.                         case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1472.                                 if (!comma(lp)) break;
  1473.                                 if (BT_NONE == OpenBracket(lp)) break;
  1474.                                 Options::noFakes();             // to display warning if "-f"
  1475.                                 switch (reg2 = GetRegister(lp)) {
  1476.                                 case Z80_HL:
  1477.                                         e[1] = 0x23; if (CloseBracket(lp)) e[0] = 0x46 + reg * 8;
  1478.                                         break;
  1479.                                 case Z80_IX:
  1480.                                 case Z80_IY:
  1481.                                         e[1] = 0x46 + reg * 8; e[4] = 0x23; e[2] = z80GetIDxoffset(lp);
  1482.                                         if (CloseBracket(lp)) e[0] = e[3] = reg2;
  1483.                                         break;
  1484.                                 default:
  1485.                                         break;
  1486.                                 }
  1487.                                 break;
  1488.                         case Z80_BC: case Z80_DE: case Z80_HL:
  1489.                                 if (!comma(lp)) break;
  1490.                                 switch (reg2 = GetRegister(lp)) {
  1491.                                 case Z80_MEM_HL:
  1492.                                         if (Z80_HL == reg) break;
  1493.                                         Options::noFakes();             // to display warning if "-f"
  1494.                                         e[0] = 0x3e + reg; e[1] = e[3] = 0x23; e[2] = 0x36 + reg;
  1495.                                         break;
  1496.                                 case Z80_MEM_IX: case Z80_MEM_IY:
  1497.                                         Options::noFakes();             // to display warning if "-f"
  1498.                                         e[2] = e[7] = GetRegister_lastIxyD;
  1499.                                         e[0] = e[3] = e[5] = e[8] = reg2&0xFF;
  1500.                                         e[1] = 0x3e + reg; e[6] = 0x36 + reg; e[4] = e[9] = 0x23;
  1501.                                         break;
  1502.                                 default:
  1503.                                         break;
  1504.                                 }
  1505.                                 break;
  1506.                         case Z80_MEM_HL:
  1507.                                 if (!comma(lp)) break;
  1508.                                 switch (reg = GetRegister(lp)) {
  1509.                                 case Z80_A: case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1510.                                         Options::noFakes();             // to display warning if "-f"
  1511.                                         e[0] = 0x70 + reg; e[1] = 0x23; break;
  1512.                                 case Z80_BC: case Z80_DE:
  1513.                                         Options::noFakes();             // to display warning if "-f"
  1514.                                         e[0] = 0x70 + GetRegister_r16Low(reg); e[2] = 0x70 + GetRegister_r16High(reg);
  1515.                                         e[1] = e[3] = 0x23; break;
  1516.                                 case Z80_UNK:
  1517.                                         Options::noFakes();             // to display warning if "-f"
  1518.                                         e[0] = 0x36; e[1] = GetByteNoMem(lp); e[2] = 0x23; break;
  1519.                                 default:
  1520.                                         break;
  1521.                                 }
  1522.                                 break;
  1523.                         case Z80_MEM_IX: case Z80_MEM_IY:
  1524.                                 if (!comma(lp)) break;
  1525.                                 switch (reg2 = GetRegister(lp)) {
  1526.                                 case Z80_A: case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L:
  1527.                                         Options::noFakes();             // to display warning if "-f"
  1528.                                         e[0] = e[3] = reg&0xFF; e[2] = GetRegister_lastIxyD; e[1] = 0x70 + reg2; e[4] = 0x23; break;
  1529.                                 case Z80_BC: case Z80_DE: case Z80_HL:
  1530.                                         Options::noFakes();             // to display warning if "-f"
  1531.                                         e[0] = e[3] = e[5] = e[8] = reg&0xFF; e[4] = e[9] = 0x23; e[2] = e[7] = GetRegister_lastIxyD;
  1532.                                         e[1] = 0x70 + GetRegister_r16Low(reg2); e[6] = 0x70 + GetRegister_r16High(reg2); break;
  1533.                                 case Z80_UNK:
  1534.                                         Options::noFakes();             // to display warning if "-f"
  1535.                                         e[0] = e[4] = reg&0xFF; e[1] = 0x36; e[2] = GetRegister_lastIxyD; e[3] = GetByteNoMem(lp); e[5] = 0x23; break;
  1536.                                 default:
  1537.                                         break;
  1538.                                 }
  1539.                                 break;
  1540.                         default:
  1541.                                 if (BT_NONE != OpenBracket(lp)) {
  1542.                                         reg = GetRegister(lp);
  1543.                                         if (!CloseBracket(lp) || !comma(lp)) break;
  1544.                                         if ((Z80_BC != reg && Z80_DE != reg) || Z80_A != GetRegister(lp)) break;
  1545.                                         Options::noFakes();
  1546.                                         e[0] = reg - 14; e[1] = reg - 13;       // LDI (bc|de),a
  1547.                                 } else {
  1548.                                         e[0] = 0xed; e[1] = 0xa0;                       // regular LDI
  1549.                                 }
  1550.                         }
  1551.  
  1552.                         EmitBytes(e);
  1553.                 } while (Options::syx.MultiArg(lp));
  1554.         }
  1555.  
  1556.         static void OpCode_LDIR() {
  1557.                 EmitByte(0xED);
  1558.                 EmitByte(0xB0);
  1559.         }
  1560.  
  1561. // LDIRSCALE is now very unlikely to happen, there's ~1% chance it may be introduced within the cased-Next release
  1562. //      static void OpCode_Next_LDIRSCALE() {
  1563. //              if (Options::syx.IsNextEnabled < 1) {
  1564. //                      Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1565. //                      return;
  1566. //              }
  1567. //              EmitByte(0xED);
  1568. //              EmitByte(0xB6);
  1569. //      }
  1570.  
  1571.         static void OpCode_Next_LDIRX() {
  1572.                 if (Options::syx.IsNextEnabled < 1) {
  1573.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1574.                         return;
  1575.                 }
  1576.                 EmitByte(0xED);
  1577.                 EmitByte(0xB4);
  1578.         }
  1579.  
  1580.         static void OpCode_Next_LDIX() {
  1581.                 if (Options::syx.IsNextEnabled < 1) {
  1582.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1583.                         return;
  1584.                 }
  1585.                 EmitByte(0xED);
  1586.                 EmitByte(0xA4);
  1587.         }
  1588.  
  1589.         static void OpCode_Next_LDPIRX() {
  1590.                 if (Options::syx.IsNextEnabled < 1) {
  1591.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1592.                         return;
  1593.                 }
  1594.                 EmitByte(0xED);
  1595.                 EmitByte(0xB7);
  1596.         }
  1597.  
  1598.         static void OpCode_Next_LDWS() {
  1599.                 if (Options::syx.IsNextEnabled < 1) {
  1600.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1601.                         return;
  1602.                 }
  1603.                 EmitByte(0xED);
  1604.                 EmitByte(0xA5);
  1605.         }
  1606.  
  1607.         static void OpCode_Next_MIRROR() {
  1608.                 if (Options::syx.IsNextEnabled < 1) {
  1609.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1610.                         return;
  1611.                 }
  1612.                 Z80Reg reg = GetRegister(lp);
  1613.                 if (Z80_UNK != reg && Z80_A != reg) {
  1614.                         Error("[MIRROR] Illegal operand (can be only register A)", line);
  1615.                         return;
  1616.                 }
  1617.                 EmitByte(0xED);
  1618.                 EmitByte(0x24);
  1619.         }
  1620.  
  1621.         static void OpCode_Next_MUL() {
  1622.                 if (Options::syx.IsNextEnabled < 1) {
  1623.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1624.                         return;
  1625.                 }
  1626.                 int e[3] { -1, -1, -1 };
  1627.                 Z80Reg r1 = GetRegister(lp);
  1628.                 if (Z80_UNK == r1 && SkipBlanks(lp) && !Options::noFakes()) {
  1629.                         r1 = Z80_DE;    // "mul" without arguments is treated as "fake" "mul de"
  1630.                 }
  1631.                 // "mul de" and "mul d,e" are both valid syntax options
  1632.                 if ((Z80_DE==r1) || (Z80_D==r1 && comma(lp) && Z80_E==GetRegister(lp))) {
  1633.                         e[0]=0xED;
  1634.                         e[1]=0x30;
  1635.                 } else {
  1636.                         Error("Z80N MUL exist only with \"D,E\" arguments", bp, SUPPRESS);
  1637.                         return;
  1638.                 }
  1639.                 EmitBytes(e);
  1640.         }
  1641.  
  1642.         static void OpCode_MULUB() {
  1643.                 Z80Reg reg;
  1644.                 int e[3];
  1645.                 e[0] = e[1] = e[2] = -1;
  1646.                 if ((reg = GetRegister(lp)) == Z80_A && comma(lp)) {
  1647.                         reg = GetRegister(lp);
  1648.                 }
  1649.                 switch (reg) {
  1650.                 case Z80_B:
  1651.                         e[0] = 0xed; e[1] = 0xc1; break;
  1652.                 case Z80_C:
  1653.                         e[0] = 0xed; e[1] = 0xc9; break;
  1654.                 case Z80_D:
  1655.                         e[0] = 0xed; e[1] = 0xd1; break;
  1656.                 case Z80_E:
  1657.                         e[0] = 0xed; e[1] = 0xd9; break;
  1658.                 default:
  1659.                         ;
  1660.                 }
  1661.                 EmitBytes(e);
  1662.         }
  1663.  
  1664.         static void OpCode_MULUW() {
  1665.                 Z80Reg reg;
  1666.                 int e[3];
  1667.                 e[0] = e[1] = e[2] = -1;
  1668.                 if ((reg = GetRegister(lp)) == Z80_HL && comma(lp)) {
  1669.                         reg = GetRegister(lp);
  1670.                 }
  1671.                 switch (reg) {
  1672.                 case Z80_BC:
  1673.                         e[0] = 0xed; e[1] = 0xc3; break;
  1674.                 case Z80_SP:
  1675.                         e[0] = 0xed; e[1] = 0xf3; break;
  1676.                 default:
  1677.                         ;
  1678.                 }
  1679.                 EmitBytes(e);
  1680.         }
  1681.  
  1682.         static void OpCode_NEG() {
  1683.                 EmitByte(0xED);
  1684.                 EmitByte(0x44);
  1685.         }
  1686.  
  1687.         static void OpCode_Next_NEXTREG() {
  1688.                 if (Options::syx.IsNextEnabled < 1) {
  1689.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1690.                         return;
  1691.                 }
  1692.                 Z80Reg reg;
  1693.                 int e[5];
  1694.                 do {
  1695.                         e[0] = e[1] = e[2] = e[3] = e[4] = -1;
  1696.                         // is operand1 register? (to give more precise error message to people using wrong `nextreg a,$nn`)
  1697.                         reg = GetRegister(lp);
  1698.                         if (Z80_UNK != reg) {
  1699.                                 Error("[NEXTREG] first operand should be register number", line, SUPPRESS); break;
  1700.                         }
  1701.                         // this code would be enough to get correct assembling, the test above is "extra"
  1702.                         e[2] = GetByteNoMem(lp);
  1703.                         if (!comma(lp)) {
  1704.                                 Error("[NEXTREG] Comma expected"); break;
  1705.                         }
  1706.                         switch (reg = GetRegister(lp)) {
  1707.                                 case Z80_A:
  1708.                                         e[0] = 0xED; e[1] = 0x92;
  1709.                                         break;
  1710.                                 case Z80_UNK:
  1711.                                         e[0] = 0xED; e[1] = 0x91;
  1712.                                         e[3] = GetByteNoMem(lp);
  1713.                                         break;
  1714.                                 default:
  1715.                                         break;
  1716.                         }
  1717.                         EmitBytes(e);
  1718.                 } while (Options::syx.MultiArg(lp));
  1719.         }
  1720.  
  1721.         static void OpCode_NOP() {
  1722.                 EmitByte(0x0);
  1723.         }
  1724.  
  1725.         static void OpCode_OR() {
  1726.                 do {
  1727.                         int e[] { -1, -1, -1, -1};
  1728.                         CommonAluOpcode(0xb0, e);
  1729.                         EmitBytes(e);
  1730.                 } while (Options::syx.MultiArg(lp));
  1731.         }
  1732.  
  1733.         static void OpCode_OTDR() {
  1734.                 EmitByte(0xED);
  1735.                 EmitByte(0xBB);
  1736.         }
  1737.  
  1738.         static void OpCode_OTIR() {
  1739.                 EmitByte(0xED);
  1740.                 EmitByte(0xB3);
  1741.         }
  1742.  
  1743.         static void OpCode_OUT() {
  1744.                 Z80Reg reg;
  1745.                 do {
  1746.                         int e[] { -1, -1, -1 };
  1747.                         if ((!Options::IsI8080) && NeedIoC()) {
  1748.                                 if (comma(lp)) {
  1749.                                         switch (reg = GetRegister(lp)) {
  1750.                                         case Z80_B: case Z80_C: case Z80_D: case Z80_E: case Z80_H: case Z80_L: case Z80_A:
  1751.                                                 e[0] = 0xed; e[1] = 0x41 + 8 * reg; break;
  1752.                                         case Z80_UNK:
  1753.                                                 if (0 == GetByteNoMem(lp)) e[0] = 0xed; // out (c),0
  1754.                                                 e[1] = 0x71; break;
  1755.                                         default:
  1756.                                                 break;
  1757.                                         }
  1758.                                 }
  1759.                         } else {
  1760.                                 e[1] = GetByte(lp);             // out ($n),a
  1761.                                 if (comma(lp) && GetRegister(lp) == Z80_A) e[0] = 0xd3;
  1762.                         }
  1763.                         EmitBytes(e);
  1764.                 } while (Options::syx.MultiArg(lp));
  1765.         }
  1766.  
  1767.         static void OpCode_OUTD() {
  1768.                 EmitByte(0xED);
  1769.                 EmitByte(0xAB);
  1770.         }
  1771.  
  1772.         static void OpCode_OUTI() {
  1773.                 EmitByte(0xED);
  1774.                 EmitByte(0xA3);
  1775.         }
  1776.  
  1777.         static void OpCode_Next_OUTINB() {
  1778.                 if (Options::syx.IsNextEnabled < 1) {
  1779.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1780.                         return;
  1781.                 }
  1782.                 EmitByte(0xED);
  1783.                 EmitByte(0x90);
  1784.         }
  1785.  
  1786.         static void OpCode_Next_PIXELAD() {
  1787.                 if (Options::syx.IsNextEnabled < 1) {
  1788.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1789.                         return;
  1790.                 }
  1791.                 char *oldLp = lp;
  1792.                 if (Z80_HL != GetRegister(lp)) lp = oldLp;              // "eat" explicit HL argument
  1793.                 EmitByte(0xED);
  1794.                 EmitByte(0x94);
  1795.         }
  1796.  
  1797.         static void OpCode_Next_PIXELDN() {
  1798.                 if (Options::syx.IsNextEnabled < 1) {
  1799.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  1800.                         return;
  1801.                 }
  1802.                 char *oldLp = lp;
  1803.                 if (Z80_HL != GetRegister(lp)) lp = oldLp;              // "eat" explicit HL argument
  1804.                 EmitByte(0xED);
  1805.                 EmitByte(0x93);
  1806.         }
  1807.  
  1808.         static void OpCode_POPreverse() {
  1809.                 int e[30],t = 29,c = 1;
  1810.                 e[t] = -1;
  1811.                 do {
  1812.                         switch (GetRegister(lp)) {
  1813.                         case Z80_AF:
  1814.                                 e[--t] = 0xf1; break;
  1815.                         case Z80_BC:
  1816.                                 e[--t] = 0xc1; break;
  1817.                         case Z80_DE:
  1818.                                 e[--t] = 0xd1; break;
  1819.                         case Z80_HL:
  1820.                                 e[--t] = 0xe1; break;
  1821.                         case Z80_IX:
  1822.                                 e[--t] = 0xe1; e[--t] = 0xdd; break;
  1823.                         case Z80_IY:
  1824.                                 e[--t] = 0xe1; e[--t] = 0xfd; break;
  1825.                         default:
  1826.                                 c = 0; break;
  1827.                         }
  1828.                 } while (c && 2 <= t && Options::syx.MultiArg(lp));
  1829.                 EmitBytes(&e[t]);
  1830.         }
  1831.  
  1832.         static void OpCode_POPnormal() {
  1833.                 Z80Reg reg;
  1834.                 do {
  1835.                         int e[3];
  1836.                         e[0] = e[1] = e[2] = -1;
  1837.                         switch (reg = GetRegister(lp)) {
  1838.                         case Z80_AF:
  1839.                                 e[0] = 0xf1; break;
  1840.                         case Z80_BC:
  1841.                                 e[0] = 0xc1; break;
  1842.                         case Z80_DE:
  1843.                                 e[0] = 0xd1; break;
  1844.                         case Z80_HL:
  1845.                                 e[0] = 0xe1; break;
  1846.                         case Z80_IX:
  1847.                         case Z80_IY:
  1848.                                 e[0] = reg; e[1] = 0xe1; break;
  1849.                         default:
  1850.                                 break;
  1851.                         }
  1852.                         EmitBytes(e);
  1853.                 } while (Options::syx.MultiArg(lp));
  1854.         }
  1855.  
  1856.         static void OpCode_POP() {
  1857.                 if (Options::syx.IsReversePOP) OpCode_POPreverse();
  1858.                 else OpCode_POPnormal();
  1859.         }
  1860.  
  1861.         static void OpCode_PUSH() {
  1862.                 Z80Reg reg;
  1863.                 do {
  1864.                         int e[5];
  1865.                         e[0] = e[1] = e[2] = e[3] = e[4] = -1;
  1866.                         switch (reg = GetRegister(lp)) {
  1867.                         case Z80_AF:
  1868.                                 e[0] = 0xf5; break;
  1869.                         case Z80_BC:
  1870.                                 e[0] = 0xc5; break;
  1871.                         case Z80_DE:
  1872.                                 e[0] = 0xd5; break;
  1873.                         case Z80_HL:
  1874.                                 e[0] = 0xe5; break;
  1875.                         case Z80_IX:
  1876.                         case Z80_IY:
  1877.                                 e[0] = reg; e[1] = 0xe5; break;
  1878.                         case Z80_UNK:
  1879.                         {
  1880.                                 if(!Options::syx.IsNextEnabled) break;
  1881.                                 word imm16 = GetWordNoMem(lp);
  1882.                                 e[0] = 0xED; e[1] = 0x8A;
  1883.                                 e[2] = (imm16 >> 8);  // push opcode is big-endian!
  1884.                                 e[3] = imm16 & 255;
  1885.                         }
  1886.                         default:
  1887.                                 break;
  1888.                         }
  1889.                         EmitBytes(e);
  1890.                 } while (Options::syx.MultiArg(lp));
  1891.         }
  1892.  
  1893.         static void OpCode_RES() {
  1894.                 do {
  1895.                         int e[] { -1, -1, -1, -1, -1 };
  1896.                         byte bit = GetByteNoMem(lp);
  1897.                         if (comma(lp) && bit <= 7) OpCode_CbFamily(8 * bit + 0x80, e);
  1898.                         EmitBytes(e);
  1899.                 } while (Options::syx.MultiArg(lp));
  1900.         }
  1901.  
  1902.         static void OpCode_RET() {
  1903.                 Z80Cond cc = getz80cond(lp);
  1904.                 if (Z80C_UNK == cc) EmitByte(0xc9);
  1905.                 else                            EmitByte(0xc0 + cc);
  1906.                 // multi-argument was intetionally removed by Ped7g (explain in issue why you want *that*?)
  1907.         }
  1908.  
  1909.         static void OpCode_RETI() {
  1910.                 EmitByte(0xED);
  1911.                 EmitByte(0x4D);
  1912.         }
  1913.  
  1914.         static void OpCode_RETN() {
  1915.                 EmitByte(0xED);
  1916.                 EmitByte(0x45);
  1917.         }
  1918.  
  1919.         static void OpCode_RL() {
  1920.                 Z80Reg reg;
  1921.                 do {
  1922.                         int e[] { -1, -1, -1, -1, -1 };
  1923.                         switch (reg = OpCode_CbFamily(0x10, e)) {
  1924.                         case Z80_A:             break;                  // fully processed by the helper function
  1925.                         case Z80_BC:    case Z80_DE:    case Z80_HL:
  1926.                                 if (Options::noFakes()) break;
  1927.                                 e[0] = e[2] = 0xcb;
  1928.                                 e[1] = 0x10 + GetRegister_r16Low(reg);
  1929.                                 e[3] = 0x10 + GetRegister_r16High(reg);
  1930.                                 break;
  1931.                         default:                break;
  1932.                         }
  1933.                         EmitBytes(e);
  1934.                 } while (Options::syx.MultiArg(lp));
  1935.         }
  1936.  
  1937.         static void OpCode_RLA() {
  1938.                 EmitByte(0x17);
  1939.         }
  1940.  
  1941.         static void OpCode_RLC() {
  1942.                 do {
  1943.                         int e[] { -1, -1, -1, -1, -1 };
  1944.                         OpCode_CbFamily(0x00, e);
  1945.                         EmitBytes(e);
  1946.                 } while (Options::syx.MultiArg(lp));
  1947.         }
  1948.  
  1949.         static void OpCode_RLCA() {
  1950.                 EmitByte(0x7);
  1951.         }
  1952.  
  1953.         static void OpCode_RLD() {
  1954.                 EmitByte(0xED);
  1955.                 EmitByte(0x6F);
  1956.         }
  1957.  
  1958.         static void OpCode_RR() {
  1959.                 Z80Reg reg;
  1960.                 do {
  1961.                         int e[] { -1, -1, -1, -1, -1 };
  1962.                         switch (reg = OpCode_CbFamily(0x18, e)) {
  1963.                         case Z80_A:             break;                  // fully processed by the helper function
  1964.                         case Z80_BC:    case Z80_DE:    case Z80_HL:
  1965.                                 if (Options::noFakes()) break;
  1966.                                 e[0] = e[2] = 0xcb;
  1967.                                 e[1] = 0x18 + GetRegister_r16High(reg);
  1968.                                 e[3] = 0x18 + GetRegister_r16Low(reg);
  1969.                                 break;
  1970.                         default:                break;
  1971.                         }
  1972.                         EmitBytes(e);
  1973.                 } while (Options::syx.MultiArg(lp));
  1974.         }
  1975.  
  1976.         static void OpCode_RRA() {
  1977.                 EmitByte(0x1f);
  1978.         }
  1979.  
  1980.         static void OpCode_RRC() {
  1981.                 do {
  1982.                         int e[] { -1, -1, -1, -1, -1 };
  1983.                         OpCode_CbFamily(0x08, e);
  1984.                         EmitBytes(e);
  1985.                 } while (Options::syx.MultiArg(lp));
  1986.         }
  1987.  
  1988.         static void OpCode_RRCA() {
  1989.                 EmitByte(0xf);
  1990.         }
  1991.  
  1992.         static void OpCode_RRD() {
  1993.                 EmitByte(0xED);
  1994.                 EmitByte(0x67);
  1995.         }
  1996.  
  1997.         static void OpCode_RST() {
  1998.                 do {
  1999.                         byte e = GetByteNoMem(lp);
  2000.                         if (e&(~0x38)) {        // some bit is set which should be not
  2001.                                 Error("[RST] Illegal operand", line); SkipToEol(lp);
  2002.                                 return;
  2003.                         } else {                        // e == { $00, $08, $10, $18, $20, $28, $30, $38 }
  2004.                                 EmitByte(0xC7 + e);
  2005.                         }
  2006.                 } while (Options::syx.MultiArg(lp));
  2007.         }
  2008.  
  2009.         static void OpCode_SBC() {
  2010.                 const bool nonZ80CPU = Options::IsI8080 || Options::IsLR35902;
  2011.                 Z80Reg reg;
  2012.                 do {
  2013.                         int e[] { -1, -1, -1, -1 };
  2014.                         if (!CommonAluOpcode(0x98, e, true, false)) {   // handle common 8-bit variants
  2015.                                 if ((!nonZ80CPU) && (Z80_HL == GetRegister(lp))) {
  2016.                                         if (!comma(lp)) {
  2017.                                                 Error("[SBC] Comma expected");
  2018.                                         } else {
  2019.                                                 switch (reg = GetRegister(lp)) {
  2020.                                                 case Z80_BC: case Z80_DE: case Z80_HL: case Z80_SP:
  2021.                                                         e[0] = 0xed; e[1] = 0x32 + reg; break;
  2022.                                                 default: break;
  2023.                                                 }
  2024.                                         }
  2025.                                 }
  2026.                         }
  2027.                         EmitBytes(e);
  2028.                 } while (Options::syx.MultiArg(lp));
  2029.         }
  2030.  
  2031.         static void OpCode_SCF() {
  2032.                 EmitByte(0x37);
  2033.         }
  2034.  
  2035.         static void OpCode_SET() {
  2036.                 do {
  2037.                         int e[] { -1, -1, -1, -1, -1 };
  2038.                         byte bit = GetByteNoMem(lp);
  2039.                         if (comma(lp) && bit <= 7) OpCode_CbFamily(8 * bit + 0xc0, e);
  2040.                         EmitBytes(e);
  2041.                 } while (Options::syx.MultiArg(lp));
  2042.         }
  2043.  
  2044.         static void OpCode_Next_SETAE() {
  2045.                 if (Options::syx.IsNextEnabled < 1) {
  2046.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  2047.                         return;
  2048.                 }
  2049.                 EmitByte(0xED);
  2050.                 EmitByte(0x95);
  2051.         }
  2052.  
  2053.         static void OpCode_SLA() {
  2054.                 Z80Reg reg;
  2055.                 do {
  2056.                         int e[] { -1, -1, -1, -1, -1 };
  2057.                         switch (reg = OpCode_CbFamily(0x20, e)) {
  2058.                         case Z80_A:             break;                  // fully processed by the helper function
  2059.                         case Z80_HL:
  2060.                                 if (Options::noFakes()) break;
  2061.                                 e[0] = 0x29; break;
  2062.                         case Z80_BC:    case Z80_DE:
  2063.                                 if (Options::noFakes()) break;
  2064.                                 e[0] = e[2] = 0xcb;
  2065.                                 e[1] = 0x20 + GetRegister_r16Low(reg);
  2066.                                 e[3] = 0x10 + GetRegister_r16High(reg);
  2067.                                 break;
  2068.                         default:                break;
  2069.                         }
  2070.                         EmitBytes(e);
  2071.                 } while (Options::syx.MultiArg(lp));
  2072.         }
  2073.  
  2074.         static void OpCode_SLL() {
  2075.                 Z80Reg reg;
  2076.                 do {
  2077.                         int e[] { -1, -1, -1, -1, -1 };
  2078.                         switch (reg = OpCode_CbFamily(0x30, e)) {
  2079.                         case Z80_A:             break;                  // fully processed by the helper function
  2080.                         case Z80_BC:    case Z80_DE:    case Z80_HL:
  2081.                                 if (Options::noFakes()) break;
  2082.                                 e[0] = e[2] = 0xcb;
  2083.                                 e[1] = 0x30 + GetRegister_r16Low(reg);
  2084.                                 e[3] = 0x10 + GetRegister_r16High(reg);
  2085.                                 break;
  2086.                         default:                break;
  2087.                         }
  2088.                         EmitBytes(e);
  2089.                 } while (Options::syx.MultiArg(lp));
  2090.         }
  2091.  
  2092.         static void OpCode_SRA() {
  2093.                 Z80Reg reg;
  2094.                 do {
  2095.                         int e[] { -1, -1, -1, -1, -1 };
  2096.                         switch (reg = OpCode_CbFamily(0x28, e)) {
  2097.                         case Z80_A:             break;                  // fully processed by the helper function
  2098.                         case Z80_BC:    case Z80_DE:    case Z80_HL:
  2099.                                 if (Options::noFakes()) break;
  2100.                                 e[0] = e[2] = 0xcb;
  2101.                                 e[1] = 0x28 + GetRegister_r16High(reg);
  2102.                                 e[3] = 0x18 + GetRegister_r16Low(reg);
  2103.                                 break;
  2104.                         default:                break;
  2105.                         }
  2106.                         EmitBytes(e);
  2107.                 } while (Options::syx.MultiArg(lp));
  2108.         }
  2109.  
  2110.         static void OpCode_SRL() {
  2111.                 Z80Reg reg;
  2112.                 do {
  2113.                         int e[] { -1, -1, -1, -1, -1 };
  2114.                         switch (reg = OpCode_CbFamily(0x38, e)) {
  2115.                         case Z80_A:             break;                  // fully processed by the helper function
  2116.                         case Z80_BC:    case Z80_DE:    case Z80_HL:
  2117.                                 if (Options::noFakes()) break;
  2118.                                 e[0] = e[2] = 0xcb;
  2119.                                 e[1] = 0x38 + GetRegister_r16High(reg);
  2120.                                 e[3] = 0x18 + GetRegister_r16Low(reg);
  2121.                                 break;
  2122.                         default:                break;
  2123.                         }
  2124.                         EmitBytes(e);
  2125.                 } while (Options::syx.MultiArg(lp));
  2126.         }
  2127.  
  2128.         static void OpCode_LR35902_STOP() {     // syntax: STOP [byte_value = 0] = opcode "10 byte_value"
  2129.                 EmitByte(0x10);
  2130.                 if (SkipBlanks(lp)) {           // is optional byte provided? (if not, default value is zero)
  2131.                         EmitByte(0x00);
  2132.                 } else {
  2133.                         EmitByte(GetByteNoMem(lp));
  2134.                 }
  2135.         }
  2136.  
  2137.         static void OpCode_SUB() {
  2138.                 Z80Reg reg;
  2139.                 do {
  2140.                         int e[] { -1, -1, -1, -1 };
  2141.                         if (!CommonAluOpcode(0x90, e, true, true)) {    // handle common 8-bit variants
  2142.                                 if ((!Options::IsI8080) && (Z80_HL == GetRegister(lp))) {
  2143.                                         if (!comma(lp)) {
  2144.                                                 Error("[SUB] Comma expected");
  2145.                                         } else {
  2146.                                                 switch (reg = GetRegister(lp)) {
  2147.                                                 case Z80_BC: case Z80_DE: case Z80_HL: case Z80_SP:
  2148.                                                         if (Options::noFakes()) break;
  2149.                                                         e[0] = 0xb7; e[1] = 0xed; e[2] = 0x32+reg; break;
  2150.                                                 default: break;
  2151.                                                 }
  2152.                                         }
  2153.                                 }
  2154.                         }
  2155.                         EmitBytes(e);
  2156.                 } while (Options::syx.MultiArg(lp));
  2157.         }
  2158.  
  2159.         //Swaps the high and low nibbles of the accumulator.
  2160.         static void OpCode_Next_SWAPNIB() {
  2161.                 if (Options::syx.IsNextEnabled < 1) {
  2162.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  2163.                         return;
  2164.                 }
  2165.                 Z80Reg reg = GetRegister(lp);
  2166.                 if (Z80_UNK != reg && Z80_A != reg) {
  2167.                         Error("[SWAPNIB] Illegal operand (can be only register A)", line);
  2168.                         return;
  2169.                 }
  2170.                 EmitByte(0xED);
  2171.                 EmitByte(0x23);
  2172.         }
  2173.  
  2174.         static void OpCode_Next_TEST() {
  2175.                 if (Options::syx.IsNextEnabled < 1) {
  2176.                         Error("Z80N instructions are currently disabled", bp, SUPPRESS);
  2177.                         return;
  2178.                 }
  2179.                 int e[] { 0xED, 0x27, GetByteNoMem(lp), -1 };
  2180.                 EmitBytes(e);
  2181.         }
  2182.  
  2183.         static void OpCode_XOR() {
  2184.                 do {
  2185.                         int e[] { -1, -1, -1, -1};
  2186.                         CommonAluOpcode(0xa8, e);
  2187.                         EmitBytes(e);
  2188.                 } while (Options::syx.MultiArg(lp));
  2189.         }
  2190.  
  2191.         void Init() {
  2192.                 // Z80, i8080 and LR35902 shared instructions first
  2193.                 OpCodeTable.Insert("adc", OpCode_ADC);
  2194.                 OpCodeTable.Insert("add", OpCode_ADD);
  2195.                 OpCodeTable.Insert("and", OpCode_AND);
  2196.                 OpCodeTable.Insert("call", OpCode_CALL);
  2197.                 OpCodeTable.Insert("ccf", OpCode_CCF);
  2198.                 OpCodeTable.Insert("cp", OpCode_CP);
  2199.                 OpCodeTable.Insert("cpl", OpCode_CPL);
  2200.                 OpCodeTable.Insert("daa", OpCode_DAA);
  2201.                 OpCodeTable.Insert("dec", OpCode_DEC);
  2202.                 OpCodeTable.Insert("di", OpCode_DI);
  2203.                 OpCodeTable.Insert("ei", OpCode_EI);
  2204.                 if (!Options::IsLR35902) OpCodeTable.Insert("ex", OpCode_EX);
  2205.                 OpCodeTable.Insert("exd", OpCode_EXD);
  2206.                 OpCodeTable.Insert("halt", OpCode_HALT);
  2207.                 if (!Options::IsLR35902) OpCodeTable.Insert("in", OpCode_IN);
  2208.                 OpCodeTable.Insert("inc", OpCode_INC);
  2209.                 OpCodeTable.Insert("jp", OpCode_JP);
  2210.                 OpCodeTable.Insert("ld", OpCode_LD);
  2211.                 OpCodeTable.Insert("nop", OpCode_NOP);
  2212.                 OpCodeTable.Insert("or", OpCode_OR);
  2213.                 if (!Options::IsLR35902) OpCodeTable.Insert("out", OpCode_OUT);
  2214.                 OpCodeTable.Insert("pop", OpCode_POP);
  2215.                 OpCodeTable.Insert("push", OpCode_PUSH);
  2216.                 OpCodeTable.Insert("ret", OpCode_RET);
  2217.                 OpCodeTable.Insert("rla", OpCode_RLA);
  2218.                 OpCodeTable.Insert("rlca", OpCode_RLCA);
  2219.                 OpCodeTable.Insert("rra", OpCode_RRA);
  2220.                 OpCodeTable.Insert("rrca", OpCode_RRCA);
  2221.                 OpCodeTable.Insert("rst", OpCode_RST);
  2222.                 OpCodeTable.Insert("sbc", OpCode_SBC);
  2223.                 OpCodeTable.Insert("scf", OpCode_SCF);
  2224.                 OpCodeTable.Insert("sub", OpCode_SUB);
  2225.                 OpCodeTable.Insert("xor", OpCode_XOR);
  2226.  
  2227.                 if (Options::IsI8080) return;   // all i8080 instructions defined
  2228.  
  2229.                 // Z80 and LR35902 shared instructions
  2230.                 OpCodeTable.Insert("bit", OpCode_BIT);
  2231.                 OpCodeTable.Insert("jr", OpCode_JR);
  2232.                 OpCodeTable.Insert("res", OpCode_RES);
  2233.                 OpCodeTable.Insert("rl", OpCode_RL);
  2234.                 OpCodeTable.Insert("rlc", OpCode_RLC);
  2235.                 OpCodeTable.Insert("rr", OpCode_RR);
  2236.                 OpCodeTable.Insert("rrc", OpCode_RRC);
  2237.                 OpCodeTable.Insert("set", OpCode_SET);
  2238.                 OpCodeTable.Insert("sla", OpCode_SLA);
  2239.                 OpCodeTable.Insert("sra", OpCode_SRA);
  2240.                 OpCodeTable.Insert("srl", OpCode_SRL);
  2241.  
  2242.                 if (Options::IsLR35902) {
  2243.                         //INIT LR35902 extras
  2244.                         OpCodeTable.Insert("ldd", OpCode_LR35902_LDD);
  2245.                         OpCodeTable.Insert("ldh", OpCode_LR35902_LDH);
  2246.                         OpCodeTable.Insert("ldi", OpCode_LR35902_LDI);
  2247.                         OpCodeTable.Insert("reti", OpCode_EXX);         // RETI has same opcode as EXX on Z80
  2248.                         OpCodeTable.Insert("stop", OpCode_LR35902_STOP);
  2249.                         OpCodeTable.Insert("swap", OpCode_SLL);         // SWAP has same opcodes as SLI on Z80
  2250.                         return;                                         // all LR35902 instructions defined
  2251.                 }
  2252.  
  2253.                 // Z80 instructions
  2254.                 OpCodeTable.Insert("cpd", OpCode_CPD);
  2255.                 OpCodeTable.Insert("cpdr", OpCode_CPDR);
  2256.                 OpCodeTable.Insert("cpi", OpCode_CPI);
  2257.                 OpCodeTable.Insert("cpir", OpCode_CPIR);
  2258.                 OpCodeTable.Insert("djnz", OpCode_DJNZ);
  2259.                 OpCodeTable.Insert("exa", OpCode_EXA);
  2260.                 OpCodeTable.Insert("exx", OpCode_EXX);
  2261.                 OpCodeTable.Insert("im", OpCode_IM);
  2262.                 OpCodeTable.Insert("ind", OpCode_IND);
  2263.                 OpCodeTable.Insert("indr", OpCode_INDR);
  2264.                 OpCodeTable.Insert("inf", OpCode_INF); // thanks to BREEZE
  2265.                 OpCodeTable.Insert("ini", OpCode_INI);
  2266.                 OpCodeTable.Insert("inir", OpCode_INIR);
  2267.                 OpCodeTable.Insert("ldd", OpCode_LDD);
  2268.                 OpCodeTable.Insert("lddr", OpCode_LDDR);
  2269.                 OpCodeTable.Insert("ldi", OpCode_LDI);
  2270.                 OpCodeTable.Insert("ldir", OpCode_LDIR);
  2271.                 OpCodeTable.Insert("mulub", OpCode_MULUB);
  2272.                 OpCodeTable.Insert("muluw", OpCode_MULUW);
  2273.                 OpCodeTable.Insert("neg", OpCode_NEG);
  2274.                 OpCodeTable.Insert("otdr", OpCode_OTDR);
  2275.                 OpCodeTable.Insert("otir", OpCode_OTIR);
  2276.                 OpCodeTable.Insert("outd", OpCode_OUTD);
  2277.                 OpCodeTable.Insert("outi", OpCode_OUTI);
  2278.                 OpCodeTable.Insert("reti", OpCode_RETI);
  2279.                 OpCodeTable.Insert("retn", OpCode_RETN);
  2280.                 OpCodeTable.Insert("rld", OpCode_RLD);
  2281.                 OpCodeTable.Insert("rrd", OpCode_RRD);
  2282.                 OpCodeTable.Insert("sli", OpCode_SLL);
  2283.                 OpCodeTable.Insert("sll", OpCode_SLL);
  2284.  
  2285.                 InitNextExtensions();
  2286.         }
  2287.  
  2288.         void InitNextExtensions() {
  2289.                 static bool nextWasInitialized = false;
  2290.                 if (!Options::syx.IsNextEnabled || nextWasInitialized) return;
  2291.                 nextWasInitialized = true;
  2292.                 // Next extended opcodes
  2293.                 OpCodeTable.Insert("brlc",              OpCode_Next_BRLC);
  2294.                 OpCodeTable.Insert("bsla",              OpCode_Next_BSLA);
  2295.                 OpCodeTable.Insert("bsra",              OpCode_Next_BSRA);
  2296.                 OpCodeTable.Insert("bsrf",              OpCode_Next_BSRF);
  2297.                 OpCodeTable.Insert("bsrl",              OpCode_Next_BSRL);
  2298.                 OpCodeTable.Insert("lddrx",             OpCode_Next_LDDRX);
  2299.                 OpCodeTable.Insert("lddx",              OpCode_Next_LDDX);
  2300.                 //OpCodeTable.Insert("ldirscale",       OpCode_Next_LDIRSCALE);
  2301.                 OpCodeTable.Insert("ldirx",             OpCode_Next_LDIRX);
  2302.                 OpCodeTable.Insert("ldix",              OpCode_Next_LDIX);
  2303.                 OpCodeTable.Insert("ldpirx",    OpCode_Next_LDPIRX);
  2304.                 OpCodeTable.Insert("ldws",              OpCode_Next_LDWS);
  2305.                 OpCodeTable.Insert("mirror",    OpCode_Next_MIRROR);
  2306.                 OpCodeTable.Insert("mul",               OpCode_Next_MUL);
  2307.                 OpCodeTable.Insert("nextreg",   OpCode_Next_NEXTREG);
  2308.                 OpCodeTable.Insert("outinb",    OpCode_Next_OUTINB);
  2309.                 OpCodeTable.Insert("pixelad",   OpCode_Next_PIXELAD);
  2310.                 OpCodeTable.Insert("pixeldn",   OpCode_Next_PIXELDN);
  2311.                 OpCodeTable.Insert("setae",             OpCode_Next_SETAE);
  2312.                 OpCodeTable.Insert("swapnib",   OpCode_Next_SWAPNIB);
  2313.                 OpCodeTable.Insert("test",              OpCode_Next_TEST);
  2314.                 // CSpect emulator extensions, fake instructions "exit" and "break"
  2315.                 OpCodeTable.Insert("exit",              OpCode_Next_EXIT);
  2316.                 OpCodeTable.Insert("break",             OpCode_Next_BREAK);
  2317.         }
  2318. } // eof namespace Z80
  2319.  
  2320.  
  2321. void InitCPU() {
  2322.         Z80::Init();
  2323.         InsertDirectives();
  2324. }
  2325. //eof z80.cpp
  2326.