Add files via upload

This commit is contained in:
alyosha-tas 2017-10-12 20:20:13 -04:00 committed by GitHub
parent ff13009e97
commit 12c46db790
8 changed files with 4684 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
using System;
namespace BizHawk.Emulation.Common.Components.Z80A
{
public partial class Z80A
{
private bool iff1;
public bool IFF1 { get { return iff1; } set { iff1 = value; } }
private bool iff2;
public bool IFF2 { get { return iff2; } set { iff2 = value; } }
private bool nonMaskableInterrupt;
public bool NonMaskableInterrupt
{
get { return nonMaskableInterrupt; }
set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; }
}
private bool nonMaskableInterruptPending;
public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } }
private int interruptMode;
public int InterruptMode
{
get { return interruptMode; }
set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; }
}
public Action IRQCallback = delegate () { };
public Action NMICallback = delegate () { };
private void NMI_()
{
cur_instr = new ushort[]
{IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCh,
IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
ASGN, PCl, 0x66,
ASGN, PCh, 0,
IDLE,
OP };
}
// Mode 0 interrupts only take effect if a CALL or RST is on the data bus
// Otherwise operation just continues as normal
// For now assume a NOP is on the data bus, in which case no stack operations occur
//NOTE: TODO: When a CALL is present on the data bus, adjust WZ accordingly
private void INTERRUPT_0(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
OP };
}
// Just jump to $0038
private void INTERRUPT_1()
{
cur_instr = new ushort[]
{DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCh,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCl,
IDLE,
ASGN, PCl, 0x38,
IDLE,
ASGN, PCh, 0,
IDLE,
OP };
}
// Interrupt mode 2 uses the I vector combined with a byte on the data bus
// Again for now we assume only a 0 on the data bus and jump to 0xI00
private void INTERRUPT_2(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
IDLE,
IDLE,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCh,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCl,
IDLE,
ASGN, PCl, 0,
IDLE,
TR, PCh, I,
IDLE,
OP };
}
private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60};
private void ResetInterrupts()
{
IFF1 = false;
IFF2 = false;
NonMaskableInterrupt = false;
NonMaskableInterruptPending = false;
InterruptMode = 1;
}
}
}

View File

@ -0,0 +1,467 @@
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Common.Components.Z80A
{
public sealed partial class Z80A : IDisassemblable
{
static string Result(string format, Func<ushort, byte> read, ref ushort addr)
{
//d immediately succeeds the opcode
//n immediate succeeds the opcode and the displacement (if present)
//nn immediately succeeds the opcode and the displacement (if present)
if (format.IndexOf("nn") != -1)
{
byte B = read(addr++);
byte C = read(addr++);
format = format.Replace("nn", string.Format("{0:X4}h", B + C * 256));
}
if (format.IndexOf("n") != -1)
{
byte B = read(addr++);
format = format.Replace("n", string.Format("{0:X2}h", B));
}
if (format.IndexOf("+d") != -1) format = format.Replace("+d", "d");
if (format.IndexOf("d") != -1)
{
byte B = read(addr++);
bool neg = ((B & 0x80) != 0);
char sign = neg ? '-' : '+';
int val = neg ? 256 - B : B;
format = format.Replace("d", string.Format("{0}{1:X2}h", sign, val));
}
return format;
}
readonly static string[] mnemonics = new string[]
{
"NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04
"INC B", "DEC B", "LD B, n", "RLCA", //0x08
"EX AF, AF'", "ADD HL, BC", "LD A, (BC)", "DEC BC", //0x0C
"INC C", "DEC C", "LD C, n", "RRCA", //0x10
"DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14
"INC D", "DEC D", "LD D, n", "RLA", //0x18
"JR d", "ADD HL, DE", "LD A, (DE)", "DEC DE", //0x1C
"INC E", "DEC E", "LD E, n", "RRA", //0x20
"JR NZ, d", "LD HL, nn", "LD (nn), HL", "INC HL", //0x24
"INC H", "DEC H", "LD H, n", "DAA", //0x28
"JR Z, d", "ADD HL, HL", "LD HL, (nn)", "DEC HL", //0x2C
"INC L", "DEC L", "LD L, n", "CPL", //0x30
"JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34
"INC (HL)", "DEC (HL)", "LD (HL), n", "SCF", //0x38
"JR C, d", "ADD HL, SP", "LD A, (nn)", "DEC SP", //0x3C
"INC A", "DEC A", "LD A, n", "CCF", //0x40
"LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44
"LD B, H", "LD B, L", "LD B, (HL)", "LD B, A", //0x48
"LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C
"LD C, H", "LD C, L", "LD C, (HL)", "LD C, A", //0x50
"LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54
"LD D, H", "LD D, L", "LD D, (HL)", "LD D, A", //0x58
"LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C
"LD E, H", "LD E, L", "LD E, (HL)", "LD E, A", //0x60
"LD H, B", "LD H, C", "LD H, D", "LD H, E", //0x64
"LD H, H", "LD H, L", "LD H, (HL)", "LD H, A", //0x68
"LD L, B", "LD L, B", "LD L, D", "LD L, E", //0x6C
"LD L, H", "LD L, L", "LD L, (HL)", "LD L, A", //0x70
"LD (HL), B", "LD (HL), C", "LD (HL), D", "LD (HL), E", //0x74
"LD (HL), H", "LD (HL), L", "HALT", "LD (HL), A", //0x78
"LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C
"LD A, H", "LD A, L", "LD A, (HL)", "LD A, A", //0x80
"ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84
"ADD A, H", "ADD A, L", "ADD A, (HL)", "ADD A, A", //0x88
"ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C
"ADC A, H", "ADC A, L", "ADC A, (HL)", "ADC A, A", //0x90
"SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94
"SUB A, H", "SUB A, L", "SUB A, (HL)", "SUB A, A", //0x98
"SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C
"SBC A, H", "SBC A, L", "SBC A, (HL)", "SBC A, A", //0xA0
"AND B", "AND C", "AND D", "AND E", //0xA4
"AND H", "AND L", "AND (HL)", "AND A", //0xA8
"XOR B", "XOR C", "XOR D", "XOR E", //0xAC
"XOR H", "XOR L", "XOR (HL)", "XOR A", //0xB0
"OR B", "OR C", "OR D", "OR E", //0xB4
"OR H", "OR L", "OR (HL)", "OR A", //0xB8
"CP B", "CP C", "CP D", "CP E", //0xBC
"CP H", "CP L", "CP (HL)", "CP A", //0xC0
"RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4
"CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8
"RET Z", "RET", "JP Z, nn", "[CB]", //0xCC
"CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0
"RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4
"CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8
"RET C", "EXX", "JP C, nn", "IN A, n", //0xDC
"CALL C, nn", "[DD]", "SBC A, n", "RST $18", //0xE0
"RET PO", "POP HL", "JP PO, nn", "EX (SP), HL", //0xE4
"CALL C, nn", "PUSH HL", "AND n", "RST $20", //0xE8
"RET PE", "JP HL", "JP PE, nn", "EX DE, HL", //0xEC
"CALL PE, nn", "[ED]", "XOR n", "RST $28", //0xF0
"RET P", "POP AF", "JP P, nn", "DI", //0xF4
"CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8
"RET M", "LD SP, HL", "JP M, nn", "EI", //0xFC
"CALL M, nn", "[FD]", "CP n", "RST $38", //0x100
};
readonly static string[] mnemonicsDD = new string[]
{
"NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04
"INC B", "DEC B", "LD B, n", "RLCA", //0x08
"EX AF, AF'", "ADD IX, BC", "LD A, (BC)", "DEC BC", //0x0C
"INC C", "DEC C", "LD C, n", "RRCA", //0x10
"DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14
"INC D", "DEC D", "LD D, n", "RLA", //0x18
"JR d", "ADD IX, DE", "LD A, (DE)", "DEC DE", //0x1C
"INC E", "DEC E", "LD E, n", "RRA", //0x20
"JR NZ, d", "LD IX, nn", "LD (nn), IX", "INC IX", //0x24
"INC IXH", "DEC IXH", "LD IXH, n", "DAA", //0x28
"JR Z, d", "ADD IX, IX", "LD IX, (nn)", "DEC IX", //0x2C
"INC IXL", "DEC IXL", "LD IXL, n", "CPL", //0x30
"JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34
"INC (IX+d)", "DEC (IX+d)", "LD (IX+d), n", "SCF", //0x38
"JR C, d", "ADD IX, SP", "LD A, (nn)", "DEC SP", //0x3C
"INC A", "DEC A", "LD A, n", "CCF", //0x40
"LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44
"LD B, IXH", "LD B, IXL", "LD B, (IX+d)", "LD B, A", //0x48
"LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C
"LD C, IXH", "LD C, IXL", "LD C, (IX+d)", "LD C, A", //0x50
"LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54
"LD D, IXH", "LD D, IXL", "LD D, (IX+d)", "LD D, A", //0x58
"LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C
"LD E, IXH", "LD E, IXL", "LD E, (IX+d)", "LD E, A", //0x60
"LD IXH, B", "LD IXH, C", "LD IXH, D", "LD IXH, E", //0x64
"LD IXH, IXH", "LD IXH, IXL", "LD H, (IX+d)", "LD IXH, A", //0x68
"LD IXL, B", "LD IXL, C", "LD IXL, D", "LD IXL, E", //0x6C
"LD IXL, IXH", "LD IXL, IXL", "LD L, (IX+d)", "LD IXL, A", //0x70
"LD (IX+d), B", "LD (IX+d), C", "LD (IX+d), D", "LD (IX+d), E", //0x74
"LD (IX+d), H", "LD (IX+d), L", "HALT", "LD (IX+d), A", //0x78
"LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C
"LD A, IXH", "LD A, IXL", "LD A, (IX+d)", "LD A, A", //0x80
"ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84
"ADD A, IXH", "ADD A, IXL", "ADD A, (IX+d)", "ADD A, A", //0x88
"ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C
"ADC A, IXH", "ADC A, IXL", "ADC A, (IX+d)", "ADC A, A", //0x90
"SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94
"SUB A, IXH", "SUB A, IXL", "SUB A, (IX+d)", "SUB A, A", //0x98
"SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C
"SBC A, IXH", "SBC A, IXL", "SBC A, (IX+d)", "SBC A, A", //0xA0
"AND B", "AND C", "AND D", "AND E", //0xA4
"AND IXH", "AND IXL", "AND (IX+d)", "AND A", //0xA8
"XOR B", "XOR C", "XOR D", "XOR E", //0xAC
"XOR IXH", "XOR IXL", "XOR (IX+d)", "XOR A", //0xB0
"OR B", "OR C", "OR D", "OR E", //0xB4
"OR IXH", "OR IXL", "OR (IX+d)", "OR A", //0xB8
"CP B", "CP C", "CP D", "CP E", //0xBC
"CP IXH", "CP IXL", "CP (IX+d)", "CP A", //0xC0
"RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4
"CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8
"RET Z", "RET", "JP Z, nn", "[DD CB]", //0xCC
"CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0
"RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4
"CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8
"RET C", "EXX", "JP C, nn", "IN A, n", //0xDC
"CALL C, nn", "[!DD DD!]", "SBC A, n", "RST $18", //0xE0
"RET PO", "POP IX", "JP PO, nn", "EX (SP), IX", //0xE4
"CALL C, nn", "PUSH IX", "AND n", "RST $20", //0xE8
"RET PE", "JP IX", "JP PE, nn", "EX DE, HL", //0xEC
"CALL PE, nn", "[DD ED]", "XOR n", "RST $28", //0xF0
"RET P", "POP AF", "JP P, nn", "DI", //0xF4
"CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8
"RET M", "LD SP, IX", "JP M, nn", "EI", //0xFC
"CALL M, nn", "[!!DD FD!!]", "CP n", "RST $38", //0x100
};
readonly static string[] mnemonicsFD = new string[]
{
"NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04
"INC B", "DEC B", "LD B, n", "RLCA", //0x08
"EX AF, AF'", "ADD IY, BC", "LD A, (BC)", "DEC BC", //0x0C
"INC C", "DEC C", "LD C, n", "RRCA", //0x10
"DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14
"INC D", "DEC D", "LD D, n", "RLA", //0x18
"JR d", "ADD IY, DE", "LD A, (DE)", "DEC DE", //0x1C
"INC E", "DEC E", "LD E, n", "RRA", //0x20
"JR NZ, d", "LD IY, nn", "LD (nn), IY", "INC IY", //0x24
"INC IYH", "DEC IYH", "LD IYH, n", "DAA", //0x28
"JR Z, d", "ADD IY, IY", "LD IY, (nn)", "DEC IY", //0x2C
"INC IYL", "DEC IYL", "LD IYL, n", "CPL", //0x30
"JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34
"INC (IY+d)", "DEC (IY+d)", "LD (IY+d), n", "SCF", //0x38
"JR C, d", "ADD IY, SP", "LD A, (nn)", "DEC SP", //0x3C
"INC A", "DEC A", "LD A, n", "CCF", //0x40
"LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44
"LD B, IYH", "LD B, IYL", "LD B, (IY+d)", "LD B, A", //0x48
"LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C
"LD C, IYH", "LD C, IYL", "LD C, (IY+d)", "LD C, A", //0x50
"LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54
"LD D, IYH", "LD D, IYL", "LD D, (IY+d)", "LD D, A", //0x58
"LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C
"LD E, IYH", "LD E, IYL", "LD E, (IY+d)", "LD E, A", //0x60
"LD IYH, B", "LD IYH, C", "LD IYH, D", "LD IYH, E", //0x64
"LD IYH, IYH", "LD IYH, IYL", "LD H, (IY+d)", "LD IYH, A", //0x68
"LD IYL, B", "LD IYL, C", "LD IYL, D", "LD IYL, E", //0x6C
"LD IYL, IYH", "LD IYL, IYL", "LD L, (IY+d)", "LD IYL, A", //0x70
"LD (IY+d), B", "LD (IY+d), C", "LD (IY+d), D", "LD (IY+d), E", //0x74
"LD (IY+d), H", "LD (IY+d), L", "HALT", "LD (IY+d), A", //0x78
"LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C
"LD A, IYH", "LD A, IYL", "LD A, (IY+d)", "LD A, A", //0x80
"ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84
"ADD A, IYH", "ADD A, IYL", "ADD A, (IY+d)", "ADD A, A", //0x88
"ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C
"ADC A, IYH", "ADC A, IYL", "ADC A, (IY+d)", "ADC A, A", //0x90
"SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94
"SUB A, IYH", "SUB A, IYL", "SUB A, (IY+d)", "SUB A, A", //0x98
"SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C
"SBC A, IYH", "SBC A, IYL", "SBC A, (IY+d)", "SBC A, A", //0xA0
"AND B", "AND C", "AND D", "AND E", //0xA4
"AND IYH", "AND IYL", "AND (IY+d)", "AND A", //0xA8
"XOR B", "XOR C", "XOR D", "XOR E", //0xAC
"XOR IYH", "XOR IYL", "XOR (IY+d)", "XOR A", //0xB0
"OR B", "OR C", "OR D", "OR E", //0xB4
"OR IYH", "OR IYL", "OR (IY+d)", "OR A", //0xB8
"CP B", "CP C", "CP D", "CP E", //0xBC
"CP IYH", "CP IYL", "CP (IY+d)", "CP A", //0xC0
"RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4
"CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8
"RET Z", "RET", "JP Z, nn", "[DD CB]", //0xCC
"CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0
"RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4
"CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8
"RET C", "EXX", "JP C, nn", "IN A, n", //0xDC
"CALL C, nn", "[!FD DD!]", "SBC A, n", "RST $18", //0xE0
"RET PO", "POP IY", "JP PO, nn", "EX (SP), IY", //0xE4
"CALL C, nn", "PUSH IY", "AND n", "RST $20", //0xE8
"RET PE", "JP IY", "JP PE, nn", "EX DE, HL", //0xEC
"CALL PE, nn", "[FD ED]", "XOR n", "RST $28", //0xF0
"RET P", "POP AF", "JP P, nn", "DI", //0xF4
"CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8
"RET M", "LD SP, IY", "JP M, nn", "EI", //0xFC
"CALL M, nn", "[!FD FD!]", "CP n", "RST $38", //0x100
};
readonly static string[] mnemonicsDDCB = new string[]
{
"RLC (IX+d)->B", "RLC (IX+d)->C", "RLC (IX+d)->D", "RLC (IX+d)->E", "RLC (IX+d)->H", "RLC (IX+d)->L", "RLC (IX+d)", "RLC (IX+d)->A",
"RRC (IX+d)->B", "RRC (IX+d)->C", "RRC (IX+d)->D", "RRC (IX+d)->E", "RRC (IX+d)->H", "RRC (IX+d)->L", "RRC (IX+d)", "RRC (IX+d)->A",
"RL (IX+d)->B", "RL (IX+d)->C", "RL (IX+d)->D", "RL (IX+d)->E", "RL (IX+d)->H", "RL (IX+d)->L", "RL (IX+d)", "RL (IX+d)->A",
"RR (IX+d)->B", "RR (IX+d)->C", "RR (IX+d)->D", "RR (IX+d)->E", "RR (IX+d)->H", "RR (IX+d)->L", "RR (IX+d)", "RR (IX+d)->A",
"SLA (IX+d)->B", "SLA (IX+d)->C", "SLA (IX+d)->D", "SLA (IX+d)->E", "SLA (IX+d)->H", "SLA (IX+d)->L", "SLA (IX+d)", "SLA (IX+d)->A",
"SRA (IX+d)->B", "SRA (IX+d)->C", "SRA (IX+d)->D", "SRA (IX+d)->E", "SRA (IX+d)->H", "SRA (IX+d)->L", "SRA (IX+d)", "SRA (IX+d)->A",
"SL1 (IX+d)->B", "SL1 (IX+d)->C", "SL1 (IX+d)->D", "SL1 (IX+d)->E", "SL1 (IX+d)->H", "SL1 (IX+d)->L", "SL1 (IX+d)", "SL1 (IX+d)->A",
"SRL (IX+d)->B", "SRL (IX+d)->C", "SRL (IX+d)->D", "SRL (IX+d)->E", "SRL (IX+d)->H", "SRL (IX+d)->L", "SRL (IX+d)", "SRL (IX+d)->A",
"BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)",
"BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)",
"BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)",
"BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)",
"BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)",
"BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)",
"BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)",
"BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)",
"RES 0 (IX+d)->B", "RES 0 (IX+d)->C", "RES 0 (IX+d)->D", "RES 0 (IX+d)->E", "RES 0 (IX+d)->H", "RES 0 (IX+d)->L", "RES 0 (IX+d)", "RES 0 (IX+d)->A",
"RES 1 (IX+d)->B", "RES 1 (IX+d)->C", "RES 1 (IX+d)->D", "RES 1 (IX+d)->E", "RES 1 (IX+d)->H", "RES 1 (IX+d)->L", "RES 1 (IX+d)", "RES 1 (IX+d)->A",
"RES 2 (IX+d)->B", "RES 2 (IX+d)->C", "RES 2 (IX+d)->D", "RES 2 (IX+d)->E", "RES 2 (IX+d)->H", "RES 2 (IX+d)->L", "RES 2 (IX+d)", "RES 2 (IX+d)->A",
"RES 3 (IX+d)->B", "RES 3 (IX+d)->C", "RES 3 (IX+d)->D", "RES 3 (IX+d)->E", "RES 3 (IX+d)->H", "RES 3 (IX+d)->L", "RES 3 (IX+d)", "RES 3 (IX+d)->A",
"RES 4 (IX+d)->B", "RES 4 (IX+d)->C", "RES 4 (IX+d)->D", "RES 4 (IX+d)->E", "RES 4 (IX+d)->H", "RES 4 (IX+d)->L", "RES 4 (IX+d)", "RES 4 (IX+d)->A",
"RES 5 (IX+d)->B", "RES 5 (IX+d)->C", "RES 5 (IX+d)->D", "RES 5 (IX+d)->E", "RES 5 (IX+d)->H", "RES 5 (IX+d)->L", "RES 5 (IX+d)", "RES 5 (IX+d)->A",
"RES 6 (IX+d)->B", "RES 6 (IX+d)->C", "RES 6 (IX+d)->D", "RES 6 (IX+d)->E", "RES 6 (IX+d)->H", "RES 6 (IX+d)->L", "RES 6 (IX+d)", "RES 6 (IX+d)->A",
"RES 7 (IX+d)->B", "RES 7 (IX+d)->C", "RES 7 (IX+d)->D", "RES 7 (IX+d)->E", "RES 7 (IX+d)->H", "RES 7 (IX+d)->L", "RES 7 (IX+d)", "RES 7 (IX+d)->A",
"SET 0 (IX+d)->B", "SET 0 (IX+d)->C", "SET 0 (IX+d)->D", "SET 0 (IX+d)->E", "SET 0 (IX+d)->H", "SET 0 (IX+d)->L", "SET 0 (IX+d)", "SET 0 (IX+d)->A",
"SET 1 (IX+d)->B", "SET 1 (IX+d)->C", "SET 1 (IX+d)->D", "SET 1 (IX+d)->E", "SET 1 (IX+d)->H", "SET 1 (IX+d)->L", "SET 1 (IX+d)", "SET 1 (IX+d)->A",
"SET 2 (IX+d)->B", "SET 2 (IX+d)->C", "SET 2 (IX+d)->D", "SET 2 (IX+d)->E", "SET 2 (IX+d)->H", "SET 2 (IX+d)->L", "SET 2 (IX+d)", "SET 2 (IX+d)->A",
"SET 3 (IX+d)->B", "SET 3 (IX+d)->C", "SET 3 (IX+d)->D", "SET 3 (IX+d)->E", "SET 3 (IX+d)->H", "SET 3 (IX+d)->L", "SET 3 (IX+d)", "SET 3 (IX+d)->A",
"SET 4 (IX+d)->B", "SET 4 (IX+d)->C", "SET 4 (IX+d)->D", "SET 4 (IX+d)->E", "SET 4 (IX+d)->H", "SET 4 (IX+d)->L", "SET 4 (IX+d)", "SET 4 (IX+d)->A",
"SET 5 (IX+d)->B", "SET 5 (IX+d)->C", "SET 5 (IX+d)->D", "SET 5 (IX+d)->E", "SET 5 (IX+d)->H", "SET 5 (IX+d)->L", "SET 5 (IX+d)", "SET 5 (IX+d)->A",
"SET 6 (IX+d)->B", "SET 6 (IX+d)->C", "SET 6 (IX+d)->D", "SET 6 (IX+d)->E", "SET 6 (IX+d)->H", "SET 6 (IX+d)->L", "SET 6 (IX+d)", "SET 6 (IX+d)->A",
"SET 7 (IX+d)->B", "SET 7 (IX+d)->C", "SET 7 (IX+d)->D", "SET 7 (IX+d)->E", "SET 7 (IX+d)->H", "SET 7 (IX+d)->L", "SET 7 (IX+d)", "SET 7 (IX+d)->A",
};
readonly static string[] mnemonicsFDCB = new string[]
{
"RLC (IY+d)->B", "RLC (IY+d)->C", "RLC (IY+d)->D", "RLC (IY+d)->E", "RLC (IY+d)->H", "RLC (IY+d)->L", "RLC (IY+d)", "RLC (IY+d)->A",
"RRC (IY+d)->B", "RRC (IY+d)->C", "RRC (IY+d)->D", "RRC (IY+d)->E", "RRC (IY+d)->H", "RRC (IY+d)->L", "RRC (IY+d)", "RRC (IY+d)->A",
"RL (IY+d)->B", "RL (IY+d)->C", "RL (IY+d)->D", "RL (IY+d)->E", "RL (IY+d)->H", "RL (IY+d)->L", "RL (IY+d)", "RL (IY+d)->A",
"RR (IY+d)->B", "RR (IY+d)->C", "RR (IY+d)->D", "RR (IY+d)->E", "RR (IY+d)->H", "RR (IY+d)->L", "RR (IY+d)", "RR (IY+d)->A",
"SLA (IY+d)->B", "SLA (IY+d)->C", "SLA (IY+d)->D", "SLA (IY+d)->E", "SLA (IY+d)->H", "SLA (IY+d)->L", "SLA (IY+d)", "SLA (IY+d)->A",
"SRA (IY+d)->B", "SRA (IY+d)->C", "SRA (IY+d)->D", "SRA (IY+d)->E", "SRA (IY+d)->H", "SRA (IY+d)->L", "SRA (IY+d)", "SRA (IY+d)->A",
"SL1 (IY+d)->B", "SL1 (IY+d)->C", "SL1 (IY+d)->D", "SL1 (IY+d)->E", "SL1 (IY+d)->H", "SL1 (IY+d)->L", "SL1 (IY+d)", "SL1 (IY+d)->A",
"SRL (IY+d)->B", "SRL (IY+d)->C", "SRL (IY+d)->D", "SRL (IY+d)->E", "SRL (IY+d)->H", "SRL (IY+d)->L", "SRL (IY+d)", "SRL (IY+d)->A",
"BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)",
"BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)",
"BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)",
"BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)",
"BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)",
"BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)",
"BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)",
"BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)",
"RES 0 (IY+d)->B", "RES 0 (IY+d)->C", "RES 0 (IY+d)->D", "RES 0 (IY+d)->E", "RES 0 (IY+d)->H", "RES 0 (IY+d)->L", "RES 0 (IY+d)", "RES 0 (IY+d)->A",
"RES 1 (IY+d)->B", "RES 1 (IY+d)->C", "RES 1 (IY+d)->D", "RES 1 (IY+d)->E", "RES 1 (IY+d)->H", "RES 1 (IY+d)->L", "RES 1 (IY+d)", "RES 1 (IY+d)->A",
"RES 2 (IY+d)->B", "RES 2 (IY+d)->C", "RES 2 (IY+d)->D", "RES 2 (IY+d)->E", "RES 2 (IY+d)->H", "RES 2 (IY+d)->L", "RES 2 (IY+d)", "RES 2 (IY+d)->A",
"RES 3 (IY+d)->B", "RES 3 (IY+d)->C", "RES 3 (IY+d)->D", "RES 3 (IY+d)->E", "RES 3 (IY+d)->H", "RES 3 (IY+d)->L", "RES 3 (IY+d)", "RES 3 (IY+d)->A",
"RES 4 (IY+d)->B", "RES 4 (IY+d)->C", "RES 4 (IY+d)->D", "RES 4 (IY+d)->E", "RES 4 (IY+d)->H", "RES 4 (IY+d)->L", "RES 4 (IY+d)", "RES 4 (IY+d)->A",
"RES 5 (IY+d)->B", "RES 5 (IY+d)->C", "RES 5 (IY+d)->D", "RES 5 (IY+d)->E", "RES 5 (IY+d)->H", "RES 5 (IY+d)->L", "RES 5 (IY+d)", "RES 5 (IY+d)->A",
"RES 6 (IY+d)->B", "RES 6 (IY+d)->C", "RES 6 (IY+d)->D", "RES 6 (IY+d)->E", "RES 6 (IY+d)->H", "RES 6 (IY+d)->L", "RES 6 (IY+d)", "RES 6 (IY+d)->A",
"RES 7 (IY+d)->B", "RES 7 (IY+d)->C", "RES 7 (IY+d)->D", "RES 7 (IY+d)->E", "RES 7 (IY+d)->H", "RES 7 (IY+d)->L", "RES 7 (IY+d)", "RES 7 (IY+d)->A",
"SET 0 (IY+d)->B", "SET 0 (IY+d)->C", "SET 0 (IY+d)->D", "SET 0 (IY+d)->E", "SET 0 (IY+d)->H", "SET 0 (IY+d)->L", "SET 0 (IY+d)", "SET 0 (IY+d)->A",
"SET 1 (IY+d)->B", "SET 1 (IY+d)->C", "SET 1 (IY+d)->D", "SET 1 (IY+d)->E", "SET 1 (IY+d)->H", "SET 1 (IY+d)->L", "SET 1 (IY+d)", "SET 1 (IY+d)->A",
"SET 2 (IY+d)->B", "SET 2 (IY+d)->C", "SET 2 (IY+d)->D", "SET 2 (IY+d)->E", "SET 2 (IY+d)->H", "SET 2 (IY+d)->L", "SET 2 (IY+d)", "SET 2 (IY+d)->A",
"SET 3 (IY+d)->B", "SET 3 (IY+d)->C", "SET 3 (IY+d)->D", "SET 3 (IY+d)->E", "SET 3 (IY+d)->H", "SET 3 (IY+d)->L", "SET 3 (IY+d)", "SET 3 (IY+d)->A",
"SET 4 (IY+d)->B", "SET 4 (IY+d)->C", "SET 4 (IY+d)->D", "SET 4 (IY+d)->E", "SET 4 (IY+d)->H", "SET 4 (IY+d)->L", "SET 4 (IY+d)", "SET 4 (IY+d)->A",
"SET 5 (IY+d)->B", "SET 5 (IY+d)->C", "SET 5 (IY+d)->D", "SET 5 (IY+d)->E", "SET 5 (IY+d)->H", "SET 5 (IY+d)->L", "SET 5 (IY+d)", "SET 5 (IY+d)->A",
"SET 6 (IY+d)->B", "SET 6 (IY+d)->C", "SET 6 (IY+d)->D", "SET 6 (IY+d)->E", "SET 6 (IY+d)->H", "SET 6 (IY+d)->L", "SET 6 (IY+d)", "SET 6 (IY+d)->A",
"SET 7 (IY+d)->B", "SET 7 (IY+d)->C", "SET 7 (IY+d)->D", "SET 7 (IY+d)->E", "SET 7 (IY+d)->H", "SET 7 (IY+d)->L", "SET 7 (IY+d)", "SET 7 (IY+d)->A",
};
readonly static string[] mnemonicsCB = new string[]
{
"RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A",
"RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A",
"RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A",
"RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A",
"SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A",
"SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A",
"SL1 B", "SL1 C", "SL1 D", "SL1 E", "SL1 H", "SL1 L", "SL1 (HL)", "SL1 A",
"SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A",
"BIT 0, B", "BIT 0, C", "BIT 0, D", "BIT 0, E", "BIT 0, H", "BIT 0, L", "BIT 0, (HL)", "BIT 0, A",
"BIT 1, B", "BIT 1, C", "BIT 1, D", "BIT 1, E", "BIT 1, H", "BIT 1, L", "BIT 1, (HL)", "BIT 1, A",
"BIT 2, B", "BIT 2, C", "BIT 2, D", "BIT 2, E", "BIT 2, H", "BIT 2, L", "BIT 2, (HL)", "BIT 2, A",
"BIT 3, B", "BIT 3, C", "BIT 3, D", "BIT 3, E", "BIT 3, H", "BIT 3, L", "BIT 3, (HL)", "BIT 3, A",
"BIT 4, B", "BIT 4, C", "BIT 4, D", "BIT 4, E", "BIT 4, H", "BIT 4, L", "BIT 4, (HL)", "BIT 4, A",
"BIT 5, B", "BIT 5, C", "BIT 5, D", "BIT 5, E", "BIT 5, H", "BIT 5, L", "BIT 5, (HL)", "BIT 5, A",
"BIT 6, B", "BIT 6, C", "BIT 6, D", "BIT 6, E", "BIT 6, H", "BIT 6, L", "BIT 6, (HL)", "BIT 6, A",
"BIT 7, B", "BIT 7, C", "BIT 7, D", "BIT 7, E", "BIT 7, H", "BIT 7, L", "BIT 7, (HL)", "BIT 7, A",
"RES 0, B", "RES 0, C", "RES 0, D", "RES 0, E", "RES 0, H", "RES 0, L", "RES 0, (HL)", "RES 0, A",
"RES 1, B", "RES 1, C", "RES 1, D", "RES 1, E", "RES 1, H", "RES 1, L", "RES 1, (HL)", "RES 1, A",
"RES 2, B", "RES 2, C", "RES 2, D", "RES 2, E", "RES 2, H", "RES 2, L", "RES 2, (HL)", "RES 2, A",
"RES 3, B", "RES 3, C", "RES 3, D", "RES 3, E", "RES 3, H", "RES 3, L", "RES 3, (HL)", "RES 3, A",
"RES 4, B", "RES 4, C", "RES 4, D", "RES 4, E", "RES 4, H", "RES 4, L", "RES 4, (HL)", "RES 4, A",
"RES 5, B", "RES 5, C", "RES 5, D", "RES 5, E", "RES 5, H", "RES 5, L", "RES 5, (HL)", "RES 5, A",
"RES 6, B", "RES 6, C", "RES 6, D", "RES 6, E", "RES 6, H", "RES 6, L", "RES 6, (HL)", "RES 6, A",
"RES 7, B", "RES 7, C", "RES 7, D", "RES 7, E", "RES 7, H", "RES 7, L", "RES 7, (HL)", "RES 7, A",
"SET 0, B", "SET 0, C", "SET 0, D", "SET 0, E", "SET 0, H", "SET 0, L", "SET 0, (HL)", "SET 0, A",
"SET 1, B", "SET 1, C", "SET 1, D", "SET 1, E", "SET 1, H", "SET 1, L", "SET 1, (HL)", "SET 1, A",
"SET 2, B", "SET 2, C", "SET 2, D", "SET 2, E", "SET 2, H", "SET 2, L", "SET 2, (HL)", "SET 2, A",
"SET 3, B", "SET 3, C", "SET 3, D", "SET 3, E", "SET 3, H", "SET 3, L", "SET 3, (HL)", "SET 3, A",
"SET 4, B", "SET 4, C", "SET 4, D", "SET 4, E", "SET 4, H", "SET 4, L", "SET 4, (HL)", "SET 4, A",
"SET 5, B", "SET 5, C", "SET 5, D", "SET 5, E", "SET 5, H", "SET 5, L", "SET 5, (HL)", "SET 5, A",
"SET 6, B", "SET 6, C", "SET 6, D", "SET 6, E", "SET 6, H", "SET 6, L", "SET 6, (HL)", "SET 6, A",
"SET 7, B", "SET 7, C", "SET 7, D", "SET 7, E", "SET 7, H", "SET 7, L", "SET 7, (HL)", "SET 7, A",
};
readonly static string[] mnemonicsED = new string[]
{
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP",
"IN B, C", "OUT C, B", "SBC HL, BC", "LD (nn), BC", //0x44
"NEG", "RETN", "IM $0", "LD I, A", //0x48
"IN C, C", "OUT C, C", "ADC HL, BC", "LD BC, (nn)", //0x4C
"NEG", "RETI", "IM $0", "LD R, A", //0x50
"IN D, C", "OUT C, D", "SBC HL, DE", "LD (nn), DE", //0x54
"NEG", "RETN", "IM $1", "LD A, I", //0x58
"IN E, C", "OUT C, E", "ADC HL, DE", "LD DE, (nn)", //0x5C
"NEG", "RETI", "IM $2", "LD A, R", //0x60
"IN H, C", "OUT C, H", "SBC HL, HL", "LD (nn), HL", //0x64
"NEG", "RETN", "IM $0", "RRD", //0x68
"IN L, C", "OUT C, L", "ADC HL, HL", "LD HL, (nn)", //0x6C
"NEG", "RETI", "IM $0", "RLD", //0x70
"IN 0, C", "OUT C, 0", "SBC HL, SP", "LD (nn), SP", //0x74
"NEG", "RETN", "IM $1", "NOP", //0x78
"IN A, C", "OUT C, A", "ADC HL, SP", "LD SP, (nn)", //0x7C
"NEG", "RETI", "IM $2", "NOP", //0x80
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x90
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xA0
"LDI", "CPI", "INI", "OUTI", //0xA4
"NOP", "NOP", "NOP", "NOP", //0xA8
"LDD", "CPD", "IND", "OUTD", //0xAC
"NOP", "NOP", "NOP", "NOP", //0xB0
"LDIR", "CPIR", "INIR", "OTIR", //0xB4
"NOP", "NOP", "NOP", "NOP", //0xB8
"LDDR", "CPDR", "INDR", "OTDR", //0xBC
"NOP", "NOP", "NOP", "NOP", //0xC0
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xD0
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xE0
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xF0
"NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x100
};
public string Disassemble(ushort addr, Func<ushort, byte> read, out ushort size)
{
ushort start_addr = addr;
byte A = read(addr++);
string format;
switch (A)
{
case 0xCB:
A = read(addr++);
format = mnemonicsCB[A];
break;
case 0xDD:
A = read(addr++);
switch (A)
{
case 0xCB: format = mnemonicsDDCB[A]; break;
case 0xED: format = mnemonicsED[A]; break;
default: format = mnemonicsDD[A]; break;
}
break;
case 0xED:
A = read(addr++);
format = mnemonicsED[A];
break;
case 0xFD:
A = read(addr++);
switch (A)
{
case 0xCB: format = mnemonicsFDCB[A]; break;
case 0xED: format = mnemonicsED[A]; break;
default: format = mnemonicsFD[A]; break;
}
break;
default: format = mnemonics[A]; break;
}
string temp = Result(format, read, ref addr);
size = (ushort)(addr - start_addr);
return temp;
}
#region IDisassemblable
public string Cpu
{
get { return "Z80"; }
set { }
}
public string PCRegisterName
{
get { return "PC"; }
}
public IEnumerable<string> AvailableCpus
{
get { yield return "Z80"; }
}
public string Disassemble(MemoryDomain m, uint addr, out int length)
{
int loc = (int)addr;
ushort unused = 0;
string ret = Disassemble((ushort) addr, a => m.PeekByte(a), out unused);
length = loc - (int)addr;
return ret;
}
#endregion
}
}

View File

@ -0,0 +1,727 @@
using BizHawk.Common.NumberExtensions;
using System;
namespace BizHawk.Emulation.Common.Components.Z80A
{
public partial class Z80A
{
public void Read_Func(ushort dest, ushort src_l, ushort src_h)
{
Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
}
public void I_Read_Func(ushort dest, ushort src_l, ushort src_h, ushort inc)
{
Regs[dest] = ReadMemory((ushort)((Regs[src_l] | (Regs[src_h]) << 8) + inc));
}
public void Write_Func(ushort dest_l, ushort dest_h, ushort src)
{
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h]) << 8), (byte)Regs[src]);
}
public void I_Write_Func(ushort dest_l, ushort dest_h, ushort inc, ushort src)
{
WriteMemory((ushort)((Regs[dest_l] | (Regs[dest_h] + inc)) << 8), (byte)Regs[src]);
}
public void TR_Func(ushort dest, ushort src)
{
Regs[dest] = Regs[src];
}
public void TR16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
Regs[dest_l] = Regs[src_l];
Regs[dest_h] = Regs[src_h];
}
public void ADD16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
int temp = Reg16_d + Reg16_s;
FlagC = temp.Bit(16);
FlagH = ((Reg16_d & 0xFFF) + (Reg16_s & 0xFFF)) > 0xFFF;
FlagN = false;
Flag3 = (temp & 0x0800) != 0;
Flag5 = (temp & 0x2000) != 0;
Regs[dest_l] = (ushort)(temp & 0xFF);
Regs[dest_h] = (ushort)((temp & 0xFF00) >> 8);
}
public void ADD8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
Reg16_d += Regs[src];
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d += (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
FlagN = false;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void SUB8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
Reg16_d -= Regs[src];
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d -= (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
FlagN = true;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void BIT_Func(ushort bit, ushort src)
{
FlagZ = !Regs[src].Bit(bit);
FlagP = FlagZ; // special case
FlagH = true;
FlagN = false;
FlagS = ((bit == 7) && Regs[src].Bit(bit));
Flag5 = Regs[src].Bit(5);
Flag3 = Regs[src].Bit(3);
}
// When doing I* + n bit tests, flags 3 and 5 come from I* + n
// This cooresponds to the high byte of WZ
// This is the same for the (HL) bit tests, except that WZ were not assigned to before the test occurs
public void I_BIT_Func(ushort bit, ushort src)
{
FlagZ = !Regs[src].Bit(bit);
FlagP = FlagZ; // special case
FlagH = true;
FlagN = false;
FlagS = ((bit == 7) && Regs[src].Bit(bit));
Flag5 = Regs[W].Bit(5);
Flag3 = Regs[W].Bit(3);
}
public void SET_Func(ushort bit, ushort src)
{
Regs[src] |= (ushort)(1 << bit);
}
public void RES_Func(ushort bit, ushort src)
{
Regs[src] &= (ushort)(0xFF - (1 << bit));
}
public void ASGN_Func(ushort src, ushort val)
{
Regs[src] = val;
}
public void SLL_Func(ushort src)
{
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | 0x1);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void SLA_Func(ushort src)
{
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)((Regs[src] << 1) & 0xFF);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void SRA_Func(ushort src)
{
FlagC = Regs[src].Bit(0);
ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation
Regs[src] = (ushort)((Regs[src] >> 1) | temp);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void SRL_Func(ushort src)
{
FlagC = Regs[src].Bit(0) ? true : false;
Regs[src] = (ushort)(Regs[src] >> 1);
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void CPL_Func(ushort src)
{
Regs[src] = (ushort)((~Regs[src]) & 0xFF);
FlagH = true;
FlagN = true;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void CCF_Func(ushort src)
{
FlagH = FlagC;
FlagC = !FlagC;
FlagN = false;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void SCF_Func(ushort src)
{
FlagC = true;
FlagH = false;
FlagN = false;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void AND8_Func(ushort dest, ushort src)
{
Regs[dest] = (ushort)(Regs[dest] & Regs[src]);
FlagZ = Regs[dest] == 0;
FlagC = false;
FlagH = true;
FlagN = false;
Flag3 = (Regs[dest] & 0x08) != 0;
Flag5 = (Regs[dest] & 0x20) != 0;
FlagS = Regs[dest] > 127;
FlagP = TableParity[Regs[dest]];
}
public void OR8_Func(ushort dest, ushort src)
{
Regs[dest] = (ushort)(Regs[dest] | Regs[src]);
FlagZ = Regs[dest] == 0;
FlagC = false;
FlagH = false;
FlagN = false;
Flag3 = (Regs[dest] & 0x08) != 0;
Flag5 = (Regs[dest] & 0x20) != 0;
FlagS = Regs[dest] > 127;
FlagP = TableParity[Regs[dest]];
}
public void XOR8_Func(ushort dest, ushort src)
{
Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]);
FlagZ = Regs[dest] == 0;
FlagC = false;
FlagH = false;
FlagN = false;
Flag3 = (Regs[dest] & 0x08) != 0;
Flag5 = (Regs[dest] & 0x20) != 0;
FlagS = Regs[dest] > 127;
FlagP = TableParity[Regs[dest]];
}
public void CP8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
Reg16_d -= Regs[src];
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d -= (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
FlagN = true;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
}
public void RRC_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
FlagC = Regs[src].Bit(0);
Regs[src] = (ushort)((FlagC ? 0x80 : 0) | (Regs[src] >> 1));
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void RR_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
ushort c = (ushort)(FlagC ? 0x80 : 0);
FlagC = Regs[src].Bit(0);
Regs[src] = (ushort)(c | (Regs[src] >> 1));
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void RLC_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
ushort c = (ushort)(Regs[src].Bit(7) ? 1 : 0);
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void RL_Func(ushort src)
{
bool imm = src == Aim;
if (imm) { src = A; }
ushort c = (ushort)(FlagC ? 1 : 0);
FlagC = Regs[src].Bit(7);
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
if (!imm)
{
FlagS = Regs[src].Bit(7);
FlagZ = Regs[src] == 0;
FlagP = TableParity[Regs[src]];
}
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
FlagH = false;
FlagN = false;
}
public void INC8_Func(ushort src)
{
int Reg16_d = Regs[src];
Reg16_d += 1;
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[src] & 0xF;
Reg16_d += 1;
FlagH = Reg16_d.Bit(4);
FlagN = false;
Regs[src] = ans;
FlagS = Regs[src].Bit(7);
FlagP = Regs[src] == 0x80;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void DEC8_Func(ushort src)
{
int Reg16_d = Regs[src];
Reg16_d -= 1;
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[src] & 0xF;
Reg16_d -= 1;
FlagH = Reg16_d.Bit(4);
FlagN = true;
Regs[src] = ans;
FlagS = Regs[src].Bit(7);
FlagP = Regs[src] == 0x7F;
Flag3 = (Regs[src] & 0x08) != 0;
Flag5 = (Regs[src] & 0x20) != 0;
}
public void INC16_Func(ushort src_l, ushort src_h)
{
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
Reg16_d += 1;
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
}
public void DEC16_Func(ushort src_l, ushort src_h)
{
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
Reg16_d -= 1;
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
}
public void ADC8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
int c = FlagC ? 1 : 0;
Reg16_d += (Regs[src] + c);
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d += ((Regs[src] & 0xF) + c);
FlagH = Reg16_d.Bit(4);
FlagN = false;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void SBC8_Func(ushort dest, ushort src)
{
int Reg16_d = Regs[dest];
int c = FlagC ? 1 : 0;
Reg16_d -= (Regs[src] + c);
FlagC = Reg16_d.Bit(8);
FlagZ = (Reg16_d & 0xFF) == 0;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = Regs[dest] & 0xF;
Reg16_d -= ((Regs[src] & 0xF) + c);
FlagH = Reg16_d.Bit(4);
FlagN = true;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
FlagS = ans > 127;
Regs[dest] = ans;
}
public void DA_Func(ushort src)
{
byte a = (byte)Regs[src];
byte temp = a;
if (FlagN)
{
if (FlagH || ((a & 0x0F) > 0x09)) { temp -= 0x06; }
if (FlagC || a > 0x99) { temp -= 0x60; }
}
else
{
if (FlagH || ((a & 0x0F) > 0x09)) { temp += 0x06; }
if (FlagC || a > 0x99) { temp += 0x60; }
}
temp &= 0xFF;
FlagC = FlagC || a > 0x99;
FlagZ = temp == 0;
FlagH = ((a ^ temp) & 0x10) != 0;
FlagP = TableParity[temp];
FlagS = temp > 127;
Flag3 = (temp & 0x08) != 0;
Flag5 = (temp & 0x20) != 0;
Regs[src] = temp;
}
// used for signed operations
public void ADDS_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l];
int Reg16_s = Regs[src_l];
Reg16_d += Reg16_s;
ushort temp = 0;
// since this is signed addition, calculate the high byte carry appropriately
// note that flags are unaffected by this operation
if (Reg16_s.Bit(7))
{
if (((Reg16_d & 0xFF) >= Regs[dest_l]))
{
temp = 0xFF;
}
else
{
temp = 0;
}
}
else
{
temp = (ushort)(Reg16_d.Bit(8) ? 1 : 0);
}
ushort ans_l = (ushort)(Reg16_d & 0xFF);
Regs[dest_l] = ans_l;
Regs[dest_h] += temp;
Regs[dest_h] &= 0xFF;
}
public void EXCH_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
ushort temp = Regs[dest_l];
Regs[dest_l] = Regs[src_l];
Regs[src_l] = temp;
temp = Regs[dest_h];
Regs[dest_h] = Regs[src_h];
Regs[src_h] = temp;
}
public void OUT_Func(ushort dest, ushort src)
{
WriteHardware(Regs[dest], (byte)(Regs[src]));
}
public void IN_Func(ushort dest, ushort src)
{
Regs[dest] = ReadHardware(Regs[src]);
}
public void SBC_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
int c = FlagC ? 1 : 0;
int ans = Reg16_d - Reg16_s - c;
FlagN = true;
FlagC = ans.Bit(16);
FlagP = (Reg16_d.Bit(15) != Reg16_s.Bit(15)) && (Reg16_d.Bit(15) != ans.Bit(15));
FlagS = (ushort)(ans & 0xFFFF) > 32767;
FlagZ = (ans & 0xFFFF) == 0;
Flag3 = (ans & 0x0800) != 0;
Flag5 = (ans & 0x2000) != 0;
// redo for half carry flag
Reg16_d &= 0xFFF;
Reg16_d -= ((Reg16_s & 0xFFF) + c);
FlagH = Reg16_d.Bit(12);
Regs[dest_l] = (ushort)(ans & 0xFF);
Regs[dest_h] = (ushort)((ans >> 8) & 0xFF);
}
public void ADC_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8);
int Reg16_s = Regs[src_l] | (Regs[src_h] << 8);
int ans = Reg16_d + Reg16_s + (FlagC ? 1 : 0);
FlagH = ((Reg16_d & 0xFFF) + (Reg16_s & 0xFFF) + (FlagC ? 1 : 0)) > 0xFFF;
FlagN = false;
FlagC = ans.Bit(16);
FlagP = (Reg16_d.Bit(15) == Reg16_s.Bit(15)) && (Reg16_d.Bit(15) != ans.Bit(15));
FlagS = (ans & 0xFFFF) > 32767;
FlagZ = (ans & 0xFFFF) == 0;
Flag3 = (ans & 0x0800) != 0;
Flag5 = (ans & 0x2000) != 0;
Regs[dest_l] = (ushort)(ans & 0xFF);
Regs[dest_h] = (ushort)((ans >> 8) & 0xFF);
}
public void NEG_8_Func(ushort src)
{
int Reg16_d = 0;
Reg16_d -= Regs[src];
FlagC = Regs[src] != 0x0;
FlagZ = (Reg16_d & 0xFF) == 0;
FlagP = Regs[src] == 0x80;
FlagS = (Reg16_d & 0xFF) > 127;
ushort ans = (ushort)(Reg16_d & 0xFF);
// redo for half carry flag
Reg16_d = 0;
Reg16_d -= (Regs[src] & 0xF);
FlagH = Reg16_d.Bit(4);
Regs[src] = ans;
FlagN = true;
Flag3 = (ans & 0x08) != 0;
Flag5 = (ans & 0x20) != 0;
}
public void RRD_Func(ushort dest, ushort src)
{
ushort temp1 = Regs[src];
ushort temp2 = Regs[dest];
Regs[dest] = (ushort)(((temp1 & 0x0F) << 4) + ((temp2 & 0xF0) >> 4));
Regs[src] = (ushort)((temp1 & 0xF0) + (temp2 & 0x0F));
temp1 = Regs[src];
FlagS = temp1 > 127;
FlagZ = temp1 == 0;
FlagH = false;
FlagP = TableParity[temp1];
FlagN = false;
Flag3 = (temp1 & 0x08) != 0;
Flag5 = (temp1 & 0x20) != 0;
}
public void RLD_Func(ushort dest, ushort src)
{
ushort temp1 = Regs[src];
ushort temp2 = Regs[dest];
Regs[dest] = (ushort)((temp1 & 0x0F) + ((temp2 & 0x0F) << 4));
Regs[src] = (ushort)((temp1 & 0xF0) + ((temp2 & 0xF0) >> 4));
temp1 = Regs[src];
FlagS = temp1 > 127;
FlagZ = temp1 == 0;
FlagH = false;
FlagP = TableParity[temp1];
FlagN = false;
Flag3 = (temp1 & 0x08) != 0;
Flag5 = (temp1 & 0x20) != 0;
}
// sets flags for LD/R
public void SET_FL_LD_Func()
{
FlagP = (Regs[C] | (Regs[B] << 8)) != 0;
FlagH = false;
FlagN = false;
Flag5 = ((Regs[ALU] + Regs[A]) & 0x02) != 0;
Flag3 = ((Regs[ALU] + Regs[A]) & 0x08) != 0;
}
// set flags for CP/R
public void SET_FL_CP_Func()
{
int Reg8_d = Regs[A];
int Reg8_s = Regs[ALU];
// get half carry flag
byte temp = (byte)((Reg8_d & 0xF) - (Reg8_s & 0xF));
FlagH = temp.Bit(4);
temp = (byte)(Reg8_d - Reg8_s);
FlagN = true;
FlagZ = temp == 0;
FlagS = temp > 127;
FlagP = (Regs[C] | (Regs[B] << 8)) != 0;
temp = (byte)(Reg8_d - Reg8_s - (FlagH ? 1 : 0));
Flag5 = (temp & 0x02) != 0;
Flag3 = (temp & 0x08) != 0;
}
}
}

View File

@ -0,0 +1,134 @@
using System.Runtime.InteropServices;
using System;
namespace BizHawk.Emulation.Common.Components.Z80A
{
public partial class Z80A
{
// registers
// note these are not constants. When shadows are used, they will be changed accordingly
public ushort PCl = 0;
public ushort PCh = 1;
public ushort SPl = 2;
public ushort SPh = 3;
public ushort A = 4;
public ushort F = 5;
public ushort B = 6;
public ushort C = 7;
public ushort D = 8;
public ushort E = 9;
public ushort H = 10;
public ushort L = 11;
public ushort W = 12;
public ushort Z = 13;
public ushort Aim = 14; // use this indicator for RLCA etc., since the Z flag is reset on those
public ushort Ixl = 15;
public ushort Ixh = 16;
public ushort Iyl = 17;
public ushort Iyh = 18;
public ushort Int = 19;
public ushort R = 20;
public ushort I = 21;
public ushort ZERO = 22; // it is convenient to have a register that is always zero, to reuse instructions
public ushort ALU = 23; // This will be temporary arthimatic storage
// shadow registers
public ushort A_s = 24;
public ushort F_s = 25;
public ushort B_s = 26;
public ushort C_s = 27;
public ushort D_s = 28;
public ushort E_s = 29;
public ushort H_s = 30;
public ushort L_s = 31;
public ushort[] Regs = new ushort[36];
// The Z80 also has ports to communicate with external components
public bool FlagI;
public bool FlagC
{
get { return (Regs[5] & 0x01) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x01) | (value ? 0x01 : 0x00)); }
}
public bool FlagN
{
get { return (Regs[5] & 0x02) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x02) | (value ? 0x02 : 0x00)); }
}
public bool FlagP
{
get { return (Regs[5] & 0x04) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x04) | (value ? 0x04 : 0x00)); }
}
public bool Flag3
{
get { return (Regs[5] & 0x08) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x08) | (value ? 0x08 : 0x00)); }
}
public bool FlagH
{
get { return (Regs[5] & 0x10) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x10) | (value ? 0x10 : 0x00)); }
}
public bool Flag5
{
get { return (Regs[5] & 0x20) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x20) | (value ? 0x20 : 0x00)); }
}
public bool FlagZ
{
get { return (Regs[5] & 0x40) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x40) | (value ? 0x40 : 0x00)); }
}
public bool FlagS
{
get { return (Regs[5] & 0x80) != 0; }
set { Regs[5] = (ushort)((Regs[5] & ~0x80) | (value ? 0x80 : 0x00)); }
}
public ushort RegPC
{
get { return (ushort)(Regs[0] | (Regs[1] << 8)); }
set
{
Regs[0] = (ushort)(value & 0xFF);
Regs[1] = (ushort)((value >> 8) & 0xFF);
}
}
private void ResetRegisters()
{
for (int i=0; i < 14; i++)
{
Regs[i] = 0;
}
}
private bool[] TableParity;
private void InitTableParity()
{
TableParity = new bool[256];
for (int i = 0; i < 256; ++i)
{
int Bits = 0;
for (int j = 0; j < 8; ++j)
{
Bits += (i >> j) & 1;
}
TableParity[i] = (Bits & 1) == 0;
}
}
}
}

View File

@ -0,0 +1,590 @@
using System;
namespace BizHawk.Emulation.Common.Components.Z80A
{
public partial class Z80A
{
// this contains the vectors of instrcution operations
// NOTE: This list is NOT confirmed accurate for each individual cycle
private void NOP_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
OP };
}
// NOTE: In a real Z80, this operation just flips a switch to choose between 2 registers
// but it's simpler to emulate just by exchanging the register with it's shadow
private void EXCH_()
{
cur_instr = new ushort[]
{EXCH,
IDLE,
IDLE,
OP };
}
private void EXX_()
{
cur_instr = new ushort[]
{EXX,
IDLE,
IDLE,
OP };
}
// this exchanges 2 16 bit registers
private void EXCH_16_(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{EXCH_16, dest_l, dest_h, src_l, src_h,
IDLE,
IDLE,
OP };
}
private void INC_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
INC16, src_l, src_h,
IDLE,
OP };
}
private void DEC_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, src_l, src_h,
IDLE,
IDLE,
OP };
}
// this is done in two steps technically, but the flags don't work out using existing funcitons
// so let's use a different function since it's an internal operation anyway
private void ADD_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
TR16, Z, W, dest_l, dest_h,
INC16, Z, W,
IDLE,
IDLE,
ADD16, dest_l, dest_h, src_l, src_h,
IDLE,
IDLE,
OP };
}
private void REG_OP(ushort operation, ushort dest, ushort src)
{
cur_instr = new ushort[]
{operation, dest, src,
IDLE,
IDLE,
OP };
}
// Operations using the I and R registers take one T-cycle longer
private void REG_OP_IR(ushort operation, ushort dest, ushort src)
{
cur_instr = new ushort[]
{operation, dest, src,
IDLE,
IDLE,
IDLE,
OP };
}
// note: do not use DEC here since no flags are affected by this operation
private void DJNZ_()
{
if ((Regs[B] - 1) != 0)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
ASGN, B, (ushort)((Regs[B] - 1) & 0xFF),
IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
ASGN, W, 0,
IDLE,
ADDS, PCl, PCh, Z, W,
TR16, Z, W, PCl, PCh,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
ASGN, B, (ushort)((Regs[B] - 1) & 0xFF),
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
OP };
}
}
private void HALT_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
HALT };
}
private void JR_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
IDLE,
ASGN, W, 0,
IDLE,
ADDS, PCl, PCh, Z, W,
TR16, Z, W, PCl, PCh,
IDLE,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
OP };
}
}
private void JP_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
TR16, PCl, PCh, Z, W,
IDLE,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
INC16, PCl, PCh,
IDLE,
IDLE,
OP };
}
}
private void RET_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
TR16, PCl, PCh, Z, W,
OP };
}
private void RETI_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
TR16, PCl, PCh, Z, W,
OP };
}
private void RETN_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
EI_RETN,
TR16, PCl, PCh, Z, W,
OP };
}
private void RET_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, SPl, SPh,
INC16, SPl, SPh,
IDLE,
IDLE,
RD, W, SPl, SPh,
INC16, SPl, SPh,
IDLE,
TR16, PCl, PCh, Z, W,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
IDLE,
OP };
}
}
private void CALL_COND(bool cond)
{
if (cond)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
INC16, PCl, PCh,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, PCh,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
TR, PCl, Z,
TR, PCh, W,
OP };
}
else
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
OP };
}
}
private void INT_OP(ushort operation, ushort src)
{
cur_instr = new ushort[]
{operation, src,
IDLE,
IDLE,
OP };
}
private void BIT_OP(ushort operation, ushort bit, ushort src)
{
cur_instr = new ushort[]
{operation, bit, src,
IDLE,
IDLE,
OP };
}
private void PUSH_(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, src_h,
IDLE,
DEC16, SPl, SPh,
IDLE,
WR, SPl, SPh, src_l,
IDLE,
OP };
}
private void POP_(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
RD, src_l, SPl, SPh,
IDLE,
INC16, SPl, SPh,
IDLE,
RD, src_h, SPl, SPh,
IDLE,
INC16, SPl, SPh,
IDLE,
OP };
}
private void RST_(ushort n)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
DEC16, SPl, SPh,
WR, SPl, SPh, PCh,
DEC16, SPl, SPh,
WR, SPl, SPh, PCl,
IDLE,
ASGN, Z, n,
ASGN, W, 0,
TR16, PCl, PCh, Z, W,
OP };
}
private void PREFIX_(ushort src)
{
cur_instr = new ushort[]
{PREFIX, src,
IDLE,
IDLE,
OP };
}
private void PREFETCH_(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{TR16, Z, W, src_l, src_h,
ADDS, Z, W, ALU, ZERO,
IDLE,
OP };
}
private void DI_()
{
cur_instr = new ushort[]
{DI,
IDLE,
IDLE,
OP };
}
private void EI_()
{
cur_instr = new ushort[]
{EI,
IDLE,
IDLE,
OP };
}
private void JP_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{TR, PCl, src_l,
IDLE,
TR, PCh, src_h,
OP };
}
private void LD_SP_16(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
TR, SPl, src_l,
IDLE,
TR, SPh, src_h,
IDLE,
OP };
}
private void JAM_()
{
cur_instr = new ushort[]
{JAM,
IDLE,
IDLE,
IDLE };
}
private void OUT_()
{
cur_instr = new ushort[]
{IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
TR, W, A,
OUT, ALU, A,
TR, Z, ALU,
INC16, Z, ALU,
IDLE,
IDLE,
OP};
}
private void OUT_REG_(ushort dest, ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
OUT, dest, src,
IDLE,
TR16, Z, W, C, B,
INC16, Z, W,
IDLE,
OP};
}
private void IN_()
{
cur_instr = new ushort[]
{IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
TR, W, A,
IN, A, ALU,
TR, Z, ALU,
INC16, Z, W,
IDLE,
IDLE,
OP};
}
private void IN_REG_(ushort dest, ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IN, dest, src,
IDLE,
TR16, Z, W, C, B,
INC16, Z, W,
IDLE,
OP};
}
private void REG_OP_16_(ushort op, ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
TR16, Z, W, dest_l, dest_h,
INC16, Z, W,
IDLE,
op, dest_l, dest_h, src_l, src_h,
IDLE,
IDLE,
OP};
}
private void INT_MODE_(ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
INT_MODE, src,
OP };
}
private void RRD_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
IDLE,
TR16, Z, W, L, H,
IDLE,
IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
RRD, ALU, A,
IDLE,
WR, Z, W, ALU,
IDLE,
INC16, Z, W,
IDLE,
IDLE,
OP };
}
private void RLD_()
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
IDLE,
TR16, Z, W, L, H,
IDLE,
IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
RLD, ALU, A,
IDLE,
WR, Z, W, ALU,
IDLE,
INC16, Z, W,
IDLE,
IDLE,
OP };
}
}
}

View File

@ -0,0 +1,478 @@
namespace BizHawk.Emulation.Common.Components.Z80A
{
public partial class Z80A
{
private void INT_OP_IND(ushort operation, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
operation, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
private void BIT_OP_IND(ushort operation, ushort bit, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
operation, bit, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
// Note that this operation uses I_BIT, same as indexed BIT.
// This is where the strange behaviour in Flag bits 3 and 5 come from.
// normally WZ contain I* + n when doing I_BIT ops, but here we use that code path
// even though WZ is not assigned to, letting it's value from other operations show through
private void BIT_TE_IND(ushort operation, ushort bit, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
I_BIT, bit, ALU,
IDLE,
OP };
}
private void REG_OP_IND_INC(ushort operation, ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
operation, dest, ALU,
INC16, src_l, src_h,
OP };
}
private void REG_OP_IND(ushort operation, ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR16, Z, W, src_l, src_h,
RD, ALU, Z, W,
INC16, Z, W,
operation, dest, ALU,
OP };
}
private void LD_16_IND_nn(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
WR, Z, W, src_l,
IDLE,
INC16, Z, W,
IDLE,
WR, Z, W, src_h,
IDLE,
OP };
}
private void LD_IND_16_nn(ushort dest_l, ushort dest_h)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, dest_l, Z, W,
IDLE,
INC16, Z, W,
IDLE,
RD, dest_h, Z, W,
IDLE,
OP };
}
private void LD_8_IND_nn(ushort src)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
WR, Z, W, src,
INC16, Z, W,
TR, W, A,
OP };
}
private void LD_IND_8_nn(ushort dest)
{
cur_instr = new ushort[]
{IDLE,
RD, Z, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, W, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
RD, dest, Z, W,
IDLE,
INC16, Z, W,
OP };
}
private void LD_8_IND(ushort dest_l, ushort dest_h, ushort src)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
TR16, Z, W, dest_l, dest_h,
WR, Z, W, src,
INC16, Z, W,
TR, W, A,
OP };
}
private void LD_8_IND_IND(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
INC16, src_l, src_h,
IDLE,
WR, dest_l, dest_h, ALU,
IDLE,
OP };
}
private void LD_IND_8_INC(ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, dest, src_l, src_h,
IDLE,
INC16, src_l, src_h,
OP };
}
private void LD_IND_8_DEC(ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, dest, src_l, src_h,
IDLE,
DEC16, src_l, src_h,
IDLE,
OP };
}
private void LD_IND_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, dest_l, src_l, src_h,
IDLE,
INC16, src_l, src_h,
RD, dest_h, src_l, src_h,
IDLE,
INC16, src_l, src_h,
OP };
}
private void INC_8_IND(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
INC8, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
private void DEC_8_IND(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, src_l, src_h,
IDLE,
DEC8, ALU,
IDLE,
WR, src_l, src_h, ALU,
IDLE,
IDLE,
OP };
}
// NOTE: WZ implied for the wollowing 3 functions
private void I_INT_OP(ushort operation, ushort dest)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
operation, ALU,
IDLE,
WR, Z, W, ALU,
IDLE,
TR, dest, ALU,
IDLE,
OP };
}
private void I_BIT_OP(ushort operation, ushort bit, ushort dest)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
operation, bit, ALU,
IDLE,
WR, Z, W, ALU,
IDLE,
TR, dest, ALU,
IDLE,
OP };
}
private void I_BIT_TE(ushort bit)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
RD, ALU, Z, W,
IDLE,
I_BIT, bit, ALU,
IDLE,
OP };
}
private void I_OP_n(ushort operation, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, src_l, src_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
RD, ALU, Z, W,
IDLE,
IDLE,
operation, ALU,
IDLE,
IDLE,
IDLE,
WR, Z, W, ALU,
IDLE,
OP };
}
private void I_OP_n_n(ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, src_l, src_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
RD, ALU, PCl, PCh,
INC16, PCl, PCh,
IDLE,
WR, Z, W, ALU,
IDLE,
OP };
}
private void I_REG_OP_IND_n(ushort operation, ushort dest, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, src_l, src_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
RD, ALU, Z, W,
IDLE,
operation, dest, ALU,
IDLE,
OP };
}
private void I_LD_8_IND_n(ushort dest_l, ushort dest_h, ushort src)
{
cur_instr = new ushort[]
{IDLE,
RD, ALU, PCl, PCh,
IDLE,
INC16, PCl, PCh,
IDLE,
TR16, Z, W, dest_l, dest_h,
IDLE,
ADDS, Z, W, ALU, ZERO,
IDLE,
WR, Z, W, src,
IDLE,
IDLE,
IDLE,
IDLE,
OP };
}
private void LD_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{RD, ALU, L, H,
IDLE,
WR, E, D, ALU,
IDLE,
operation, L, H,
IDLE,
operation, E, D,
IDLE,
DEC16, C, B,
SET_FL_LD,
IDLE,
OP_R, 0, operation, repeat_instr };
}
private void CP_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, ALU, L, H,
operation, L, H,
IDLE,
IDLE,
DEC16, C, B,
SET_FL_CP,
IDLE,
operation, Z, W,
IDLE,
OP_R, 1, operation, repeat_instr };
}
private void IN_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{IN, ALU, C,
IDLE,
WR, L, H, ALU,
IDLE,
operation, L, H,
IDLE,
TR16, Z, W, C, B,
operation, Z, W,
IDLE,
DEC8, B,
IDLE,
OP_R, 2, operation, repeat_instr };
}
private void OUT_OP_R(ushort operation, ushort repeat_instr)
{
cur_instr = new ushort[]
{RD, ALU, L, H,
IDLE,
OUT, C, ALU,
IDLE,
IDLE,
operation, L, H,
DEC8, B,
IDLE,
TR16, Z, W, C, B,
operation, Z, W,
IDLE,
OP_R, 3, operation, repeat_instr };
}
// this is an indirect change of a a 16 bit register with memory
private void EXCH_16_IND_(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
{
cur_instr = new ushort[]
{IDLE,
IDLE,
RD, Z, dest_l, dest_h,
IDLE,
IDLE,
I_RD, W, dest_l, dest_h, 1,
IDLE,
IDLE,
WR, dest_l, dest_h, src_l,
IDLE,
IDLE,
I_WR, dest_l, dest_h, 1, src_h,
IDLE,
IDLE,
TR16, src_l, src_h, Z, W,
IDLE,
IDLE,
IDLE,
OP };
}
}
}

View File

@ -0,0 +1,697 @@
using System;
using System.Globalization;
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Common.NumberExtensions;
// Z80A CPU
namespace BizHawk.Emulation.Common.Components.Z80A
{
public sealed partial class Z80A
{
// operations that can take place in an instruction
public const ushort IDLE = 0;
public const ushort OP = 1;
public const ushort OP_R = 2; // used for repeating operations
public const ushort HALT = 3;
public const ushort RD = 4;
public const ushort WR = 5;
public const ushort I_RD = 6;
public const ushort I_WR = 7;
public const ushort TR = 8;
public const ushort TR16 = 9;
public const ushort ADD16 = 10;
public const ushort ADD8 = 11;
public const ushort SUB8 = 12;
public const ushort ADC8 = 13;
public const ushort SBC8 = 14;
public const ushort SBC16 = 15;
public const ushort ADC16 = 16;
public const ushort INC16 = 17;
public const ushort INC8 = 18;
public const ushort DEC16 = 19;
public const ushort DEC8 = 20;
public const ushort RLC = 21;
public const ushort RL = 22;
public const ushort RRC = 23;
public const ushort RR = 24;
public const ushort CPL = 25;
public const ushort DA = 26;
public const ushort SCF = 27;
public const ushort CCF = 28;
public const ushort AND8 = 29;
public const ushort XOR8 = 30;
public const ushort OR8 = 31;
public const ushort CP8 = 32;
public const ushort SLA = 33;
public const ushort SRA = 34;
public const ushort SRL = 35;
public const ushort SLL = 36;
public const ushort BIT = 37;
public const ushort RES = 38;
public const ushort SET = 39;
public const ushort EI = 40;
public const ushort DI = 41;
public const ushort EXCH = 42;
public const ushort EXX = 43;
public const ushort EXCH_16 = 44;
public const ushort PREFIX = 45;
public const ushort PREFETCH = 46;
public const ushort ASGN = 47;
public const ushort ADDS = 48; // signed 16 bit operation used in 2 instructions
public const ushort JAM = 49; // all undocumented opcodes jam the machine
public const ushort EI_RETN = 50;
public const ushort EI_RETI = 51; // reti has no delay in interrupt enable
public const ushort OUT = 52;
public const ushort IN = 53;
public const ushort NEG = 54;
public const ushort INT_MODE = 55;
public const ushort RRD = 56;
public const ushort RLD = 57;
public const ushort SET_FL_LD = 58;
public const ushort SET_FL_CP = 59;
public const ushort I_BIT = 60;
public const ushort HL_BIT = 61;
public Z80A()
{
Reset();
InitTableParity();
}
public void Reset()
{
ResetRegisters();
ResetInterrupts();
TotalExecutedCycles = 0;
cur_instr = new ushort[] { OP };
NO_prefix = true;
}
public IMemoryCallbackSystem MemoryCallbacks { get; set; }
// Memory Access
public Func<ushort, bool, byte> FetchMemory;
public Func<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
public Func<ushort, byte> PeekMemory;
public Func<ushort, byte> DummyReadMemory;
// Hardware I/O Port Access
public Func<ushort, byte> ReadHardware;
public Action<ushort, byte> WriteHardware;
//this only calls when the first byte of an instruction is fetched.
public Action<ushort> OnExecFetch;
public void UnregisterMemoryMapper()
{
ReadMemory = null;
WriteMemory = null;
PeekMemory = null;
DummyReadMemory = null;
ReadHardware = null;
WriteHardware = null;
}
public void SetCallbacks
(
Func<ushort, byte> ReadMemory,
Func<ushort, byte> DummyReadMemory,
Func<ushort, byte> PeekMemory,
Action<ushort, byte> WriteMemory,
Func<ushort, byte> ReadHardware,
Action<ushort, byte> WriteHardware
)
{
this.ReadMemory = ReadMemory;
this.DummyReadMemory = DummyReadMemory;
this.PeekMemory = PeekMemory;
this.WriteMemory = WriteMemory;
this.ReadHardware = ReadHardware;
this.WriteHardware = WriteHardware;
}
// Execute instructions
public void ExecuteOne()
{
switch (cur_instr[instr_pntr++])
{
case IDLE:
// do nothing
break;
case OP:
// Read the opcode of the next instruction
if (EI_pending > 0 && NO_prefix)
{
EI_pending--;
if (EI_pending == 0)
{
IFF1 = IFF2 = true;
}
}
// Process interrupt requests.
if (nonMaskableInterruptPending && NO_prefix)
{
nonMaskableInterruptPending = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo
{
Disassembly = "====NMI====",
RegisterInfo = ""
});
}
iff2 = iff1;
iff1 = false;
NMI_();
NMICallback();
}
else if (iff1 && FlagI && NO_prefix)
{
iff1 = iff2 = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo
{
Disassembly = "====IRQ====",
RegisterInfo = ""
});
}
switch (interruptMode)
{
case 0:
// Requires something to be pushed onto the data bus
// we'll assume it's a zero for now
INTERRUPT_0(0);
break;
case 1:
INTERRUPT_1();
break;
case 2:
// Low byte of interrupt vector comes from data bus
// We'll assume it's zero for now
INTERRUPT_2(0);
break;
}
IRQCallback();
}
else
{
if (OnExecFetch != null) OnExecFetch(RegPC);
if (TraceCallback != null && NO_prefix) TraceCallback(State());
FetchInstruction(ReadMemory(RegPC++));
}
instr_pntr = 0;
Regs[R]++;
break;
case OP_R:
// determine if we repeat based on what operation we are doing
// single execution versions also come here, but never repeat
ushort temp1 = cur_instr[instr_pntr++];
ushort temp2 = cur_instr[instr_pntr++];
ushort temp3 = cur_instr[instr_pntr++];
bool repeat = false;
int Reg16_d = Regs[C] | (Regs[B] << 8);
switch (temp1)
{
case 0:
repeat = Reg16_d != 0;
break;
case 1:
repeat = (Reg16_d != 0) && !FlagZ;
break;
case 2:
repeat = Regs[B] != 0;
break;
case 3:
repeat = Regs[B] != 0;
break;
}
// if we repeat, we do a 5 cycle refresh which decrements PC by 2
// if we don't repeat, continue on as a normal opcode fetch
if (repeat && temp3 > 0)
{
instr_pntr = 0;
cur_instr = new ushort[]
{IDLE,
DEC16, PCl, PCh,
IDLE,
DEC16, PCl, PCh,
OP };
// adjust WZ register accordingly
switch (temp1)
{
case 0:
// TEST: PC before or after the instruction?
Regs[Z] = Regs[PCl];
Regs[W] = Regs[PCh];
INC16_Func(Z, W);
break;
case 1:
// TEST: PC before or after the instruction?
Regs[Z] = Regs[PCl];
Regs[W] = Regs[PCh];
INC16_Func(Z, W);
break;
case 2:
// Nothing
break;
case 3:
// Nothing
break;
}
}
else
{
// Interrupts can occur at this point, so process them accordingly
// Read the opcode of the next instruction
if (EI_pending > 0)
{
EI_pending--;
if (EI_pending == 0)
{
IFF1 = IFF2 = true;
}
}
// Process interrupt requests.
if (nonMaskableInterruptPending && NO_prefix)
{
nonMaskableInterruptPending = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo
{
Disassembly = "====NMI====",
RegisterInfo = ""
});
}
iff2 = iff1;
iff1 = false;
NMI_();
NMICallback();
}
else if (iff1 && FlagI && NO_prefix)
{
iff1 = iff2 = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo
{
Disassembly = "====IRQ====",
RegisterInfo = ""
});
}
switch (interruptMode)
{
case 0:
// Requires something to be pushed onto the data bus
// we'll assume it's a zero for now
INTERRUPT_0(0);
break;
case 1:
INTERRUPT_1();
break;
case 2:
// Low byte of interrupt vector comes from data bus
// We'll assume it's zero for now
INTERRUPT_2(0);
break;
}
IRQCallback();
}
else
{
if (OnExecFetch != null) OnExecFetch(RegPC);
if (TraceCallback != null) TraceCallback(State());
FetchInstruction(ReadMemory(RegPC++));
instr_pntr = 0;
Regs[R]++;
}
}
break;
case HALT:
halted = true;
if (EI_pending > 0 && NO_prefix)
{
EI_pending--;
if (EI_pending == 0)
{
IFF1 = IFF2 = true;
}
}
// Process interrupt requests.
if (nonMaskableInterruptPending && NO_prefix)
{
nonMaskableInterruptPending = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo
{
Disassembly = "====NMI====",
RegisterInfo = ""
});
}
iff2 = iff1;
iff1 = false;
NMI_();
NMICallback();
}
else if (iff1 && FlagI && NO_prefix)
{
iff1 = iff2 = false;
if (TraceCallback != null)
{
TraceCallback(new TraceInfo
{
Disassembly = "====IRQ====",
RegisterInfo = ""
});
}
switch (interruptMode)
{
case 0:
// Requires something to be pushed onto the data bus
// we'll assume it's a zero for now
INTERRUPT_0(0);
break;
case 1:
INTERRUPT_1();
break;
case 2:
// Low byte of interrupt vector comes from data bus
// We'll assume it's zero for now
INTERRUPT_2(0);
break;
}
IRQCallback();
}
else
{
instr_pntr = 0;
Regs[R]++;
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
HALT };
}
break;
case RD:
Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case WR:
Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case I_RD:
I_Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case I_WR:
I_Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case TR:
TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case TR16:
TR16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADD16:
ADD16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADD8:
ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SUB8:
SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADC8:
ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADC16:
ADC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SBC8:
SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SBC16:
SBC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case INC16:
INC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case INC8:
INC8_Func(cur_instr[instr_pntr++]);
break;
case DEC16:
DEC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case DEC8:
DEC8_Func(cur_instr[instr_pntr++]);
break;
case RLC:
RLC_Func(cur_instr[instr_pntr++]);
break;
case RL:
RL_Func(cur_instr[instr_pntr++]);
break;
case RRC:
RRC_Func(cur_instr[instr_pntr++]);
break;
case RR:
RR_Func(cur_instr[instr_pntr++]);
break;
case CPL:
CPL_Func(cur_instr[instr_pntr++]);
break;
case DA:
DA_Func(cur_instr[instr_pntr++]);
break;
case SCF:
SCF_Func(cur_instr[instr_pntr++]);
break;
case CCF:
CCF_Func(cur_instr[instr_pntr++]);
break;
case AND8:
AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case XOR8:
XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case OR8:
OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case CP8:
CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SLA:
SLA_Func(cur_instr[instr_pntr++]);
break;
case SRA:
SRA_Func(cur_instr[instr_pntr++]);
break;
case SRL:
SRL_Func(cur_instr[instr_pntr++]);
break;
case SLL:
SLL_Func(cur_instr[instr_pntr++]);
break;
case BIT:
BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case I_BIT:
I_BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case RES:
RES_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SET:
SET_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case EI:
EI_pending = 2;
break;
case DI:
IFF1 = IFF2 = false;
EI_pending = 0;
break;
case EXCH:
EXCH_16_Func(F_s, A_s, F, A);
break;
case EXX:
EXCH_16_Func(C_s, B_s, C, B);
EXCH_16_Func(E_s, D_s, E, D);
EXCH_16_Func(L_s, H_s, L, H);
break;
case EXCH_16:
EXCH_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case PREFIX:
ushort prefix_src = cur_instr[instr_pntr++];
NO_prefix = false;
if (prefix_src == CBpre) { CB_prefix = true; }
if (prefix_src == EXTDpre) { EXTD_prefix = true; }
if (prefix_src == IXpre) { IX_prefix = true; }
if (prefix_src == IYpre) { IY_prefix = true; }
if (prefix_src == IXCBpre) { IXCB_prefix = true; IXCB_prefetch = true; }
if (prefix_src == IYCBpre) { IYCB_prefix = true; IYCB_prefetch = true; }
Regs[R]++;
break;
case ASGN:
ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case ADDS:
ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case JAM:
jammed = true;
instr_pntr--;
break;
case EI_RETI:
// NOTE: This is needed for systems using multiple interrupt sources, it triggers the next interrupt
// Not currently implemented here
break;
case EI_RETN:
EI_pending = 1;
break;
case OUT:
OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case IN:
IN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case NEG:
NEG_8_Func(cur_instr[instr_pntr++]);
break;
case INT_MODE:
interruptMode = cur_instr[instr_pntr++];
break;
case RRD:
RRD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case RLD:
RLD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
case SET_FL_LD:
SET_FL_LD_Func();
break;
case SET_FL_CP:
SET_FL_CP_Func();
break;
}
totalExecutedCycles++;
}
// tracer stuff
public Action<TraceInfo> TraceCallback;
public string TraceHeader
{
get { return "Z80A: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)"; }
}
public TraceInfo State(bool disassemble = true)
{
ushort bytes_read = 0;
string disasm = disassemble ? Disassemble(RegPC, ReadMemory, out bytes_read) : "---";
string byte_code = null;
for (ushort i = 0; i < bytes_read; i++)
{
byte_code += ReadMemory((ushort)(RegPC + i)).ToHexString(2);
if (i < (bytes_read - 1))
{
byte_code += " ";
}
}
return new TraceInfo
{
Disassembly = string.Format(
"{0:X4}: {1} {2}",
RegPC,
byte_code.PadRight(12),
disasm.PadRight(26)),
RegisterInfo = string.Format(
"AF:{0:X4} BC:{1:X4} DE:{2:X4} HL:{3:X4} IX:{4:X4} IY:{5:X4} SP:{6:X4} Cy:{7} {8}{9}{10}{11}{12}{13}{14}{15}{16}",
(Regs[A] << 8) + Regs[F],
(Regs[B] << 8) + Regs[C],
(Regs[D] << 8) + Regs[E],
(Regs[H] << 8) + Regs[L],
(Regs[Ixh] << 8) + Regs[Ixl],
(Regs[Iyh] << 8) + Regs[Iyl],
Regs[SPl] | (Regs[SPh] << 8),
TotalExecutedCycles,
FlagC ? "C" : "c",
FlagN ? "N" : "n",
FlagP ? "P" : "p",
Flag3 ? "3" : "-",
FlagH ? "H" : "h",
Flag5 ? "5" : "-",
FlagZ ? "Z" : "z",
FlagS ? "S" : "s",
FlagI ? "E" : "e")
};
}
// State Save/Load
public void SyncState(Serializer ser)
{
ser.BeginSection("Z80A");
ser.Sync("Regs", ref Regs, false);
ser.Sync("NMI", ref nonMaskableInterrupt);
ser.Sync("NMIPending", ref nonMaskableInterruptPending);
ser.Sync("IM", ref interruptMode);
ser.Sync("IFF1", ref iff1);
ser.Sync("IFF2", ref iff2);
ser.Sync("Halted", ref halted);
ser.Sync("ExecutedCycles", ref totalExecutedCycles);
ser.Sync("EI_pending", ref EI_pending);
ser.Sync("instruction_pointer", ref instr_pntr);
ser.Sync("current instruction", ref cur_instr, false);
ser.Sync("opcode", ref opcode);
ser.Sync("jammped", ref jammed);
ser.Sync("FlagI", ref FlagI);
ser.Sync("NO Preifx", ref NO_prefix);
ser.Sync("CB Preifx", ref CB_prefix);
ser.Sync("IX_prefix", ref IX_prefix);
ser.Sync("IY_prefix", ref IY_prefix);
ser.Sync("IXCB_prefix", ref IXCB_prefix);
ser.Sync("IYCB_prefix", ref IYCB_prefix);
ser.Sync("EXTD_prefix", ref EXTD_prefix);
ser.Sync("IXCB_prefetch", ref IXCB_prefetch);
ser.Sync("IYCB_prefetch", ref IYCB_prefetch);
ser.Sync("PF", ref PF);
ser.EndSection();
}
}
}