Implemented a load more Z80 OpCodes

This commit is contained in:
2026-04-09 16:08:56 +01:00
parent 340583d663
commit f22da937b5
3 changed files with 179 additions and 6 deletions

View File

@@ -127,8 +127,121 @@ namespace Core.Cpu
if (result < 0) AF.Low |= 0x01;
}
private void Sbc16(ushort value)
{
int hl = HL.Word;
int carry = AF.Low & 0x01;
// Calculate the raw integer result to check for underflows
int result = hl - value - carry;
// Update the HL register
HL.Word = (ushort)result;
// --- Update Flags (F Register) ---
AF.Low = 0; // Clear all flags
// Sign Flag (Bit 7) - Set if the 16-bit result is negative (bit 15 is 1)
if ((result & 0x8000) != 0) AF.Low |= 0x80;
// Zero Flag (Bit 6) - Set if the entire 16-bit result is exactly 0
if ((ushort)result == 0) AF.Low |= 0x40;
// Half-Carry Flag (Bit 4) - Set if borrow from bit 11
if (((hl & 0x0FFF) - (value & 0x0FFF) - carry) < 0) AF.Low |= 0x10;
// Overflow Flag (Bit 2) - Set if operands have different signs and result sign changes
if ((((hl ^ value) & 0x8000) != 0) && (((hl ^ result) & 0x8000) != 0)) AF.Low |= 0x04;
// Subtract Flag (Bit 1) - ALWAYS set for subtraction
AF.Low |= 0x02;
// Carry Flag (Bit 0) - Set if the overall 16-bit result dropped below 0
if (result < 0) AF.Low |= 0x01;
}
private void Cp(byte value)
{
byte a = AF.High;
int result = a - value;
// --- Update Flags (F Register) ---
AF.Low = 0; // Clear all flags
// Sign Flag (Bit 7)
if ((result & 0x80) != 0) AF.Low |= 0x80;
// Zero Flag (Bit 6)
if ((byte)result == 0) AF.Low |= 0x40;
// Half-Carry Flag (Bit 4) - Set if borrow from bit 4
if (((a & 0x0F) - (value & 0x0F)) < 0) AF.Low |= 0x10;
// Overflow Flag (Bit 2) - Set if operands have different signs and result sign changes
if ((((a ^ value) & 0x80) != 0) && (((a ^ result) & 0x80) != 0)) AF.Low |= 0x04;
// Subtract Flag (Bit 1) - ALWAYS set for CP/SUB
AF.Low |= 0x02;
// Carry Flag (Bit 0) - Set if the overall result dropped below 0
if (result < 0) AF.Low |= 0x01;
}
private void And(byte value)
{
AF.High = (byte)(AF.High & value);
// --- Update Flags ---
AF.Low = 0; // Clear all flags
// 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;
// Half-Carry Flag (Bit 4) - ALWAYS SET to 1 for Z80 AND instructions!
AF.Low |= 0x10;
// Parity Flag (Bit 2) - Set if the result has an even number of 1 bits
if (HasEvenParity(AF.High)) AF.Low |= 0x04;
// Subtract Flag (N) and Carry Flag (C) are ALWAYS 0
}
private void Add16(ushort value)
{
int hl = HL.Word;
int result = hl + value;
// Update the HL register
HL.Word = (ushort)result;
// --- Update Flags (F Register) ---
// 16-bit ADD preserves S, Z, P/V (and the undocumented X/Y flags).
// We clear H (Bit 4), N (Bit 1), and C (Bit 0) using a bitwise AND mask (0xEC = 1110 1100)
AF.Low &= 0xEC;
// Half-Carry Flag (Bit 4) - Set if there is a carry from bit 11
if (((hl & 0x0FFF) + (value & 0x0FFF)) > 0x0FFF) AF.Low |= 0x10;
// Carry Flag (Bit 0) - Set if the result overflows 16 bits
if (result > 0xFFFF) AF.Low |= 0x01;
}
private bool HasEvenParity(byte value)
{
int bits = 0;
for (int i = 0; i < 8; i++)
{
if ((value & (1 << i)) != 0) bits++;
}
return (bits % 2) == 0;
}
private int ExecuteOpcode(byte opcode)
{
sbyte offset = 0;
switch (opcode)
{
case 0x00: // NOP
@@ -136,9 +249,33 @@ namespace Core.Cpu
case 0x11: //LD DE, nn
DE.Word = FetchWord();
return 10;
case 0x19: // ADD HL, DE
Add16(DE.Word);
return 11;
case 0x20: // JR NZ, e
offset = (sbyte)FetchByte();
if ((AF.Low & 0x40) == 0)
{
PC = (ushort)(PC + offset);
return 12;
}
return 7;
case 0x23: // INC HL
HL.Word++;
return 6;
case 0x2B: // DEC HL
HL.Word--;
return 6;
case 0x30: // JR NC, e
offset = (sbyte)FetchByte();
// Check if the Carry Flag (Bit 0) is NOT set
if ((AF.Low & 0x01) == 0)
{
PC = (ushort)(PC + offset);
return 12; // Jump taken
}
return 7; // Jump not taken
case 0x36: // LD (HL), n
byte nValue = FetchByte();
_memory.Write(HL.Word, nValue);
@@ -155,6 +292,12 @@ namespace Core.Cpu
case 0x6B: // LD L, E
HL.Low = DE.Low;
return 4;
case 0xA7: // AND A
And(AF.High);
return 4;
case 0xBC: // CP H
Cp(HL.High);
return 4;
case 0xC3:
PC = FetchWord();
return 10;
@@ -195,6 +338,9 @@ namespace Core.Cpu
case 0x47: // LD I, A
I = AF.High;
return 9;
case 0x52: // SBC HL, DE
Sbc16(DE.Word);
return 15; // Takes 15 T-States
default:
throw new NotImplementedException($"Extended ED Opcode 0x{extendedOpcode:X2} at PC 0x{(PC - 1):X4} is not implemented.");
}