From 2b8d49726e448e22b5055da5ba4395d043030984 Mon Sep 17 00:00:00 2001 From: Ian C Date: Sun, 1 Jan 2012 14:21:26 +0000 Subject: Moved sources to help in compilation for other platforms and isolated phone projects. --- .../Z80CpuBaseOpcodes.cs | 695 +++++++++++++++++++++ 1 file changed, 695 insertions(+) create mode 100644 src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs (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 new file mode 100644 index 0000000..40b31ca --- /dev/null +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs @@ -0,0 +1,695 @@ +// +// 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 Status register helpers + + /// + /// Set a flag in the status register. + /// + /// The flag. + private void SetFlag(Z80Flags flag) + { + F |= flag; + } + + /// + /// Clear a flag in the status register. + /// + /// The flag. + private void ClearFlag(Z80Flags flag) + { + F &= ~flag; + } + + #endregion + + #region Stack commands + + /// + /// Push a value on the stack. + /// + /// The value. + private void PUSH(ushort val) + { + memory.Write(--SP, (byte)(val & 0xff)); + memory.Write(--SP, (byte)(Binary.ShiftRight(val, 8) & 0xff)); + } + + /// + /// Pop a value from the stack. + /// + /// + private ushort POP() + { + SP = (ushort)((SP + 2) & 0xffff); + return (ushort)(memory.Read((ushort)(SP-2)) | + (memory.Read((ushort)(SP - 1)) >> 8)); + } + + #endregion + + #region ALU arithmetic and comparison + + /// + /// Add an 8-bit value to the accumulator without carry. + /// + /// The vakue. + private void Add8(byte b) + { + int w = A + b; + + 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; + } + + A = (byte)(w & 0xff); + } + + /// + /// Add an 8-bit value to the accumulator with carry. + /// + /// The vakue. + private void Adc8(byte b) + { + int w = A + b + (int)(F & Z80Flags.Carry); + + 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; + } + + A = (byte)(w & 0xff); + } + + /// + /// Subtract an 8-bit value from the accumulator without carry. + /// + /// The vakue. + private void Sub8(byte b) + { + int w = A - b; + + if (w < 0) + { + w += 0x200; + } + + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + + A = (byte)(w & 0xff); + } + + /// + /// Compare an 8-bit value with the accumulator. + /// + /// The vakue. + private void Cmp8(byte b) + { + int w = A - b; + + if (w < 0) + { + w += 0x200; + } + + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + } + + /// + /// Subtract an 8-bit value from the accumulator with carry. + /// + /// The vakue. + private void Sbc8(byte b) + { + int w = A - b - (int)(F & Z80Flags.Carry); + + if (w < 0) + { + w += 0x200; + } + + F = SZtable[w] | H35table[w & 0xff] | Z80Flags.Neg; + + if (((A ^ w ^ b) & (int)Z80Flags.HalfCarry) == (int)Z80Flags.HalfCarry) + { + F |= Z80Flags.HalfCarry; + } + + if (((b ^ A) & (b ^ w) & 0x80) > 0) + { + F |= Z80Flags.PV; + } + + A = (byte)(w & 0xff); + } + + /// + /// Add a 16-bit value to a register without carry. + /// + /// The vakue. + private void Add16(ref ushort reg, ushort b) + { + int w = reg + b; + + F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; + + if (w > 0xffff) + { + F |= Z80Flags.Carry; + } + + if ((reg ^ w ^ b) == 0x1000) + { + F |= Z80Flags.HalfCarry; + } + + reg = (ushort)(w & 0xffff); + + F |= H35table[reg >> 8]; + } + + /// + /// Add a 16-bit value to a register with carry. + /// + /// The vakue. + private void Adc16(ref ushort reg, ushort b) + { + int w = reg + b + (int)(F & Z80Flags.Carry); + + F = Z80Flags.None; + + if ((w & 0xffff) == 0) + { + F |= Z80Flags.Zero; + } + + if ((w & 0x8000) == 0x8000) + { + F |= Z80Flags.Sign; + } + + if (w > 0xffff) + { + F |= Z80Flags.Carry; + } + + if (((b ^ reg ^ 0x8000) & ((reg ^ w) & 0x8000)) == 0x8000) + { + F |= Z80Flags.PV; + } + + if ((reg ^ w ^ b) == 0x1000) + { + F |= Z80Flags.HalfCarry; + } + + reg = (ushort)(w & 0xffff); + + F |= H35table[reg >> 8]; + } + + + /// + /// Subtract a 16-bit value from a register with carry. + /// + /// The vakue. + private void Sbc16(ref ushort reg, ushort b) + { + int w = reg - b - (int)(F & Z80Flags.Carry); + + F = Z80Flags.Neg; + + if (w < 0) + { + w += 0x10000; + F |= Z80Flags.Carry; + } + + if ((w & 0xffff) == 0) + { + F |= Z80Flags.Zero; + } + + if ((w & 0x8000) == 0x8000) + { + F |= Z80Flags.Sign; + } + + if (((b ^ reg) & ((reg ^ w) & 0x8000)) == 0x8000) + { + F |= Z80Flags.PV; + } + + if ((reg ^ w ^ b) == 0x1000) + { + F |= Z80Flags.HalfCarry; + } + + reg = (ushort)(w & 0xffff); + + F |= H35table[reg >> 8]; + } + + /// + /// Increment an 8-bit register. + /// + /// The register to increment. + void Inc8(ref byte reg) + { + reg++; + + F = Z80Flags.Carry; + + if (reg == 0x80) + { + F |= Z80Flags.PV; + } + + if ((reg & 0x0f) == 0x00) + { + F |= Z80Flags.HalfCarry; + } + } + + /// + /// Decrement an 8-bit register. + /// + /// The register to decrement. + void Dec8(ref byte reg) + { + reg--; + + F = Z80Flags.Carry | Z80Flags.Neg; + + if (reg == 0x7f) + { + F |= Z80Flags.PV; + } + + if ((reg & 0x0f) == 0x0f) + { + F |= Z80Flags.HalfCarry; + } + } + + #endregion + + #region ALU rotate and shift operations + + /// + /// Do RRCA. + /// + private void RRCA() + { + F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; + F |= (Z80Flags)(A & 1); + A = (byte)(Binary.ShiftRight(A, 1) | Binary.ShiftLeft(A, 7)); + F |= H35table[A]; + } + + /// + /// Do RRA. + /// + private void RRA() + { + byte carry = (byte)(F & Z80Flags.Carry); + F &= Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV; + F |= (Z80Flags)(A & 1); + A = (byte)(Binary.ShiftRight(A, 1) | Binary.ShiftLeft(carry, 7)); + F |= H35table[A]; + } + + /// + /// Do RRC. + /// + /// The register to operate on. + private void RRC(ref byte reg) + { + F = (Z80Flags)(reg & (int)Z80Flags.Carry); + reg = (byte)(Binary.ShiftRight(reg, 1) | Binary.ShiftLeft(reg, 7)); + F |= PSZtable[reg] | H35table[reg]; + } + + /// + /// Do RR. + /// + /// The register to operate on. + private void RR(ref byte reg) + { + byte carry = (byte)(F & Z80Flags.Carry); + F = (Z80Flags)(reg & (int)Z80Flags.Carry); + reg = (byte)(Binary.ShiftRight(reg, 1) | Binary.ShiftLeft(carry, 7)); + F |= PSZtable[reg] | H35table[reg]; + } + + /// + /// Do RLCA. + /// + private void RLCA() + { + F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) + | (Z80Flags)Binary.ShiftRight(A, 7); + + A = (byte)(Binary.ShiftLeft(A, 1) | Binary.ShiftRight(A, 7)); + + F |= H35table[A]; + } + + /// + /// Do RLA. + /// + private void RLA() + { + byte carry = (byte)(F & Z80Flags.Carry); + F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) + | (Z80Flags)Binary.ShiftRight(A, 7); + A = (byte)(Binary.ShiftRight(A, 1) | carry); + F |= H35table[A]; + } + + /// + /// Do RLC. + /// + /// The register to operate on. + private void RLC(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = (byte)(Binary.ShiftLeft(reg, 1) | carry); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do RL. + /// + /// The register to operate on. + private void RL(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = (byte)(Binary.ShiftLeft(reg, 1) | (int)(F & Z80Flags.Carry)); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SRL. + /// + /// The register to operate on. + private void SRL(ref byte reg) + { + byte carry = (byte)(reg & 1); + reg = Binary.ShiftLeft(reg, 1); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SRA. + /// + /// The register to operate on. + private void SRA(ref byte reg) + { + byte carry = (byte)(reg & 1); + reg = (byte)(Binary.ShiftLeft(reg, 1) | (reg & 0x80)); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SLL. + /// + /// The register to operate on. + private void SLL(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = (byte)(Binary.ShiftRight(reg, 1) | 0x01); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + /// + /// Do SLA. + /// + /// The register to operate on. + private void SLA(ref byte reg) + { + byte carry = Binary.ShiftRight(reg, 7); + reg = Binary.ShiftRight(reg, 1); + F = PSZtable[reg] | (Z80Flags)carry | H35table[reg]; + } + + #endregion + + #region ALU boolean operations + + /// + /// AND a value with the accumulator. + /// + /// The value. + void AND(byte val) + { + A &= val; + F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + } + + /// + /// OR a value with the accumulator. + /// + /// The value. + void OR(byte val) + { + A |= val; + F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + } + + /// + /// XOR a value with the accumulator. + /// + /// The value. + void XOR(byte val) + { + A ^= val; + F = PSZtable[A] | Z80Flags.HalfCarry | H35table[A]; + } + + /// + /// Perform the BIT operation. + /// + /// The register to operate on. + /// The bit to test. + void BIT(ref byte reg, int bit) + { + F &= Z80Flags.Carry; + F |= Z80Flags.HalfCarry; + + if ((reg & (1 << bit)) != 0) + { + if (bit == 7 && (reg & (int)Z80Flags.Sign) != 0) + { + F |= Z80Flags.Sign; + } + + if (bit == 5 && (reg & (int)Z80Flags.Hidden5) != 0) + { + F |= Z80Flags.Hidden5; + } + + if (bit == 3 && (reg & (int)Z80Flags.Hidden3) != 0) + { + F |= Z80Flags.Hidden3; + } + } + else + { + F |= Z80Flags.Zero | Z80Flags.PV; + } + } + + /// + /// Perform the bit set operation. + /// + /// The register to operate on. + /// The bit to test. + void BIT_SET(ref byte reg, int bit) + { + reg |= (byte)(1 << bit); + } + + /// + /// Perform the bit clear operation. + /// + /// The register to operate on. + /// The bit to test. + void BIT_RES(ref byte reg, int bit) + { + reg &= (byte)~(1 << bit); + } + + #endregion + + #region Jump operations + + /// + /// The call operation. + /// + private void CALL() + { + PUSH((ushort)(PC + 2)); + PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); + } + + /// + /// The jump operation. + /// + private void JP() + { + PC = (ushort)(memory.Read(PC) | memory.Read((ushort)(PC+1)) >> 8); + } + + /// + /// The jump relative operation. + /// + private void JR() + { + PC = (ushort)(PC + (sbyte)memory.Read(PC) + 1); + } + + /// + /// Jump relative if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void JR_COND(Z80Flags cond, Z80Flags val) + { + if ((F & cond) == val) + { + clock.Add(12); + JR(); + } + else + { + clock.Add(7); + PC++; + } + } + + /// + /// Jump if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void JP_COND(Z80Flags cond, Z80Flags val) + { + clock.Add(10); + + if ((F & cond) == val) + { + JP(); + } + else + { + PC+=2; + } + } + + /// + /// Call if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void CALL_COND(Z80Flags cond, Z80Flags val) + { + if ((F & cond) == val) + { + clock.Add(17); + CALL(); + } + else + { + clock.Add(10); + PC+=2; + } + } + + /// + /// Return if the passed condition flag ANDed with the flag + /// register equals the passed check value. + /// + /// The condition flag. + /// The check value. + private void RET_COND(Z80Flags cond, Z80Flags val) + { + if ((F & cond) == val) + { + clock.Add(11); + PC = POP(); + } + else + { + clock.Add(5); + } + } + + /// + /// Reset the PC to an address + /// register equals the passed check value. + /// + /// The address. + private void RST(ushort addr) + { + clock.Add(11); + PUSH(PC); + PC = addr; + } + + #endregion + } +} -- cgit v1.3