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;
|
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)
|
private void Add16(ushort value)
|
||||||
{
|
{
|
||||||
int hl = HL.Word;
|
int hl = HL.Word;
|
||||||
@@ -539,16 +557,35 @@ namespace Core.Cpu
|
|||||||
case 0x37: // SCF
|
case 0x37: // SCF
|
||||||
AF.Low |= 0x01; // Force Carry Flag (Bit 0) to 1
|
AF.Low |= 0x01; // Force Carry Flag (Bit 0) to 1
|
||||||
AF.Low &= 0xED;
|
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
|
case 0x3E: //LD A, n
|
||||||
AF.High = FetchByte();
|
AF.High = FetchByte();
|
||||||
return 7;
|
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
|
case 0x47: // LD B, A
|
||||||
BC.High = AF.High;
|
BC.High = AF.High;
|
||||||
return 4;
|
return 4;
|
||||||
case 0x4E: // LD C, (HL)
|
case 0x4E: // LD C, (HL)
|
||||||
BC.Low = _memory.Read(HL.Word);
|
BC.Low = _memory.Read(HL.Word);
|
||||||
return 7; // Takes 7 T-States
|
return 7;
|
||||||
case 0x56: // LD D, (HL)
|
case 0x56: // LD D, (HL)
|
||||||
DE.High = _memory.Read(HL.Word);
|
DE.High = _memory.Read(HL.Word);
|
||||||
return 7; // Takes 7 T-States
|
return 7; // Takes 7 T-States
|
||||||
@@ -558,9 +595,18 @@ namespace Core.Cpu
|
|||||||
case 0x62: // LD H, D
|
case 0x62: // LD H, D
|
||||||
HL.High = DE.High;
|
HL.High = DE.High;
|
||||||
return 4;
|
return 4;
|
||||||
|
case 0x67: // LD H, A
|
||||||
|
HL.High = AF.High;
|
||||||
|
return 4;
|
||||||
case 0x6B: // LD L, E
|
case 0x6B: // LD L, E
|
||||||
HL.Low = DE.Low;
|
HL.Low = DE.Low;
|
||||||
return 4;
|
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
|
case 0x77: // LD (HL), A
|
||||||
_memory.Write(HL.Word, AF.High);
|
_memory.Write(HL.Word, AF.High);
|
||||||
return 7;
|
return 7;
|
||||||
@@ -585,6 +631,9 @@ namespace Core.Cpu
|
|||||||
case 0x6F: // LD L, A
|
case 0x6F: // LD L, A
|
||||||
HL.Low = AF.High;
|
HL.Low = AF.High;
|
||||||
return 4;
|
return 4;
|
||||||
|
case 0xAE: // XOR (HL)
|
||||||
|
Xor(_memory.Read(HL.Word));
|
||||||
|
return 7;
|
||||||
case 0xAF: // XOR A
|
case 0xAF: // XOR A
|
||||||
AF.High = 0;
|
AF.High = 0;
|
||||||
AF.Low = 0x44;
|
AF.Low = 0x44;
|
||||||
@@ -654,6 +703,9 @@ namespace Core.Cpu
|
|||||||
case 0xDE: // SBC A, n
|
case 0xDE: // SBC A, n
|
||||||
Sbc(FetchByte());
|
Sbc(FetchByte());
|
||||||
return 7;
|
return 7;
|
||||||
|
case 0xE6: // AND n
|
||||||
|
And(FetchByte());
|
||||||
|
return 7;
|
||||||
case 0xE9: // JP (HL)
|
case 0xE9: // JP (HL)
|
||||||
PC = HL.Word;
|
PC = HL.Word;
|
||||||
return 4; // Takes 4 T-States
|
return 4; // Takes 4 T-States
|
||||||
@@ -797,6 +849,12 @@ namespace Core.Cpu
|
|||||||
_memory.Write(targetAddress, nValue);
|
_memory.Write(targetAddress, nValue);
|
||||||
return 19; // Takes 19 T-States
|
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
|
case 0x71: // LD (IY+d), C
|
||||||
{
|
{
|
||||||
sbyte offset71 = (sbyte)FetchByte();
|
sbyte offset71 = (sbyte)FetchByte();
|
||||||
@@ -820,6 +878,22 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
switch (bitOpcode)
|
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)
|
case 0x4E: // BIT 1, (IY+d)
|
||||||
{
|
{
|
||||||
byte memValBit = _memory.Read(targetAddress);
|
byte memValBit = _memory.Read(targetAddress);
|
||||||
@@ -839,7 +913,7 @@ namespace Core.Cpu
|
|||||||
AF.Low |= 0x04; // Set P/V Flag (Bit 2)
|
AF.Low |= 0x04; // Set P/V Flag (Bit 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 20; // Takes 20 T-States
|
return 20;
|
||||||
}
|
}
|
||||||
case 0x86: // RES 0, (IY+d)
|
case 0x86: // RES 0, (IY+d)
|
||||||
byte memValRes0 = _memory.Read(targetAddress);
|
byte memValRes0 = _memory.Read(targetAddress);
|
||||||
@@ -901,11 +975,11 @@ namespace Core.Cpu
|
|||||||
return 23;
|
return 23;
|
||||||
|
|
||||||
default:
|
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:
|
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:
|
case 0x37:
|
||||||
mnemonic = "SCF";
|
mnemonic = "SCF";
|
||||||
break;
|
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:
|
case 0x3E:
|
||||||
mnemonic = $"LD A, 0x{_memoryBus.Read((ushort)(currentPc + 1)):X2}";
|
mnemonic = $"LD A, 0x{_memoryBus.Read((ushort)(currentPc + 1)):X2}";
|
||||||
instructionLength = 2;
|
instructionLength = 2;
|
||||||
break;
|
break;
|
||||||
|
case 0x3F:
|
||||||
|
mnemonic = "CCF";
|
||||||
|
break;
|
||||||
case 0x47:
|
case 0x47:
|
||||||
mnemonic = "LD B, A";
|
mnemonic = "LD B, A";
|
||||||
break;
|
break;
|
||||||
@@ -384,12 +394,21 @@ namespace Desktop
|
|||||||
case 0x62:
|
case 0x62:
|
||||||
mnemonic = "LD H, D";
|
mnemonic = "LD H, D";
|
||||||
break;
|
break;
|
||||||
|
case 0x67:
|
||||||
|
mnemonic = "LD H, A";
|
||||||
|
break;
|
||||||
case 0x6B:
|
case 0x6B:
|
||||||
mnemonic = "LD L, E";
|
mnemonic = "LD L, E";
|
||||||
break;
|
break;
|
||||||
case 0x6F:
|
case 0x6F:
|
||||||
mnemonic = "LD L, A";
|
mnemonic = "LD L, A";
|
||||||
break;
|
break;
|
||||||
|
case 0x72:
|
||||||
|
mnemonic = "LD (HL), D";
|
||||||
|
break;
|
||||||
|
case 0x73:
|
||||||
|
mnemonic = "LD (HL), E";
|
||||||
|
break;
|
||||||
case 0x77:
|
case 0x77:
|
||||||
mnemonic = "LD (HL), A";
|
mnemonic = "LD (HL), A";
|
||||||
break;
|
break;
|
||||||
@@ -408,6 +427,9 @@ namespace Desktop
|
|||||||
case 0xA7:
|
case 0xA7:
|
||||||
mnemonic = "AND A";
|
mnemonic = "AND A";
|
||||||
break;
|
break;
|
||||||
|
case 0xAE:
|
||||||
|
mnemonic = "XOR (HL)";
|
||||||
|
break;
|
||||||
case 0xAF:
|
case 0xAF:
|
||||||
mnemonic = "XOR A";
|
mnemonic = "XOR A";
|
||||||
break;
|
break;
|
||||||
@@ -461,6 +483,11 @@ namespace Desktop
|
|||||||
mnemonic = $"SBC A, 0x{sbcValue:X2}";
|
mnemonic = $"SBC A, 0x{sbcValue:X2}";
|
||||||
instructionLength = 2;
|
instructionLength = 2;
|
||||||
break;
|
break;
|
||||||
|
case 0xE6:
|
||||||
|
byte andImm = _memoryBus.Read((ushort)(currentPc + 1));
|
||||||
|
mnemonic = $"AND 0x{andImm:X2}";
|
||||||
|
instructionLength = 2;
|
||||||
|
break;
|
||||||
case 0xE9:
|
case 0xE9:
|
||||||
mnemonic = "JP (HL)";
|
mnemonic = "JP (HL)";
|
||||||
break;
|
break;
|
||||||
@@ -543,12 +570,24 @@ namespace Desktop
|
|||||||
mnemonic = $"LD (IY{sign}{d}), 0x{n:X2}";
|
mnemonic = $"LD (IY{sign}{d}), 0x{n:X2}";
|
||||||
instructionLength = 4;
|
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
|
else if (fdOpcode == 0xCB) // FD CB prefix
|
||||||
{
|
{
|
||||||
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
byte cbOpcode = _memoryBus.Read((ushort)(currentPc + 3));
|
byte cbOpcode = _memoryBus.Read((ushort)(currentPc + 3));
|
||||||
string sign = d >= 0 ? "+" : "";
|
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})";
|
mnemonic = $"BIT 1, (IY{sign}{d})";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user