diff options
Diffstat (limited to 'src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs')
| -rw-r--r-- | src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs | 305 |
1 files changed, 284 insertions, 21 deletions
diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs index 40b31ca..378fd05 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs @@ -2,20 +2,58 @@ // Copyright (c) 2012 Ian Cowburn
//
using System;
-using System.Net;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Documents;
-using System.Windows.Ink;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Animation;
-using System.Windows.Shapes;
namespace Noddybox.Emulation.EightBit.Z80
{
public partial class Z80Cpu
{
+ #region Fetch and helper operations
+
+ /// <summary>
+ /// Fetch the next word from the PC.
+ /// </summary>
+ /// <returns>The word.</returns>
+ ushort FetchWord()
+ {
+ Register16 r = new Register16(0);
+
+ r.low = memory.Read(PC++);
+ r.high = memory.Read(PC++);
+
+ return r.reg;
+ }
+
+ /// <summary>
+ /// Swap two 16-bit registers.
+ /// </summary>
+ /// <param name="a">The first register.</param>
+ /// <param name="b">The second register.</param>
+ void Swap(ref Register16 a, ref Register16 b)
+ {
+ Register16 t = a;
+ a = b;
+ b = t;
+ }
+
+ /// <summary>
+ /// Fetch the offset if the current opcode is shifted.
+ /// </summary>
+ /// <returns>The offset, or zero if the current opcode is not shifted.</returns>
+ sbyte Offset()
+ {
+ if (shift == 0xdd || shift == 0xfd)
+ {
+ byte b = memory.Read(PC++);
+ return (sbyte)b;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ #endregion
+
#region Status register helpers
/// <summary>
@@ -69,7 +107,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Add an 8-bit value to the accumulator without carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Add8(byte b)
+ private void ADD8(byte b)
{
int w = A + b;
@@ -92,7 +130,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Add an 8-bit value to the accumulator with carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Adc8(byte b)
+ private void ADC8(byte b)
{
int w = A + b + (int)(F & Z80Flags.Carry);
@@ -115,7 +153,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Subtract an 8-bit value from the accumulator without carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Sub8(byte b)
+ private void SUB8(byte b)
{
int w = A - b;
@@ -143,7 +181,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Compare an 8-bit value with the accumulator.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Cmp8(byte b)
+ private void CMP8(byte b)
{
int w = A - b;
@@ -169,7 +207,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Subtract an 8-bit value from the accumulator with carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Sbc8(byte b)
+ private void SBC8(byte b)
{
int w = A - b - (int)(F & Z80Flags.Carry);
@@ -197,7 +235,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Add a 16-bit value to a register without carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Add16(ref ushort reg, ushort b)
+ private void ADD16(ref ushort reg, ushort b)
{
int w = reg + b;
@@ -222,7 +260,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Add a 16-bit value to a register with carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Adc16(ref ushort reg, ushort b)
+ private void ADC16(ref ushort reg, ushort b)
{
int w = reg + b + (int)(F & Z80Flags.Carry);
@@ -263,7 +301,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Subtract a 16-bit value from a register with carry.
/// </summary>
/// <param name="b">The vakue.</param>
- private void Sbc16(ref ushort reg, ushort b)
+ private void SBC(ref ushort reg, ushort b)
{
int w = reg - b - (int)(F & Z80Flags.Carry);
@@ -304,7 +342,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Increment an 8-bit register.
/// </summary>
/// <param name="reg">The register to increment.</param>
- void Inc8(ref byte reg)
+ void INC8(ref byte reg)
{
reg++;
@@ -325,7 +363,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Decrement an 8-bit register.
/// </summary>
/// <param name="reg">The register to decrement.</param>
- void Dec8(ref byte reg)
+ void DEC8(ref byte reg)
{
reg--;
@@ -342,6 +380,44 @@ namespace Noddybox.Emulation.EightBit.Z80 }
}
+ /// <summary>
+ /// Decimally adjust the accumulator. A bugger of an opcode.
+ /// Based on info from http://www.worldofspectrum.org/faq/reference/z80reference.htm
+ /// </summary>
+ void DAA()
+ {
+ byte add = 0;
+ Z80Flags carry = Z80Flags.None;
+ Z80Flags nf = F & Z80Flags.Neg;
+ byte acc = A;
+
+ if (acc>0x99 || (F & Z80Flags.Carry) == Z80Flags.Carry)
+ {
+ add |= 0x60;
+ carry = Z80Flags.Carry;
+ }
+
+ if ((acc & 0xf) > 0x9 || (F & Z80Flags.HalfCarry) == Z80Flags.HalfCarry)
+ {
+ add|=0x06;
+ }
+
+ if (nf == Z80Flags.Neg)
+ {
+ A -= add;
+ }
+ else
+ {
+ A += add;
+ }
+
+ F = PSZtable[A]
+ | carry
+ | nf |
+ ((Z80Flags)(acc ^ A) & Z80Flags.HalfCarry)
+ | H35table[A];
+ }
+
#endregion
#region ALU rotate and shift operations
@@ -679,8 +755,7 @@ namespace Noddybox.Emulation.EightBit.Z80 }
/// <summary>
- /// Reset the PC to an address
- /// register equals the passed check value.
+ /// Reset the PC to an address.
/// </summary>
/// <param name="addr">The address.</param>
private void RST(ushort addr)
@@ -691,5 +766,193 @@ namespace Noddybox.Emulation.EightBit.Z80 }
#endregion
+
+ #region Block operations
+
+ /// <summary>
+ /// LDI instruction.
+ /// </summary>
+ private void LDI()
+ {
+ byte b = memory.Read(HL.reg);
+ memory.Write(DE.reg, b);
+ DE.reg++;
+ HL.reg++;
+ BC.reg--;
+
+ if (BC.reg != 0)
+ {
+ ClearFlag(Z80Flags.HalfCarry | Z80Flags.Neg);
+ SetFlag(Z80Flags.PV);
+ }
+ else
+ {
+ ClearFlag(Z80Flags.HalfCarry | Z80Flags.Neg | Z80Flags.PV);
+ }
+
+ F |= H35table[A + b];
+ }
+
+ /// <summary>
+ /// LDD instruction.
+ /// </summary>
+ private void LDD()
+ {
+ byte b = memory.Read(HL.reg);
+ memory.Write(DE.reg, b);
+ DE.reg--;
+ HL.reg--;
+ BC.reg--;
+
+ if (BC.reg != 0)
+ {
+ ClearFlag(Z80Flags.HalfCarry | Z80Flags.Neg);
+ SetFlag(Z80Flags.PV);
+ }
+ else
+ {
+ ClearFlag(Z80Flags.HalfCarry | Z80Flags.Neg | Z80Flags.PV);
+ }
+
+ F |= H35table[A + b];
+ }
+
+ /// <summary>
+ /// CPI instruction.
+ /// </summary>
+ private void CPI()
+ {
+ Z80Flags c = F & Z80Flags.Carry;
+ byte b = memory.Read(HL.reg);
+
+ CMP8(b);
+ F |= c;
+
+ HL.reg++;
+ BC.reg--;
+
+ if (BC.reg != 0)
+ {
+ SetFlag(Z80Flags.PV);
+ }
+ else
+ {
+ ClearFlag(Z80Flags.PV);
+ }
+ }
+
+ /// <summary>
+ /// CPD instruction.
+ /// </summary>
+ private void CPD()
+ {
+ Z80Flags c = F & Z80Flags.Carry;
+ byte b = memory.Read(HL.reg);
+
+ CMP8(b);
+ F |= c;
+
+ HL.reg--;
+ BC.reg--;
+
+ if (BC.reg != 0)
+ {
+ SetFlag(Z80Flags.PV);
+ }
+ else
+ {
+ ClearFlag(Z80Flags.PV);
+ }
+ }
+
+ /// <summary>
+ /// INI instruction.
+ /// </summary>
+ private void INI()
+ {
+ int w;
+ byte b = device.Read(BC.reg);
+ memory.Write(HL.reg, b);
+
+ BC.high--;
+ HL.reg++;
+
+ F = SZtable[BC.high] | H35table[BC.high];
+
+ w = BC.low + b;
+
+ if ((w & 0x80) == 0x80)
+ {
+ SetFlag(Z80Flags.Neg);
+ }
+
+ if ((w & 0x100) == 0x100)
+ {
+ SetFlag(Z80Flags.Carry | Z80Flags.HalfCarry);
+ }
+ else
+ {
+ ClearFlag(Z80Flags.Carry | Z80Flags.HalfCarry);
+ }
+ }
+
+ /// <summary>
+ /// IND instruction.
+ /// </summary>
+ private void IND()
+ {
+ int w;
+ byte b = device.Read(BC.reg);
+ memory.Write(HL.reg, b);
+
+ BC.high--;
+ HL.reg--;
+
+ F = SZtable[BC.high] | H35table[BC.high];
+
+ w = BC.low + b;
+
+ if ((w & 0x80) == 0x80)
+ {
+ SetFlag(Z80Flags.Neg);
+ }
+
+ if ((w & 0x100) == 0x100)
+ {
+ SetFlag(Z80Flags.Carry | Z80Flags.HalfCarry);
+ }
+ else
+ {
+ ClearFlag(Z80Flags.Carry | Z80Flags.HalfCarry);
+ }
+ }
+
+ /// <summary>
+ /// OUTI instruction.
+ /// </summary>
+ private void OUTI()
+ {
+ device.Write(BC.reg, memory.Read(HL.reg));
+
+ HL.reg++;
+ BC.high--;
+
+ F = SZtable[BC.high] | H35table[BC.high];
+ }
+
+ /// <summary>
+ /// OUTD instruction.
+ /// </summary>
+ private void OUTD()
+ {
+ device.Write(BC.reg, memory.Read(HL.reg));
+
+ HL.reg--;
+ BC.high--;
+
+ F = SZtable[BC.high] | H35table[BC.high] | Z80Flags.Neg;
+ }
+
+ #endregion
}
}
|
