Implemented a load more Z80 OpCodes
This commit is contained in:
@@ -339,6 +339,24 @@ namespace Core.Cpu
|
||||
if (HasEvenParity(AF.High)) AF.Low |= 0x04;
|
||||
}
|
||||
|
||||
private void Xor(byte value)
|
||||
{
|
||||
// The caret (^) is the C# Bitwise XOR operator
|
||||
AF.High = (byte)(AF.High ^ value);
|
||||
|
||||
// --- Update Flags ---
|
||||
AF.Low = 0; // Clear all flags (H, N, and C are always 0 for XOR)
|
||||
|
||||
// Sign Flag (Bit 7) - Set if the highest bit is 1
|
||||
if ((AF.High & 0x80) != 0) AF.Low |= 0x80;
|
||||
|
||||
// Zero Flag (Bit 6) - Set if the result is 0
|
||||
if (AF.High == 0) AF.Low |= 0x40;
|
||||
|
||||
// Parity Flag (Bit 2) - Set if the result has an even number of 1 bits
|
||||
if (HasEvenParity(AF.High)) AF.Low |= 0x04;
|
||||
}
|
||||
|
||||
private void Add16(ushort value)
|
||||
{
|
||||
int hl = HL.Word;
|
||||
@@ -539,16 +557,35 @@ namespace Core.Cpu
|
||||
case 0x37: // SCF
|
||||
AF.Low |= 0x01; // Force Carry Flag (Bit 0) to 1
|
||||
AF.Low &= 0xED;
|
||||
return 4; // Takes 4 T-States
|
||||
return 4;
|
||||
case 0x38: // JR C, d
|
||||
sbyte jrCOffset = (sbyte)FetchByte();
|
||||
// Check if the Carry Flag (Bit 0) IS set (1)
|
||||
if ((AF.Low & 0x01) != 0)
|
||||
{
|
||||
PC = (ushort)(PC + jrCOffset);
|
||||
return 12;
|
||||
}
|
||||
return 7;
|
||||
case 0x3E: //LD A, n
|
||||
AF.High = FetchByte();
|
||||
return 7;
|
||||
case 0x3F: // CCF
|
||||
bool previousCarry = (AF.Low & 0x01) != 0;
|
||||
AF.Low ^= 0x01; // Invert Carry Flag (Bit 0)
|
||||
AF.Low &= 0xFD; // Force Subtract Flag (N, Bit 1) to 0
|
||||
// Set Half-Carry (H, Bit 4) to the previous Carry state
|
||||
if (previousCarry)
|
||||
AF.Low |= 0x10;
|
||||
else
|
||||
AF.Low &= 0xEF;
|
||||
return 4;
|
||||
case 0x47: // LD B, A
|
||||
BC.High = AF.High;
|
||||
return 4;
|
||||
case 0x4E: // LD C, (HL)
|
||||
BC.Low = _memory.Read(HL.Word);
|
||||
return 7; // Takes 7 T-States
|
||||
return 7;
|
||||
case 0x56: // LD D, (HL)
|
||||
DE.High = _memory.Read(HL.Word);
|
||||
return 7; // Takes 7 T-States
|
||||
@@ -558,9 +595,18 @@ namespace Core.Cpu
|
||||
case 0x62: // LD H, D
|
||||
HL.High = DE.High;
|
||||
return 4;
|
||||
case 0x67: // LD H, A
|
||||
HL.High = AF.High;
|
||||
return 4;
|
||||
case 0x6B: // LD L, E
|
||||
HL.Low = DE.Low;
|
||||
return 4;
|
||||
case 0x72: // LD (HL), D
|
||||
_memory.Write(HL.Word, DE.High);
|
||||
return 7;
|
||||
case 0x73: // LD (HL), E
|
||||
_memory.Write(HL.Word, DE.Low);
|
||||
return 7;
|
||||
case 0x77: // LD (HL), A
|
||||
_memory.Write(HL.Word, AF.High);
|
||||
return 7;
|
||||
@@ -585,6 +631,9 @@ namespace Core.Cpu
|
||||
case 0x6F: // LD L, A
|
||||
HL.Low = AF.High;
|
||||
return 4;
|
||||
case 0xAE: // XOR (HL)
|
||||
Xor(_memory.Read(HL.Word));
|
||||
return 7;
|
||||
case 0xAF: // XOR A
|
||||
AF.High = 0;
|
||||
AF.Low = 0x44;
|
||||
@@ -654,6 +703,9 @@ namespace Core.Cpu
|
||||
case 0xDE: // SBC A, n
|
||||
Sbc(FetchByte());
|
||||
return 7;
|
||||
case 0xE6: // AND n
|
||||
And(FetchByte());
|
||||
return 7;
|
||||
case 0xE9: // JP (HL)
|
||||
PC = HL.Word;
|
||||
return 4; // Takes 4 T-States
|
||||
@@ -797,6 +849,12 @@ namespace Core.Cpu
|
||||
_memory.Write(targetAddress, nValue);
|
||||
return 19; // Takes 19 T-States
|
||||
}
|
||||
case 0x6E: // LD L, (IY+d)
|
||||
sbyte displacementVal = (sbyte)FetchByte();
|
||||
ushort targetAddr = (ushort)(IY.Word + displacementVal);
|
||||
|
||||
HL.Low = _memory.Read(targetAddr);
|
||||
return 19;
|
||||
case 0x71: // LD (IY+d), C
|
||||
{
|
||||
sbyte offset71 = (sbyte)FetchByte();
|
||||
@@ -820,6 +878,22 @@ namespace Core.Cpu
|
||||
|
||||
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);
|
||||
@@ -839,7 +913,7 @@ namespace Core.Cpu
|
||||
AF.Low |= 0x04; // Set P/V Flag (Bit 2)
|
||||
}
|
||||
|
||||
return 20; // Takes 20 T-States
|
||||
return 20;
|
||||
}
|
||||
case 0x86: // RES 0, (IY+d)
|
||||
byte memValRes0 = _memory.Read(targetAddress);
|
||||
@@ -901,11 +975,11 @@ namespace Core.Cpu
|
||||
return 23;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"FD CB opcode {bitOpcode:X2} not implemented!");
|
||||
throw new NotImplementedException($"FD CB opcode {bitOpcode:X2} at PC 0x{(PC - 1):X4} not implemented!");
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException($"FD prefix opcode {opcode:X2} not implemented!");
|
||||
throw new NotImplementedException($"FD prefix opcode {opcode:X2} at PC 0x{(PC - 2):X4} not implemented!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,10 +362,20 @@ namespace Desktop
|
||||
case 0x37:
|
||||
mnemonic = "SCF";
|
||||
break;
|
||||
case 0x38:
|
||||
sbyte dC = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
|
||||
ushort targetC = (ushort)(currentPc + 2 + dC);
|
||||
|
||||
mnemonic = $"JR C, 0x{targetC:X4}";
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0x3E:
|
||||
mnemonic = $"LD A, 0x{_memoryBus.Read((ushort)(currentPc + 1)):X2}";
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0x3F:
|
||||
mnemonic = "CCF";
|
||||
break;
|
||||
case 0x47:
|
||||
mnemonic = "LD B, A";
|
||||
break;
|
||||
@@ -384,12 +394,21 @@ namespace Desktop
|
||||
case 0x62:
|
||||
mnemonic = "LD H, D";
|
||||
break;
|
||||
case 0x67:
|
||||
mnemonic = "LD H, A";
|
||||
break;
|
||||
case 0x6B:
|
||||
mnemonic = "LD L, E";
|
||||
break;
|
||||
case 0x6F:
|
||||
mnemonic = "LD L, A";
|
||||
break;
|
||||
case 0x72:
|
||||
mnemonic = "LD (HL), D";
|
||||
break;
|
||||
case 0x73:
|
||||
mnemonic = "LD (HL), E";
|
||||
break;
|
||||
case 0x77:
|
||||
mnemonic = "LD (HL), A";
|
||||
break;
|
||||
@@ -408,6 +427,9 @@ namespace Desktop
|
||||
case 0xA7:
|
||||
mnemonic = "AND A";
|
||||
break;
|
||||
case 0xAE:
|
||||
mnemonic = "XOR (HL)";
|
||||
break;
|
||||
case 0xAF:
|
||||
mnemonic = "XOR A";
|
||||
break;
|
||||
@@ -461,6 +483,11 @@ namespace Desktop
|
||||
mnemonic = $"SBC A, 0x{sbcValue:X2}";
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0xE6:
|
||||
byte andImm = _memoryBus.Read((ushort)(currentPc + 1));
|
||||
mnemonic = $"AND 0x{andImm:X2}";
|
||||
instructionLength = 2;
|
||||
break;
|
||||
case 0xE9:
|
||||
mnemonic = "JP (HL)";
|
||||
break;
|
||||
@@ -543,12 +570,24 @@ namespace Desktop
|
||||
mnemonic = $"LD (IY{sign}{d}), 0x{n:X2}";
|
||||
instructionLength = 4;
|
||||
}
|
||||
else if (fdOpcode == 0x6E)
|
||||
{
|
||||
sbyte offsetL = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||
string signL = offsetL >= 0 ? "+" : "";
|
||||
|
||||
mnemonic = $"LD L, (IY{signL}{offsetL})";
|
||||
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 == 0x4E)
|
||||
if (cbOpcode == 0x46)
|
||||
{
|
||||
mnemonic = $"BIT 0, (IY{sign}{d})";
|
||||
}
|
||||
else if (cbOpcode == 0x4E)
|
||||
{
|
||||
mnemonic = $"BIT 1, (IY{sign}{d})";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user