diff --git a/Core/Cpu/Z80.cs b/Core/Cpu/Z80.cs index 1588a6d..389339d 100644 --- a/Core/Cpu/Z80.cs +++ b/Core/Cpu/Z80.cs @@ -702,7 +702,8 @@ namespace Core.Cpu else AF.Low &= 0xEF; return 4; - case 0x40: BC.High = BC.High; return 4; + case 0x40: //BC.High = BC.High; + return 4; case 0x41: BC.High = BC.Low; return 4; case 0x42: BC.High = DE.High; return 4; case 0x43: BC.High = DE.Low; return 4; @@ -713,7 +714,8 @@ namespace Core.Cpu // --- LD C, r --- case 0x48: BC.Low = BC.High; return 4; - case 0x49: BC.Low = BC.Low; return 4; + case 0x49: //BC.Low = BC.Low; + return 4; case 0x4A: BC.Low = DE.High; return 4; case 0x4B: BC.Low = DE.Low; return 4; case 0x4C: BC.Low = HL.High; return 4; @@ -724,7 +726,8 @@ namespace Core.Cpu // --- LD D, r --- case 0x50: DE.High = BC.High; return 4; case 0x51: DE.High = BC.Low; return 4; - case 0x52: DE.High = DE.High; return 4; + case 0x52: //DE.High = DE.High; + return 4; case 0x53: DE.High = DE.Low; return 4; case 0x54: DE.High = HL.High; return 4; case 0x55: DE.High = HL.Low; return 4; @@ -735,7 +738,8 @@ namespace Core.Cpu case 0x58: DE.Low = BC.High; return 4; case 0x59: DE.Low = BC.Low; return 4; case 0x5A: DE.Low = DE.High; return 4; - case 0x5B: DE.Low = DE.Low; return 4; + case 0x5B: //DE.Low = DE.Low; + return 4; case 0x5C: DE.Low = HL.High; return 4; case 0x5D: DE.Low = HL.Low; return 4; case 0x5E: DE.Low = _memory.Read(HL.Word); return 7; @@ -746,7 +750,8 @@ namespace Core.Cpu case 0x61: HL.High = BC.Low; return 4; case 0x62: HL.High = DE.High; return 4; case 0x63: HL.High = DE.Low; return 4; - case 0x64: HL.High = HL.High; return 4; + case 0x64: //HL.High = HL.High; + return 4; case 0x65: HL.High = HL.Low; return 4; case 0x66: HL.High = _memory.Read(HL.Word); return 7; case 0x67: HL.High = AF.High; return 4; @@ -757,7 +762,8 @@ namespace Core.Cpu case 0x6A: HL.Low = DE.High; return 4; case 0x6B: HL.Low = DE.Low; return 4; case 0x6C: HL.Low = HL.High; return 4; - case 0x6D: HL.Low = HL.Low; return 4; + case 0x6D: //HL.Low = HL.Low; + return 4; case 0x6E: HL.Low = _memory.Read(HL.Word); return 7; case 0x6F: HL.Low = AF.High; return 4; @@ -778,7 +784,8 @@ namespace Core.Cpu case 0x7C: AF.High = HL.High; return 4; case 0x7D: AF.High = HL.Low; return 4; case 0x7E: AF.High = _memory.Read(HL.Word); return 7; - case 0x7F: AF.High = AF.High; return 4; + case 0x7F: //AF.High = AF.High; + return 4; case 0x80: Add(BC.High); return 4; // ADD A, B case 0x81: Add(BC.Low); return 4; // ADD A, C case 0x82: Add(DE.High); return 4; // ADD A, D @@ -1144,6 +1151,11 @@ namespace Core.Cpu DE.Low = _memory.Read(src5B); DE.High = _memory.Read((ushort)(src5B + 1)); return 20; + case 0x73: // LD (nn), SP + ushort dest73 = FetchWord(); + _memory.Write(dest73, (byte)SP); + _memory.Write((ushort)(dest73 + 1), (byte)(SP >> 8)); + return 20; case 0xB0: // LDIR // 1. Read byte from (HL) val = _memory.Read(HL.Word); @@ -1207,67 +1219,77 @@ namespace Core.Cpu private int ExecuteCBPrefix() { byte cbOpcode = FetchByte(); - byte memVal; - switch (cbOpcode) + // Extract the exact same mathematical properties + int operation = cbOpcode >> 6; // 00 = Shift, 01 = BIT, 10 = RES, 11 = SET + int bitIndex = (cbOpcode >> 3) & 0x07; // Extracts a number 0-7 + int regIndex = cbOpcode & 0x07; // Extracts register index 0-7 + + byte bitMask = (byte)(1 << bitIndex); + + // --- PHASE 1: Fetch the target value --- + byte val = 0; + switch (regIndex) { - case 0x7E: // BIT 7, (HL) - byte memValBit7 = _memory.Read(HL.Word); + case 0: val = BC.High; break; + case 1: val = BC.Low; break; + case 2: val = DE.High; break; + case 3: val = DE.Low; break; + case 4: val = HL.High; break; + case 5: val = HL.Low; break; + case 6: val = _memory.Read(HL.Word); break; // The 0x110 (HL) exception + case 7: val = AF.High; break; + } - // Preserve ONLY the Carry Flag (Bit 0). This clears N and everything else. - AF.Low &= 0x01; + // --- PHASE 2: Perform the bitwise math --- + switch (operation) + { + case 1: // ALL BIT Instructions + AF.Low &= 0x01; // Preserve ONLY Carry + AF.Low |= 0x10; // Set Half-Carry - // Half-Carry (Bit 4) is ALWAYS set to 1 for Z80 BIT instructions - AF.Low |= 0x10; - - // Test Bit 7 (0x80 is Binary 1000 0000) - if ((memValBit7 & 0x80) == 0) + if ((val & bitMask) == 0) { - // If the bit is 0, turn ON the Zero Flag (Bit 6) - AF.Low |= 0x40; - - // Parity/Overflow (Bit 2) is historically set along with the Zero flag on BIT - AF.Low |= 0x04; + AF.Low |= 0x44; // Set Zero and P/V } - else + else if (bitIndex == 7) { - // If testing Bit 7 and it is 1, the Sign Flag (Bit 7) perfectly mirrors it - AF.Low |= 0x80; + AF.Low |= 0x80; // If testing Bit 7 and it is 1, set Sign } - return 12; - case 0x86: // RES 0, (HL) - memVal = _memory.Read(HL.Word); + // BIT (HL) takes 12 T-States. Standard register BIT takes 8. + return (regIndex == 6) ? 12 : 8; - // 0xFE is Binary 1111 1110. - // ANDing preserves all bits except Bit 0, which becomes 0. - memVal &= 0xFE; + case 2: // ALL RES Instructions + val &= (byte)(~bitMask); + break; // Proceed to write-back - _memory.Write(HL.Word, memVal); - return 15; - case 0xAE: // RES 5, (HL) - memVal = _memory.Read(HL.Word); + case 3: // ALL SET Instructions + val |= bitMask; + break; // Proceed to write-back - // 0xDF is Binary 1101 1111 - // ANDing preserves all other bits while forcing Bit 5 to 0 - memVal &= 0xDF; - - _memory.Write(HL.Word, memVal); - return 15; - - case 0xC6: // SET 0, (HL) - memVal = _memory.Read(HL.Word); - - // 0x01 is Binary 0000 0001 - // ORing forces Bit 0 to 1 and perfectly preserves all other bits - memVal |= 0x01; - - _memory.Write(HL.Word, memVal); - return 15; + case 0: // ALL Shift/Rotate Instructions + throw new NotImplementedException($"CB Shift/Rotate opcode {cbOpcode:X2} at PC 0x{(PC - 1):X4} not implemented!"); default: - throw new NotImplementedException($"CB prefix opcode 0x{cbOpcode:X2} at PC 0x{(PC - 1):X4} is not implemented."); + throw new Exception("Invalid CB operation."); } + + // --- PHASE 3: Write back the modified value (RES and SET only) --- + switch (regIndex) + { + case 0: BC.High = val; break; + case 1: BC.Low = val; break; + case 2: DE.High = val; break; + case 3: DE.Low = val; break; + case 4: HL.High = val; break; + case 5: HL.Low = val; break; + case 6: _memory.Write(HL.Word, val); break; + case 7: AF.High = val; break; + } + + // RES/SET (HL) takes 15 T-States. Standard register RES/SET takes 8. + return (regIndex == 6) ? 15 : 8; } private int ExecuteFDPrefix() @@ -1323,11 +1345,11 @@ namespace Core.Cpu return 19; // Takes 19 T-States } case 0x75: // LD (IY+d), L - sbyte offset75 = (sbyte)FetchByte(); - targetAddress = (ushort)(IY.Word + offset75); - // Write the low byte of HL to memory - _memory.Write(targetAddress, HL.Low); - return 19; + sbyte offset75 = (sbyte)FetchByte(); + targetAddress = (ushort)(IY.Word + offset75); + // Write the low byte of HL to memory + _memory.Write(targetAddress, HL.Low); + return 19; case 0x86: // ADD A, (IY+d) { sbyte displacementAdd = (sbyte)FetchByte(); @@ -1340,110 +1362,48 @@ namespace Core.Cpu } case 0xCB: // The FD CB nested prefix { - sbyte offsetCB = (sbyte)FetchByte(); // This is the '01' - byte bitOpcode = FetchByte(); // This is the 'CE' - targetAddress = (ushort)(IY.Word + offsetCB); + sbyte displacement = (sbyte)FetchByte(); + byte cbOpcode = FetchByte(); + targetAddress = (ushort)(IY.Word + displacement); + memVal = _memory.Read(targetAddress); - switch (bitOpcode) + // Extract the mathematical properties of the opcode + int operation = cbOpcode >> 6; // 01 = BIT, 10 = RES, 11 = SET + int bitIndex = (cbOpcode >> 3) & 0x07; // Extracts a number 0-7 + byte bitMask = (byte)(1 << bitIndex); // Creates the bitmask (e.g., 0x01, 0x02, 0x80) + + switch (operation) { - case 0x46: // BIT 0, (IY+d) - byte memValBit0 = _memory.Read(targetAddress); + case 1: // ALL BIT Instructions + AF.Low &= 0x01; // Preserve ONLY Carry + AF.Low |= 0x10; // Set Half-Carry - // Preserve the existing Carry Flag (Bit 0) - byte newFlags = (byte)(AF.Low & 0x01); - - newFlags |= 0x10; // Force Half-Carry (Bit 4) to 1 - - // Test Bit 0. If it is 0, turn ON the Zero Flag (Bit 6) - if ((memValBit0 & 0x01) == 0) + if ((memVal & bitMask) == 0) { - newFlags |= 0x40; + AF.Low |= 0x44; // Set Zero (Bit 6) and P/V (Bit 2) + } + else if (bitIndex == 7) + { + AF.Low |= 0x80; // If testing Bit 7 and it is 1, set Sign (Bit 7) } - - AF.Low = newFlags; return 20; - case 0x4E: // BIT 1, (IY+d) - { - byte memValBit = _memory.Read(targetAddress); - // Check if bit 1 is 0 - bool bitIsZero = (memValBit & 0x02) == 0; - - // Preserve the Carry flag (Bit 0), clear everything else - AF.Low &= 0x01; - - // Set Half-Carry (Bit 4) - Standard Z80 behavior for BIT - AF.Low |= 0x10; - - if (bitIsZero) - { - AF.Low |= 0x40; // Set Zero Flag (Bit 6) - AF.Low |= 0x04; // Set P/V Flag (Bit 2) - } - - return 20; - } - case 0x86: // RES 0, (IY+d) - byte memValRes0 = _memory.Read(targetAddress); - - // 0xFE is Binary 1111 1110. - // ANDing preserves all bits except Bit 0, which becomes 0. - memValRes0 &= 0xFE; - - _memory.Write(targetAddress, memValRes0); - return 23; // Takes 23 T-States - case 0x8E: // RES 1, (IY+d) - byte memValRes = _memory.Read(targetAddress); - - // 0xFD is Binary 1111 1101. - // ANDing with this preserves all bits except Bit 1, which becomes 0. - memValRes &= 0xFD; - _memory.Write(targetAddress, memValRes); - return 23; - case 0xA6: // RES 4, (IY+d) - byte memValRes4 = _memory.Read(targetAddress); - - // 0xEF is Binary 1110 1111 - // ANDing preserves all bits except Bit 4, which becomes 0. - memValRes4 &= 0xEF; - - _memory.Write(targetAddress, memValRes4); - return 23; - case 0xAE: // RES 5, (IY+d) - byte memValRes5 = _memory.Read(targetAddress); - - // 0xDF is Binary 1101 1111 - // ANDing perfectly preserves all other bits while forcing Bit 5 to 0 - memValRes5 &= 0xDF; - - _memory.Write(targetAddress, memValRes5); - return 23; - case 0xC6: // SET 0, (IY+d) - byte memValSet0 = _memory.Read(targetAddress); - - // 0x01 is Binary 0000 0001 - // ORing forces Bit 0 to 1 and perfectly preserves all other bits - memValSet0 |= 0x01; - - _memory.Write(targetAddress, memValSet0); - return 23; // Takes 23 T-States - case 0xCE: // SET 1, (IY+d) - memVal = _memory.Read(targetAddress); - memVal |= 0x02; // 0x02 is Binary 0000 0010 (Bit 1) + case 2: // ALL RES Instructions + memVal &= (byte)(~bitMask); // Invert mask and AND it to clear the bit _memory.Write(targetAddress, memVal); return 23; - case 0xE6: // SET 4, (IY+d) - byte memValSet4 = _memory.Read(targetAddress); - // 0x10 is Binary 0001 0000 - // ORing perfectly preserves all other bits while forcing Bit 4 to 1 - memValSet4 |= 0x10; - - _memory.Write(targetAddress, memValSet4); + case 3: // ALL SET Instructions + memVal |= bitMask; // OR the mask to force the bit to 1 + _memory.Write(targetAddress, memVal); return 23; + case 0: + // Shift/Rotate instructions will go here later + throw new NotImplementedException($"FD CB Shift/Rotate opcode {cbOpcode:X2} at PC 0x{(PC - 1):X4} not implemented!"); + default: - throw new NotImplementedException($"FD CB opcode {bitOpcode:X2} at PC 0x{(PC - 1):X4} not implemented!"); + throw new Exception("Invalid bitwise operation."); } } default: @@ -1451,4 +1411,183 @@ namespace Core.Cpu } } } -} \ No newline at end of file +} + + +//sbyte offsetCB = (sbyte)FetchByte(); // This is the '01' +//byte bitOpcode = FetchByte(); // This is the 'CE' +//targetAddress = (ushort)(IY.Word + offsetCB); + +//switch (bitOpcode) +//{ +// case 0x46: // BIT 0, (IY+d) +// byte memValBit0 = _memory.Read(targetAddress); + +// // Preserve the existing Carry Flag (Bit 0) +// byte newFlags = (byte)(AF.Low & 0x01); + +// newFlags |= 0x10; // Force Half-Carry (Bit 4) to 1 + +// // Test Bit 0. If it is 0, turn ON the Zero Flag (Bit 6) +// if ((memValBit0 & 0x01) == 0) +// { +// newFlags |= 0x40; +// } + +// AF.Low = newFlags; +// return 20; +// case 0x4E: // BIT 1, (IY+d) +// { +// byte memValBit = _memory.Read(targetAddress); + +// // Check if bit 1 is 0 +// bool bitIsZero = (memValBit & 0x02) == 0; + +// // Preserve the Carry flag (Bit 0), clear everything else +// AF.Low &= 0x01; + +// // Set Half-Carry (Bit 4) - Standard Z80 behavior for BIT +// AF.Low |= 0x10; + +// if (bitIsZero) +// { +// AF.Low |= 0x40; // Set Zero Flag (Bit 6) +// AF.Low |= 0x04; // Set P/V Flag (Bit 2) +// } + +// return 20; +// } +// case 0x66: // BIT 4, (IY+d) +// byte memValBit4 = _memory.Read(targetAddress); + +// // Preserve ONLY the Carry flag (Bit 0). This clears N and everything else. +// AF.Low &= 0x01; + +// // Set Half-Carry (Bit 4) - Standard Z80 behavior for BIT instructions +// AF.Low |= 0x10; + +// // Test Bit 4 (0x10 is Binary 0001 0000) +// if ((memValBit4 & 0x10) == 0) +// { +// // If the bit is 0, turn ON the Zero Flag (Bit 6) +// AF.Low |= 0x40; + +// // Parity/Overflow (Bit 2) is historically set along with the Zero flag on BIT +// AF.Low |= 0x04; +// } +// // (Note: The Sign Flag remains 0 because we are not testing Bit 7) + +// return 20; +// case 0x6E: // BIT 5, (IY+d) +// byte memValBit5 = _memory.Read(targetAddress); + +// // Preserve ONLY the Carry flag (Bit 0). This clears N and everything else. +// AF.Low &= 0x01; + +// // Set Half-Carry (Bit 4) - Standard Z80 behavior for BIT instructions +// AF.Low |= 0x10; + +// // Test Bit 5 (0x20 is Binary 0010 0000) +// if ((memValBit5 & 0x20) == 0) +// { +// // If the bit is 0, turn ON the Zero Flag (Bit 6) +// AF.Low |= 0x40; + +// // Parity/Overflow (Bit 2) is historically set along with the Zero flag on BIT +// AF.Low |= 0x04; +// } +// // (Note: The Sign Flag remains 0 because we are not testing Bit 7) + +// return 20; +// case 0x76: // BIT 6, (IY+d) +// byte memValBit6 = _memory.Read(targetAddress); + +// // Preserve ONLY the Carry flag (Bit 0). This clears N and everything else. +// AF.Low &= 0x01; + +// // Set Half-Carry (Bit 4) - Standard Z80 behavior for BIT +// AF.Low |= 0x10; + +// // Test Bit 6 (0x40 is Binary 0100 0000) +// if ((memValBit6 & 0x40) == 0) +// { +// // If the bit is 0, turn ON the Zero Flag (Bit 6) +// AF.Low |= 0x40; + +// // Parity/Overflow (Bit 2) is historically set along with the Zero flag on BIT +// AF.Low |= 0x04; +// } +// // (Note: The Sign Flag remains 0 because we are not testing Bit 7) + +// return 20; +// case 0x86: // RES 0, (IY+d) +// byte memValRes0 = _memory.Read(targetAddress); + +// // 0xFE is Binary 1111 1110. +// // ANDing preserves all bits except Bit 0, which becomes 0. +// memValRes0 &= 0xFE; + +// _memory.Write(targetAddress, memValRes0); +// return 23; // Takes 23 T-States +// case 0x8E: // RES 1, (IY+d) +// byte memValRes = _memory.Read(targetAddress); + +// // 0xFD is Binary 1111 1101. +// // ANDing with this preserves all bits except Bit 1, which becomes 0. +// memValRes &= 0xFD; +// _memory.Write(targetAddress, memValRes); +// return 23; +// case 0xA6: // RES 4, (IY+d) +// byte memValRes4 = _memory.Read(targetAddress); + +// // 0xEF is Binary 1110 1111 +// // ANDing preserves all bits except Bit 4, which becomes 0. +// memValRes4 &= 0xEF; + +// _memory.Write(targetAddress, memValRes4); +// return 23; +// case 0xAE: // RES 5, (IY+d) +// byte memValRes5 = _memory.Read(targetAddress); + +// // 0xDF is Binary 1101 1111 +// // ANDing perfectly preserves all other bits while forcing Bit 5 to 0 +// memValRes5 &= 0xDF; + +// _memory.Write(targetAddress, memValRes5); +// return 23; +// case 0xC6: // SET 0, (IY+d) +// byte memValSet0 = _memory.Read(targetAddress); + +// // 0x01 is Binary 0000 0001 +// // ORing forces Bit 0 to 1 and perfectly preserves all other bits +// memValSet0 |= 0x01; + +// _memory.Write(targetAddress, memValSet0); +// return 23; // Takes 23 T-States +// case 0xCE: // SET 1, (IY+d) +// memVal = _memory.Read(targetAddress); +// memVal |= 0x02; // 0x02 is Binary 0000 0010 (Bit 1) +// _memory.Write(targetAddress, memVal); +// return 23; +// case 0xE6: // SET 4, (IY+d) +// byte memValSet4 = _memory.Read(targetAddress); + +// // 0x10 is Binary 0001 0000 +// // ORing perfectly preserves all other bits while forcing Bit 4 to 1 +// memValSet4 |= 0x10; + +// _memory.Write(targetAddress, memValSet4); +// return 23; +// case 0xEE: // SET 5, (IY+d) +// byte memValSet5 = _memory.Read(targetAddress); + +// // 0x20 is Binary 0010 0000 +// // ORing perfectly preserves all other bits while forcing Bit 5 to 1 +// memValSet5 |= 0x20; + +// _memory.Write(targetAddress, memValSet5); +// return 23; + +// default: +// throw new NotImplementedException($"FD CB opcode {bitOpcode:X2} at PC 0x{(PC - 1):X4} not implemented!"); +//} \ No newline at end of file diff --git a/Desktop/DebuggerForm.cs b/Desktop/DebuggerForm.cs index c2b50d9..f12d861 100644 --- a/Desktop/DebuggerForm.cs +++ b/Desktop/DebuggerForm.cs @@ -249,6 +249,7 @@ namespace Desktop byte opcode = _memoryBus.Read(currentPc); string mnemonic; int instructionLength = 1; // Default to 1 + byte cbOp = 0; switch (opcode) { @@ -668,7 +669,7 @@ namespace Desktop mnemonic = "RET"; break; case 0xCB: - byte cbOp = _memoryBus.Read((ushort)(currentPc + 1)); + cbOp = _memoryBus.Read((ushort)(currentPc + 1)); if (cbOp == 0x7E) { mnemonic = "BIT 7, (HL)"; @@ -709,7 +710,6 @@ namespace Desktop case 0xD9: mnemonic = "EXX"; break; - break; case 0xd5: mnemonic = "PUSH DE"; break; @@ -781,6 +781,11 @@ namespace Desktop mnemonic = $"LD DE, (0x{addr5B:X4})"; instructionLength = 4; break; + case 0x73: + ushort addr73 = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8)); + mnemonic = $"LD (0x{addr73:X4}), SP"; + instructionLength = 4; + break; case 0xB0: mnemonic = "LDIR"; instructionLength = 2; @@ -865,34 +870,22 @@ namespace Desktop } else if (fdOpcode == 0xCB) // FD CB prefix { - sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); - byte cbOpcode = _memoryBus.Read((ushort)(currentPc + 3)); - string sign = d >= 0 ? "+" : ""; - if (cbOpcode == 0x46) - { - mnemonic = $"BIT 0, (IY{sign}{d})"; - } - else if (cbOpcode == 0x4E) - { - mnemonic = $"BIT 1, (IY{sign}{d})"; - } - else if (cbOpcode == 0x86) - { - mnemonic = $"RES 0, (IY{sign}{d})"; - } - else if (cbOpcode == 0xA6) - { - mnemonic = $"RES 4, (IY{sign}{d})"; - } - else if (cbOpcode == 0xCE) - { - mnemonic = $"SET 1, (IY{sign}{d})"; - } - else - { - mnemonic = $"FD CB {d:X2} {cbOpcode:X2}"; // Fallback - } - instructionLength = 4; + cbOp = _memoryBus.Read((ushort)(currentPc + 1)); + + int opGroup = cbOp >> 6; + int targetBit = (cbOp >> 3) & 0x07; + int regIdx = cbOp & 0x07; + + // Map the 0-7 index directly to the Z80 register names + string[] regNames = { "B", "C", "D", "E", "H", "L", "(HL)", "A" }; + string targetReg = regNames[regIdx]; + + if (opGroup == 1) mnemonic = $"BIT {targetBit}, {targetReg}"; + else if (opGroup == 2) mnemonic = $"RES {targetBit}, {targetReg}"; + else if (opGroup == 3) mnemonic = $"SET {targetBit}, {targetReg}"; + else mnemonic = $"CB SHIFT/ROTATE (0x{cbOp:X2})"; + + instructionLength = 2; } else if (fdOpcode == 0x71) // LD (IY+d), C { @@ -907,38 +900,7 @@ namespace Desktop string sign = d >= 0 ? "+" : ""; mnemonic = $"LD (IY{sign}{d}), L"; instructionLength = 3; - } - else if (fdOpcode == 0xCB) // FD CB prefix - { - sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2)); - byte cbOpcode = _memoryBus.Read((ushort)(currentPc + 3)); - string sign = d >= 0 ? "+" : ""; - if (cbOpcode == 0x8E) - { - mnemonic = $"RES 1, (IY{sign}{d})"; - } - else if (cbOpcode == 0xAE) - { - mnemonic = $"RES 5, (IY{sign}{d})"; - } - else if (cbOpcode == 0xC6) - { - mnemonic = $"SET 0, (IY{sign}{d})"; - } - else if (cbOpcode == 0xCE) - { - mnemonic = $"SET 1, (IY{sign}{d})"; - } - else if (cbOpcode == 0xE6) - { - mnemonic = $"SET 4, (IY{sign}{d})"; - } - else - { - mnemonic = $"FD CB {d:X2} {cbOpcode:X2}"; // Fallback - } - instructionLength = 4; - } + } else { mnemonic = $"FD PREFIX UNKNOWN (0x{fdOpcode:X2})";