//
// 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 Decode(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(7);
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
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 0x2d: // 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);
SetFlag(H35table[A]);
break;
default:
break;
}
}
}
}