From 7a79ba9eb1e7cbee6386d8c8e019fdc4738228a4 Mon Sep 17 00:00:00 2001 From: Ian C Date: Mon, 5 Mar 2012 23:55:51 +0000 Subject: None compiling safe-keeping commit. Started on Z80 disassembler. --- .../Z80Disassembler.cs | 2371 ++++++++++++++++++++ .../Z80CpuBaseOpcodes.cs | 6 +- src/Noddybox.Emulation.EightBit/IDisassembler.cs | 43 + 3 files changed, 2417 insertions(+), 3 deletions(-) create mode 100644 src/Noddybox.Emulation.EightBit.Z80.Disassembler/Z80Disassembler.cs create mode 100644 src/Noddybox.Emulation.EightBit/IDisassembler.cs (limited to 'src') diff --git a/src/Noddybox.Emulation.EightBit.Z80.Disassembler/Z80Disassembler.cs b/src/Noddybox.Emulation.EightBit.Z80.Disassembler/Z80Disassembler.cs new file mode 100644 index 0000000..cdb378d --- /dev/null +++ b/src/Noddybox.Emulation.EightBit.Z80.Disassembler/Z80Disassembler.cs @@ -0,0 +1,2371 @@ +// 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.Disassembler +{ + /// + /// Provides an implementation of a Zilog Z80 disassembler. + /// + public class Z80Disassembler : IDisassembler + { + #region Private data + + private IMemory memory; + private sbyte cb_off; + + private readonly string[] z80_dis_reg8 = new string[] {"b","c","d","e","h","l","(hl)","a"}; + private readonly string[] z80_dis_reg16 = new string[] {"bc","de","hl","sp"}; + private readonly string[] z80_dis_condition = new string[] {"nz","z","nc","c","po","pe","p","m"}; + + private delegate void disassemble(byte opcode, ref ushort address); + + private disassemble[] dis_CB_opcode; + private disassemble[] dis_DD_opcode; + private disassemble[] dis_DD_CB_opcode; + private disassemble[] dis_ED_opcode; + private disassemble[] dis_FD_opcode; + private disassemble[] dis_FD_CB_opcode; + private disassemble[] dis_opcode_z80; + + #endregion + + #region Private. Some of these routines are to support the original C code. + + private byte Z80_Dis_FetchByte(ref ushort addr) + { + return memory.Read(addr++); + } + + private ushort FetchWord(ref ushort addr) + { + Register16 r = new Register16(0); + + r.low = memory.Read(addr++); + r.high = memory.Read(addr++); + + return r.reg; + } + + private string Opcode {get; set;} + private string Argument {get; set;} + + private void Z80_Dis_Set(string a, string b) + { + Opcode = a; + Argument = b; + } + + #endregion + + #region Disassembler functions. This code pretty much pasted as-is from my original C version + + /* ---------------------------------------- CB xx BYTE OPCODES + */ + private void DIS_RLC_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("rlc", reg); + } + + private void DIS_RRC_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("rrc", reg); + } + + private void DIS_RL_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("rl", reg); + } + + private void DIS_RR_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("rr", reg); + } + + private void DIS_SLA_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("sla", reg); + } + + private void DIS_SRA_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("sra", reg); + } + + private void DIS_SLL_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("sll", reg); + } + + private void DIS_SRL_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("srl", reg); + } + + private void DIS_BIT_R8(byte op, ref ushort pc) + { + string reg; + int bit; + + reg = z80_dis_reg8[op % 8]; + bit = (op - 0x40) / 8; + Z80_Dis_Set("bit", Z80_Dis_Printf("%d,%s", bit, reg)); + } + + private void DIS_RES_R8(byte op, ref ushort pc) + { + string reg; + int bit; + + reg = z80_dis_reg8[op % 8]; + bit = (op - 0x80) / 8; + Z80_Dis_Set("res", Z80_Dis_Printf("%d,%s", bit, reg)); + } + + private void DIS_SET_R8(byte op, ref ushort pc) + { + string reg; + int bit; + + reg = z80_dis_reg8[op % 8]; + bit = (op - 0xc0) / 8; + Z80_Dis_Set("set", Z80_Dis_Printf("%d,%s", bit, reg)); + } + + /* ---------------------------------------- DD OPCODES + */ + + string IX_RelStr(byte op, ref ushort pc) + { + sbyte r; + + r=(sbyte)Z80_Dis_FetchByte(z80,pc); + + if (r<0) + return String.Format("(ix-{0:x2})",-r); + else + return String.Format("(ix+{0:x2})", r); + } + + + string IX_RelStrCB(byte op, ref ushort pc) + { + sbyte r; + + r=(sbyte)cb_off; + + if (r<0) + return String.Format("(ix-{0:x2})",-r); + else + return String.Format("(ix+{0:x2})", r); + } + + + string XR8(int reg, ref ushort pc) + { + switch (reg) + { + case 0: + return ("b"); + break; + case 1: + return ("c"); + break; + case 2: + return ("d"); + break; + case 3: + return ("e"); + break; + case 4: + return ("ixh"); + break; + case 5: + return ("ixl"); + break; + case 6: + return (IX_RelStr(0, pc)); + break; + case 7: + return ("a"); + break; + default: + return String.Format("BUG {0}", reg); + break; + } + } + + private void DIS_DD_NOP(byte op, ref ushort pc) + { + dis_opcode_z80[op](op, pc); + } + + private void DIS_ADD_IX_BC(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "ix,bc"); + } + + private void DIS_ADD_IX_DE(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "ix,de"); + } + + private void DIS_LD_IX_WORD(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", Z80_Dis_Printf("ix,$%.4x", Z80_Dis_FetchWord(pc))); + } + + private void DIS_LD_ADDR_IX(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("($%.4x),ix", w)); + } + + private void DIS_INC_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", "ix"); + } + + private void DIS_INC_IXH(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", "ixh"); + } + + private void DIS_DEC_IXH(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", "ixh"); + } + + private void DIS_LD_IXH_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", Z80_Dis_Printf("ixh,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_ADD_IX_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "ix,ix"); + } + + private void DIS_LD_IX_ADDR(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("ix,($%.4x)", w)); + } + + private void DIS_DEC_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", "ix"); + } + + private void DIS_INC_IXL(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", "ixl"); + } + + private void DIS_DEC_IXL(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", "ixl"); + } + + private void DIS_LD_IXL_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", Z80_Dis_Printf("ixl,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_INC_IIX(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", Z80_Dis_Printf("%s", IX_RelStr(op, pc))); + } + + private void DIS_DEC_IIX(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", Z80_Dis_Printf("%s", IX_RelStr(op, pc))); + } + + private void DIS_LD_IIX_BYTE(byte op, ref ushort pc) + { + string rel; + int b; + + rel = IX_RelStr(op, pc); + b = Z80_Dis_FetchByte(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("%s,$%.2x", rel, b)); + } + + + private void DIS_ADD_IX_SP(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "ix,sp"); + } + + private void DIS_XLD_R8_R8(byte op, ref ushort pc) + { + int src_r,dest_r; + string src,dest; + + dest_r=(op-0x40)/8; + src_r=op%8; + + /* IX can't be used as source and destination when reading z80ory + */ + if (dest_r==6) + { + dest=XR8(dest_r,pc); + src=z80_dis_reg8[src_r]; + } + else if (((dest_r==4)||(dest_r==5))&&(src_r==6)) + { + dest=z80_dis_reg8[dest_r]; + src=XR8(src_r,pc); + } + else + { + dest=XR8(dest_r,pc); + src=XR8(src_r,pc); + } + + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src)); + } + + private void DIS_XADD_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("add", Z80_Dis_Printf("a,%s", XR8((op % 8), pc))); + } + + private void DIS_XADC_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("adc", Z80_Dis_Printf("a,%s", XR8((op % 8), pc))); + } + + private void DIS_XSUB_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("sub", Z80_Dis_Printf("a,%s", XR8((op % 8), pc))); + } + + private void DIS_XSBC_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("sbc", Z80_Dis_Printf("a,%s", XR8((op % 8), pc))); + } + + private void DIS_XAND_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("and", Z80_Dis_Printf("%s", XR8((op % 8), pc))); + } + + private void DIS_XXOR_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("xor", Z80_Dis_Printf("%s", XR8((op % 8), pc))); + } + + private void DIS_X_OR_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("or", Z80_Dis_Printf("%s", XR8((op % 8), pc))); + } + + private void DIS_XCP_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("cp", Z80_Dis_Printf("%s", XR8((op % 8), pc))); + } + + private void DIS_POP_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("pop", "ix"); + } + + private void DIS_EX_ISP_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("ex", "(sp),ix"); + } + + private void DIS_PUSH_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("push", "ix"); + } + + private void DIS_JP_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("jp", "(ix)"); + } + + private void DIS_LD_SP_IX(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "sp,ix"); + } + + private void DIS_DD_CB_DECODE(byte op, ref ushort pc) + { + int nop; + + cb_off = (sbyte)Z80_Dis_FetchByte(pc); + nop = Z80_Dis_FetchByte(pc); + dis_DD_CB_opcode[nop](nop, pc); + } + + private void DIS_DD_DD_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_DD_opcode[nop](nop, pc); + } + + private void DIS_DD_ED_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_ED_opcode[nop](nop, pc); + } + + private void DIS_DD_FD_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_FD_opcode[nop](nop, pc); + } + + + /* ---------------------------------------- DD CB OPCODES + */ + + private void DIS_RLC_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rlc", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + { + Z80_Dis_Set("rlc", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + } + + private void DIS_RRC_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rrc", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("rrc", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RL_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rl", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("rl", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RR_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rr", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("rr", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SLA_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("sla", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("sla", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SRA_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("sra", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("sra", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SRL_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("srl", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("srl", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SLL_IX(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("sll", Z80_Dis_Printf("%s", IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("sll", Z80_Dis_Printf("%s[%s]", IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_BIT_IX(byte op, ref ushort pc) + { + int reg; + int bit; + + reg = (op % 8); + bit = (op - 0x40) / 8; + + if (reg == 6) + Z80_Dis_Set("bit", Z80_Dis_Printf("%d,%s", bit, IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("bit", Z80_Dis_Printf("%d,%s[%s]", bit, IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RES_IX(byte op, ref ushort pc) + { + int reg; + int bit; + + reg = (op % 8); + bit = (op - 0x80) / 8; + + if (reg == 6) + Z80_Dis_Set("res", Z80_Dis_Printf("%d,%s", bit, IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("res", Z80_Dis_Printf("%d,%s[%s]", bit, IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SET_IX(byte op, ref ushort pc) + { + int reg; + int bit; + + reg = (op % 8); + bit = (op - 0xc0) / 8; + + if (reg == 6) + Z80_Dis_Set("set", Z80_Dis_Printf("%d,%s", bit, IX_RelStrCB(op, pc))); + else + Z80_Dis_Set("set", Z80_Dis_Printf("%d,%s[%s]", bit, IX_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + + /* ---------------------------------------- ED OPCODES + */ + + string ER8(int reg) + { + switch (reg) + { + case 0: + return ("b"); + break; + case 1: + return ("c"); + break; + case 2: + return ("d"); + break; + case 3: + return ("e"); + break; + case 4: + return ("h"); + break; + case 5: + return ("l"); + break; + case 6: + return ("0"); + break; + case 7: + return ("a"); + break; + } + + return "?"; + } + + /* Assumes illegal ED ops are being used for break points + */ + private void DIS_ED_NOP(byte op, ref ushort pc) + { + Z80_Dis_Set("brk", Z80_Dis_Printf("$%.2x", op)); + } + + private void DIS_IN_R8_C(byte op, ref ushort pc) + { + Z80_Dis_Set("in", Z80_Dis_Printf("%s,(c)", ER8((op - 0x40) / 8))); + } + + private void DIS_OUT_C_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("out", Z80_Dis_Printf("(c),%s", ER8((op - 0x40) / 8))); + } + + private void DIS_SBC_HL_R16(byte op, ref ushort pc) + { + Z80_Dis_Set("sbc", Z80_Dis_Printf("hl,%s", z80_dis_reg16[(op - 0x40) / 16])); + } + + private void DIS_ED_LD_ADDR_R16(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("($%.4x),%s", w, z80_dis_reg16[(op - 0x40) / 16])); + } + + private void DIS_NEG(byte op, ref ushort pc) + { + Z80_Dis_Set("neg", null); + } + + private void DIS_RETN(byte op, ref ushort pc) + { + Z80_Dis_Set("retn", null); + } + + private void DIS_IM_0(byte op, ref ushort pc) + { + Z80_Dis_Set("im", "0"); + } + + private void DIS_LD_I_A(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "i,a"); + } + + private void DIS_ADC_HL_R16(byte op, ref ushort pc) + { + Z80_Dis_Set("adc", Z80_Dis_Printf("hl,%s", z80_dis_reg16[(op - 0x40) / 16])); + } + + private void DIS_ED_LD_R16_ADDR(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("%s,($%.4x)", z80_dis_reg16[(op - 0x40) / 16], w)); + } + + private void DIS_RETI(byte op, ref ushort pc) + { + Z80_Dis_Set("reti", null); + } + + private void DIS_LD_R_A(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "r,a"); + } + + private void DIS_IM_1(byte op, ref ushort pc) + { + Z80_Dis_Set("im", "1"); + } + + private void DIS_LD_A_I(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "a,i"); + } + + private void DIS_IM_2(byte op, ref ushort pc) + { + Z80_Dis_Set("im", "2"); + } + + private void DIS_LD_A_R(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "a,r"); + } + + private void DIS_RRD(byte op, ref ushort pc) + { + Z80_Dis_Set("rrd", null); + } + + private void DIS_RLD(byte op, ref ushort pc) + { + Z80_Dis_Set("rld", null); + } + + private void DIS_LDI(byte op, ref ushort pc) + { + Z80_Dis_Set("ldi", null); + } + + private void DIS_CPI(byte op, ref ushort pc) + { + Z80_Dis_Set("cpi", null); + } + + private void DIS_INI(byte op, ref ushort pc) + { + Z80_Dis_Set("ini", null); + } + + private void DIS_OUTI(byte op, ref ushort pc) + { + Z80_Dis_Set("outi", null); + } + + private void DIS_LDD(byte op, ref ushort pc) + { + Z80_Dis_Set("ldd", null); + } + + private void DIS_CPD(byte op, ref ushort pc) + { + Z80_Dis_Set("cpd", null); + } + + private void DIS_IND(byte op, ref ushort pc) + { + Z80_Dis_Set("ind", null); + } + + private void DIS_OUTD(byte op, ref ushort pc) + { + Z80_Dis_Set("outd", null); + } + + private void DIS_LDIR(byte op, ref ushort pc) + { + Z80_Dis_Set("ldir", null); + } + + private void DIS_CPIR(byte op, ref ushort pc) + { + Z80_Dis_Set("cpir", null); + } + + private void DIS_INIR(byte op, ref ushort pc) + { + Z80_Dis_Set("inir", null); + } + + private void DIS_OTIR(byte op, ref ushort pc) + { + Z80_Dis_Set("otir", null); + } + + private void DIS_LDDR(byte op, ref ushort pc) + { + Z80_Dis_Set("lddr", null); + } + + private void DIS_CPDR(byte op, ref ushort pc) + { + Z80_Dis_Set("cpdr", null); + } + + private void DIS_INDR(byte op, ref ushort pc) + { + Z80_Dis_Set("indr", null); + } + + private void DIS_OTDR(byte op, ref ushort pc) + { + Z80_Dis_Set("otdr", null); + } + + + /* ---------------------------------------- FD OPCODES + */ + + string IY_RelStr(byte op, ref ushort pc) + { + sbyte r; + + r=(sbyte)Z80_Dis_FetchByte(z80,pc); + + if (r<0) + return String.Format("(iy-${0:x2})",-r); + else + return String.Format("(iy+${0:x2})", r); + } + + + string IY_RelStrCB(byte op, ref ushort pc) + { + sbyte r; + + r=(sbyte)cb_off; + + if (r<0) + return String.Format("(iy-${0:x2})",-r); + else + return String.Format("(iy+${0:x2})", r); + } + + + string YR8(int reg, ref ushort pc) + { + switch (reg) + { + case 0: + return ("b"); + break; + case 1: + return ("c"); + break; + case 2: + return ("d"); + break; + case 3: + return ("e"); + break; + case 4: + return ("iyh"); + break; + case 5: + return ("iyl"); + break; + case 6: + return (IY_RelStr(0, pc)); + break; + case 7: + return ("a"); + break; + default: + return String.Format("BUG {0}", reg); + break; + } + } + + private void DIS_FD_NOP(byte op, ref ushort pc) + { + dis_opcode_z80[op](op, pc); + } + + private void DIS_ADD_IY_BC(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "iy,bc"); + } + + private void DIS_ADD_IY_DE(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "iy,de"); + } + + private void DIS_LD_IY_WORD(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", Z80_Dis_Printf("iy,$%.4x", Z80_Dis_FetchWord(pc))); + } + + private void DIS_LD_ADDR_IY(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("($%.4x),iy", w)); + } + + private void DIS_INC_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", "iy"); + } + + private void DIS_INC_IYH(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", "iyh"); + } + + private void DIS_DEC_IYH(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", "iyh"); + } + + private void DIS_LD_IYH_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", Z80_Dis_Printf("iyh,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_ADD_IY_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "iy,iy"); + } + + private void DIS_LD_IY_ADDR(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("iy,($%.4x)", w)); + } + + private void DIS_DEC_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", "iy"); + } + + private void DIS_INC_IYL(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", "iyl"); + } + + private void DIS_DEC_IYL(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", "iyl"); + } + + private void DIS_LD_IYL_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", Z80_Dis_Printf("iyl,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_INC_IIY(byte op, ref ushort pc) + { + Z80_Dis_Set("inc", Z80_Dis_Printf("%s", IY_RelStr(op, pc))); + } + + private void DIS_DEC_IIY(byte op, ref ushort pc) + { + Z80_Dis_Set("dec", Z80_Dis_Printf("%s", IY_RelStr(op, pc))); + } + + private void DIS_LD_IIY_BYTE(byte op, ref ushort pc) + { + string rel; + int b; + + rel = IY_RelStr(op, pc); + b = Z80_Dis_FetchByte(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("%s,$%.2x", rel, b)); + } + + + private void DIS_ADD_IY_SP(byte op, ref ushort pc) + { + Z80_Dis_Set("add", "iy,sp"); + } + + private void DIS_YLD_R8_R8(byte op, ref ushort pc) + { + int src_r,dest_r; + string src,dest; + + dest_r=(op-0x40)/8; + src_r=op%8; + + /* IY can't be used as source and destination when reading z80ory + */ + if (dest_r==6) + { + dest=YR8(z80,dest_r,pc); + src=z80_dis_reg8[src_r]; + } + else if (((dest_r==4)||(dest_r==5))&&(src_r==6)) + { + dest=z80_dis_reg8[dest_r]; + src=YR8(z80,src_r,pc); + } + else + { + dest=YR8(z80,dest_r,pc); + src=YR8(z80,src_r,pc); + } + + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src)); + } + + private void DIS_YADD_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("add", Z80_Dis_Printf("a,%s", YR8((op % 8), pc))); + } + + private void DIS_YADC_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("adc", Z80_Dis_Printf("a,%s", YR8((op % 8), pc))); + } + + private void DIS_YSUB_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("sub", Z80_Dis_Printf("a,%s", YR8((op % 8), pc))); + } + + private void DIS_YSBC_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("sbc", Z80_Dis_Printf("a,%s", YR8((op % 8), pc))); + } + + private void DIS_YAND_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("and", Z80_Dis_Printf("%s", YR8((op % 8), pc))); + } + + private void DIS_YYOR_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("xor", Z80_Dis_Printf("%s", YR8((op % 8), pc))); + } + + private void DIS_Y_OR_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("or", Z80_Dis_Printf("%s", YR8((op % 8), pc))); + } + + private void DIS_YCP_R8(byte op, ref ushort pc) + { + Z80_Dis_Set("cp", Z80_Dis_Printf("%s", YR8((op % 8), pc))); + } + + private void DIS_POP_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("pop", "iy"); + } + + private void DIS_EY_ISP_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("ex", "(sp),iy"); + } + + private void DIS_PUSH_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("push", "iy"); + } + + private void DIS_JP_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("jp", "(iy)"); + } + + private void DIS_LD_SP_IY(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "sp,iy"); + } + + private void DIS_FD_CB_DECODE(byte op, ref ushort pc) + { + int nop; + + cb_off = (sbyte)Z80_Dis_FetchByte(pc); + nop = Z80_Dis_FetchByte(pc); + dis_FD_CB_opcode[nop](nop, pc); + } + + private void DIS_FD_DD_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_DD_opcode[nop](nop, pc); + } + + private void DIS_FD_ED_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_ED_opcode[nop](nop, pc); + } + + private void DIS_FD_FD_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_FD_opcode[nop](nop, pc); + } + + + /* ---------------------------------------- FD CB OPCODES + */ + + private void DIS_RLC_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rlc", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("rlc", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RRC_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rrc", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("rrc", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RL_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rl", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("rl", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RR_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("rr", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("rr", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SLA_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("sla", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("sla", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SRA_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("sra", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("sra", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SRL_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("srl", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("srl", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SLL_IY(byte op, ref ushort pc) + { + int reg; + + reg = (op % 8); + + if (reg == 6) + Z80_Dis_Set("sll", Z80_Dis_Printf("%s", IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("sll", Z80_Dis_Printf("%s[%s]", IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_BIT_IY(byte op, ref ushort pc) + { + int reg; + int bit; + + reg = (op % 8); + bit = (op - 0x40) / 8; + + if (reg == 6) + Z80_Dis_Set("bit", Z80_Dis_Printf("%d,%s", bit, IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("bit", Z80_Dis_Printf("%d,%s[%s]", bit, IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_RES_IY(byte op, ref ushort pc) + { + int reg; + int bit; + + reg = (op % 8); + bit = (op - 0x80) / 8; + + if (reg == 6) + Z80_Dis_Set("res", Z80_Dis_Printf("%d,%s", bit, IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("res", Z80_Dis_Printf("%d,%s[%s]", bit, IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + private void DIS_SET_IY(byte op, ref ushort pc) + { + int reg; + int bit; + + reg = (op % 8); + bit = (op - 0xc0) / 8; + + if (reg == 6) + Z80_Dis_Set("set", Z80_Dis_Printf("%d,%s", bit, IY_RelStrCB(op, pc))); + else + Z80_Dis_Set("set", Z80_Dis_Printf("%d,%s[%s]", bit, IY_RelStrCB(op, pc), z80_dis_reg8[reg])); + } + + + /* ---------------------------------------- SINGLE BYTE OPCODES + */ + private void DIS_NOP(byte op, ref ushort pc) + { + Z80_Dis_Set("nop", null); + } + + private void DIS_LD_R16_WORD(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op & 0x30) / 0x10]; + Z80_Dis_Set("ld", Z80_Dis_Printf("%s,$%.4x", reg, Z80_Dis_FetchWord(pc))); + } + + private void DIS_LD_R16_A(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op & 0x30) / 0x10]; + Z80_Dis_Set("ld", Z80_Dis_Printf("(%s),a", reg)); + } + + private void DIS_INC_R16(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op & 0x30) / 0x10]; + Z80_Dis_Set("inc", reg); + } + + private void DIS_INC_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[(op & 0x38) / 0x8]; + Z80_Dis_Set("inc", reg); + } + + private void DIS_DEC_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[(op & 0x38) / 0x8]; + Z80_Dis_Set("dec", reg); + } + + private void DIS_LD_R8_BYTE(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[(op & 0x38) / 0x8]; + Z80_Dis_Set("ld", Z80_Dis_Printf("%s,$%.2x", reg, Z80_Dis_FetchByte(pc))); + } + + private void DIS_RLCA(byte op, ref ushort pc) + { + Z80_Dis_Set("rlca", null); + } + + private void DIS_EX_AF_AF(byte op, ref ushort pc) + { + Z80_Dis_Set("ex", "af,af'"); + } + + private void DIS_ADD_HL_R16(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op & 0x30) / 0x10]; + Z80_Dis_Set("add", Z80_Dis_Printf("hl,%s", reg)); + } + + private void DIS_LD_A_R16(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op & 0x30) / 0x10]; + Z80_Dis_Set("ld", Z80_Dis_Printf("a,(%s)", reg)); + } + + private void DIS_DEC_R16(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op & 0x30) / 0x10]; + Z80_Dis_Set("dec", reg); + } + + private void DIS_RRCA(byte op, ref ushort pc) + { + Z80_Dis_Set("rrca", null); + } + + private void DIS_DJNZ(byte op, ref ushort pc) + { + ushort n; + + n = pc + (sbyte)memory.Read(pc) + 1; + pc++; + Z80_Dis_Set("djnz", Z80_Dis_Printf("$%.4x", n)); + } + + private void DIS_RLA(byte op, ref ushort pc) + { + Z80_Dis_Set("rla", null); + } + + private void DIS_JR(byte op, ref ushort pc) + { + ushort n; + + n = pc + (sbyte)memory.Read(pc) + 1; + pc++; + Z80_Dis_Set("jr", Z80_Dis_Printf("$%.4x", n)); + } + + private void DIS_RRA(byte op, ref ushort pc) + { + Z80_Dis_Set("rra", null); + } + + private void DIS_JR_CO(byte op, ref ushort pc) + { + string con; + ushort n; + + con = z80_dis_condition[(op - 0x20) / 8]; + n = pc + (sbyte)memory.Read(pc) + 1; + pc++; + Z80_Dis_Set("jr", Z80_Dis_Printf("%s,$%.4x", con, n)); + } + + private void DIS_LD_ADDR_HL(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("($%.4x),hl", w)); + } + + private void DIS_DAA(byte op, ref ushort pc) + { + Z80_Dis_Set("daa", null); + } + + private void DIS_LD_HL_ADDR(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("hl,($%.4x)", w)); + } + + private void DIS_CPL(byte op, ref ushort pc) + { + Z80_Dis_Set("cpl", null); + } + + private void DIS_LD_ADDR_A(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("($%.4x),a", w)); + } + + private void DIS_SCF(byte op, ref ushort pc) + { + Z80_Dis_Set("scf", null); + } + + private void DIS_LD_A_ADDR(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("ld", Z80_Dis_Printf("a,($%.4x)", w)); + } + + private void DIS_CCF(byte op, ref ushort pc) + { + Z80_Dis_Set("ccf", null); + } + + private void DIS_LD_R8_R8(byte op, ref ushort pc) + { + string src,dest; + + dest=z80_dis_reg8[(op-0x40)/8]; + src=z80_dis_reg8[op%8]; + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src)); + } + + private void DIS_HALT(byte op, ref ushort pc) + { + Z80_Dis_Set("halt", null); + } + + private void DIS_ADD_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("add", Z80_Dis_Printf("a,%s", reg)); + } + + private void DIS_ADC_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("adc", Z80_Dis_Printf("a,%s", reg)); + } + + private void DIS_SUB_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("sub", Z80_Dis_Printf("a,%s", reg)); + } + + private void DIS_SBC_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("sbc", Z80_Dis_Printf("a,%s", reg)); + } + + private void DIS_AND_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("and", Z80_Dis_Printf("%s", reg)); + } + + private void DIS_XOR_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("xor", Z80_Dis_Printf("%s", reg)); + } + + private void DIS_OR_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("or", Z80_Dis_Printf("%s", reg)); + } + + private void DIS_CP_R8(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg8[op % 8]; + Z80_Dis_Set("cp", Z80_Dis_Printf("%s", reg)); + } + + + private void DIS_RET_CO(byte op, ref ushort pc) + { + string con; + + con = z80_dis_condition[(op - 0xc0) / 8]; + Z80_Dis_Set("ret", con); + } + + private void DIS_POP_R16(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op - 0xc0) / 16]; + + if (!strcmp(reg, "sp")) + reg = "af"; + + Z80_Dis_Set("pop", reg); + } + + private void DIS_JP(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("jp", Z80_Dis_Printf("$%.4x", w)); + } + + private void DIS_PUSH_R16(byte op, ref ushort pc) + { + string reg; + + reg = z80_dis_reg16[(op - 0xc0) / 16]; + + if (!strcmp(reg, "sp")) + reg = "af"; + + Z80_Dis_Set("push", reg); + } + + private void DIS_ADD_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("add", Z80_Dis_Printf("a,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_RST(byte op, ref ushort pc) + { + int add; + + add = (op & 0x3f) - 7; + Z80_Dis_Set("rst", Z80_Dis_Printf("%.2xh", add)); + } + + private void DIS_RET(byte op, ref ushort pc) + { + Z80_Dis_Set("ret", null); + } + + private void DIS_JP_CO(byte op, ref ushort pc) + { + string con; + ushort w; + + w = Z80_Dis_FetchWord(pc); + con = z80_dis_condition[(op - 0xc0) / 8]; + Z80_Dis_Set("jp", Z80_Dis_Printf("%s,$%.4x", con, w)); + } + + private void DIS_CB_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_CB_opcode[nop](nop, pc); + } + + private void DIS_CALL_CO(byte op, ref ushort pc) + { + string con; + ushort w; + + w = Z80_Dis_FetchWord(pc); + con = z80_dis_condition[(op - 0xc0) / 8]; + Z80_Dis_Set("call", Z80_Dis_Printf("%s,$%.4x", con, w)); + } + + private void DIS_CALL(byte op, ref ushort pc) + { + ushort w; + + w = Z80_Dis_FetchWord(pc); + Z80_Dis_Set("call", Z80_Dis_Printf("$%.4x", w)); + } + + private void DIS_ADC_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("adc", Z80_Dis_Printf("a,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_OUT_BYTE_A(byte op, ref ushort pc) + { + Z80_Dis_Set("out", Z80_Dis_Printf("($%.2x),a", Z80_Dis_FetchByte(pc))); + } + + private void DIS_SUB_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("sub", Z80_Dis_Printf("a,$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_EXX(byte op, ref ushort pc) + { + Z80_Dis_Set("exx", null); + } + + private void DIS_IN_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("in", Z80_Dis_Printf("a,($%.2x)", Z80_Dis_FetchByte(pc))); + } + + private void DIS_DD_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_DD_opcode[nop](nop, pc); + } + + private void DIS_SBC_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("sbc", Z80_Dis_Printf("a,$%.2x", Z80_Dis_FetchByte(pc))); + } + + + private void DIS_EX_ISP_HL(byte op, ref ushort pc) + { + Z80_Dis_Set("ex", "(sp),hl"); + } + + private void DIS_AND_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("and", Z80_Dis_Printf("$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_JP_HL(byte op, ref ushort pc) + { + Z80_Dis_Set("jp", "(hl)"); + } + + private void DIS_EX_DE_HL(byte op, ref ushort pc) + { + Z80_Dis_Set("ex", "de,hl"); + } + + private void DIS_ED_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_ED_opcode[nop](nop, pc); + } + + private void DIS_XOR_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("xor", Z80_Dis_Printf("$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_DI(byte op, ref ushort pc) + { + Z80_Dis_Set("di", null); + } + + private void DIS_OR_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("or", Z80_Dis_Printf("$%.2x", Z80_Dis_FetchByte(pc))); + } + + private void DIS_LD_SP_HL(byte op, ref ushort pc) + { + Z80_Dis_Set("ld", "sp,hl"); + } + + private void DIS_EI(byte op, ref ushort pc) + { + Z80_Dis_Set("ei", null); + } + + private void DIS_FD_DECODE(byte op, ref ushort pc) + { + int nop; + + nop = Z80_Dis_FetchByte(pc); + dis_FD_opcode[nop](nop, pc); + } + + private void DIS_CP_A_BYTE(byte op, ref ushort pc) + { + Z80_Dis_Set("cp", Z80_Dis_Printf("$%.2x", Z80_Dis_FetchByte(pc))); + } + + #endregion + + #region Constructors + + public Z80Disassembler() + { + // Verify runtime + // + Register16.Verify(); + + // Setup function tables + // + dis_CB_opcode = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, + /* 0x04 - 0x07 */ DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, + /* 0x08 - 0x0b */ DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, + /* 0x0c - 0x0f */ DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, + + /* 0x10 - 0x13 */ DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, + /* 0x14 - 0x17 */ DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, + /* 0x18 - 0x1b */ DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, + /* 0x1c - 0x1f */ DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, + + /* 0x20 - 0x23 */ DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, + /* 0x24 - 0x27 */ DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, + /* 0x28 - 0x2b */ DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, + /* 0x2c - 0x2f */ DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, + + /* 0x30 - 0x33 */ DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, + /* 0x34 - 0x37 */ DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, + /* 0x38 - 0x3b */ DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, + /* 0x3c - 0x3f */ DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, + + /* 0x40 - 0x43 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x44 - 0x47 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x48 - 0x4b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x4c - 0x4f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + + /* 0x50 - 0x53 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x54 - 0x57 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x58 - 0x5b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x5c - 0x5f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + + /* 0x60 - 0x63 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x64 - 0x67 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x68 - 0x6b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x6c - 0x6f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + + /* 0x70 - 0x73 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x74 - 0x77 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x78 - 0x7b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + /* 0x7c - 0x7f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + + /* 0x80 - 0x83 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0x84 - 0x87 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0x88 - 0x8b */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0x8c - 0x8f */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + + /* 0x90 - 0x93 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0x94 - 0x97 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0x98 - 0x9b */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0x9c - 0x9f */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + + /* 0xa0 - 0xa3 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0xa4 - 0xa7 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0xa8 - 0xab */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0xac - 0xaf */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + + /* 0xb0 - 0xb3 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0xb4 - 0xb7 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0xb8 - 0xbb */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + /* 0xbc - 0xbf */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + + /* 0xc0 - 0xc3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xc4 - 0xc7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xc8 - 0xcb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xcc - 0xcf */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + + /* 0xd0 - 0xd3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xd4 - 0xd7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xd8 - 0xdb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xdc - 0xdf */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + + /* 0xe0 - 0xe3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xe4 - 0xe7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xe8 - 0xeb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xec - 0xef */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + + /* 0xf0 - 0xf3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xf4 - 0xf7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xf8 - 0xfb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + /* 0xfc - 0xff */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + }; + + /* DIS_DD opcodes + */ + dis_DD_opcode = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x04 - 0x07 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x08 - 0x0b */ DIS_DD_NOP, DIS_ADD_IX_BC, DIS_DD_NOP, DIS_DD_NOP, + /* 0x0c - 0x0f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + + /* 0x10 - 0x13 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x14 - 0x17 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x18 - 0x1b */ DIS_DD_NOP, DIS_ADD_IX_DE, DIS_DD_NOP, DIS_DD_NOP, + /* 0x1c - 0x1f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + + /* 0x20 - 0x23 */ DIS_DD_NOP, DIS_LD_IX_WORD, DIS_LD_ADDR_IX, DIS_INC_IX, + /* 0x24 - 0x27 */ DIS_INC_IXH, DIS_DEC_IXH, DIS_LD_IXH_BYTE, DIS_DD_NOP, + /* 0x28 - 0x2b */ DIS_DD_NOP, DIS_ADD_IX_IX, DIS_LD_IX_ADDR, DIS_DEC_IX, + /* 0x2c - 0x2f */ DIS_INC_IXL, DIS_DEC_IXL, DIS_LD_IXL_BYTE, DIS_DD_NOP, + + /* 0x30 - 0x33 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x34 - 0x37 */ DIS_INC_IIX, DIS_DEC_IIX, DIS_LD_IIX_BYTE, DIS_DD_NOP, + /* 0x38 - 0x3b */ DIS_DD_NOP, DIS_ADD_IX_SP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x3c - 0x3f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + + /* 0x40 - 0x43 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x44 - 0x47 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + /* 0x48 - 0x4b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x4c - 0x4f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + + /* 0x50 - 0x53 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x54 - 0x57 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + /* 0x58 - 0x5b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x5c - 0x5f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + + /* 0x60 - 0x63 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, + /* 0x64 - 0x67 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, + /* 0x68 - 0x6b */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, + /* 0x6c - 0x6f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, + + /* 0x70 - 0x73 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, + /* 0x74 - 0x77 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, DIS_XLD_R8_R8, + /* 0x78 - 0x7b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x7c - 0x7f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + + /* 0x80 - 0x83 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x84 - 0x87 */ DIS_XADD_R8, DIS_XADD_R8, DIS_XADD_R8, DIS_DD_NOP, + /* 0x88 - 0x8b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x8c - 0x8f */ DIS_XADC_R8, DIS_XADC_R8, DIS_XADC_R8, DIS_DD_NOP, + + /* 0x90 - 0x93 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x94 - 0x97 */ DIS_XSUB_R8, DIS_XSUB_R8, DIS_XSUB_R8, DIS_DD_NOP, + /* 0x98 - 0x9b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0x9c - 0x9f */ DIS_XSBC_R8, DIS_XSBC_R8, DIS_XSBC_R8, DIS_DD_NOP, + + /* 0xa0 - 0xa3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xa4 - 0xa7 */ DIS_XAND_R8, DIS_XAND_R8, DIS_XAND_R8, DIS_DD_NOP, + /* 0xa8 - 0xab */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xac - 0xaf */ DIS_XXOR_R8, DIS_XXOR_R8, DIS_XXOR_R8, DIS_DD_NOP, + + /* 0xb0 - 0xb3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xb4 - 0xb7 */ DIS_X_OR_R8, DIS_X_OR_R8, DIS_X_OR_R8, DIS_DD_NOP, + /* 0xb8 - 0xbb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xbc - 0xbf */ DIS_XCP_R8, DIS_XCP_R8, DIS_XCP_R8, DIS_DD_NOP, + + /* 0xc0 - 0xc3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xc4 - 0xc7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xc8 - 0xcb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_CB_DECODE, + /* 0xcc - 0xcf */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + + /* 0xd0 - 0xd3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xd4 - 0xd7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xd8 - 0xdb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xdc - 0xdf */ DIS_DD_NOP, DIS_DD_DD_DECODE, DIS_DD_NOP, DIS_DD_NOP, + + /* 0xe0 - 0xe3 */ DIS_DD_NOP, DIS_POP_IX, DIS_DD_NOP, DIS_EX_ISP_IX, + /* 0xe4 - 0xe7 */ DIS_DD_NOP, DIS_PUSH_IX, DIS_DD_NOP, DIS_DD_NOP, + /* 0xe8 - 0xeb */ DIS_DD_NOP, DIS_JP_IX, DIS_DD_NOP, DIS_DD_NOP, + /* 0xec - 0xef */ DIS_DD_NOP, DIS_DD_ED_DECODE, DIS_DD_NOP, DIS_DD_NOP, + + /* 0xf0 - 0xf3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xf4 - 0xf7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + /* 0xf8 - 0xfb */ DIS_DD_NOP, DIS_LD_SP_IX, DIS_DD_NOP, DIS_DD_NOP, + /* 0xfc - 0xff */ DIS_DD_NOP, DIS_DD_FD_DECODE, DIS_DD_NOP, DIS_DD_NOP, + }; + + + /* DIS_DD DIS_CB opcodes + */ + dis_DD_CB_opcode = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, + /* 0x04 - 0x07 */ DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, + /* 0x08 - 0x0b */ DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, + /* 0x0c - 0x0f */ DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, + + /* 0x10 - 0x13 */ DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, + /* 0x14 - 0x17 */ DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, + /* 0x18 - 0x1b */ DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, + /* 0x1c - 0x1f */ DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, + + /* 0x20 - 0x23 */ DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, + /* 0x24 - 0x27 */ DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, + /* 0x28 - 0x2b */ DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, + /* 0x2c - 0x2f */ DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, + + /* 0x30 - 0x33 */ DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, + /* 0x34 - 0x37 */ DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, + /* 0x38 - 0x3b */ DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, + /* 0x3c - 0x3f */ DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, + + /* 0x40 - 0x43 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x44 - 0x47 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x48 - 0x4b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x4c - 0x4f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + + /* 0x50 - 0x53 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x54 - 0x57 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x58 - 0x5b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x5c - 0x5f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + + /* 0x60 - 0x63 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x64 - 0x67 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x68 - 0x6b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x6c - 0x6f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + + /* 0x70 - 0x73 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x74 - 0x77 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x78 - 0x7b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + /* 0x7c - 0x7f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + + /* 0x80 - 0x83 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0x84 - 0x87 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0x88 - 0x8b */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0x8c - 0x8f */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + + /* 0x90 - 0x93 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0x94 - 0x97 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0x98 - 0x9b */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0x9c - 0x9f */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + + /* 0xa0 - 0xa3 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0xa4 - 0xa7 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0xa8 - 0xab */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0xac - 0xaf */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + + /* 0xb0 - 0xb3 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0xb4 - 0xb7 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0xb8 - 0xbb */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + /* 0xbc - 0xbf */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + + /* 0xc0 - 0xc3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xc4 - 0xc7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xc8 - 0xcb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xcc - 0xcf */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + + /* 0xd0 - 0xd3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xd4 - 0xd7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xd8 - 0xdb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xdc - 0xdf */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + + /* 0xe0 - 0xe3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xe4 - 0xe7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xe8 - 0xeb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xec - 0xef */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + + /* 0xf0 - 0xf3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xf4 - 0xf7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xf8 - 0xfb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + /* 0xfc - 0xff */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + }; + + /* DIS_ED opcodes + */ + dis_ED_opcode = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x04 - 0x07 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x08 - 0x0b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x0c - 0x0f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0x10 - 0x13 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x14 - 0x17 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x18 - 0x1b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x1c - 0x1f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0x20 - 0x23 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x24 - 0x27 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x28 - 0x2b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x2c - 0x2f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0x30 - 0x33 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x34 - 0x37 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x38 - 0x3b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x3c - 0x3f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0x40 - 0x43 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, + /* 0x44 - 0x47 */ DIS_NEG, DIS_RETN, DIS_IM_0, DIS_LD_I_A, + /* 0x48 - 0x4b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, + /* 0x4c - 0x4f */ DIS_NEG, DIS_RETI, DIS_IM_0, DIS_LD_R_A, + + /* 0x50 - 0x53 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, + /* 0x54 - 0x57 */ DIS_NEG, DIS_RETN, DIS_IM_1, DIS_LD_A_I, + /* 0x58 - 0x5b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, + /* 0x5c - 0x5f */ DIS_NEG, DIS_RETI, DIS_IM_2, DIS_LD_A_R, + + /* 0x60 - 0x63 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, + /* 0x64 - 0x67 */ DIS_NEG, DIS_RETN, DIS_IM_0, DIS_RRD, + /* 0x68 - 0x6b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, + /* 0x6c - 0x6f */ DIS_NEG, DIS_RETI, DIS_IM_0, DIS_RLD, + + /* 0x70 - 0x73 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, + /* 0x74 - 0x77 */ DIS_NEG, DIS_RETN, DIS_IM_1, DIS_ED_NOP, + /* 0x78 - 0x7b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, + /* 0x7c - 0x7f */ DIS_NEG, DIS_RETI, DIS_IM_2, DIS_ED_NOP, + + /* 0x80 - 0x83 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x84 - 0x87 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x88 - 0x8b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x8c - 0x8f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0x90 - 0x93 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x94 - 0x97 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x98 - 0x9b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0x9c - 0x9f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0xa0 - 0xa3 */ DIS_LDI, DIS_CPI, DIS_INI, DIS_OUTI, + /* 0xa4 - 0xa7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xa8 - 0xab */ DIS_LDD, DIS_CPD, DIS_IND, DIS_OUTD, + /* 0xac - 0xaf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0xb0 - 0xb3 */ DIS_LDIR, DIS_CPIR, DIS_INIR, DIS_OTIR, + /* 0xb4 - 0xb7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xb8 - 0xbb */ DIS_LDDR, DIS_CPDR, DIS_INDR, DIS_OTDR, + /* 0xbc - 0xbf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0xc0 - 0xc3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xc4 - 0xc7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xc8 - 0xcb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xcc - 0xcf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0xd0 - 0xd3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xd4 - 0xd7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xd8 - 0xdb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xdc - 0xdf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0xe0 - 0xe3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xe4 - 0xe7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xe8 - 0xeb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xec - 0xef */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + + /* 0xf0 - 0xf3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xf4 - 0xf7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xf8 - 0xfb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + /* 0xfc - 0xff */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + }; + + /* DIS_FD opcodes + */ + dis_FD_opcode = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x04 - 0x07 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x08 - 0x0b */ DIS_FD_NOP, DIS_ADD_IY_BC, DIS_FD_NOP, DIS_FD_NOP, + /* 0x0c - 0x0f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + + /* 0x10 - 0x13 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x14 - 0x17 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x18 - 0x1b */ DIS_FD_NOP, DIS_ADD_IY_DE, DIS_FD_NOP, DIS_FD_NOP, + /* 0x1c - 0x1f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + + /* 0x20 - 0x23 */ DIS_FD_NOP, DIS_LD_IY_WORD, DIS_LD_ADDR_IY, DIS_INC_IY, + /* 0x24 - 0x27 */ DIS_INC_IYH, DIS_DEC_IYH, DIS_LD_IYH_BYTE, DIS_FD_NOP, + /* 0x28 - 0x2b */ DIS_FD_NOP, DIS_ADD_IY_IY, DIS_LD_IY_ADDR, DIS_DEC_IY, + /* 0x2c - 0x2f */ DIS_INC_IYL, DIS_DEC_IYL, DIS_LD_IYL_BYTE, DIS_FD_NOP, + + /* 0x30 - 0x33 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x34 - 0x37 */ DIS_INC_IIY, DIS_DEC_IIY, DIS_LD_IIY_BYTE, DIS_FD_NOP, + /* 0x38 - 0x3b */ DIS_FD_NOP, DIS_ADD_IY_SP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x3c - 0x3f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + + /* 0x40 - 0x43 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x44 - 0x47 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + /* 0x48 - 0x4b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x4c - 0x4f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + + /* 0x50 - 0x53 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x54 - 0x57 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + /* 0x58 - 0x5b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x5c - 0x5f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + + /* 0x60 - 0x63 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, + /* 0x64 - 0x67 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, + /* 0x68 - 0x6b */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, + /* 0x6c - 0x6f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, + + /* 0x70 - 0x73 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, + /* 0x74 - 0x77 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, DIS_YLD_R8_R8, + /* 0x78 - 0x7b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x7c - 0x7f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + + /* 0x80 - 0x83 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x84 - 0x87 */ DIS_YADD_R8, DIS_YADD_R8, DIS_YADD_R8, DIS_FD_NOP, + /* 0x88 - 0x8b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x8c - 0x8f */ DIS_YADC_R8, DIS_YADC_R8, DIS_YADC_R8, DIS_FD_NOP, + + /* 0x90 - 0x93 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x94 - 0x97 */ DIS_YSUB_R8, DIS_YSUB_R8, DIS_YSUB_R8, DIS_FD_NOP, + /* 0x98 - 0x9b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0x9c - 0x9f */ DIS_YSBC_R8, DIS_YSBC_R8, DIS_YSBC_R8, DIS_FD_NOP, + + /* 0xa0 - 0xa3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xa4 - 0xa7 */ DIS_YAND_R8, DIS_YAND_R8, DIS_YAND_R8, DIS_FD_NOP, + /* 0xa8 - 0xab */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xac - 0xaf */ DIS_YYOR_R8, DIS_YYOR_R8, DIS_YYOR_R8, DIS_FD_NOP, + + /* 0xb0 - 0xb3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xb4 - 0xb7 */ DIS_Y_OR_R8, DIS_Y_OR_R8, DIS_Y_OR_R8, DIS_FD_NOP, + /* 0xb8 - 0xbb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xbc - 0xbf */ DIS_YCP_R8, DIS_YCP_R8, DIS_YCP_R8, DIS_FD_NOP, + + /* 0xc0 - 0xc3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xc4 - 0xc7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xc8 - 0xcb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_CB_DECODE, + /* 0xcc - 0xcf */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + + /* 0xd0 - 0xd3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xd4 - 0xd7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xd8 - 0xdb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xdc - 0xdf */ DIS_FD_NOP, DIS_FD_DD_DECODE, DIS_FD_NOP, DIS_FD_NOP, + + /* 0xe0 - 0xe3 */ DIS_FD_NOP, DIS_POP_IY, DIS_FD_NOP, DIS_EY_ISP_IY, + /* 0xe4 - 0xe7 */ DIS_FD_NOP, DIS_PUSH_IY, DIS_FD_NOP, DIS_FD_NOP, + /* 0xe8 - 0xeb */ DIS_FD_NOP, DIS_JP_IY, DIS_FD_NOP, DIS_FD_NOP, + /* 0xec - 0xef */ DIS_FD_NOP, DIS_FD_ED_DECODE, DIS_FD_NOP, DIS_FD_NOP, + + /* 0xf0 - 0xf3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xf4 - 0xf7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + /* 0xf8 - 0xfb */ DIS_FD_NOP, DIS_LD_SP_IY, DIS_FD_NOP, DIS_FD_NOP, + /* 0xfc - 0xff */ DIS_FD_NOP, DIS_FD_FD_DECODE, DIS_FD_NOP, DIS_FD_NOP, + }; + + /* DIS_FD DIS_CB opcodes + */ + dis_FD_CB_opcode = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, + /* 0x04 - 0x07 */ DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, + /* 0x08 - 0x0b */ DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, + /* 0x0c - 0x0f */ DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, + + /* 0x10 - 0x13 */ DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, + /* 0x14 - 0x17 */ DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, + /* 0x18 - 0x1b */ DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, + /* 0x1c - 0x1f */ DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, + + /* 0x20 - 0x23 */ DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, + /* 0x24 - 0x27 */ DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, + /* 0x28 - 0x2b */ DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, + /* 0x2c - 0x2f */ DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, + + /* 0x30 - 0x33 */ DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, + /* 0x34 - 0x37 */ DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, + /* 0x38 - 0x3b */ DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, + /* 0x3c - 0x3f */ DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, + + /* 0x40 - 0x43 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x44 - 0x47 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x48 - 0x4b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x4c - 0x4f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + + /* 0x50 - 0x53 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x54 - 0x57 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x58 - 0x5b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x5c - 0x5f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + + /* 0x60 - 0x63 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x64 - 0x67 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x68 - 0x6b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x6c - 0x6f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + + /* 0x70 - 0x73 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x74 - 0x77 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x78 - 0x7b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + /* 0x7c - 0x7f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + + /* 0x80 - 0x83 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0x84 - 0x87 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0x88 - 0x8b */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0x8c - 0x8f */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + + /* 0x90 - 0x93 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0x94 - 0x97 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0x98 - 0x9b */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0x9c - 0x9f */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + + /* 0xa0 - 0xa3 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0xa4 - 0xa7 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0xa8 - 0xab */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0xac - 0xaf */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + + /* 0xb0 - 0xb3 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0xb4 - 0xb7 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0xb8 - 0xbb */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + /* 0xbc - 0xbf */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + + /* 0xc0 - 0xc3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xc4 - 0xc7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xc8 - 0xcb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xcc - 0xcf */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + + /* 0xd0 - 0xd3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xd4 - 0xd7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xd8 - 0xdb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xdc - 0xdf */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + + /* 0xe0 - 0xe3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xe4 - 0xe7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xe8 - 0xeb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xec - 0xef */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + + /* 0xf0 - 0xf3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xf4 - 0xf7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xf8 - 0xfb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + /* 0xfc - 0xff */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + }; + + /* DIS_First/single byte opcodes + */ + dis_opcode_z80 = new disassemble[0x100] + { + /* 0x00 - 0x03 */ DIS_NOP, DIS_LD_R16_WORD, DIS_LD_R16_A, DIS_INC_R16, + /* 0x04 - 0x07 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RLCA, + /* 0x08 - 0x0b */ DIS_EX_AF_AF, DIS_ADD_HL_R16, DIS_LD_A_R16, DIS_DEC_R16, + /* 0x0c - 0x0f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RRCA, + + /* 0x10 - 0x13 */ DIS_DJNZ, DIS_LD_R16_WORD, DIS_LD_R16_A, DIS_INC_R16, + /* 0x14 - 0x17 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RLA, + /* 0x18 - 0x1b */ DIS_JR, DIS_ADD_HL_R16, DIS_LD_A_R16, DIS_DEC_R16, + /* 0x1c - 0x1f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RRA, + + /* 0x20 - 0x23 */ DIS_JR_CO, DIS_LD_R16_WORD, DIS_LD_ADDR_HL, DIS_INC_R16, + /* 0x24 - 0x27 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_DAA, + /* 0x28 - 0x2b */ DIS_JR_CO, DIS_ADD_HL_R16, DIS_LD_HL_ADDR, DIS_DEC_R16, + /* 0x2c - 0x2f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_CPL, + + /* 0x30 - 0x33 */ DIS_JR_CO, DIS_LD_R16_WORD, DIS_LD_ADDR_A, DIS_INC_R16, + /* 0x34 - 0x37 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_SCF, + /* 0x38 - 0x3b */ DIS_JR_CO, DIS_ADD_HL_R16, DIS_LD_A_ADDR, DIS_DEC_R16, + /* 0x3c - 0x3f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_CCF, + + /* 0x40 - 0x43 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x44 - 0x47 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x48 - 0x4b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x4c - 0x4f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + + /* 0x50 - 0x53 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x54 - 0x57 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x58 - 0x5b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x5c - 0x5f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + + /* 0x60 - 0x63 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x64 - 0x67 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x68 - 0x6b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x6c - 0x6f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + + /* 0x70 - 0x73 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x74 - 0x77 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_HALT, DIS_LD_R8_R8, + /* 0x78 - 0x7b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + /* 0x7c - 0x7f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + + /* 0x80 - 0x83 */ DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, + /* 0x84 - 0x87 */ DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, + /* 0x88 - 0x8b */ DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, + /* 0x8c - 0x8f */ DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, + + /* 0x90 - 0x93 */ DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, + /* 0x94 - 0x97 */ DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, + /* 0x98 - 0x9b */ DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, + /* 0x9c - 0x9f */ DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, + + /* 0xa0 - 0xa3 */ DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, + /* 0xa4 - 0xa7 */ DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, + /* 0xa8 - 0xab */ DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, + /* 0xac - 0xaf */ DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, + + /* 0xb0 - 0xb3 */ DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, + /* 0xb4 - 0xb7 */ DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, + /* 0xb8 - 0xbb */ DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, + /* 0xbc - 0xbf */ DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, + + /* 0xc0 - 0xc3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_JP, + /* 0xc4 - 0xc7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_ADD_A_BYTE, DIS_RST, + /* 0xc8 - 0xcb */ DIS_RET_CO, DIS_RET, DIS_JP_CO, DIS_CB_DECODE, + /* 0xcc - 0xcf */ DIS_CALL_CO, DIS_CALL, DIS_ADC_A_BYTE, DIS_RST, + + /* 0xd0 - 0xd3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_OUT_BYTE_A, + /* 0xd4 - 0xd7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_SUB_A_BYTE, DIS_RST, + /* 0xd8 - 0xdb */ DIS_RET_CO, DIS_EXX, DIS_JP_CO, DIS_IN_A_BYTE, + /* 0xdc - 0xdf */ DIS_CALL_CO, DIS_DD_DECODE, DIS_SBC_A_BYTE, DIS_RST, + + /* 0xe0 - 0xe3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_EX_ISP_HL, + /* 0xe4 - 0xe7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_AND_A_BYTE, DIS_RST, + /* 0xe8 - 0xeb */ DIS_RET_CO, DIS_JP_HL, DIS_JP_CO, DIS_EX_DE_HL, + /* 0xec - 0xef */ DIS_CALL_CO, DIS_ED_DECODE, DIS_XOR_A_BYTE, DIS_RST, + + /* 0xf0 - 0xf3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_DI, + /* 0xf4 - 0xf7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_OR_A_BYTE, DIS_RST, + /* 0xf8 - 0xfb */ DIS_RET_CO, DIS_LD_SP_HL, DIS_JP_CO, DIS_EI, + /* 0xfc - 0xff */ DIS_CALL_CO, DIS_FD_DECODE, DIS_CP_A_BYTE, DIS_RST, + }; + + } + + #endregion + + #region IDisassembler interface + + public void Initialise(IMemory memory) + { + this.memory = memory; + } + + public ushort Disassemble(ushort startAddress, out string address, out string opcode, out string hexdump) + { + address = String.Empty; + opcode = String.Empty; + hexdump = String.Empty; + Opcode = String.Empty; + Argument = String.Empty; + + String.Format(address, "{0:X4}", address); + + return startAddress; + } + + #endregion + } +} diff --git a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs index 24f8093..bc09ce2 100644 --- a/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs +++ b/src/Noddybox.Emulation.EightBit.Z80/Z80CpuBaseOpcodes.cs @@ -269,7 +269,7 @@ namespace Noddybox.Emulation.EightBit.Z80 F |= Z80Flags.Carry; } - if ((reg ^ w ^ b) == 0x1000) + if (((reg ^ w ^ b) & 0x1000) == 0x1000) { F |= Z80Flags.HalfCarry; } @@ -501,7 +501,7 @@ namespace Noddybox.Emulation.EightBit.Z80 /// private void RLCA() { - F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) + F = (F & (Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero)) | (Z80Flags)Binary.ShiftRight(A, 7); A = (byte)(Binary.ShiftLeft(A, 1) | Binary.ShiftRight(A, 7)); @@ -515,7 +515,7 @@ namespace Noddybox.Emulation.EightBit.Z80 private void RLA() { byte carry = (byte)(F & Z80Flags.Carry); - F = (F & Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero) + F = (F & (Z80Flags.PV | Z80Flags.Sign | Z80Flags.Zero)) | (Z80Flags)Binary.ShiftRight(A, 7); A = (byte)(Binary.ShiftRight(A, 1) | carry); F |= H35table[A]; diff --git a/src/Noddybox.Emulation.EightBit/IDisassembler.cs b/src/Noddybox.Emulation.EightBit/IDisassembler.cs new file mode 100644 index 0000000..fed7fee --- /dev/null +++ b/src/Noddybox.Emulation.EightBit/IDisassembler.cs @@ -0,0 +1,43 @@ +// 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 +{ + /// + /// Defines an 8-bit disassembler. + /// + public interface IDisassembler + { + /// + /// Initialise the disaasembler to give it access to memory. + /// + /// The memory to access. + void Initialise(IMemory memory); + + /// + /// Disassembles memory. + /// + /// The address to start disassembling from. + /// Contains a formated address. + /// Contains the formatted opcode. + /// Contains a formatted string of the hex making up the opcode. + /// The address after the last byte disassembled. + ushort Disassemble(ushort startAddress, out string address, out string opcode, out string hexdump); + } +} -- cgit v1.2.3