From 998b64d14c9d055562d8c1611813d40af4cb030b Mon Sep 17 00:00:00 2001 From: Ian C Date: Fri, 9 Mar 2012 23:01:13 +0000 Subject: Further bug fixes to Z80. Now starts the Spectrum ROM OK. --- .../Z80CpuBaseOpcodes.cs | 171 +++++++++------------ 1 file changed, 74 insertions(+), 97 deletions(-) (limited to 'src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs') diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs index e0cc4e4..cc02e94 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs @@ -15,6 +15,12 @@ // // Copyright (c) 2012 Ian Cowburn // +// Some of the concepts and code in here are taken from FUSE, the open source UNIX +// Spectrum emulator Copyright (c) 1999-2003 Philip Kendall. +// See +// +// Any introduced bugs in that code are mine, and not the original authors. +// using System; namespace Noddybox.Emulation.EightBit.Z80 @@ -57,6 +63,7 @@ namespace Noddybox.Emulation.EightBit.Z80 { if (shift == 0xdd || shift == 0xfd) { + clock.Add(8); byte b = memory.Read(PC++); return (sbyte)b; } @@ -107,8 +114,9 @@ namespace Noddybox.Emulation.EightBit.Z80 /// The value. private void PUSH(ushort val) { - memory.Write(--SP, (byte)(val & 0xff)); - memory.Write(--SP, (byte)(Binary.ShiftRight(val, 8) & 0xff)); + Register16 r = new Register16(val); + memory.Write(--SP, r.high); + memory.Write(--SP, r.low); } /// @@ -117,9 +125,12 @@ namespace Noddybox.Emulation.EightBit.Z80 /// private ushort POP() { - SP = (ushort)((SP + 2) & 0xffff); - return (ushort)(memory.Read((ushort)(SP-2)) | - (memory.Read((ushort)(SP - 1)) >> 8)); + Register16 r = new Register16(0); + + r.low = memory.Read(SP++); + r.high = memory.Read(SP++); + + return r.reg; } #endregion @@ -133,18 +144,10 @@ namespace Noddybox.Emulation.EightBit.Z80 private void ADD8(byte b) { int w = A + b; + int lookup = ((A & 0x88) >> 3) | ((b & 0x88) >> 2) | ((w & 0x88) >> 1); - F = SZtable[w] | H35table[w & 0xff]; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } + F = SZtable[w] | H35table[w & 0xff] | + halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4]; A = (byte)(w & 0xff); } @@ -156,18 +159,10 @@ namespace Noddybox.Emulation.EightBit.Z80 private void ADC8(byte b) { int w = A + b + (int)(F & Z80Flags.Carry); + int lookup = ((A & 0x88) >> 3) | ((b & 0x88) >> 2) | ((w & 0x88) >> 1); - F = SZtable[w] | H35table[w & 0xff]; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } + F = SZtable[w] | H35table[w & 0xff] | + halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4]; A = (byte)(w & 0xff); } @@ -185,17 +180,10 @@ namespace Noddybox.Emulation.EightBit.Z80 w += 0x200; } - F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + int lookup = ((A & 0x88) >> 3) | ((b & 0x88) >> 2) | ((w & 0x88) >> 1); - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } + F = SZtable[w] | H35table[w] | Z80Flags.Neg | + halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4]; A = (byte)(w & 0xff); } @@ -213,17 +201,10 @@ namespace Noddybox.Emulation.EightBit.Z80 w += 0x200; } - F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + int lookup = ((A & 0x88) >> 3) | ((b & 0x88) >> 2) | ((w & 0x88) >> 1); - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } - - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } + F = SZtable[w] | H35table[b] | Z80Flags.Neg | + halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4]; } /// @@ -239,17 +220,10 @@ namespace Noddybox.Emulation.EightBit.Z80 w += 0x200; } - F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; - - if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) - { - F |= Z80Flags.HalfCarry; - } + int lookup = ((A & 0x88) >> 3) | ((b & 0x88) >> 2) | ((w & 0x88) >> 1); - if (((b ^ A) & (b ^ w) & 0x80) > 0) - { - F |= Z80Flags.PV; - } + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg | + halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4]; A = (byte)(w & 0xff); } @@ -269,14 +243,13 @@ namespace Noddybox.Emulation.EightBit.Z80 F |= Z80Flags.Carry; } - if (((reg ^ w ^ b) & 0x1000) == 0x1000) - { - F |= Z80Flags.HalfCarry; - } + int lookup = ((reg & 0x8800) >> 11) | + ((b & 0x8800) >> 10) | + ((w & 0x8800) >> 9); reg = (ushort)(w & 0xffff); - F |= H35table[reg >> 8]; + F |= halfcarry_add_table[lookup & 0x07] | H35table[reg >> 8]; } /// @@ -304,19 +277,14 @@ namespace Noddybox.Emulation.EightBit.Z80 F |= Z80Flags.Carry; } - if (((b ^ reg ^ 0x8000) & ((reg ^ w) & 0x8000)) == 0x8000) - { - F |= Z80Flags.PV; - } - - if ((reg ^ w ^ b) == 0x1000) - { - F |= Z80Flags.HalfCarry; - } + int lookup = ((reg & 0x8800) >> 11) | + ((b & 0x8800) >> 10) | + ((w & 0x8800) >> 9); reg = (ushort)(w & 0xffff); - F |= H35table[reg >> 8]; + F |= halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] | + H35table[reg >> 8]; } @@ -346,19 +314,14 @@ namespace Noddybox.Emulation.EightBit.Z80 F |= Z80Flags.Sign; } - if (((b ^ reg) & ((reg ^ w) & 0x8000)) == 0x8000) - { - F |= Z80Flags.PV; - } - - if ((reg ^ w ^ b) == 0x1000) - { - F |= Z80Flags.HalfCarry; - } + int lookup = ((reg & 0x8800) >> 11) | + ((b & 0x8800) >> 10) | + ((w & 0x8800) >> 9); reg = (ushort)(w & 0xffff); - F |= H35table[reg >> 8]; + F |= halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] | + H35table[reg >> 8]; } /// @@ -554,7 +517,7 @@ namespace Noddybox.Emulation.EightBit.Z80 private void SRL(ref byte reg) { byte carry = (byte)(reg & 1); - reg = Binary.ShiftLeft(reg, 1); + reg = Binary.ShiftRight(reg, 1); F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; } @@ -565,7 +528,7 @@ namespace Noddybox.Emulation.EightBit.Z80 private void SRA(ref byte reg) { byte carry = (byte)(reg & 1); - reg = (byte)(Binary.ShiftLeft(reg, 1) | (reg & 0x80)); + reg = (byte)(Binary.ShiftRight(reg, 1) | (reg & 0x80)); F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; } @@ -576,7 +539,7 @@ namespace Noddybox.Emulation.EightBit.Z80 private void SLL(ref byte reg) { byte carry = Binary.ShiftRight(reg, 7); - reg = (byte)(Binary.ShiftRight(reg, 1) | 0x01); + reg = (byte)(Binary.ShiftLeft(reg, 1) | 0x01); F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; } @@ -587,7 +550,7 @@ namespace Noddybox.Emulation.EightBit.Z80 private void SLA(ref byte reg) { byte carry = Binary.ShiftRight(reg, 7); - reg = Binary.ShiftRight(reg, 1); + reg = Binary.ShiftLeft(reg, 1); F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; } @@ -612,7 +575,7 @@ namespace Noddybox.Emulation.EightBit.Z80 void OR(byte val) { A |= val; - F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + F = PSZtable[A] | H35table[A]; } /// @@ -622,7 +585,7 @@ namespace Noddybox.Emulation.EightBit.Z80 void XOR(byte val) { A ^= val; - F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + F = PSZtable[A] | H35table[A]; } /// @@ -633,7 +596,7 @@ namespace Noddybox.Emulation.EightBit.Z80 void BIT(ref byte reg, int bit) { F &= Z80Flags.Carry; - F |= Z80Flags.HalfCarry; + F |= Z80Flags.HalfCarry | H35table[reg]; if ((reg & (1 << bit)) != 0) { @@ -641,15 +604,29 @@ namespace Noddybox.Emulation.EightBit.Z80 { F |= Z80Flags.Sign; } + } + else + { + F |= Z80Flags.Zero | Z80Flags.PV; + } + } - if (bit == 5 && (reg & (int)Z80Flags.Hidden5) != 0) - { - F |= Z80Flags.Hidden5; - } + /// + /// Perform the BIT operation on an indexed location. + /// + /// The register to operate on. + /// The bit to test. + /// The address being checked. + void BIT(ref byte reg, int bit, ushort addr) + { + F &= Z80Flags.Carry; + F |= Z80Flags.HalfCarry | H35table[addr>>8]; - if (bit == 3 && (reg & (int)Z80Flags.Hidden3) != 0) + if ((reg & (1 << bit)) != 0) + { + if (bit == 7 && (reg & (int)Z80Flags.Sign) != 0) { - F |= Z80Flags.Hidden3; + F |= Z80Flags.Sign; } } else @@ -688,7 +665,7 @@ namespace Noddybox.Emulation.EightBit.Z80 private void CALL() { PUSH((ushort)(PC + 2)); - PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); + PC = FetchWord(); } /// @@ -696,7 +673,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// private void JP() { - PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); + PC = FetchWord(); } /// -- cgit v1.3