// This file is part of the Noddybox.Emulation C# suite.
//
// Noddybox.Emulation is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Noddybox.Emulation is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Noddybox.Emulation. If not, see .
//
// Copyright (c) 2012 Ian Cowburn
//
using System;
namespace Noddybox.Emulation.EightBit.Z80
{
public partial class Z80Cpu
{
///
/// Decode and execute an opcode.
///
/// The opcode.
private void DecodeByte(byte opcode)
{
// Check for shifted opcodes
//
switch(shift)
{
case 0xdd:
Decode(opcode, ref IX);
break;
case 0xfd:
Decode(opcode, ref IY);
break;
default:
Decode(opcode, ref HL);
break;
}
}
///
/// Decode and execute an opcode.
///
/// The opcode.
/// The register to use for HL register operations.
private void Decode(byte opcode, ref Register16 hl)
{
ushort addr;
byte b;
switch(opcode)
{
case 0x00: // NOP
clock.Add(4);
break;
case 0x01: // LD BC, nnnn
clock.Add(10);
BC.reg = FetchWord();
break;
case 0x02: // LD (BC), A
clock.Add(7);
memory.Write(BC.reg, A);
break;
case 0x03: // INC BC
clock.Add(6);
BC.reg++;
break;
case 0x04: // INC B
clock.Add(4);
INC8(ref BC.high);
break;
case 0x05: // DEC B
clock.Add(4);
DEC8(ref BC.high);
break;
case 0x06: // LD B,n
clock.Add(7);
BC.high = memory.Read(PC++);
break;
case 0x07: // RLCA
clock.Add(4);
RLCA();
break;
case 0x08: // EX AF, AF'
clock.Add(4);
Register16 t = AF_;
AF_.high = A;
AF_.low = (byte)F;
A = t.high;
F = (Z80Flags)t.low;
break;
case 0x09: // ADD HL, BC
clock.Add(11);
ADD16(ref hl.reg, BC.reg);
break;
case 0x0a: // LD A,(BC)
clock.Add(7);
A = memory.Read(BC.reg);
break;
case 0x0b: // DEC BC
clock.Add(6);
BC.reg--;
break;
case 0x0c: // INC C
clock.Add(4);
INC8(ref BC.low);
break;
case 0x0d: // DEC C
clock.Add(4);
DEC8(ref BC.low);
break;
case 0x0e: // LD C,n
clock.Add(7);
BC.low = memory.Read(PC++);
break;
case 0x0f: // RRCA
clock.Add(4);
RRCA();
break;
case 0x10: // DJNZ
if (--BC.high != 0)
{
clock.Add(13);
JR();
}
else
{
clock.Add(8);
PC++;
}
break;
case 0x11: // LD DE, nnnn
clock.Add(10);
DE.reg = FetchWord();
break;
case 0x12: // LD (DE), A
clock.Add(7);
memory.Write(DE.reg, A);
break;
case 0x13: // INC DE
clock.Add(6);
DE.reg++;
break;
case 0x14: // INC D
clock.Add(4);
INC8(ref DE.high);
break;
case 0x15: // DEC D
clock.Add(4);
DEC8(ref DE.high);
break;
case 0x16: // LD D,n
clock.Add(7);
DE.high = memory.Read(PC++);
break;
case 0x17: // RLA
clock.Add(4);
RLA();
break;
case 0x18: // JR
clock.Add(12);
JR();
break;
case 0x19: // ADD HL, DE
clock.Add(11);
ADD16(ref hl.reg, DE.reg);
break;
case 0x1a: // LD A,(DE)
clock.Add(7);
A = memory.Read(DE.reg);
break;
case 0x1b: // DEC DE
clock.Add(6);
DE.reg--;
break;
case 0x1c: // INC E
clock.Add(4);
INC8(ref DE.low);
break;
case 0x1d: // DEC E
clock.Add(4);
DEC8(ref DE.low);
break;
case 0x1e: // LD E,n
clock.Add(7);
DE.low = memory.Read(PC++);
break;
case 0x1f: // RRA
clock.Add(4);
RRA();
break;
case 0x20: // JR NZ, r
JR_COND(Z80Flags.Zero, Z80Flags.None);
break;
case 0x21: // LD HL, nnnn
clock.Add(10);
hl.reg = FetchWord();
break;
case 0x22: // LD (nnnn), HL
clock.Add(16);
addr = FetchWord();
memory.Write(addr, hl.low);
memory.Write((ushort)(addr + 1), hl.high);
break;
case 0x23: // INC HL
clock.Add(6);
hl.reg++;
break;
case 0x24: // INC H
clock.Add(4);
INC8(ref hl.high);
break;
case 0x25: // DEC H
clock.Add(4);
DEC8(ref hl.high);
break;
case 0x26: // LD H,n
clock.Add(7);
hl.high = memory.Read(PC++);
break;
case 0x27: // DAA
clock.Add(4);
DAA();
break;
case 0x28: // JR Z,d
JR_COND(Z80Flags.Zero, Z80Flags.Zero);
break;
case 0x29: // ADD HL, HL
clock.Add(11);
ADD16(ref hl.reg, hl.reg);
break;
case 0x2a: // LD HL,(nnnnn)
clock.Add(16);
addr = FetchWord();
hl.low = memory.Read(addr);
hl.high = memory.Read((ushort)(addr + 1));
break;
case 0x2b: // DEC HL
clock.Add(6);
hl.reg--;
break;
case 0x2c: // INC L
clock.Add(4);
INC8(ref hl.low);
break;
case 0x2d: // DEC L
clock.Add(4);
DEC8(ref hl.low);
break;
case 0x2e: // LD L,n
clock.Add(7);
hl.low = memory.Read(PC++);
break;
case 0x2f: // CPL
clock.Add(4);
A ^= 0xff;
ClearFlag(Z80Flags.Hidden);
SetFlag(Z80Flags.HalfCarry | Z80Flags.Neg | H35table[A]);
break;
case 0x30: // JR NC, r
JR_COND(Z80Flags.Carry, Z80Flags.None);
break;
case 0x31: // LD SP, nnnn
clock.Add(10);
SP = FetchWord();
break;
case 0x32: // LD (nnnn), A
clock.Add(13);
addr = FetchWord();
memory.Write(addr, A);
break;
case 0x33: // INC SP
clock.Add(6);
SP++;
break;
case 0x34: // INC (HL)
clock.Add(11);
addr = (ushort)(hl.reg + Offset());
b = memory.Read(addr);
INC8(ref b);
memory.Write(addr, b);
break;
case 0x35: // DEC (HL)
clock.Add(11);
addr = (ushort)(hl.reg + Offset());
b = memory.Read(addr);
DEC8(ref b);
memory.Write(addr, b);
break;
case 0x36: // LD (HL),n
if (shift == 0xdd || shift == 0xfd)
{
clock.Add(7);
}
else
{
clock.Add(10);
}
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, memory.Read(PC++));
break;
case 0x37: // SCF
clock.Add(4);
F = (F & (Z80Flags.Sign | Z80Flags.Zero | Z80Flags.PV))
| Z80Flags.Carry
| H35table[A];
break;
case 0x38: // JR C,d
JR_COND(Z80Flags.Carry, Z80Flags.Carry);
break;
case 0x39: // ADD HL, SP
clock.Add(11);
ADD16(ref hl.reg, SP);
break;
case 0x3a: // LD A,(nnnnn)
clock.Add(13);
addr = FetchWord();
A = memory.Read(addr);
break;
case 0x3b: // DEC SP
clock.Add(6);
SP--;
break;
case 0x3c: // INC A
clock.Add(4);
INC8(ref A);
break;
case 0x3d: // DEC A
clock.Add(4);
DEC8(ref A);
break;
case 0x3e: // LD A,n
clock.Add(7);
A = memory.Read(PC++);
break;
case 0x3f: // CCF
clock.Add(4);
if ((F & Z80Flags.Carry) == Z80Flags.Carry)
{
SetFlag(Z80Flags.HalfCarry);
}
else
{
ClearFlag(Z80Flags.HalfCarry);
}
F ^= Z80Flags.Carry;
ClearFlag(Z80Flags.Hidden);
ClearFlag(Z80Flags.Neg);
SetFlag(H35table[A]);
break;
case 0x40: // LD B,B
clock.Add(4);
break;
case 0x41: // LD B,C
clock.Add(4);
BC.high = BC.low;
break;
case 0x42: // LD B,D
clock.Add(4);
BC.high = DE.high;
break;
case 0x43: // LD B,E
clock.Add(4);
BC.high = DE.low;
break;
case 0x44: // LD B,H
clock.Add(4);
BC.high = hl.high;
break;
case 0x45: // LD B,L
clock.Add(4);
BC.high = hl.low;
break;
case 0x46: // LD B,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
BC.high = memory.Read(addr);
break;
case 0x47: // LD B,A
clock.Add(4);
BC.high = A;
break;
case 0x48: // LD C,B
clock.Add(4);
BC.low = BC.high;
break;
case 0x49: // LD C,C
clock.Add(4);
break;
case 0x4a: // LD C,D
clock.Add(4);
BC.low = DE.high;
break;
case 0x4b: // LD C,E
clock.Add(4);
BC.low = DE.low;
break;
case 0x4c: // LD C,H
clock.Add(4);
BC.low = hl.high;
break;
case 0x4d: // LD C,L
clock.Add(4);
BC.low = hl.low;
break;
case 0x4e: // LD C,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
BC.low = memory.Read(addr);
break;
case 0x4f: // LD C,A
clock.Add(4);
BC.low = A;
break;
case 0x50: // LD D,B
clock.Add(4);
DE.high = BC.high;
break;
case 0x51: // LD D,C
clock.Add(4);
DE.high = BC.low;
break;
case 0x52: // LD D,D
clock.Add(4);
break;
case 0x53: // LD D,E
clock.Add(4);
DE.high = DE.low;
break;
case 0x54: // LD D,H
clock.Add(4);
DE.high = hl.high;
break;
case 0x55: // LD D,L
clock.Add(4);
DE.high = hl.low;
break;
case 0x56: // LD D,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
DE.high = memory.Read(addr);
break;
case 0x57: // LD D,A
clock.Add(4);
DE.high = A;
break;
case 0x58: // LD E,B
clock.Add(4);
DE.low = BC.high;
break;
case 0x59: // LD E,C
clock.Add(4);
DE.low = BC.low;
break;
case 0x5a: // LD E,D
clock.Add(4);
DE.low = DE.high;
break;
case 0x5b: // LD E,E
clock.Add(4);
break;
case 0x5c: // LD E,H
clock.Add(4);
DE.low = hl.high;
break;
case 0x5d: // LD E,L
clock.Add(4);
DE.low = hl.low;
break;
case 0x5e: // LD E,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
DE.low = memory.Read(addr);
break;
case 0x5f: // LD E,A
clock.Add(4);
DE.low = A;
break;
case 0x60: // LD H,B
clock.Add(4);
hl.high = BC.high;
break;
case 0x61: // LD H,C
clock.Add(4);
hl.high = BC.low;
break;
case 0x62: // LD H,D
clock.Add(4);
hl.high = DE.high;
break;
case 0x63: // LD H,E
clock.Add(4);
hl.high = DE.low;
break;
case 0x64: // LD H,H
clock.Add(4);
break;
case 0x65: // LD H,L
clock.Add(4);
hl.high = hl.low;
break;
case 0x66: // LD H,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
HL.high = memory.Read(addr);
break;
case 0x67: // LD H,A
clock.Add(4);
hl.high = A;
break;
case 0x68: // LD L,B
clock.Add(4);
hl.low = BC.high;
break;
case 0x69: // LD L,C
clock.Add(4);
hl.low = BC.low;
break;
case 0x6a: // LD L,D
clock.Add(4);
hl.low = DE.high;
break;
case 0x6b: // LD L,E
clock.Add(4);
hl.low = DE.low;
break;
case 0x6c: // LD L,H
clock.Add(4);
hl.low = hl.high;
break;
case 0x6d: // LD L,L
clock.Add(4);
break;
case 0x6e: // LD L,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
HL.low = memory.Read(addr);
break;
case 0x6f: // LD L,A
clock.Add(4);
hl.low = A;
break;
case 0x70: // LD (HL),B
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, BC.high);
break;
case 0x71: // LD (HL),C
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, BC.low);
break;
case 0x72: // LD (HL),D
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, DE.high);
break;
case 0x73: // LD (HL),E
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, DE.low);
break;
case 0x74: // LD (HL),H
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, HL.high);
break;
case 0x75: // LD (HL),L
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, HL.low);
break;
case 0x76: // HALT
clock.Add(4);
PC--;
HALT = true;
break;
case 0x77: // LD (HL),A
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
memory.Write(addr, A);
break;
case 0x78: // LD A,B
clock.Add(4);
A = BC.high;
break;
case 0x79: // LD A,C
clock.Add(4);
A = BC.low;
break;
case 0x7a: // LD A,D
clock.Add(4);
A = DE.high;
break;
case 0x7b: // LD A,E
clock.Add(4);
A = DE.low;
break;
case 0x7c: // LD A,H
clock.Add(4);
A = hl.high;
break;
case 0x7d: // LD A,L
clock.Add(4);
A = hl.low;
break;
case 0x7e: // LD A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
A = memory.Read(addr);
break;
case 0x7f: // LD A,A
clock.Add(4);
break;
case 0x80: // ADD A,B
clock.Add(4);
ADD8(BC.high);
break;
case 0x81: // ADD A,C
clock.Add(4);
ADD8(BC.low);
break;
case 0x82: // ADD A,D
clock.Add(4);
ADD8(DE.high);
break;
case 0x83: // ADD A,E
clock.Add(4);
ADD8(DE.low);
break;
case 0x84: // ADD A,H
clock.Add(4);
ADD8(hl.high);
break;
case 0x85: // ADD A,L
clock.Add(4);
ADD8(hl.low);
break;
case 0x86: // ADD A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
ADD8(memory.Read(addr));
break;
case 0x87: // ADD A,A
clock.Add(4);
ADD8(A);
break;
case 0x88: // ADC A,B
clock.Add(4);
ADC8(BC.high);
break;
case 0x89: // ADC A,C
clock.Add(4);
ADC8(BC.low);
break;
case 0x8a: // ADC A,D
clock.Add(4);
ADC8(DE.high);
break;
case 0x8b: // ADC A,E
clock.Add(4);
ADC8(DE.low);
break;
case 0x8c: // ADC A,H
clock.Add(4);
ADC8(hl.high);
break;
case 0x8d: // ADC A,L
clock.Add(4);
ADC8(hl.low);
break;
case 0x8e: // ADC A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
ADC8(memory.Read(addr));
break;
case 0x8f: // ADC A,A
clock.Add(4);
ADC8(A);
break;
case 0x90: // SUB A,B
clock.Add(4);
SUB8(BC.high);
break;
case 0x91: // SUB A,C
clock.Add(4);
SUB8(BC.low);
break;
case 0x92: // SUB A,D
clock.Add(4);
SUB8(DE.high);
break;
case 0x93: // SUB A,E
clock.Add(4);
SUB8(DE.low);
break;
case 0x94: // SUB A,H
clock.Add(4);
SUB8(hl.high);
break;
case 0x95: // SUB A,L
clock.Add(4);
SUB8(hl.low);
break;
case 0x96: // SUB A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
SUB8(memory.Read(addr));
break;
case 0x97: // SUB A,A
clock.Add(4);
SUB8(A);
break;
case 0x98: // SBC A,B
clock.Add(4);
SBC8(BC.high);
break;
case 0x99: // SBC A,C
clock.Add(4);
SBC8(BC.low);
break;
case 0x9a: // SBC A,D
clock.Add(4);
SBC8(DE.high);
break;
case 0x9b: // SBC A,E
clock.Add(4);
SBC8(DE.low);
break;
case 0x9c: // SBC A,H
clock.Add(4);
SBC8(hl.high);
break;
case 0x9d: // SBC A,L
clock.Add(4);
SBC8(hl.low);
break;
case 0x9e: // SBC A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
SBC8(memory.Read(addr));
break;
case 0x9f: // SBC A,A
clock.Add(4);
SBC8(A);
break;
case 0xa0: // AND A,B
clock.Add(4);
AND(BC.high);
break;
case 0xa1: // AND A,C
clock.Add(4);
AND(BC.low);
break;
case 0xa2: // AND A,D
clock.Add(4);
AND(DE.high);
break;
case 0xa3: // AND A,E
clock.Add(4);
AND(DE.low);
break;
case 0xa4: // AND A,H
clock.Add(4);
AND(hl.high);
break;
case 0xa5: // AND A,L
clock.Add(4);
AND(hl.low);
break;
case 0xa6: // AND A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
AND(memory.Read(addr));
break;
case 0xa7: // AND A,A
clock.Add(4);
AND(A);
break;
case 0xa8: // XOR A,B
clock.Add(4);
XOR(BC.high);
break;
case 0xa9: // XOR A,C
clock.Add(4);
XOR(BC.low);
break;
case 0xaa: // XOR A,D
clock.Add(4);
XOR(DE.high);
break;
case 0xab: // XOR A,E
clock.Add(4);
XOR(DE.low);
break;
case 0xac: // XOR A,H
clock.Add(4);
XOR(hl.high);
break;
case 0xad: // XOR A,L
clock.Add(4);
XOR(hl.low);
break;
case 0xae: // XOR A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
XOR(memory.Read(addr));
break;
case 0xaf: // XOR A,A
clock.Add(4);
XOR(A);
break;
case 0xb0: // OR A,B
clock.Add(4);
OR(BC.high);
break;
case 0xb1: // OR A,C
clock.Add(4);
OR(BC.low);
break;
case 0xb2: // OR A,D
clock.Add(4);
OR(DE.high);
break;
case 0xb3: // OR A,E
clock.Add(4);
OR(DE.low);
break;
case 0xb4: // OR A,H
clock.Add(4);
OR(hl.high);
break;
case 0xb5: // OR A,L
clock.Add(4);
OR(hl.low);
break;
case 0xb6: // OR A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
OR(memory.Read(addr));
break;
case 0xb7: // OR A,A
clock.Add(4);
OR(A);
break;
case 0xb8: // CP A,B
clock.Add(4);
CP(BC.high);
break;
case 0xb9: // CP A,C
clock.Add(4);
CP(BC.low);
break;
case 0xba: // CP A,D
clock.Add(4);
CP(DE.high);
break;
case 0xbb: // CP A,E
clock.Add(4);
CP(DE.low);
break;
case 0xbc: // CP A,H
clock.Add(4);
CP(hl.high);
break;
case 0xbd: // CP A,L
clock.Add(4);
CP(hl.low);
break;
case 0xbe: // CP A,(HL)
clock.Add(7);
addr = (ushort)(hl.reg + Offset());
CP(memory.Read(addr));
break;
case 0xbf: // CP A,A
clock.Add(4);
CP(A);
break;
case 0xc0: // RET NZ
RET_COND(Z80Flags.Zero, Z80Flags.None);
break;
case 0xc1: // POP BC
clock.Add(10);
BC.reg = POP();
break;
case 0xc2: // JP NZ,nnnn
JP_COND(Z80Flags.Zero, Z80Flags.None);
break;
case 0xc3: // JP nnnn
clock.Add(10);
JP();
break;
case 0xc4: // CALL NZ,nnnn
CALL_COND(Z80Flags.Zero, Z80Flags.None);
break;
case 0xc5: // PUSH BC
clock.Add(11);
PUSH(BC.reg);
break;
case 0xc6: // ADD A,n
clock.Add(7);
ADD8(memory.Read(PC++));
break;
case 0xc7: // RST 0
RST(0x00);
break;
case 0xc8: // RET Z
RET_COND(Z80Flags.Zero, Z80Flags.Zero);
break;
case 0xc9: // RET
clock.Add(10);
PC = POP();
break;
case 0xca: // JP Z,nnnn
JP_COND(Z80Flags.Zero, Z80Flags.Zero);
break;
case 0xcb: // CB shift
// Check for IX/IY shift
//
if (shift != 0)
{
if (shift == 0xdd)
{
addr = (ushort)(IX.reg + Offset());
}
else
{
addr = (ushort)(IY.reg + Offset());
}
DecodeShiftedCB(memory.Read(PC++), addr);
}
else
{
AddR(1);
DecodeCB(memory.Read(PC++));
}
break;
case 0xcc: // CALL Z,nnnn
CALL_COND(Z80Flags.Zero, Z80Flags.Zero);
break;
case 0xcd: // CALL nnnn
clock.Add(17);
CALL();
break;
case 0xce: // ADC A,n
clock.Add(7);
ADC8(memory.Read(PC++));
break;
case 0xcf: // RST 8
RST(0x08);
break;
case 0xd0: // RET NC
RET_COND(Z80Flags.Carry, Z80Flags.None);
break;
case 0xd1: // POP DE
clock.Add(10);
DE.reg = POP();
break;
case 0xd2: // JP NC,nnnn
JP_COND(Z80Flags.Carry, Z80Flags.None);
break;
case 0xd3: // OUT(n),A
clock.Add(11);
addr = memory.Read(PC++);
addr |= (ushort)(A << 8);
device.Write(addr, A);
break;
case 0xd4: // CALL NC,nnnn
CALL_COND(Z80Flags.Carry, Z80Flags.None);
break;
case 0xd5: // PUSH DE
clock.Add(11);
PUSH(DE.reg);
break;
case 0xd6: // SUB A,n
clock.Add(7);
SUB8(memory.Read(PC++));
break;
case 0xd7: // RST 10
RST(0x10);
break;
case 0xd8: // RET C
RET_COND(Z80Flags.Carry, Z80Flags.Carry);
break;
case 0xd9: // EXX
clock.Add(4);
Swap(ref BC, ref BC_);
Swap(ref DE, ref DE_);
Swap(ref HL, ref HL_);
break;
case 0xda: // JP C,nnnn
JP_COND(Z80Flags.Carry, Z80Flags.Carry);
break;
case 0xdb: // IN A,(n)
clock.Add(11);
addr = memory.Read(PC++);
addr |= (ushort)(A << 8);
A = device.Read(addr);
break;
case 0xdc: // CALL C,nnnn
CALL_COND(Z80Flags.Carry, Z80Flags.Carry);
break;
case 0xdd: // DD (IX) PREFIX
AddR(1);
clock.Add(4);
shift = opcode;
DecodeByte(memory.Read(PC++));
break;
case 0xde: // SBC A,n
clock.Add(7);
SBC8(memory.Read(PC++));
break;
case 0xdf: // RST 18
RST(0x18);
break;
case 0xe0: // RET PO
RET_COND(Z80Flags.PV, Z80Flags.None);
break;
case 0xe1: // POP HL
clock.Add(10);
hl.reg = POP();
break;
case 0xe2: // JP PO,nnnn
JP_COND(Z80Flags.PV, Z80Flags.None);
break;
case 0xe3: // EX (SP),HL
clock.Add(19);
addr = POP();
PUSH(hl.reg);
hl.reg = addr;
break;
case 0xe4: // CALL PO,nnnn
CALL_COND(Z80Flags.PV, Z80Flags.None);
break;
case 0xe5: // PUSH HL
clock.Add(11);
PUSH(hl.reg);
break;
case 0xe6: // AND A,n
clock.Add(7);
AND(memory.Read(PC++));
break;
case 0xe7: // RST 20
RST(0x20);
break;
case 0xe8: // RET PE
RET_COND(Z80Flags.PV, Z80Flags.PV);
break;
case 0xe9: // JP (HL)
clock.Add(4);
PC = hl.reg;
break;
case 0xea: // JP PE,nnnn
JP_COND(Z80Flags.PV, Z80Flags.PV);
break;
case 0xeb: // EX DE,HL
clock.Add(4);
Swap(ref DE, ref hl);
break;
case 0xec: // CALL PE,nnnn
CALL_COND(Z80Flags.PV, Z80Flags.PV);
break;
case 0xed: // ED PREFIX
AddR(1);
DecodeED(memory.Read(PC++));
break;
case 0xee: // XOR A,n
clock.Add(7);
XOR(memory.Read(PC++));
break;
case 0xef: // RST 28
RST(0x28);
break;
case 0xf0: // RET P
RET_COND(Z80Flags.Sign, Z80Flags.None);
break;
case 0xf1: // POP AF
clock.Add(10);
addr = POP();
A = (byte)(addr >> 8);
F = (Z80Flags)(addr & 0xff);
break;
case 0xf2: // JP P,nnnn
JP_COND(Z80Flags.Sign, Z80Flags.None);
break;
case 0xf3: // DI
clock.Add(4);
IFF1 = false;
IFF2 = false;
break;
case 0xf4: // CALL P,nnnn
CALL_COND(Z80Flags.Sign, Z80Flags.None);
break;
case 0xf5: // PUSH AF
clock.Add(11);
PUSH((ushort)((A << 8) | (int)(F)));
break;
case 0xf6: // OR A,n
clock.Add(7);
OR(memory.Read(PC++));
break;
case 0xf7: // RST 30
RST(0x30);
break;
case 0xf8: // RET M
RET_COND(Z80Flags.Sign, Z80Flags.Sign);
break;
case 0xf9: // LD SP,HL
clock.Add(6);
SP = hl.reg;
break;
case 0xfa: // JP N,nnnn
JP_COND(Z80Flags.Sign, Z80Flags.Sign);
break;
case 0xfb: // EI
clock.Add(4);
IFF1 = true;
IFF2 = true;
break;
case 0xfc: // CALL M,nnnn
CALL_COND(Z80Flags.Sign, Z80Flags.Sign);
break;
case 0xfd: // DD (IY) PREFIX
AddR(1);
clock.Add(4);
shift = opcode;
DecodeByte(memory.Read(PC++));
break;
case 0xfe: // CP A,n
clock.Add(7);
CP(memory.Read(PC++));
break;
case 0xff: // RST 38
RST(0x38);
break;
default:
break;
}
}
}
}