From 647083a1f53bbec58e5058616b84f706b0402911 Mon Sep 17 00:00:00 2001 From: Ian C Date: Mon, 2 Jan 2012 23:37:51 +0000 Subject: Added some opcodes and removed unnecessary using statements. --- .../Z80CpuBaseOpcodes.cs | 305 +++++++++++++++++++-- 1 file changed, 284 insertions(+), 21 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 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 + + /// + /// Fetch the next word from the PC. + /// + /// The word. + ushort FetchWord() + { + Register16 r = new Register16(0); + + r.low = memory.Read(PC++); + r.high = memory.Read(PC++); + + return r.reg; + } + + /// + /// Swap two 16-bit registers. + /// + /// The first register. + /// The second register. + void Swap(ref Register16 a, ref Register16 b) + { + Register16 t = a; + a = b; + b = t; + } + + /// + /// Fetch the offset if the current opcode is shifted. + /// + /// The offset, or zero if the current opcode is not shifted. + sbyte Offset() + { + if (shift == 0xdd || shift == 0xfd) + { + byte b = memory.Read(PC++); + return (sbyte)b; + } + else + { + return 0; + } + } + + #endregion + #region Status register helpers /// @@ -69,7 +107,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// Add an 8-bit value to the accumulator without carry. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The vakue. - 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. /// /// The register to increment. - 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. /// /// The register to decrement. - void Dec8(ref byte reg) + void DEC8(ref byte reg) { reg--; @@ -342,6 +380,44 @@ namespace Noddybox.Emulation.EightBit.Z80 } } + /// + /// Decimally adjust the accumulator. A bugger of an opcode. + /// Based on info from http://www.worldofspectrum.org/faq/reference/z80reference.htm + /// + 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 } /// - /// Reset the PC to an address - /// register equals the passed check value. + /// Reset the PC to an address. /// /// The address. private void RST(ushort addr) @@ -691,5 +766,193 @@ namespace Noddybox.Emulation.EightBit.Z80 } #endregion + + #region Block operations + + /// + /// LDI instruction. + /// + 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]; + } + + /// + /// LDD instruction. + /// + 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]; + } + + /// + /// CPI instruction. + /// + 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); + } + } + + /// + /// CPD instruction. + /// + 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); + } + } + + /// + /// INI instruction. + /// + 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); + } + } + + /// + /// IND instruction. + /// + 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); + } + } + + /// + /// OUTI instruction. + /// + private void OUTI() + { + device.Write(BC.reg, memory.Read(HL.reg)); + + HL.reg++; + BC.high--; + + F = SZtable[BC.high] | H35table[BC.high]; + } + + /// + /// OUTD instruction. + /// + 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 } } -- cgit v1.3