Add files via upload
This commit is contained in:
parent
ff13009e97
commit
12c46db790
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue