Chuckie Egg runs fully from a snapshot file! Fully playable!
This commit is contained in:
206
Core/Cpu/Z80.cs
206
Core/Cpu/Z80.cs
@@ -43,6 +43,10 @@ namespace Core.Cpu
|
|||||||
private readonly IO_Bus _simpleIoBus;
|
private readonly IO_Bus _simpleIoBus;
|
||||||
public TapManager _tapManager;
|
public TapManager _tapManager;
|
||||||
|
|
||||||
|
//Misc Variables
|
||||||
|
byte newFlags = 0;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
public Z80(IMemory memory, IO_Bus ioBus, TapManager tapManager)
|
public Z80(IMemory memory, IO_Bus ioBus, TapManager tapManager)
|
||||||
{
|
{
|
||||||
_memory = memory;
|
_memory = memory;
|
||||||
@@ -278,7 +282,7 @@ namespace Core.Cpu
|
|||||||
private void Sub(byte value)
|
private void Sub(byte value)
|
||||||
{
|
{
|
||||||
byte a = AF.High;
|
byte a = AF.High;
|
||||||
int result = a - value;
|
result = a - value;
|
||||||
|
|
||||||
// Save the result back to the Accumulator
|
// Save the result back to the Accumulator
|
||||||
AF.High = (byte)result;
|
AF.High = (byte)result;
|
||||||
@@ -311,7 +315,7 @@ namespace Core.Cpu
|
|||||||
byte carry = (byte)(AF.Low & 0x01); // Get the current Carry flag (Bit 0)
|
byte carry = (byte)(AF.Low & 0x01); // Get the current Carry flag (Bit 0)
|
||||||
|
|
||||||
// Calculate the raw integer result to check for borrows/underflows
|
// Calculate the raw integer result to check for borrows/underflows
|
||||||
int result = a - value - carry;
|
result = a - value - carry;
|
||||||
|
|
||||||
// Update the Accumulator
|
// Update the Accumulator
|
||||||
AF.High = (byte)result;
|
AF.High = (byte)result;
|
||||||
@@ -344,7 +348,7 @@ namespace Core.Cpu
|
|||||||
int carry = AF.Low & 0x01;
|
int carry = AF.Low & 0x01;
|
||||||
|
|
||||||
// Calculate the raw integer result to check for underflows
|
// Calculate the raw integer result to check for underflows
|
||||||
int result = hl - value - carry;
|
result = hl - value - carry;
|
||||||
|
|
||||||
// Update the HL register
|
// Update the HL register
|
||||||
HL.Word = (ushort)result;
|
HL.Word = (ushort)result;
|
||||||
@@ -435,7 +439,7 @@ namespace Core.Cpu
|
|||||||
private void Cp(byte value)
|
private void Cp(byte value)
|
||||||
{
|
{
|
||||||
byte a = AF.High;
|
byte a = AF.High;
|
||||||
int result = a - value;
|
result = a - value;
|
||||||
|
|
||||||
// --- Update Flags (F Register) ---
|
// --- Update Flags (F Register) ---
|
||||||
AF.Low = 0; // Clear all flags
|
AF.Low = 0; // Clear all flags
|
||||||
@@ -519,7 +523,7 @@ namespace Core.Cpu
|
|||||||
private void Add16(ushort value)
|
private void Add16(ushort value)
|
||||||
{
|
{
|
||||||
int hl = HL.Word;
|
int hl = HL.Word;
|
||||||
int result = hl + value;
|
result = hl + value;
|
||||||
|
|
||||||
// Update the HL register
|
// Update the HL register
|
||||||
HL.Word = (ushort)result;
|
HL.Word = (ushort)result;
|
||||||
@@ -531,11 +535,30 @@ namespace Core.Cpu
|
|||||||
// Carry Flag (Bit 0) - Set if the result overflows 16 bits
|
// Carry Flag (Bit 0) - Set if the result overflows 16 bits
|
||||||
if (result > 0xFFFF) AF.Low |= 0x01;
|
if (result > 0xFFFF) AF.Low |= 0x01;
|
||||||
}
|
}
|
||||||
|
private void Add16IX(ushort value)
|
||||||
|
{
|
||||||
|
int ixVal = IX.Word;
|
||||||
|
result = ixVal + value;
|
||||||
|
|
||||||
|
// --- 16-Bit ADD IX Flag Calculation ---
|
||||||
|
// Preserve S (Bit 7), Z (Bit 6), and P/V (Bit 2).
|
||||||
|
// This perfectly resets N (Bit 1) to 0 at the same time.
|
||||||
|
newFlags = (byte)(AF.Low & 0xC4);
|
||||||
|
|
||||||
|
// Half-Carry (H - Bit 4): Set if carry from Bit 11
|
||||||
|
if (((ixVal & 0x0FFF) + (value & 0x0FFF)) > 0x0FFF) newFlags |= 0x10;
|
||||||
|
|
||||||
|
// Carry (C - Bit 0): Set if the total result overflows 16 bits
|
||||||
|
if (result > 0xFFFF) newFlags |= 0x01;
|
||||||
|
|
||||||
|
AF.Low = newFlags;
|
||||||
|
IX.Word = (ushort)result;
|
||||||
|
}
|
||||||
|
|
||||||
private void Add(byte value)
|
private void Add(byte value)
|
||||||
{
|
{
|
||||||
byte a = AF.High;
|
byte a = AF.High;
|
||||||
int result = a + value;
|
result = a + value;
|
||||||
|
|
||||||
// Save the result back to the Accumulator
|
// Save the result back to the Accumulator
|
||||||
AF.High = (byte)result;
|
AF.High = (byte)result;
|
||||||
@@ -565,7 +588,7 @@ namespace Core.Cpu
|
|||||||
int aVal = AF.High;
|
int aVal = AF.High;
|
||||||
int carryIn = AF.Low & 0x01;
|
int carryIn = AF.Low & 0x01;
|
||||||
|
|
||||||
int result = aVal + operand + carryIn;
|
result = aVal + operand + carryIn;
|
||||||
|
|
||||||
byte newFlags = 0;
|
byte newFlags = 0;
|
||||||
|
|
||||||
@@ -585,7 +608,7 @@ namespace Core.Cpu
|
|||||||
int carry = AF.Low & 0x01;
|
int carry = AF.Low & 0x01;
|
||||||
|
|
||||||
// Calculate the raw integer result to check for overflows
|
// Calculate the raw integer result to check for overflows
|
||||||
int result = hl + value + carry;
|
result = hl + value + carry;
|
||||||
|
|
||||||
// --- Update Flags (F Register) ---
|
// --- Update Flags (F Register) ---
|
||||||
byte newFlags = 0; // Clear all flags (which forces N to 0, correctly!)
|
byte newFlags = 0; // Clear all flags (which forces N to 0, correctly!)
|
||||||
@@ -612,7 +635,7 @@ namespace Core.Cpu
|
|||||||
private void AddA(byte operand)
|
private void AddA(byte operand)
|
||||||
{
|
{
|
||||||
byte a = AF.High;
|
byte a = AF.High;
|
||||||
int result = a + operand;
|
result = a + operand;
|
||||||
|
|
||||||
AF.High = (byte)result;
|
AF.High = (byte)result;
|
||||||
|
|
||||||
@@ -1487,8 +1510,6 @@ namespace Core.Cpu
|
|||||||
// Fetch the actual extended instruction
|
// Fetch the actual extended instruction
|
||||||
byte extendedOpcode = _memory.Read(PC++);
|
byte extendedOpcode = _memory.Read(PC++);
|
||||||
byte val = 0;
|
byte val = 0;
|
||||||
byte newFlags = 0;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (extendedOpcode)
|
switch (extendedOpcode)
|
||||||
{
|
{
|
||||||
@@ -1561,6 +1582,10 @@ namespace Core.Cpu
|
|||||||
DE.Low = _memory.Read(src5B);
|
DE.Low = _memory.Read(src5B);
|
||||||
DE.High = _memory.Read((ushort)(src5B + 1));
|
DE.High = _memory.Read((ushort)(src5B + 1));
|
||||||
return 20;
|
return 20;
|
||||||
|
case 0x5E: // IM 2
|
||||||
|
// Set the CPU's internal interrupt mode state
|
||||||
|
InterruptMode = 2;
|
||||||
|
return 8;
|
||||||
case 0x5F: // LD A, R
|
case 0x5F: // LD A, R
|
||||||
// 1. Load the Refresh register into the Accumulator
|
// 1. Load the Refresh register into the Accumulator
|
||||||
AF.High = R;
|
AF.High = R;
|
||||||
@@ -1920,25 +1945,16 @@ namespace Core.Cpu
|
|||||||
switch (ddOpcode)
|
switch (ddOpcode)
|
||||||
{
|
{
|
||||||
case 0x09: // ADD IX, BC
|
case 0x09: // ADD IX, BC
|
||||||
int result = IX.Word + BC.Word;
|
Add16IX(BC.Word);
|
||||||
|
return 15;
|
||||||
// --- 16-Bit Flag Calculation ---
|
case 0x19: // ADD IX, DE
|
||||||
// Preserve S (Bit 7), Z (Bit 6), and P/V (Bit 2).
|
Add16IX(DE.Word);
|
||||||
byte newFlags = (byte)(AF.Low & 0xC4);
|
return 15;
|
||||||
|
case 0x29: // ADD IX, IX
|
||||||
// Half-Carry (H - Bit 4): Set if carry from Bit 11
|
Add16IX(IX.Word); // Multiplies IX by 2!
|
||||||
if (((IX.Word & 0x0FFF) + (BC.Word & 0x0FFF)) > 0x0FFF)
|
return 15;
|
||||||
newFlags |= 0x10;
|
case 0x39: // ADD IX, SP
|
||||||
|
Add16IX(SP);
|
||||||
// Carry (C - Bit 0): Set if the total result overflows 16 bits
|
|
||||||
if (result > 0xFFFF)
|
|
||||||
newFlags |= 0x01;
|
|
||||||
|
|
||||||
// (N - Bit 1 is left at 0 because the bitwise AND above cleared it)
|
|
||||||
|
|
||||||
AF.Low = newFlags;
|
|
||||||
IX.Word = (ushort)result;
|
|
||||||
|
|
||||||
return 15;
|
return 15;
|
||||||
case 0x21: // LD IX, nn
|
case 0x21: // LD IX, nn
|
||||||
byte low = FetchByte();
|
byte low = FetchByte();
|
||||||
@@ -2002,6 +2018,40 @@ namespace Core.Cpu
|
|||||||
// Fetch the immediate 8-bit value and drop it straight into the low byte of IX
|
// Fetch the immediate 8-bit value and drop it straight into the low byte of IX
|
||||||
IX.Low = FetchByte();
|
IX.Low = FetchByte();
|
||||||
return 11;
|
return 11;
|
||||||
|
case 0x34: // INC (IX+d)
|
||||||
|
// 1. Fetch the displacement byte and cast to a signed sbyte
|
||||||
|
sbyte offset34 = (sbyte)FetchByte();
|
||||||
|
|
||||||
|
// 2. Calculate the target memory address
|
||||||
|
ushort address34 = (ushort)(IX.Word + offset34);
|
||||||
|
|
||||||
|
// 3. Read the value from memory
|
||||||
|
byte val34 = _memory.Read(address34);
|
||||||
|
|
||||||
|
// 4. Pass it through your helper to increment and set the flags perfectly
|
||||||
|
byte result34 = Inc8(val34);
|
||||||
|
|
||||||
|
// 5. Write the incremented value back to memory
|
||||||
|
_memory.Write(address34, result34);
|
||||||
|
|
||||||
|
return 23;
|
||||||
|
case 0x35: // DEC (IX+d)
|
||||||
|
// 1. Fetch the displacement byte and cast to a signed sbyte
|
||||||
|
sbyte offset35 = (sbyte)FetchByte();
|
||||||
|
|
||||||
|
// 2. Calculate the target memory address
|
||||||
|
ushort address35 = (ushort)(IX.Word + offset35);
|
||||||
|
|
||||||
|
// 3. Read the value from memory
|
||||||
|
byte val35 = _memory.Read(address35);
|
||||||
|
|
||||||
|
// 4. Pass it through your helper to decrement and set the flags
|
||||||
|
byte result35 = Dec8(val35);
|
||||||
|
|
||||||
|
// 5. Write the decremented value back to memory
|
||||||
|
_memory.Write(address35, result35);
|
||||||
|
|
||||||
|
return 23;
|
||||||
case 0x36: // LD (IX+d), n
|
case 0x36: // LD (IX+d), n
|
||||||
// 1. Fetch the displacement byte first
|
// 1. Fetch the displacement byte first
|
||||||
sbyte offset36 = (sbyte)FetchByte();
|
sbyte offset36 = (sbyte)FetchByte();
|
||||||
@@ -2071,9 +2121,22 @@ namespace Core.Cpu
|
|||||||
HL.High = _memory.Read(address66);
|
HL.High = _memory.Read(address66);
|
||||||
|
|
||||||
return 19;
|
return 19;
|
||||||
|
case 0x67: // LD IXH, A
|
||||||
|
// Load the Accumulator (AF.High) directly into the high byte of IX
|
||||||
|
IX.High = AF.High;
|
||||||
|
return 8;
|
||||||
case 0x68: // LD IXL, B
|
case 0x68: // LD IXL, B
|
||||||
IX.Low = BC.High;
|
IX.Low = BC.High;
|
||||||
return 8;
|
return 8;
|
||||||
|
case 0x69: // LD IXL, C
|
||||||
|
// Load the C register (BC.Low) into the low byte of IX
|
||||||
|
IX.Low = BC.Low;
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
case 0x6A: // LD IXL, D
|
||||||
|
// Load the D register (DE.High) into the low byte of IX
|
||||||
|
IX.Low = DE.High;
|
||||||
|
return 8;
|
||||||
case 0x6E: // LD L, (IX+d)
|
case 0x6E: // LD L, (IX+d)
|
||||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||||
sbyte offset6E = (sbyte)FetchByte();
|
sbyte offset6E = (sbyte)FetchByte();
|
||||||
@@ -2085,7 +2148,29 @@ namespace Core.Cpu
|
|||||||
HL.Low = _memory.Read(address6E);
|
HL.Low = _memory.Read(address6E);
|
||||||
|
|
||||||
return 19;
|
return 19;
|
||||||
|
case 0x72: // LD (IX+d), D
|
||||||
|
// 1. Fetch the displacement byte and cast to a signed sbyte
|
||||||
|
sbyte offset72 = (sbyte)FetchByte();
|
||||||
|
|
||||||
|
// 2. Calculate the target memory address
|
||||||
|
ushort address72 = (ushort)(IX.Word + offset72);
|
||||||
|
|
||||||
|
// 3. Write the D register (DE.High) to memory
|
||||||
|
_memory.Write(address72, DE.High);
|
||||||
|
|
||||||
|
return 19; // 19 T-States
|
||||||
|
case 0x73: // LD (IX+d), E
|
||||||
|
// 1. Fetch the displacement byte and cast to a signed sbyte
|
||||||
|
sbyte offset73 = (sbyte)FetchByte();
|
||||||
|
|
||||||
|
// 2. Calculate the target memory address
|
||||||
|
ushort address73 = (ushort)(IX.Word + offset73);
|
||||||
|
|
||||||
|
// 3. Write the E register (DE.Low) to memory
|
||||||
|
_memory.Write(address73, DE.Low);
|
||||||
|
|
||||||
|
return 19;
|
||||||
|
|
||||||
case 0x74: // LD (IX+d), H
|
case 0x74: // LD (IX+d), H
|
||||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||||
sbyte offset74 = (sbyte)FetchByte();
|
sbyte offset74 = (sbyte)FetchByte();
|
||||||
@@ -2119,6 +2204,10 @@ namespace Core.Cpu
|
|||||||
_memory.Write(address77, AF.High);
|
_memory.Write(address77, AF.High);
|
||||||
|
|
||||||
return 19;
|
return 19;
|
||||||
|
case 0x7C: // LD A, IXH
|
||||||
|
// Load the high byte of IX directly into the Accumulator
|
||||||
|
AF.High = IX.High;
|
||||||
|
return 8;
|
||||||
case 0x7E: // LD A, (IX+d)
|
case 0x7E: // LD A, (IX+d)
|
||||||
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
// 1. Fetch the displacement byte and cast it to a signed sbyte
|
||||||
sbyte offset7E = (sbyte)FetchByte();
|
sbyte offset7E = (sbyte)FetchByte();
|
||||||
@@ -2129,6 +2218,21 @@ namespace Core.Cpu
|
|||||||
// 3. Read the byte from memory and drop it straight into the Accumulator (A)
|
// 3. Read the byte from memory and drop it straight into the Accumulator (A)
|
||||||
AF.High = _memory.Read(address7E);
|
AF.High = _memory.Read(address7E);
|
||||||
|
|
||||||
|
return 19;
|
||||||
|
case 0x86: // ADD A, (IX+d)
|
||||||
|
sbyte offset86 = (sbyte)FetchByte();
|
||||||
|
ushort address86 = (ushort)(IX.Word + offset86);
|
||||||
|
|
||||||
|
// Read the memory and pass it straight into your flawless helper!
|
||||||
|
Add(_memory.Read(address86));
|
||||||
|
return 19;
|
||||||
|
|
||||||
|
case 0x96: // SUB (IX+d)
|
||||||
|
sbyte offset96 = (sbyte)FetchByte();
|
||||||
|
ushort address96 = (ushort)(IX.Word + offset96);
|
||||||
|
|
||||||
|
// Read the memory and pass it straight into your flawless helper!
|
||||||
|
Sub(_memory.Read(address96));
|
||||||
return 19;
|
return 19;
|
||||||
case 0xBE: // CP (IX+d)
|
case 0xBE: // CP (IX+d)
|
||||||
// 1. Fetch the displacement byte and calculate the address
|
// 1. Fetch the displacement byte and calculate the address
|
||||||
@@ -2167,7 +2271,45 @@ namespace Core.Cpu
|
|||||||
|
|
||||||
// CRITICAL: Notice we do NOT update AF.High! The Accumulator is preserved.
|
// CRITICAL: Notice we do NOT update AF.High! The Accumulator is preserved.
|
||||||
|
|
||||||
return 19; // 19 T-States
|
return 19;
|
||||||
|
case 0xCB: // The DD CB nested prefix
|
||||||
|
{
|
||||||
|
// 1. Fetch the displacement byte first
|
||||||
|
sbyte displacement = (sbyte)FetchByte();
|
||||||
|
|
||||||
|
// 2. Fetch the actual operation opcode (like your 0x72) second
|
||||||
|
byte cbOpcode = FetchByte();
|
||||||
|
|
||||||
|
ushort targetAddress = (ushort)(IX.Word + displacement);
|
||||||
|
byte memVal = _memory.Read(targetAddress);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
case 1: // ALL BIT Instructions
|
||||||
|
AF.Low &= 0x01; // Preserve ONLY Carry
|
||||||
|
AF.Low |= 0x10; // Set Half-Carry
|
||||||
|
|
||||||
|
if ((memVal & bitMask) == 0)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
return 20; // 20 T-States
|
||||||
|
|
||||||
|
// (You can copy your RES and SET logic from ExecuteFDPrefix here later!)
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"DD CB opcode {cbOpcode:X2} not fully implemented!");
|
||||||
|
}
|
||||||
|
}
|
||||||
case 0xE1: // POP IX
|
case 0xE1: // POP IX
|
||||||
// 1. Read the low byte from the top of the stack
|
// 1. Read the low byte from the top of the stack
|
||||||
byte popLow = _memory.Read(SP);
|
byte popLow = _memory.Read(SP);
|
||||||
|
|||||||
@@ -832,11 +832,10 @@ namespace Desktop
|
|||||||
case 0xDD:
|
case 0xDD:
|
||||||
{
|
{
|
||||||
byte ddOpcode = _memoryBus.Read((ushort)(currentPc + 1));
|
byte ddOpcode = _memoryBus.Read((ushort)(currentPc + 1));
|
||||||
if (ddOpcode == 0x09) // ADD IX, BC
|
if (ddOpcode == 0x09) { mnemonic = "ADD IX, BC"; instructionLength = 2; }
|
||||||
{
|
else if (ddOpcode == 0x19) { mnemonic = "ADD IX, DE"; instructionLength = 2; }
|
||||||
mnemonic = "ADD IX, BC";
|
else if (ddOpcode == 0x29) { mnemonic = "ADD IX, IX"; instructionLength = 2; }
|
||||||
instructionLength = 2;
|
else if (ddOpcode == 0x39) { mnemonic = "ADD IX, SP"; instructionLength = 2; }
|
||||||
}
|
|
||||||
else if (ddOpcode == 0x21) // LD IX, nn
|
else if (ddOpcode == 0x21) // LD IX, nn
|
||||||
{
|
{
|
||||||
ushort ixVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
|
ushort ixVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
|
||||||
@@ -892,6 +891,20 @@ namespace Desktop
|
|||||||
mnemonic = $"LD IXL, 0x{nValue:X2}";
|
mnemonic = $"LD IXL, 0x{nValue:X2}";
|
||||||
instructionLength = 3;
|
instructionLength = 3;
|
||||||
}
|
}
|
||||||
|
else if (ddOpcode == 0x34) // INC (IX+d)
|
||||||
|
{
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
mnemonic = $"INC (IX{sign}{offset})";
|
||||||
|
instructionLength = 3;
|
||||||
|
}
|
||||||
|
else if (ddOpcode == 0x35) // DEC (IX+d)
|
||||||
|
{
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
mnemonic = $"DEC (IX{sign}{offset})";
|
||||||
|
instructionLength = 3;
|
||||||
|
}
|
||||||
else if (ddOpcode == 0x36) // LD (IX+d), n
|
else if (ddOpcode == 0x36) // LD (IX+d), n
|
||||||
{
|
{
|
||||||
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
@@ -936,11 +949,26 @@ namespace Desktop
|
|||||||
mnemonic = $"LD H, (IX{sign}{d})";
|
mnemonic = $"LD H, (IX{sign}{d})";
|
||||||
instructionLength = 3;
|
instructionLength = 3;
|
||||||
}
|
}
|
||||||
|
else if (ddOpcode == 0x67) // LD IXH, A
|
||||||
|
{
|
||||||
|
mnemonic = "LD IXH, A";
|
||||||
|
instructionLength = 2;
|
||||||
|
}
|
||||||
else if (ddOpcode == 0x68) // LD IXL, B
|
else if (ddOpcode == 0x68) // LD IXL, B
|
||||||
{
|
{
|
||||||
mnemonic = "LD IXL, B";
|
mnemonic = "LD IXL, B";
|
||||||
instructionLength = 2;
|
instructionLength = 2;
|
||||||
}
|
}
|
||||||
|
else if (ddOpcode == 0x69) // LD IXL, C
|
||||||
|
{
|
||||||
|
mnemonic = "LD IXL, C";
|
||||||
|
instructionLength = 2;
|
||||||
|
}
|
||||||
|
else if (ddOpcode == 0x6A) // LD IXL, D
|
||||||
|
{
|
||||||
|
mnemonic = "LD IXL, D";
|
||||||
|
instructionLength = 2;
|
||||||
|
}
|
||||||
else if (ddOpcode == 0x6E) // LD L, (IX+d)
|
else if (ddOpcode == 0x6E) // LD L, (IX+d)
|
||||||
{
|
{
|
||||||
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
@@ -948,6 +976,20 @@ namespace Desktop
|
|||||||
mnemonic = $"LD L, (IX{sign}{d})";
|
mnemonic = $"LD L, (IX{sign}{d})";
|
||||||
instructionLength = 3;
|
instructionLength = 3;
|
||||||
}
|
}
|
||||||
|
else if (ddOpcode == 0x72) // LD (IX+d), D
|
||||||
|
{
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
mnemonic = $"LD (IX{sign}{offset}), D";
|
||||||
|
instructionLength = 3;
|
||||||
|
}
|
||||||
|
else if (ddOpcode == 0x73) // LD (IX+d), E
|
||||||
|
{
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
mnemonic = $"LD (IX{sign}{offset}), E";
|
||||||
|
instructionLength = 3;
|
||||||
|
}
|
||||||
else if (ddOpcode == 0x74) // LD (IX+d), H
|
else if (ddOpcode == 0x74) // LD (IX+d), H
|
||||||
{
|
{
|
||||||
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
@@ -973,6 +1015,11 @@ namespace Desktop
|
|||||||
|
|
||||||
instructionLength = 3;
|
instructionLength = 3;
|
||||||
}
|
}
|
||||||
|
else if (ddOpcode == 0x7C) // LD A, IXH
|
||||||
|
{
|
||||||
|
mnemonic = "LD A, IXH";
|
||||||
|
instructionLength = 2;
|
||||||
|
}
|
||||||
else if (ddOpcode == 0x7E) // LD A, (IX+d)
|
else if (ddOpcode == 0x7E) // LD A, (IX+d)
|
||||||
{
|
{
|
||||||
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
@@ -980,6 +1027,35 @@ namespace Desktop
|
|||||||
mnemonic = $"LD A, (IX{sign}{d})";
|
mnemonic = $"LD A, (IX{sign}{d})";
|
||||||
instructionLength = 3;
|
instructionLength = 3;
|
||||||
}
|
}
|
||||||
|
else if (ddOpcode == 0x86)
|
||||||
|
{
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
mnemonic = $"ADD A, (IX{sign}{offset})";
|
||||||
|
instructionLength = 3;
|
||||||
|
}
|
||||||
|
else if (ddOpcode == 0x96)
|
||||||
|
{
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
mnemonic = $"SUB (IX{sign}{offset})";
|
||||||
|
instructionLength = 3;
|
||||||
|
}
|
||||||
|
else if (ddOpcode == 0xCB)
|
||||||
|
{
|
||||||
|
// DD CB instructions are 4 bytes long!
|
||||||
|
sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
|
cbOp = _memoryBus.Read((ushort)(currentPc + 3));
|
||||||
|
|
||||||
|
int operation = cbOp >> 6;
|
||||||
|
int bitIndex = (cbOp >> 3) & 0x07;
|
||||||
|
string sign = offset >= 0 ? "+" : "";
|
||||||
|
|
||||||
|
if (operation == 1) mnemonic = $"BIT {bitIndex}, (IX{sign}{offset})";
|
||||||
|
else mnemonic = $"DD CB (IX{sign}{offset}) {cbOp:X2}"; // Fallback
|
||||||
|
|
||||||
|
instructionLength = 4;
|
||||||
|
}
|
||||||
else if (ddOpcode == 0xBE) // CP (IX+d)
|
else if (ddOpcode == 0xBE) // CP (IX+d)
|
||||||
{
|
{
|
||||||
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
|
||||||
@@ -1081,6 +1157,7 @@ namespace Desktop
|
|||||||
mnemonic = $"LD DE, (0x{addr5B:X4})";
|
mnemonic = $"LD DE, (0x{addr5B:X4})";
|
||||||
instructionLength = 4;
|
instructionLength = 4;
|
||||||
break;
|
break;
|
||||||
|
case 0x5E: mnemonic = "IM 2"; instructionLength = 2; break;
|
||||||
case 0x5F: mnemonic = "LD A, R"; instructionLength = 2; break;
|
case 0x5F: mnemonic = "LD A, R"; instructionLength = 2; break;
|
||||||
case 0x6A: mnemonic = "ADC HL, HL"; instructionLength = 2; break;
|
case 0x6A: mnemonic = "ADC HL, HL"; instructionLength = 2; break;
|
||||||
case 0x62: mnemonic = "SBC HL, HL"; instructionLength = 2; break;
|
case 0x62: mnemonic = "SBC HL, HL"; instructionLength = 2; break;
|
||||||
|
|||||||
Reference in New Issue
Block a user