// // 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; } } } }