summaryrefslogtreecommitdiff
path: root/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs')
-rw-r--r--src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs171
1 files changed, 74 insertions, 97 deletions
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 <http://fuse-emulator.sourceforge.net/>
+//
+// 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
/// <param name="val">The value.</param>
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);
}
/// <summary>
@@ -117,9 +125,12 @@ namespace Noddybox.Emulation.EightBit.Z80
/// <returns></returns>
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];
}
/// <summary>
@@ -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];
}
/// <summary>
@@ -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];
}
/// <summary>
@@ -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];
}
/// <summary>
@@ -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];
}
/// <summary>
@@ -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;
- }
+ /// <summary>
+ /// Perform the BIT operation on an indexed location.
+ /// </summary>
+ /// <param name="reg">The register to operate on.</param>
+ /// <param name="bit">The bit to test.</param>
+ /// <param name="addr">The address being checked.</param>
+ 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();
}
/// <summary>
@@ -696,7 +673,7 @@ namespace Noddybox.Emulation.EightBit.Z80
/// </summary>
private void JP()
{
- PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8);
+ PC = FetchWord();
}
/// <summary>