Add OPL4 playback and analyzer support
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent masks for the Z80 flags register
|
||||
/// </summary>
|
||||
public static class CpuFlags
|
||||
{
|
||||
#region Flags
|
||||
|
||||
/// <summary>
|
||||
/// Sign Flag
|
||||
/// [Set if the 2-complement value is negative (copy of MSB)]
|
||||
/// </summary>
|
||||
public const byte S = 0x80;
|
||||
|
||||
/// <summary>
|
||||
/// Zero Flag
|
||||
/// [Set if the value is zero]
|
||||
/// </summary>
|
||||
public const byte Z = 0x40;
|
||||
|
||||
/// <summary>
|
||||
/// Undocumented flag F5
|
||||
/// </summary>
|
||||
public const byte F5 = 0x20;
|
||||
|
||||
/// <summary>
|
||||
/// Half Carry Flag
|
||||
/// [Carry from bit 3 to bit 4]
|
||||
/// </summary>
|
||||
public const byte H = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Undocumented flag F3
|
||||
/// </summary>
|
||||
public const byte F3 = 0x08;
|
||||
|
||||
/// <summary>
|
||||
/// P/V - Parity/Overflow Flag
|
||||
/// [Parity set if even number of bits set.
|
||||
/// Overflow set if the 2-complement result does not fit in the register]
|
||||
/// </summary>
|
||||
public const byte P = 0x04;
|
||||
|
||||
/// <summary>
|
||||
/// Add/Subtract Flag
|
||||
/// [Set if the last operation was a subtraction]
|
||||
/// </summary>
|
||||
public const byte N = 0x02;
|
||||
|
||||
/// <summary>
|
||||
/// Carry Flag
|
||||
/// [Set if the result did not fit in the register]
|
||||
/// </summary>
|
||||
public const byte C = 0x01;
|
||||
|
||||
#endregion Flags
|
||||
|
||||
|
||||
#region Inverted Masks
|
||||
|
||||
public const byte NotS = S ^ 0xFF;
|
||||
public const byte NotZ = Z ^ 0xFF;
|
||||
public const byte NotF5 = F5 ^ 0xFF;
|
||||
public const byte NotH = H ^ 0xFF;
|
||||
public const byte NotF3 = F3 ^ 0xFF;
|
||||
public const byte NotP = P ^ 0xFF;
|
||||
public const byte NotN = N ^ 0xFF;
|
||||
public const byte NotC = C ^ 0xFF;
|
||||
|
||||
#endregion Inverted Masks
|
||||
|
||||
|
||||
#region Internal flag sets (used by engine)
|
||||
|
||||
internal const byte F3F5 = F3 | F5;
|
||||
internal const byte SF3F5 = S | F3 | F5;
|
||||
internal const byte PCF3F5 = P | C | F3 | F5;
|
||||
internal const byte HNCF3F5 = H | N | C | F3 | F5;
|
||||
internal const byte HPNF3F5 = H | P | N | F3 | F5;
|
||||
internal const byte HC = H | C;
|
||||
internal const byte SZP = S | Z | P;
|
||||
internal const byte SZPC = S | Z | P | C;
|
||||
internal const byte HN = H | N;
|
||||
|
||||
internal const byte NotF3F5 = F3F5 ^ 0xFF;
|
||||
internal const byte NotSF3F5 = SF3F5 ^ 0xFF;
|
||||
internal const byte NotPCF3F5 = PCF3F5 ^ 0xFF;
|
||||
internal const byte NotHNCF3F5 = HNCF3F5 ^ 0xFF;
|
||||
internal const byte NotHPNF3F5 = HPNF3F5 ^ 0xFF;
|
||||
internal const byte NotHC = HC ^ 0xFF;
|
||||
internal const byte NotSZP = SZP ^ 0xFF;
|
||||
internal const byte NotSZPC = SZPC ^ 0xFF;
|
||||
internal const byte NotHN = HN ^ 0xFF;
|
||||
|
||||
#endregion Internal flag sets (used by engine)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu
|
||||
{
|
||||
public enum CpuModeEx
|
||||
{
|
||||
None = 0,
|
||||
Cb,
|
||||
Ed,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu
|
||||
{
|
||||
public enum CpuModeIndex
|
||||
{
|
||||
None = 0,
|
||||
Ix,
|
||||
Iy,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [registers part]
|
||||
* Date: 18.03.2007
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using ZXMAK2.Engine.Cpu.Processor;
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public sealed class CpuRegs
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public ushort AF = 0;
|
||||
[FieldOffset(2)]
|
||||
public ushort BC = 0;
|
||||
[FieldOffset(4)]
|
||||
public ushort DE = 0;
|
||||
[FieldOffset(6)]
|
||||
public ushort HL = 0;
|
||||
[FieldOffset(8)]
|
||||
public ushort _AF = 0;
|
||||
[FieldOffset(10)]
|
||||
public ushort _BC = 0;
|
||||
[FieldOffset(12)]
|
||||
public ushort _DE = 0;
|
||||
[FieldOffset(14)]
|
||||
public ushort _HL = 0;
|
||||
[FieldOffset(16)]
|
||||
public ushort IX = 0;
|
||||
[FieldOffset(18)]
|
||||
public ushort IY = 0;
|
||||
[FieldOffset(20)]
|
||||
public ushort IR = 0;
|
||||
[FieldOffset(22)]
|
||||
public ushort PC = 0;
|
||||
[FieldOffset(24)]
|
||||
public ushort SP = 0;
|
||||
[FieldOffset(26)]
|
||||
public ushort MW = 0; // MEMPTR
|
||||
[FieldOffset(28)]
|
||||
public byte Q = 0; // TODO: Q flags
|
||||
|
||||
|
||||
[FieldOffset(1)]
|
||||
public byte A;
|
||||
[FieldOffset(0)]
|
||||
public byte F;
|
||||
[FieldOffset(3)]
|
||||
public byte B;
|
||||
[FieldOffset(2)]
|
||||
public byte C;
|
||||
[FieldOffset(5)]
|
||||
public byte D;
|
||||
[FieldOffset(4)]
|
||||
public byte E;
|
||||
[FieldOffset(7)]
|
||||
public byte H;
|
||||
[FieldOffset(6)]
|
||||
public byte L;
|
||||
[FieldOffset(17)]
|
||||
public byte XH;
|
||||
[FieldOffset(16)]
|
||||
public byte XL;
|
||||
[FieldOffset(19)]
|
||||
public byte YH;
|
||||
[FieldOffset(18)]
|
||||
public byte YL;
|
||||
[FieldOffset(21)]
|
||||
public byte I;
|
||||
[FieldOffset(20)]
|
||||
public byte R;
|
||||
|
||||
[FieldOffset(27)]
|
||||
public byte MH;
|
||||
[FieldOffset(26)]
|
||||
public byte ML;
|
||||
|
||||
[FieldOffset(23)]
|
||||
public byte PCH = 0;
|
||||
[FieldOffset(22)]
|
||||
public byte PCL = 0;
|
||||
|
||||
|
||||
#region Access Lamda Generators
|
||||
|
||||
// Access field from an object context
|
||||
// makes one native instruction lesser
|
||||
|
||||
internal Func<byte> CreateRegGetter(int r)
|
||||
{
|
||||
return r switch
|
||||
{
|
||||
CpuRegId.B => () => B,
|
||||
CpuRegId.C => () => C,
|
||||
CpuRegId.D => () => D,
|
||||
CpuRegId.E => () => E,
|
||||
CpuRegId.H => () => H,
|
||||
CpuRegId.L => () => L,
|
||||
CpuRegId.A => () => A,
|
||||
CpuRegId.F => () => F,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(r)),
|
||||
};
|
||||
}
|
||||
|
||||
internal Action<byte> CreateRegSetter(int r)
|
||||
{
|
||||
return r switch
|
||||
{
|
||||
CpuRegId.B => arg => B = arg,
|
||||
CpuRegId.C => arg => C = arg,
|
||||
CpuRegId.D => arg => D = arg,
|
||||
CpuRegId.E => arg => E = arg,
|
||||
CpuRegId.H => arg => H = arg,
|
||||
CpuRegId.L => arg => L = arg,
|
||||
CpuRegId.A => arg => A = arg,
|
||||
CpuRegId.F => arg => F = arg,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(r)),
|
||||
};
|
||||
}
|
||||
|
||||
internal Func<ushort> CreatePairGetter(int rr)
|
||||
{
|
||||
return rr switch
|
||||
{
|
||||
CpuRegId.Bc => () => BC,
|
||||
CpuRegId.De => () => DE,
|
||||
CpuRegId.Hl => () => HL,
|
||||
CpuRegId.Sp => () => SP,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rr)),
|
||||
};
|
||||
}
|
||||
|
||||
internal Action<ushort> CreatePairSetter(int rr)
|
||||
{
|
||||
return rr switch
|
||||
{
|
||||
CpuRegId.Bc => arg => BC = arg,
|
||||
CpuRegId.De => arg => DE = arg,
|
||||
CpuRegId.Hl => arg => HL = arg,
|
||||
CpuRegId.Sp => arg => SP = arg,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rr)),
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Access Lamda Generators
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu
|
||||
{
|
||||
public enum CpuType
|
||||
{
|
||||
ZILOG_NMOS = 0,
|
||||
ZILOG_CMOS = 1,
|
||||
NEC_NMOS = 2, // NEC
|
||||
ST_CMOS = 3, // Z84?
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
using ZXMAK2.Engine.Cpu.Processor;
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu
|
||||
{
|
||||
public sealed class CpuUnit : Z80Cpu
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
internal static class CpuRegId
|
||||
{
|
||||
public const int Bc = 0;
|
||||
public const int De = 1;
|
||||
public const int Hl = 2;
|
||||
public const int Sp = 3;
|
||||
|
||||
public const int B = 0;
|
||||
public const int C = 1;
|
||||
public const int D = 2;
|
||||
public const int E = 3;
|
||||
public const int H = 4;
|
||||
public const int L = 5;
|
||||
public const int F = 6;
|
||||
public const int A = 7;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* Copyright 2015 Alex Makeev
|
||||
* Copyright 2009 SMT (ALU tables)
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --------------------------------------------------------------------
|
||||
* Most of the tables based on the source code of UnrealSpeccy emulator
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public static class CpuTables
|
||||
{
|
||||
#region .ctor
|
||||
|
||||
static CpuTables()
|
||||
{
|
||||
Logf = CreateLogf();
|
||||
Adcf = CreateAdcf();
|
||||
|
||||
// === make_rot === credits to SMT (Unreal)
|
||||
Rlcaf = new byte[0x100];
|
||||
Rrcaf = new byte[0x100];
|
||||
for (var i = 0; i < 0x100; i++)
|
||||
{
|
||||
Rlcaf[i] = (byte)(Rlcf[i] & 0x3B); // rra,rla uses same tables
|
||||
}
|
||||
for (var i = 0; i < 0x100; i++)
|
||||
{
|
||||
Rrcaf[i] = (byte)(Rrcf[i] & 0x3B);
|
||||
}
|
||||
|
||||
// === make_sbc === credits to SMT (Unreal)
|
||||
Sbcf = new byte[0x20000];
|
||||
Cpf = new byte[0x10000];
|
||||
Cpf8b = new byte[0x10000];
|
||||
for (var c = 0; c < 2; c++)
|
||||
{
|
||||
for (var x = 0; x < 0x100; x++)
|
||||
{
|
||||
for (var y = 0; y < 0x100; y++)
|
||||
{
|
||||
var res = x - y - c;
|
||||
var fl = res & CpuFlags.SF3F5;
|
||||
if ((res & 0xFF) == 0) fl |= CpuFlags.Z;
|
||||
if ((res & 0x10000) != 0) fl |= CpuFlags.C;
|
||||
var r = (sbyte)x - (sbyte)y - c;
|
||||
if (r >= 0x80 || r < -0x80) fl |= CpuFlags.P;
|
||||
if ((((x & 0x0F) - (res & 0x0F) - c) & 0x10) != 0) fl |= CpuFlags.H;
|
||||
fl |= CpuFlags.N;
|
||||
Sbcf[c * 0x10000 + x * 0x100 + y] = (byte)fl;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 0x10000; i++)
|
||||
{
|
||||
Cpf[i] = (byte)((Sbcf[i] & CpuFlags.NotF3F5) | (i & CpuFlags.F3F5));
|
||||
var val = (byte)((i >> 8) - (i & 0xFF) - ((Sbcf[i] & CpuFlags.H) >> 4));
|
||||
Cpf8b[i] = (byte)((Sbcf[i] & CpuFlags.NotPCF3F5) + (val & CpuFlags.F3) + ((val << 4) & CpuFlags.F5));
|
||||
}
|
||||
|
||||
Parity = new byte[256];
|
||||
for (var i = 0; i < Parity.Length; i++)
|
||||
{
|
||||
// Bit Twiddling Hacks: Compute parity in parallel, 8-bit
|
||||
var p = (0x6996 >> ((i ^ (i >> 4)) & 0xf)) & 1;
|
||||
Parity[i] = p == 0 ? CpuFlags.P : (byte)0;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] CreateLogf()
|
||||
{
|
||||
// === make_log === credits to SMT (Unreal)
|
||||
var log_f = new byte[0x100];
|
||||
for (var x = 0; x < 0x100; x++)
|
||||
{
|
||||
var fl = x & CpuFlags.SF3F5;
|
||||
var p = CpuFlags.P;
|
||||
for (var i = 0x80; i != 0; i /= 2)
|
||||
{
|
||||
if ((x & i) == i) p ^= CpuFlags.P;
|
||||
}
|
||||
log_f[x] = (byte)(fl | p);
|
||||
}
|
||||
log_f[0] |= CpuFlags.Z;
|
||||
return log_f;
|
||||
}
|
||||
|
||||
private static byte[] CreateAdcf()
|
||||
{
|
||||
// === make_adc === credits to SMT (Unreal)
|
||||
var adcf = new byte[0x20000];
|
||||
for (var c = 0; c < 2; c++)
|
||||
{
|
||||
for (var x = 0; x < 0x100; x++)
|
||||
{
|
||||
for (var y = 0; y < 0x100; y++)
|
||||
{
|
||||
uint res = (uint)(x + y + c);
|
||||
byte fl = 0;
|
||||
if ((res & 0xFF) == 0) fl |= CpuFlags.Z;
|
||||
fl |= (byte)(res & CpuFlags.SF3F5);
|
||||
if (res >= 0x100) fl |= CpuFlags.C;
|
||||
if ((((x & 0x0F) + (y & 0x0F) + c) & 0x10) != 0) fl |= CpuFlags.H;
|
||||
int ri = (sbyte)x + (sbyte)y + c;
|
||||
if (ri >= 0x80 || ri <= -0x81) fl |= CpuFlags.P;
|
||||
adcf[c * 0x10000 + x * 0x100 + y] = fl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return adcf;
|
||||
}
|
||||
|
||||
#endregion .ctor
|
||||
|
||||
|
||||
public static readonly byte[] Logf;
|
||||
public static readonly byte[] Adcf; // flags for adc and add
|
||||
public static readonly byte[] Rlcaf; // flags for RLCA
|
||||
public static readonly byte[] Rrcaf; // flags for RRCA
|
||||
public static readonly byte[] Sbcf; // flags for sub and sbc
|
||||
public static readonly byte[] Cpf; // flags for cp
|
||||
public static readonly byte[] Cpf8b; // flags for cpi(r)/cpd(r)
|
||||
public static readonly byte[] Parity; // parity calculator
|
||||
|
||||
|
||||
public static readonly byte[] Rlcf =
|
||||
// credits to SMT (Unreal)
|
||||
[ // for rlc r. may be for rlca (0x3B mask)
|
||||
0x44,0x00,0x00,0x04,0x08,0x0c,0x0c,0x08
|
||||
,0x00,0x04,0x04,0x00,0x0c,0x08,0x08,0x0c
|
||||
,0x20,0x24,0x24,0x20,0x2c,0x28,0x28,0x2c
|
||||
,0x24,0x20,0x20,0x24,0x28,0x2c,0x2c,0x28
|
||||
,0x00,0x04,0x04,0x00,0x0c,0x08,0x08,0x0c
|
||||
,0x04,0x00,0x00,0x04,0x08,0x0c,0x0c,0x08
|
||||
,0x24,0x20,0x20,0x24,0x28,0x2c,0x2c,0x28
|
||||
,0x20,0x24,0x24,0x20,0x2c,0x28,0x28,0x2c
|
||||
,0x80,0x84,0x84,0x80,0x8c,0x88,0x88,0x8c
|
||||
,0x84,0x80,0x80,0x84,0x88,0x8c,0x8c,0x88
|
||||
,0xa4,0xa0,0xa0,0xa4,0xa8,0xac,0xac,0xa8
|
||||
,0xa0,0xa4,0xa4,0xa0,0xac,0xa8,0xa8,0xac
|
||||
,0x84,0x80,0x80,0x84,0x88,0x8c,0x8c,0x88
|
||||
,0x80,0x84,0x84,0x80,0x8c,0x88,0x88,0x8c
|
||||
,0xa0,0xa4,0xa4,0xa0,0xac,0xa8,0xa8,0xac
|
||||
,0xa4,0xa0,0xa0,0xa4,0xa8,0xac,0xac,0xa8
|
||||
,0x01,0x05,0x05,0x01,0x0d,0x09,0x09,0x0d
|
||||
,0x05,0x01,0x01,0x05,0x09,0x0d,0x0d,0x09
|
||||
,0x25,0x21,0x21,0x25,0x29,0x2d,0x2d,0x29
|
||||
,0x21,0x25,0x25,0x21,0x2d,0x29,0x29,0x2d
|
||||
,0x05,0x01,0x01,0x05,0x09,0x0d,0x0d,0x09
|
||||
,0x01,0x05,0x05,0x01,0x0d,0x09,0x09,0x0d
|
||||
,0x21,0x25,0x25,0x21,0x2d,0x29,0x29,0x2d
|
||||
,0x25,0x21,0x21,0x25,0x29,0x2d,0x2d,0x29
|
||||
,0x85,0x81,0x81,0x85,0x89,0x8d,0x8d,0x89
|
||||
,0x81,0x85,0x85,0x81,0x8d,0x89,0x89,0x8d
|
||||
,0xa1,0xa5,0xa5,0xa1,0xad,0xa9,0xa9,0xad
|
||||
,0xa5,0xa1,0xa1,0xa5,0xa9,0xad,0xad,0xa9
|
||||
,0x81,0x85,0x85,0x81,0x8d,0x89,0x89,0x8d
|
||||
,0x85,0x81,0x81,0x85,0x89,0x8d,0x8d,0x89
|
||||
,0xa5,0xa1,0xa1,0xa5,0xa9,0xad,0xad,0xa9
|
||||
,0xa1,0xa5,0xa5,0xa1,0xad,0xa9,0xa9,0xad
|
||||
];
|
||||
|
||||
public static readonly byte[] Rrcf =
|
||||
// credits to SMT (Unreal)
|
||||
[ // rrc r. may be for rlca (0x3B mask)
|
||||
0x44,0x81,0x00,0x85,0x00,0x85,0x04,0x81
|
||||
,0x00,0x85,0x04,0x81,0x04,0x81,0x00,0x85
|
||||
,0x08,0x8d,0x0c,0x89,0x0c,0x89,0x08,0x8d
|
||||
,0x0c,0x89,0x08,0x8d,0x08,0x8d,0x0c,0x89
|
||||
,0x00,0x85,0x04,0x81,0x04,0x81,0x00,0x85
|
||||
,0x04,0x81,0x00,0x85,0x00,0x85,0x04,0x81
|
||||
,0x0c,0x89,0x08,0x8d,0x08,0x8d,0x0c,0x89
|
||||
,0x08,0x8d,0x0c,0x89,0x0c,0x89,0x08,0x8d
|
||||
,0x20,0xa5,0x24,0xa1,0x24,0xa1,0x20,0xa5
|
||||
,0x24,0xa1,0x20,0xa5,0x20,0xa5,0x24,0xa1
|
||||
,0x2c,0xa9,0x28,0xad,0x28,0xad,0x2c,0xa9
|
||||
,0x28,0xad,0x2c,0xa9,0x2c,0xa9,0x28,0xad
|
||||
,0x24,0xa1,0x20,0xa5,0x20,0xa5,0x24,0xa1
|
||||
,0x20,0xa5,0x24,0xa1,0x24,0xa1,0x20,0xa5
|
||||
,0x28,0xad,0x2c,0xa9,0x2c,0xa9,0x28,0xad
|
||||
,0x2c,0xa9,0x28,0xad,0x28,0xad,0x2c,0xa9
|
||||
,0x00,0x85,0x04,0x81,0x04,0x81,0x00,0x85
|
||||
,0x04,0x81,0x00,0x85,0x00,0x85,0x04,0x81
|
||||
,0x0c,0x89,0x08,0x8d,0x08,0x8d,0x0c,0x89
|
||||
,0x08,0x8d,0x0c,0x89,0x0c,0x89,0x08,0x8d
|
||||
,0x04,0x81,0x00,0x85,0x00,0x85,0x04,0x81
|
||||
,0x00,0x85,0x04,0x81,0x04,0x81,0x00,0x85
|
||||
,0x08,0x8d,0x0c,0x89,0x0c,0x89,0x08,0x8d
|
||||
,0x0c,0x89,0x08,0x8d,0x08,0x8d,0x0c,0x89
|
||||
,0x24,0xa1,0x20,0xa5,0x20,0xa5,0x24,0xa1
|
||||
,0x20,0xa5,0x24,0xa1,0x24,0xa1,0x20,0xa5
|
||||
,0x28,0xad,0x2c,0xa9,0x2c,0xa9,0x28,0xad
|
||||
,0x2c,0xa9,0x28,0xad,0x28,0xad,0x2c,0xa9
|
||||
,0x20,0xa5,0x24,0xa1,0x24,0xa1,0x20,0xa5
|
||||
,0x24,0xa1,0x20,0xa5,0x20,0xa5,0x24,0xa1
|
||||
,0x2c,0xa9,0x28,0xad,0x28,0xad,0x2c,0xa9
|
||||
,0x28,0xad,0x2c,0xa9,0x2c,0xa9,0x28,0xad
|
||||
];
|
||||
|
||||
public static readonly byte[] Incf =
|
||||
// credits to SMT (Unreal)
|
||||
[
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08
|
||||
,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10
|
||||
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08
|
||||
,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x30
|
||||
,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28
|
||||
,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x30
|
||||
,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28
|
||||
,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x10
|
||||
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08
|
||||
,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10
|
||||
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08
|
||||
,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x30
|
||||
,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28
|
||||
,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x30
|
||||
,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28
|
||||
,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x94
|
||||
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88
|
||||
,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x90
|
||||
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88
|
||||
,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0xb0
|
||||
,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa8
|
||||
,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xb0
|
||||
,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa8
|
||||
,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x90
|
||||
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88
|
||||
,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x90
|
||||
,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88
|
||||
,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0xb0
|
||||
,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa8
|
||||
,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xb0
|
||||
,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa8
|
||||
,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x50
|
||||
];
|
||||
|
||||
public static readonly byte[] Decf =
|
||||
// credits to SMT (Unreal)
|
||||
[
|
||||
0xba,0x42,0x02,0x02,0x02,0x02,0x02,0x02
|
||||
,0x02,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a
|
||||
,0x1a,0x02,0x02,0x02,0x02,0x02,0x02,0x02
|
||||
,0x02,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a
|
||||
,0x1a,0x22,0x22,0x22,0x22,0x22,0x22,0x22
|
||||
,0x22,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a
|
||||
,0x3a,0x22,0x22,0x22,0x22,0x22,0x22,0x22
|
||||
,0x22,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a
|
||||
,0x3a,0x02,0x02,0x02,0x02,0x02,0x02,0x02
|
||||
,0x02,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a
|
||||
,0x1a,0x02,0x02,0x02,0x02,0x02,0x02,0x02
|
||||
,0x02,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a
|
||||
,0x1a,0x22,0x22,0x22,0x22,0x22,0x22,0x22
|
||||
,0x22,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a
|
||||
,0x3a,0x22,0x22,0x22,0x22,0x22,0x22,0x22
|
||||
,0x22,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a
|
||||
,0x3e,0x82,0x82,0x82,0x82,0x82,0x82,0x82
|
||||
,0x82,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a
|
||||
,0x9a,0x82,0x82,0x82,0x82,0x82,0x82,0x82
|
||||
,0x82,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a
|
||||
,0x9a,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2
|
||||
,0xa2,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
|
||||
,0xba,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2
|
||||
,0xa2,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
|
||||
,0xba,0x82,0x82,0x82,0x82,0x82,0x82,0x82
|
||||
,0x82,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a
|
||||
,0x9a,0x82,0x82,0x82,0x82,0x82,0x82,0x82
|
||||
,0x82,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a
|
||||
,0x9a,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2
|
||||
,0xa2,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
|
||||
,0xba,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2
|
||||
,0xa2,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
|
||||
];
|
||||
|
||||
public static readonly ushort[] Daaf =
|
||||
// credits to SMT (converted from Unreal)
|
||||
[
|
||||
0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700,0x0808,0x090C,
|
||||
0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,0x1000,0x1104,0x1204,0x1300,
|
||||
0x1404,0x1500,0x1600,0x1704,0x180C,0x1908,0x2030,0x2134,0x2234,0x2330,
|
||||
0x2434,0x2530,0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724,
|
||||
0x282C,0x2928,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,0x3024,0x3120,
|
||||
0x3220,0x3324,0x3420,0x3524,0x3624,0x3720,0x3828,0x392C,0x4010,0x4114,
|
||||
0x4214,0x4310,0x4414,0x4510,0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,
|
||||
0x4600,0x4704,0x480C,0x4908,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700,0x5808,0x590C,
|
||||
0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,0x6024,0x6120,0x6220,0x6324,
|
||||
0x6420,0x6524,0x6624,0x6720,0x6828,0x692C,0x7030,0x7134,0x7234,0x7330,
|
||||
0x7434,0x7530,0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724,
|
||||
0x782C,0x7928,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,0x8080,0x8184,
|
||||
0x8284,0x8380,0x8484,0x8580,0x8680,0x8784,0x888C,0x8988,0x9094,0x9190,
|
||||
0x9290,0x9394,0x9490,0x9594,0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,
|
||||
0x9684,0x9780,0x9888,0x998C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,0x0809,0x090D,
|
||||
0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,0x1001,0x1105,0x1205,0x1301,
|
||||
0x1405,0x1501,0x1601,0x1705,0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,
|
||||
0x2435,0x2531,0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,0x3025,0x3121,
|
||||
0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,0x3829,0x392D,0x4011,0x4115,
|
||||
0x4215,0x4311,0x4415,0x4511,0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,
|
||||
0x4601,0x4705,0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,0x5809,0x590D,
|
||||
0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,0x6025,0x6121,0x6221,0x6325,
|
||||
0x6421,0x6525,0x6625,0x6721,0x6829,0x692D,0x7031,0x7135,0x7235,0x7331,
|
||||
0x7435,0x7531,0x7021,0x7125,0x7225,0x7321,0x7425,0x7521,0x7621,0x7725,
|
||||
0x782D,0x7929,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,0x8081,0x8185,
|
||||
0x8285,0x8381,0x8485,0x8581,0x8681,0x8785,0x888D,0x8989,0x9095,0x9191,
|
||||
0x9291,0x9395,0x9491,0x9595,0x9085,0x9181,0x9281,0x9385,0x9481,0x9585,
|
||||
0x9685,0x9781,0x9889,0x998D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA0A5,0xA1A1,0xA2A1,0xA3A5,0xA4A1,0xA5A5,0xA6A5,0xA7A1,0xA8A9,0xA9AD,
|
||||
0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,0xB0A1,0xB1A5,0xB2A5,0xB3A1,
|
||||
0xB4A5,0xB5A1,0xB6A1,0xB7A5,0xB8AD,0xB9A9,0xC095,0xC191,0xC291,0xC395,
|
||||
0xC491,0xC595,0xC085,0xC181,0xC281,0xC385,0xC481,0xC585,0xC685,0xC781,
|
||||
0xC889,0xC98D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,0xD081,0xD185,
|
||||
0xD285,0xD381,0xD485,0xD581,0xD681,0xD785,0xD88D,0xD989,0xE0B1,0xE1B5,
|
||||
0xE2B5,0xE3B1,0xE4B5,0xE5B1,0xE0A1,0xE1A5,0xE2A5,0xE3A1,0xE4A5,0xE5A1,
|
||||
0xE6A1,0xE7A5,0xE8AD,0xE9A9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF0A5,0xF1A1,0xF2A1,0xF3A5,0xF4A1,0xF5A5,0xF6A5,0xF7A1,0xF8A9,0xF9AD,
|
||||
0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,0x0045,0x0101,0x0201,0x0305,
|
||||
0x0401,0x0505,0x0605,0x0701,0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,
|
||||
0x1415,0x1511,0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,0x2021,0x2125,
|
||||
0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,0x282D,0x2929,0x3035,0x3131,
|
||||
0x3231,0x3335,0x3431,0x3535,0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,
|
||||
0x3625,0x3721,0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,0x480D,0x4909,
|
||||
0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,0x5005,0x5101,0x5201,0x5305,
|
||||
0x5401,0x5505,0x5605,0x5701,0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,
|
||||
0x6431,0x6535,0x0046,0x0102,0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,
|
||||
0x080A,0x090E,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,0x1002,0x1106,
|
||||
0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,0x1406,0x1502,
|
||||
0x1602,0x1706,0x180E,0x190A,0x2022,0x2126,0x2226,0x2322,0x2426,0x2522,
|
||||
0x2622,0x2726,0x282E,0x292A,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x3026,0x3122,0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,0x4002,0x4106,0x4206,0x4302,
|
||||
0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,0x4406,0x4502,0x4602,0x4706,
|
||||
0x480E,0x490A,0x5006,0x5102,0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,
|
||||
0x580A,0x590E,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,0x6026,0x6122,
|
||||
0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,0x6422,0x6526,
|
||||
0x6626,0x6722,0x682A,0x692E,0x7022,0x7126,0x7226,0x7322,0x7426,0x7522,
|
||||
0x7622,0x7726,0x782E,0x792A,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x8082,0x8186,0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,0x9086,0x9182,0x9282,0x9386,
|
||||
0x9482,0x9586,0x9686,0x9782,0x988A,0x998E,0x3423,0x3527,0x3627,0x3723,
|
||||
0x382B,0x392F,0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,0x5403,0x5507,
|
||||
0x5607,0x5703,0x580B,0x590F,0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,
|
||||
0x6627,0x6723,0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,0x8083,0x8187,0x8287,0x8383,
|
||||
0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,0xA0A7,0xA1A3,
|
||||
0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,0xA4A3,0xA5A7,
|
||||
0xA6A7,0xA7A3,0xA8AB,0xA9AF,0xB0A3,0xB1A7,0xB2A7,0xB3A3,0xB4A7,0xB5A3,
|
||||
0xB6A3,0xB7A7,0xB8AF,0xB9AB,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xC087,0xC183,0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,0xD083,0xD187,0xD287,0xD383,
|
||||
0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,0xD487,0xD583,0xD683,0xD787,
|
||||
0xD88F,0xD98B,0xE0A3,0xE1A7,0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,
|
||||
0xE8AF,0xE9AB,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,0xF0A7,0xF1A3,
|
||||
0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,0xF4A3,0xF5A7,
|
||||
0xF6A7,0xF7A3,0xF8AB,0xF9AF,0x0047,0x0103,0x0203,0x0307,0x0403,0x0507,
|
||||
0x0607,0x0703,0x080B,0x090F,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x1003,0x1107,0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,0x2023,0x2127,0x2227,0x2323,
|
||||
0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,0x2427,0x2523,0x2623,0x2727,
|
||||
0x282F,0x292B,0x3027,0x3123,0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,
|
||||
0x382B,0x392F,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,0x4407,0x4503,
|
||||
0x4603,0x4707,0x480F,0x490B,0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,
|
||||
0x5607,0x5703,0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,0x7023,0x7127,0x7227,0x7323,
|
||||
0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,0x9483,0x9587,
|
||||
0x9687,0x9783,0x988B,0x998F,0x0604,0x0700,0x0808,0x090C,0x0A0C,0x0B08,
|
||||
0x0C0C,0x0D08,0x0E08,0x0F0C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1600,0x1704,0x180C,0x1908,0x1A08,0x1B0C,0x1C08,0x1D0C,0x1E0C,0x1F08,
|
||||
0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,0x2620,0x2724,0x282C,0x2928,
|
||||
0x2A28,0x2B2C,0x2C28,0x2D2C,0x2E2C,0x2F28,0x3034,0x3130,0x3230,0x3334,
|
||||
0x3430,0x3534,0x3624,0x3720,0x3828,0x392C,0x3A2C,0x3B28,0x3C2C,0x3D28,
|
||||
0x3E28,0x3F2C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,0x4600,0x4704,
|
||||
0x480C,0x4908,0x4A08,0x4B0C,0x4C08,0x4D0C,0x4E0C,0x4F08,0x5014,0x5110,
|
||||
0x5210,0x5314,0x5410,0x5514,0x5604,0x5700,0x5808,0x590C,0x5A0C,0x5B08,
|
||||
0x5C0C,0x5D08,0x5E08,0x5F0C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6624,0x6720,0x6828,0x692C,0x6A2C,0x6B28,0x6C2C,0x6D28,0x6E28,0x6F2C,
|
||||
0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,0x7620,0x7724,0x782C,0x7928,
|
||||
0x7A28,0x7B2C,0x7C28,0x7D2C,0x7E2C,0x7F28,0x8090,0x8194,0x8294,0x8390,
|
||||
0x8494,0x8590,0x8680,0x8784,0x888C,0x8988,0x8A88,0x8B8C,0x8C88,0x8D8C,
|
||||
0x8E8C,0x8F88,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,0x9684,0x9780,
|
||||
0x9888,0x998C,0x9A8C,0x9B88,0x9C8C,0x9D88,0x9E88,0x9F8C,0x0055,0x0111,
|
||||
0x0211,0x0315,0x0411,0x0515,0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,
|
||||
0x0C0D,0x0D09,0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,0x1E0D,0x1F09,
|
||||
0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,0x2621,0x2725,0x282D,0x2929,
|
||||
0x2A29,0x2B2D,0x2C29,0x2D2D,0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,
|
||||
0x3431,0x3535,0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,0x4601,0x4705,
|
||||
0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,0x4E0D,0x4F09,0x5015,0x5111,
|
||||
0x5211,0x5315,0x5411,0x5515,0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,
|
||||
0x5C0D,0x5D09,0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6625,0x6721,0x6829,0x692D,0x6A2D,0x6B29,0x6C2D,0x6D29,0x6E29,0x6F2D,
|
||||
0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,0x7621,0x7725,0x782D,0x7929,
|
||||
0x7A29,0x7B2D,0x7C29,0x7D2D,0x7E2D,0x7F29,0x8091,0x8195,0x8295,0x8391,
|
||||
0x8495,0x8591,0x8681,0x8785,0x888D,0x8989,0x8A89,0x8B8D,0x8C89,0x8D8D,
|
||||
0x8E8D,0x8F89,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,0x9685,0x9781,
|
||||
0x9889,0x998D,0x9A8D,0x9B89,0x9C8D,0x9D89,0x9E89,0x9F8D,0xA0B5,0xA1B1,
|
||||
0xA2B1,0xA3B5,0xA4B1,0xA5B5,0xA6A5,0xA7A1,0xA8A9,0xA9AD,0xAAAD,0xABA9,
|
||||
0xACAD,0xADA9,0xAEA9,0xAFAD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB6A1,0xB7A5,0xB8AD,0xB9A9,0xBAA9,0xBBAD,0xBCA9,0xBDAD,0xBEAD,0xBFA9,
|
||||
0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,0xC685,0xC781,0xC889,0xC98D,
|
||||
0xCA8D,0xCB89,0xCC8D,0xCD89,0xCE89,0xCF8D,0xD091,0xD195,0xD295,0xD391,
|
||||
0xD495,0xD591,0xD681,0xD785,0xD88D,0xD989,0xDA89,0xDB8D,0xDC89,0xDD8D,
|
||||
0xDE8D,0xDF89,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,0xE6A1,0xE7A5,
|
||||
0xE8AD,0xE9A9,0xEAA9,0xEBAD,0xECA9,0xEDAD,0xEEAD,0xEFA9,0xF0B5,0xF1B1,
|
||||
0xF2B1,0xF3B5,0xF4B1,0xF5B5,0xF6A5,0xF7A1,0xF8A9,0xF9AD,0xFAAD,0xFBA9,
|
||||
0xFCAD,0xFDA9,0xFEA9,0xFFAD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,0x0E09,0x0F0D,
|
||||
0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,0x1601,0x1705,0x180D,0x1909,
|
||||
0x1A09,0x1B0D,0x1C09,0x1D0D,0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,
|
||||
0x2435,0x2531,0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,0x3625,0x3721,
|
||||
0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,0x3E29,0x3F2D,0x4011,0x4115,
|
||||
0x4215,0x4311,0x4415,0x4511,0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,
|
||||
0x4C09,0x4D0D,0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,0x5E09,0x5F0D,
|
||||
0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,0xFABE,0xFBBA,0xFCBE,0xFDBA,
|
||||
0xFEBA,0xFFBE,0x0046,0x0102,0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,
|
||||
0x080A,0x090E,0x0A1E,0x0B1A,0x0C1E,0x0D1A,0x0E1A,0x0F1E,0x1002,0x1106,
|
||||
0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,0x1A1A,0x1B1E,
|
||||
0x1C1A,0x1D1E,0x1E1E,0x1F1A,0x2022,0x2126,0x2226,0x2322,0x2426,0x2522,
|
||||
0x2622,0x2726,0x282E,0x292A,0x2A3A,0x2B3E,0x2C3A,0x2D3E,0x2E3E,0x2F3A,
|
||||
0x3026,0x3122,0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x3A3E,0x3B3A,0x3C3E,0x3D3A,0x3E3A,0x3F3E,0x4002,0x4106,0x4206,0x4302,
|
||||
0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,0x4A1A,0x4B1E,0x4C1A,0x4D1E,
|
||||
0x4E1E,0x4F1A,0x5006,0x5102,0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,
|
||||
0x580A,0x590E,0x5A1E,0x5B1A,0x5C1E,0x5D1A,0x5E1A,0x5F1E,0x6026,0x6122,
|
||||
0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,0x6A3E,0x6B3A,
|
||||
0x6C3E,0x6D3A,0x6E3A,0x6F3E,0x7022,0x7126,0x7226,0x7322,0x7426,0x7522,
|
||||
0x7622,0x7726,0x782E,0x792A,0x7A3A,0x7B3E,0x7C3A,0x7D3E,0x7E3E,0x7F3A,
|
||||
0x8082,0x8186,0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x8A9A,0x8B9E,0x8C9A,0x8D9E,0x8E9E,0x8F9A,0x9086,0x9182,0x9282,0x9386,
|
||||
0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,0x3A3F,0x3B3B,0x3C3F,0x3D3B,
|
||||
0x3E3B,0x3F3F,0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,0x5A1F,0x5B1B,
|
||||
0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,
|
||||
0x6627,0x6723,0x682B,0x692F,0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,0x8287,0x8383,
|
||||
0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,0x8A9B,0x8B9F,0x8C9B,0x8D9F,
|
||||
0x8E9F,0x8F9B,0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9A9F,0x9B9B,0x9C9F,0x9D9B,0x9E9B,0x9F9F,0xA0A7,0xA1A3,
|
||||
0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,0xAABF,0xABBB,
|
||||
0xACBF,0xADBB,0xAEBB,0xAFBF,0xB0A3,0xB1A7,0xB2A7,0xB3A3,0xB4A7,0xB5A3,
|
||||
0xB6A3,0xB7A7,0xB8AF,0xB9AB,0xBABB,0xBBBF,0xBCBB,0xBDBF,0xBEBF,0xBFBB,
|
||||
0xC087,0xC183,0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xCA9F,0xCB9B,0xCC9F,0xCD9B,0xCE9B,0xCF9F,0xD083,0xD187,0xD287,0xD383,
|
||||
0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,0xDA9B,0xDB9F,0xDC9B,0xDD9F,
|
||||
0xDE9F,0xDF9B,0xE0A3,0xE1A7,0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,
|
||||
0xE8AF,0xE9AB,0xEABB,0xEBBF,0xECBB,0xEDBF,0xEEBF,0xEFBB,0xF0A7,0xF1A3,
|
||||
0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,0xFABF,0xFBBB,
|
||||
0xFCBF,0xFDBB,0xFEBB,0xFFBF,0x0047,0x0103,0x0203,0x0307,0x0403,0x0507,
|
||||
0x0607,0x0703,0x080B,0x090F,0x0A1F,0x0B1B,0x0C1F,0x0D1B,0x0E1B,0x0F1F,
|
||||
0x1003,0x1107,0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x1A1B,0x1B1F,0x1C1B,0x1D1F,0x1E1F,0x1F1B,0x2023,0x2127,0x2227,0x2323,
|
||||
0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,0x2A3B,0x2B3F,0x2C3B,0x2D3F,
|
||||
0x2E3F,0x2F3B,0x3027,0x3123,0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,
|
||||
0x382B,0x392F,0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,0x4A1B,0x4B1F,
|
||||
0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,
|
||||
0x5607,0x5703,0x580B,0x590F,0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,0x7227,0x7323,
|
||||
0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,0x7A3B,0x7B3F,0x7C3B,0x7D3F,
|
||||
0x7E3F,0x7F3B,0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
];
|
||||
|
||||
public static readonly byte[] Rl0 =
|
||||
[
|
||||
0x44,0x00,0x00,0x04,0x08,0x0c,0x0c,0x08
|
||||
,0x00,0x04,0x04,0x00,0x0c,0x08,0x08,0x0c
|
||||
,0x20,0x24,0x24,0x20,0x2c,0x28,0x28,0x2c
|
||||
,0x24,0x20,0x20,0x24,0x28,0x2c,0x2c,0x28
|
||||
,0x00,0x04,0x04,0x00,0x0c,0x08,0x08,0x0c
|
||||
,0x04,0x00,0x00,0x04,0x08,0x0c,0x0c,0x08
|
||||
,0x24,0x20,0x20,0x24,0x28,0x2c,0x2c,0x28
|
||||
,0x20,0x24,0x24,0x20,0x2c,0x28,0x28,0x2c
|
||||
,0x80,0x84,0x84,0x80,0x8c,0x88,0x88,0x8c
|
||||
,0x84,0x80,0x80,0x84,0x88,0x8c,0x8c,0x88
|
||||
,0xa4,0xa0,0xa0,0xa4,0xa8,0xac,0xac,0xa8
|
||||
,0xa0,0xa4,0xa4,0xa0,0xac,0xa8,0xa8,0xac
|
||||
,0x84,0x80,0x80,0x84,0x88,0x8c,0x8c,0x88
|
||||
,0x80,0x84,0x84,0x80,0x8c,0x88,0x88,0x8c
|
||||
,0xa0,0xa4,0xa4,0xa0,0xac,0xa8,0xa8,0xac
|
||||
,0xa4,0xa0,0xa0,0xa4,0xa8,0xac,0xac,0xa8
|
||||
,0x45,0x01,0x01,0x05,0x09,0x0d,0x0d,0x09
|
||||
,0x01,0x05,0x05,0x01,0x0d,0x09,0x09,0x0d
|
||||
,0x21,0x25,0x25,0x21,0x2d,0x29,0x29,0x2d
|
||||
,0x25,0x21,0x21,0x25,0x29,0x2d,0x2d,0x29
|
||||
,0x01,0x05,0x05,0x01,0x0d,0x09,0x09,0x0d
|
||||
,0x05,0x01,0x01,0x05,0x09,0x0d,0x0d,0x09
|
||||
,0x25,0x21,0x21,0x25,0x29,0x2d,0x2d,0x29
|
||||
,0x21,0x25,0x25,0x21,0x2d,0x29,0x29,0x2d
|
||||
,0x81,0x85,0x85,0x81,0x8d,0x89,0x89,0x8d
|
||||
,0x85,0x81,0x81,0x85,0x89,0x8d,0x8d,0x89
|
||||
,0xa5,0xa1,0xa1,0xa5,0xa9,0xad,0xad,0xa9
|
||||
,0xa1,0xa5,0xa5,0xa1,0xad,0xa9,0xa9,0xad
|
||||
,0x85,0x81,0x81,0x85,0x89,0x8d,0x8d,0x89
|
||||
,0x81,0x85,0x85,0x81,0x8d,0x89,0x89,0x8d
|
||||
,0xa1,0xa5,0xa5,0xa1,0xad,0xa9,0xa9,0xad
|
||||
,0xa5,0xa1,0xa1,0xa5,0xa9,0xad,0xad,0xa9
|
||||
];
|
||||
|
||||
public static readonly byte[] Rl1 =
|
||||
[
|
||||
0x00,0x04,0x04,0x00,0x0c,0x08,0x08,0x0c
|
||||
,0x04,0x00,0x00,0x04,0x08,0x0c,0x0c,0x08
|
||||
,0x24,0x20,0x20,0x24,0x28,0x2c,0x2c,0x28
|
||||
,0x20,0x24,0x24,0x20,0x2c,0x28,0x28,0x2c
|
||||
,0x04,0x00,0x00,0x04,0x08,0x0c,0x0c,0x08
|
||||
,0x00,0x04,0x04,0x00,0x0c,0x08,0x08,0x0c
|
||||
,0x20,0x24,0x24,0x20,0x2c,0x28,0x28,0x2c
|
||||
,0x24,0x20,0x20,0x24,0x28,0x2c,0x2c,0x28
|
||||
,0x84,0x80,0x80,0x84,0x88,0x8c,0x8c,0x88
|
||||
,0x80,0x84,0x84,0x80,0x8c,0x88,0x88,0x8c
|
||||
,0xa0,0xa4,0xa4,0xa0,0xac,0xa8,0xa8,0xac
|
||||
,0xa4,0xa0,0xa0,0xa4,0xa8,0xac,0xac,0xa8
|
||||
,0x80,0x84,0x84,0x80,0x8c,0x88,0x88,0x8c
|
||||
,0x84,0x80,0x80,0x84,0x88,0x8c,0x8c,0x88
|
||||
,0xa4,0xa0,0xa0,0xa4,0xa8,0xac,0xac,0xa8
|
||||
,0xa0,0xa4,0xa4,0xa0,0xac,0xa8,0xa8,0xac
|
||||
,0x01,0x05,0x05,0x01,0x0d,0x09,0x09,0x0d
|
||||
,0x05,0x01,0x01,0x05,0x09,0x0d,0x0d,0x09
|
||||
,0x25,0x21,0x21,0x25,0x29,0x2d,0x2d,0x29
|
||||
,0x21,0x25,0x25,0x21,0x2d,0x29,0x29,0x2d
|
||||
,0x05,0x01,0x01,0x05,0x09,0x0d,0x0d,0x09
|
||||
,0x01,0x05,0x05,0x01,0x0d,0x09,0x09,0x0d
|
||||
,0x21,0x25,0x25,0x21,0x2d,0x29,0x29,0x2d
|
||||
,0x25,0x21,0x21,0x25,0x29,0x2d,0x2d,0x29
|
||||
,0x85,0x81,0x81,0x85,0x89,0x8d,0x8d,0x89
|
||||
,0x81,0x85,0x85,0x81,0x8d,0x89,0x89,0x8d
|
||||
,0xa1,0xa5,0xa5,0xa1,0xad,0xa9,0xa9,0xad
|
||||
,0xa5,0xa1,0xa1,0xa5,0xa9,0xad,0xad,0xa9
|
||||
,0x81,0x85,0x85,0x81,0x8d,0x89,0x89,0x8d
|
||||
,0x85,0x81,0x81,0x85,0x89,0x8d,0x8d,0x89
|
||||
,0xa5,0xa1,0xa1,0xa5,0xa9,0xad,0xad,0xa9
|
||||
,0xa1,0xa5,0xa5,0xa1,0xad,0xa9,0xa9,0xad
|
||||
];
|
||||
|
||||
public static readonly byte[] Rr0 =
|
||||
[
|
||||
0x44,0x45,0x00,0x01,0x00,0x01,0x04,0x05
|
||||
,0x00,0x01,0x04,0x05,0x04,0x05,0x00,0x01
|
||||
,0x08,0x09,0x0c,0x0d,0x0c,0x0d,0x08,0x09
|
||||
,0x0c,0x0d,0x08,0x09,0x08,0x09,0x0c,0x0d
|
||||
,0x00,0x01,0x04,0x05,0x04,0x05,0x00,0x01
|
||||
,0x04,0x05,0x00,0x01,0x00,0x01,0x04,0x05
|
||||
,0x0c,0x0d,0x08,0x09,0x08,0x09,0x0c,0x0d
|
||||
,0x08,0x09,0x0c,0x0d,0x0c,0x0d,0x08,0x09
|
||||
,0x20,0x21,0x24,0x25,0x24,0x25,0x20,0x21
|
||||
,0x24,0x25,0x20,0x21,0x20,0x21,0x24,0x25
|
||||
,0x2c,0x2d,0x28,0x29,0x28,0x29,0x2c,0x2d
|
||||
,0x28,0x29,0x2c,0x2d,0x2c,0x2d,0x28,0x29
|
||||
,0x24,0x25,0x20,0x21,0x20,0x21,0x24,0x25
|
||||
,0x20,0x21,0x24,0x25,0x24,0x25,0x20,0x21
|
||||
,0x28,0x29,0x2c,0x2d,0x2c,0x2d,0x28,0x29
|
||||
,0x2c,0x2d,0x28,0x29,0x28,0x29,0x2c,0x2d
|
||||
,0x00,0x01,0x04,0x05,0x04,0x05,0x00,0x01
|
||||
,0x04,0x05,0x00,0x01,0x00,0x01,0x04,0x05
|
||||
,0x0c,0x0d,0x08,0x09,0x08,0x09,0x0c,0x0d
|
||||
,0x08,0x09,0x0c,0x0d,0x0c,0x0d,0x08,0x09
|
||||
,0x04,0x05,0x00,0x01,0x00,0x01,0x04,0x05
|
||||
,0x00,0x01,0x04,0x05,0x04,0x05,0x00,0x01
|
||||
,0x08,0x09,0x0c,0x0d,0x0c,0x0d,0x08,0x09
|
||||
,0x0c,0x0d,0x08,0x09,0x08,0x09,0x0c,0x0d
|
||||
,0x24,0x25,0x20,0x21,0x20,0x21,0x24,0x25
|
||||
,0x20,0x21,0x24,0x25,0x24,0x25,0x20,0x21
|
||||
,0x28,0x29,0x2c,0x2d,0x2c,0x2d,0x28,0x29
|
||||
,0x2c,0x2d,0x28,0x29,0x28,0x29,0x2c,0x2d
|
||||
,0x20,0x21,0x24,0x25,0x24,0x25,0x20,0x21
|
||||
,0x24,0x25,0x20,0x21,0x20,0x21,0x24,0x25
|
||||
,0x2c,0x2d,0x28,0x29,0x28,0x29,0x2c,0x2d
|
||||
,0x28,0x29,0x2c,0x2d,0x2c,0x2d,0x28,0x29
|
||||
];
|
||||
|
||||
public static readonly byte[] Rr1 =
|
||||
[
|
||||
0x80,0x81,0x84,0x85,0x84,0x85,0x80,0x81
|
||||
,0x84,0x85,0x80,0x81,0x80,0x81,0x84,0x85
|
||||
,0x8c,0x8d,0x88,0x89,0x88,0x89,0x8c,0x8d
|
||||
,0x88,0x89,0x8c,0x8d,0x8c,0x8d,0x88,0x89
|
||||
,0x84,0x85,0x80,0x81,0x80,0x81,0x84,0x85
|
||||
,0x80,0x81,0x84,0x85,0x84,0x85,0x80,0x81
|
||||
,0x88,0x89,0x8c,0x8d,0x8c,0x8d,0x88,0x89
|
||||
,0x8c,0x8d,0x88,0x89,0x88,0x89,0x8c,0x8d
|
||||
,0xa4,0xa5,0xa0,0xa1,0xa0,0xa1,0xa4,0xa5
|
||||
,0xa0,0xa1,0xa4,0xa5,0xa4,0xa5,0xa0,0xa1
|
||||
,0xa8,0xa9,0xac,0xad,0xac,0xad,0xa8,0xa9
|
||||
,0xac,0xad,0xa8,0xa9,0xa8,0xa9,0xac,0xad
|
||||
,0xa0,0xa1,0xa4,0xa5,0xa4,0xa5,0xa0,0xa1
|
||||
,0xa4,0xa5,0xa0,0xa1,0xa0,0xa1,0xa4,0xa5
|
||||
,0xac,0xad,0xa8,0xa9,0xa8,0xa9,0xac,0xad
|
||||
,0xa8,0xa9,0xac,0xad,0xac,0xad,0xa8,0xa9
|
||||
,0x84,0x85,0x80,0x81,0x80,0x81,0x84,0x85
|
||||
,0x80,0x81,0x84,0x85,0x84,0x85,0x80,0x81
|
||||
,0x88,0x89,0x8c,0x8d,0x8c,0x8d,0x88,0x89
|
||||
,0x8c,0x8d,0x88,0x89,0x88,0x89,0x8c,0x8d
|
||||
,0x80,0x81,0x84,0x85,0x84,0x85,0x80,0x81
|
||||
,0x84,0x85,0x80,0x81,0x80,0x81,0x84,0x85
|
||||
,0x8c,0x8d,0x88,0x89,0x88,0x89,0x8c,0x8d
|
||||
,0x88,0x89,0x8c,0x8d,0x8c,0x8d,0x88,0x89
|
||||
,0xa0,0xa1,0xa4,0xa5,0xa4,0xa5,0xa0,0xa1
|
||||
,0xa4,0xa5,0xa0,0xa1,0xa0,0xa1,0xa4,0xa5
|
||||
,0xac,0xad,0xa8,0xa9,0xa8,0xa9,0xac,0xad
|
||||
,0xa8,0xa9,0xac,0xad,0xac,0xad,0xa8,0xa9
|
||||
,0xa4,0xa5,0xa0,0xa1,0xa0,0xa1,0xa4,0xa5
|
||||
,0xa0,0xa1,0xa4,0xa5,0xa4,0xa5,0xa0,0xa1
|
||||
,0xa8,0xa9,0xac,0xad,0xac,0xad,0xa8,0xa9
|
||||
,0xac,0xad,0xa8,0xa9,0xa8,0xa9,0xac,0xad
|
||||
];
|
||||
|
||||
public static readonly byte[] Sraf =
|
||||
[
|
||||
0x44,0x45,0x00,0x01,0x00,0x01,0x04,0x05
|
||||
,0x00,0x01,0x04,0x05,0x04,0x05,0x00,0x01
|
||||
,0x08,0x09,0x0c,0x0d,0x0c,0x0d,0x08,0x09
|
||||
,0x0c,0x0d,0x08,0x09,0x08,0x09,0x0c,0x0d
|
||||
,0x00,0x01,0x04,0x05,0x04,0x05,0x00,0x01
|
||||
,0x04,0x05,0x00,0x01,0x00,0x01,0x04,0x05
|
||||
,0x0c,0x0d,0x08,0x09,0x08,0x09,0x0c,0x0d
|
||||
,0x08,0x09,0x0c,0x0d,0x0c,0x0d,0x08,0x09
|
||||
,0x20,0x21,0x24,0x25,0x24,0x25,0x20,0x21
|
||||
,0x24,0x25,0x20,0x21,0x20,0x21,0x24,0x25
|
||||
,0x2c,0x2d,0x28,0x29,0x28,0x29,0x2c,0x2d
|
||||
,0x28,0x29,0x2c,0x2d,0x2c,0x2d,0x28,0x29
|
||||
,0x24,0x25,0x20,0x21,0x20,0x21,0x24,0x25
|
||||
,0x20,0x21,0x24,0x25,0x24,0x25,0x20,0x21
|
||||
,0x28,0x29,0x2c,0x2d,0x2c,0x2d,0x28,0x29
|
||||
,0x2c,0x2d,0x28,0x29,0x28,0x29,0x2c,0x2d
|
||||
,0x84,0x85,0x80,0x81,0x80,0x81,0x84,0x85
|
||||
,0x80,0x81,0x84,0x85,0x84,0x85,0x80,0x81
|
||||
,0x88,0x89,0x8c,0x8d,0x8c,0x8d,0x88,0x89
|
||||
,0x8c,0x8d,0x88,0x89,0x88,0x89,0x8c,0x8d
|
||||
,0x80,0x81,0x84,0x85,0x84,0x85,0x80,0x81
|
||||
,0x84,0x85,0x80,0x81,0x80,0x81,0x84,0x85
|
||||
,0x8c,0x8d,0x88,0x89,0x88,0x89,0x8c,0x8d
|
||||
,0x88,0x89,0x8c,0x8d,0x8c,0x8d,0x88,0x89
|
||||
,0xa0,0xa1,0xa4,0xa5,0xa4,0xa5,0xa0,0xa1
|
||||
,0xa4,0xa5,0xa0,0xa1,0xa0,0xa1,0xa4,0xa5
|
||||
,0xac,0xad,0xa8,0xa9,0xa8,0xa9,0xac,0xad
|
||||
,0xa8,0xa9,0xac,0xad,0xac,0xad,0xa8,0xa9
|
||||
,0xa4,0xa5,0xa0,0xa1,0xa0,0xa1,0xa4,0xa5
|
||||
,0xa0,0xa1,0xa4,0xa5,0xa4,0xa5,0xa0,0xa1
|
||||
,0xa8,0xa9,0xac,0xad,0xac,0xad,0xa8,0xa9
|
||||
,0xac,0xad,0xa8,0xa9,0xa8,0xa9,0xac,0xad
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [ALU part]
|
||||
* Date: 13.04.2007
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
#region ALU
|
||||
|
||||
private void ALU_ADDR(byte src)
|
||||
{
|
||||
regs.F = CpuTables.Adcf[regs.A + src * 0x100];
|
||||
regs.A += src;
|
||||
}
|
||||
|
||||
private void ALU_ADCR(byte src)
|
||||
{
|
||||
var carry = regs.F & CpuFlags.C;
|
||||
regs.F = CpuTables.Adcf[regs.A + src * 0x100 + 0x10000 * carry];
|
||||
regs.A += (byte)(src + carry);
|
||||
}
|
||||
|
||||
private void ALU_SUBR(byte src)
|
||||
{
|
||||
regs.F = CpuTables.Sbcf[regs.A * 0x100 + src];
|
||||
regs.A -= src;
|
||||
}
|
||||
|
||||
private void ALU_SBCR(byte src)
|
||||
{
|
||||
var carry = regs.F & CpuFlags.C;
|
||||
regs.F = CpuTables.Sbcf[regs.A * 0x100 + src + 0x10000 * carry];
|
||||
regs.A -= (byte)(src + carry);
|
||||
}
|
||||
|
||||
private void ALU_ANDR(byte src)
|
||||
{
|
||||
regs.A &= src;
|
||||
regs.F = (byte)(CpuTables.Logf[regs.A] | CpuFlags.H);
|
||||
}
|
||||
|
||||
private void ALU_XORR(byte src)
|
||||
{
|
||||
regs.A ^= src;
|
||||
regs.F = CpuTables.Logf[regs.A];
|
||||
}
|
||||
|
||||
private void ALU_ORR(byte src)
|
||||
{
|
||||
regs.A |= src;
|
||||
regs.F = CpuTables.Logf[regs.A];
|
||||
}
|
||||
|
||||
private void ALU_CPR(byte src)
|
||||
{
|
||||
regs.F = CpuTables.Cpf[regs.A * 0x100 + src];
|
||||
}
|
||||
|
||||
private byte ALU_INCR(byte x)
|
||||
{
|
||||
regs.F = (byte)(CpuTables.Incf[x] | (regs.F & CpuFlags.C));
|
||||
x++;
|
||||
return x;
|
||||
}
|
||||
|
||||
private byte ALU_DECR(byte x)
|
||||
{
|
||||
regs.F = (byte)(CpuTables.Decf[x] | (regs.F & CpuFlags.C));
|
||||
x--;
|
||||
return x;
|
||||
}
|
||||
|
||||
private ushort ALU_ADDHLRR(ushort rhl, ushort rde)
|
||||
{
|
||||
regs.F = (byte)(regs.F & CpuFlags.NotHNCF3F5);
|
||||
regs.F |= (byte)((((rhl & 0x0FFF) + (rde & 0x0FFF)) >> 8) & CpuFlags.H);
|
||||
uint res = (uint)((rhl & 0xFFFF) + (rde & 0xFFFF));
|
||||
|
||||
if ((res & 0x10000) != 0) regs.F |= CpuFlags.C;
|
||||
regs.F |= (byte)((res >> 8) & CpuFlags.F3F5);
|
||||
return (ushort)res;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ALU #CB
|
||||
|
||||
private byte ALU_RLC(int x)
|
||||
{
|
||||
regs.F = CpuTables.Rlcf[x];
|
||||
x <<= 1;
|
||||
if ((x & 0x100) != 0) x |= 0x01;
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_RRC(int x)
|
||||
{
|
||||
regs.F = CpuTables.Rrcf[x];
|
||||
if ((x & 0x01) != 0) x = (x >> 1) | 0x80;
|
||||
else x >>= 1;
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_RL(int x)
|
||||
{
|
||||
if ((regs.F & CpuFlags.C) != 0)
|
||||
{
|
||||
regs.F = CpuTables.Rl1[x];
|
||||
x <<= 1;
|
||||
x++;
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.F = CpuTables.Rl0[x];
|
||||
x <<= 1;
|
||||
}
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_RR(int x)
|
||||
{
|
||||
if ((regs.F & CpuFlags.C) != 0)
|
||||
{
|
||||
regs.F = CpuTables.Rr1[x];
|
||||
x >>= 1;
|
||||
x += 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.F = CpuTables.Rr0[x];
|
||||
x >>= 1;
|
||||
}
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_SLA(int x)
|
||||
{
|
||||
regs.F = CpuTables.Rl0[x];
|
||||
x <<= 1;
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_SRA(int x)
|
||||
{
|
||||
regs.F = CpuTables.Sraf[x];
|
||||
x = (x >> 1) + (x & 0x80);
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_SLL(int x)
|
||||
{
|
||||
regs.F = CpuTables.Rl1[x];
|
||||
x <<= 1;
|
||||
x++;
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private byte ALU_SRL(int x)
|
||||
{
|
||||
regs.F = CpuTables.Rr0[x];
|
||||
x >>= 1;
|
||||
return (byte)x;
|
||||
}
|
||||
|
||||
private void ALU_BIT(byte src, int bit)
|
||||
{
|
||||
regs.F = (byte)(CpuTables.Logf[src & (1 << bit)] | CpuFlags.H | (regs.F & CpuFlags.C) | (src & CpuFlags.F3F5));
|
||||
}
|
||||
|
||||
private void ALU_BITMEM(byte src, int bit)
|
||||
{
|
||||
regs.F = (byte)(CpuTables.Logf[src & (1 << bit)] | CpuFlags.H | (regs.F & CpuFlags.C));
|
||||
regs.F = (byte)((regs.F & CpuFlags.NotF3F5) | (regs.MH & CpuFlags.F3F5));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,722 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [direct opcode part]
|
||||
* Date: 13.04.2007
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
#region direct/DD/FD
|
||||
|
||||
private void INA_NN_(byte cmd) // IN A,(N) [11T]
|
||||
{
|
||||
// 11T (4, 3, 4)
|
||||
|
||||
regs.MW = RDMEM(regs.PC++); Tact += 3;
|
||||
regs.MW += (ushort)(regs.A << 8);
|
||||
|
||||
regs.A = RDPORT(regs.MW); Tact += 4;
|
||||
regs.MW++;
|
||||
}
|
||||
|
||||
private void OUT_NN_A(byte cmd) // OUT (N),A [11T]+
|
||||
{
|
||||
// 11T (4, 3, 4)
|
||||
|
||||
regs.MW = RDMEM(regs.PC++); Tact += 3;
|
||||
regs.MW += (ushort)(regs.A << 8);
|
||||
|
||||
WRPORT(regs.MW, regs.A); Tact += 4;
|
||||
regs.ML++;
|
||||
}
|
||||
|
||||
private void DI(byte cmd)
|
||||
{
|
||||
IFF1 = false;
|
||||
IFF2 = false;
|
||||
}
|
||||
|
||||
private void EI(byte cmd)
|
||||
{
|
||||
IFF1 = true;
|
||||
IFF2 = true;
|
||||
BINT = true;
|
||||
}
|
||||
|
||||
private void LDSPHL(byte cmd) // LD SP,HL
|
||||
{
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
regs.SP = regs.HL;
|
||||
}
|
||||
|
||||
private void EX_SP_HL(byte cmd) // EX (SP),HL
|
||||
{
|
||||
// 19T (4, 3, 4, 3, 5)
|
||||
|
||||
ushort tmpsp = regs.SP;
|
||||
regs.MW = RDMEM(tmpsp); Tact += 3;
|
||||
tmpsp++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(tmpsp) * 0x100); Tact += 3;
|
||||
RDNOMREQ(tmpsp); Tact += 1;
|
||||
|
||||
WRMEM(tmpsp, regs.H); Tact += 3;
|
||||
tmpsp--;
|
||||
|
||||
WRMEM(tmpsp, regs.L); Tact += 3;
|
||||
WRNOMREQ(tmpsp); Tact++;
|
||||
WRNOMREQ(tmpsp); Tact++;
|
||||
regs.HL = regs.MW;
|
||||
}
|
||||
|
||||
private void JP_HL_(byte cmd) // JP (HL)
|
||||
{
|
||||
regs.PC = regs.HL;
|
||||
}
|
||||
|
||||
private void EXDEHL(byte cmd) // EX DE,HL
|
||||
{
|
||||
(regs.DE, regs.HL) = (regs.HL, regs.DE);
|
||||
}
|
||||
|
||||
private void EXAFAF(byte cmd) // EX AF,AF'
|
||||
{
|
||||
(regs._AF, regs.AF) = (regs.AF, regs._AF);
|
||||
}
|
||||
|
||||
private void EXX(byte cmd) // EXX
|
||||
{
|
||||
(regs._BC, regs.BC) = (regs.BC, regs._BC);
|
||||
(regs._DE, regs.DE) = (regs.DE, regs._DE);
|
||||
(regs._HL, regs.HL) = (regs.HL, regs._HL);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region logical
|
||||
|
||||
private void RLCA(byte cmd)
|
||||
{
|
||||
regs.F = (byte)(CpuTables.Rlcaf[regs.A] | (regs.F & CpuFlags.SZP));
|
||||
int x = regs.A;
|
||||
x <<= 1;
|
||||
if ((x & 0x100) != 0) x |= 0x01;
|
||||
regs.A = (byte)x;
|
||||
}
|
||||
|
||||
private void RRCA(byte cmd)
|
||||
{
|
||||
regs.F = (byte)(CpuTables.Rrcaf[regs.A] | (regs.F & CpuFlags.SZP));
|
||||
int x = regs.A;
|
||||
if ((x & 0x01) != 0) x = (x >> 1) | 0x80;
|
||||
else x >>= 1;
|
||||
regs.A = (byte)x;
|
||||
}
|
||||
|
||||
private void RLA(byte cmd)
|
||||
{
|
||||
var carry = (regs.F & CpuFlags.C) != 0;
|
||||
regs.F = (byte)(CpuTables.Rlcaf[regs.A] | (regs.F & CpuFlags.SZP)); // use same table with rlca
|
||||
regs.A = (byte)(regs.A << 1);
|
||||
if (carry) regs.A |= 0x01;
|
||||
}
|
||||
|
||||
private void RRA(byte cmd)
|
||||
{
|
||||
var carry = (regs.F & CpuFlags.C) != 0;
|
||||
regs.F = (byte)(CpuTables.Rrcaf[regs.A] | (regs.F & CpuFlags.SZP)); // use same table with rrca
|
||||
regs.A = (byte)(regs.A >> 1);
|
||||
if (carry) regs.A |= 0x80;
|
||||
}
|
||||
|
||||
private void DAA(byte cmd)
|
||||
{
|
||||
regs.AF = CpuTables.Daaf[regs.A + 0x100 * ((regs.F & 3) + ((regs.F >> 2) & 4))];
|
||||
}
|
||||
|
||||
private void CPL(byte cmd)
|
||||
{
|
||||
regs.A = (byte)~regs.A;
|
||||
regs.F = (byte)((regs.F & CpuFlags.NotF3F5) | CpuFlags.HN | (regs.A & CpuFlags.F3F5));
|
||||
}
|
||||
|
||||
private void SCF_ZILOG(byte cmd)
|
||||
{
|
||||
regs.F = (byte)((regs.F & CpuFlags.SZP) |
|
||||
(((regs.F ^ regs.Q) | regs.A) & CpuFlags.F3F5) |
|
||||
CpuFlags.C);
|
||||
}
|
||||
|
||||
private void SCF_ST_CMOS(byte cmd)
|
||||
{
|
||||
regs.F = (byte)((regs.F & CpuFlags.SZP) |
|
||||
((((regs.F ^ regs.Q) & CpuFlags.F5) | regs.A) & CpuFlags.F3F5) |
|
||||
CpuFlags.C);
|
||||
}
|
||||
|
||||
private void SCF_NEC_NMOS(byte cmd)
|
||||
{
|
||||
regs.F = (byte)((regs.F & CpuFlags.SZP) |
|
||||
(regs.A & CpuFlags.F3F5) |
|
||||
CpuFlags.C);
|
||||
}
|
||||
|
||||
private void CCF_ZILOG(byte cmd)
|
||||
{
|
||||
regs.F = (byte)(((regs.F & CpuFlags.SZPC) ^ CpuFlags.C) |
|
||||
(((regs.F ^ regs.Q) | regs.A) & CpuFlags.F3F5) |
|
||||
((regs.F & CpuFlags.C) << 4));
|
||||
}
|
||||
|
||||
private void CCF_ST_CMOS(byte cmd)
|
||||
{
|
||||
regs.F = (byte)(((regs.F & CpuFlags.SZPC) ^ CpuFlags.C) |
|
||||
((((regs.F ^ regs.Q) & CpuFlags.F5) | regs.A) & CpuFlags.F3F5) |
|
||||
((regs.F & CpuFlags.C) << 4));
|
||||
}
|
||||
|
||||
private void CCF_NEC_NMOS(byte cmd)
|
||||
{
|
||||
regs.F = (byte)(((regs.F & CpuFlags.SZPC) ^ CpuFlags.C) |
|
||||
(regs.A & CpuFlags.F3F5) |
|
||||
((regs.F & CpuFlags.C) << 4));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region jmp/call/ret/jr
|
||||
|
||||
private static readonly byte[] s_conds =
|
||||
[
|
||||
CpuFlags.Z,
|
||||
CpuFlags.C,
|
||||
CpuFlags.P,
|
||||
CpuFlags.S
|
||||
];
|
||||
|
||||
private void DJNZ(byte cmd) // DJNZ nn
|
||||
{
|
||||
// B==0 => 8T (5, 3)
|
||||
// B!=0 => 13T (5, 3, 5)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
if (--regs.B != 0)
|
||||
{
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
regs.MW = (ushort)(regs.PC + drel);
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
}
|
||||
|
||||
private void JRNN(byte cmd) // JR nn
|
||||
{
|
||||
// 12T (4, 3, 5)
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
regs.MW = (ushort)(regs.PC + drel);
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
|
||||
private void JRXNN(byte cmd) // JR x,nn
|
||||
{
|
||||
// false => 7T (4, 3)
|
||||
// true => 12 (4, 3, 5)
|
||||
var cond = (cmd & 0x18) >> 3;
|
||||
var mask = s_conds[cond >> 1];
|
||||
var f = regs.AF & mask;
|
||||
if ((cond & 1) != 0) f ^= mask;
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
if (f == 0)
|
||||
{
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
regs.MW = (ushort)(regs.PC + drel);
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
}
|
||||
|
||||
private void CALLNNNN(byte cmd) // CALL
|
||||
{
|
||||
// 17T (4, 3, 4, 3, 3)
|
||||
|
||||
regs.MW = RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(regs.PC) * 0x100); Tact += 3;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
regs.PC++;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)(regs.PC >> 8)); Tact += 3;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)regs.PC); Tact += 3;
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
|
||||
private void CALLXNNNN(byte cmd) // CALL x,#nn
|
||||
{
|
||||
// false => 10T (4, 3, 3)
|
||||
// true => 17T (4, 3, 4, 3, 3)
|
||||
var cond = (cmd & 0x38) >> 3;
|
||||
var mask = s_conds[cond >> 1];
|
||||
var f = regs.AF & mask;
|
||||
if ((cond & 1) != 0) f ^= mask;
|
||||
|
||||
regs.MW = RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(regs.PC) * 0x100); Tact += 3;
|
||||
if (f == 0)
|
||||
{
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
}
|
||||
regs.PC++;
|
||||
|
||||
if (f == 0)
|
||||
{
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)(regs.PC >> 8)); Tact += 3;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)regs.PC); Tact += 3;
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
}
|
||||
|
||||
private void RET(byte cmd) // RET
|
||||
{
|
||||
// 10T (4, 3, 3)
|
||||
|
||||
regs.MW = RDMEM(regs.SP); Tact += 3;
|
||||
regs.SP++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(regs.SP) * 0x100); Tact += 3;
|
||||
regs.SP++;
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
|
||||
private void RETX(byte cmd) // RET x
|
||||
{
|
||||
// false => 5T (5)
|
||||
// true => 11T (5, 3, 3)
|
||||
var cond = (cmd & 0x38) >> 3;
|
||||
var mask = s_conds[cond >> 1];
|
||||
var f = regs.AF & mask;
|
||||
if ((cond & 1) != 0) f ^= mask;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
if (f == 0)
|
||||
{
|
||||
regs.MW = RDMEM(regs.SP); Tact += 3;
|
||||
regs.SP++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(regs.SP) * 0x100); Tact += 3;
|
||||
regs.SP++;
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
}
|
||||
|
||||
private void JPNNNN(byte cmd) // JP nnnn
|
||||
{
|
||||
// 10T (4, 3, 3)
|
||||
|
||||
regs.MW = RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(regs.PC) * 0x100); Tact += 3;
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
|
||||
private void JPXNN(byte cmd) // JP x,#nn ???
|
||||
{
|
||||
// 10T (4, 3, 3)
|
||||
var cond = (cmd & 0x38) >> 3;
|
||||
var mask = s_conds[cond >> 1];
|
||||
var f = regs.AF & mask;
|
||||
if ((cond & 1) != 0) f ^= mask;
|
||||
|
||||
regs.MW = RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(regs.PC) * 0x100); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
if (f == 0)
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
|
||||
private void RSTNN(byte cmd) // RST #nn ?TIME?
|
||||
{
|
||||
// 11T (5, 3, 3)
|
||||
var rst = (ushort)(cmd & 0x38);
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)(regs.PC >> 8)); Tact += 3;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)regs.PC); Tact += 3;
|
||||
regs.MW = rst;
|
||||
regs.PC = regs.MW;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region push/pop
|
||||
|
||||
private void PUSHRR(byte cmd) // PUSH RR ?TIME?
|
||||
{
|
||||
// 11T (5, 3, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
ushort val = rr == CpuRegId.Sp ? regs.AF : _pairGetters[rr]();
|
||||
|
||||
regs.SP--;
|
||||
WRMEM(regs.SP, (byte)(val >> 8)); Tact += 3;
|
||||
|
||||
regs.SP--;
|
||||
WRMEM(regs.SP, (byte)val); Tact += 3;
|
||||
}
|
||||
|
||||
private void POPRR(byte cmd) // POP RR
|
||||
{
|
||||
// 10T (4, 3, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
var val = (ushort)RDMEM(regs.SP);
|
||||
regs.SP++;
|
||||
Tact += 3;
|
||||
|
||||
val |= (ushort)(RDMEM(regs.SP) << 8);
|
||||
regs.SP++;
|
||||
if (rr == CpuRegId.Sp) regs.AF = val;
|
||||
else _pairSetters[rr](val);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ALU
|
||||
|
||||
private void ALUAN(byte cmd)
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var op = (cmd & 0x38) >> 3;
|
||||
|
||||
var val = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
_alualg[op](val);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void ALUAR(byte cmd) // ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,R
|
||||
{
|
||||
var r = cmd & 0x07;
|
||||
var op = (cmd & 0x38) >> 3;
|
||||
|
||||
_alualg[op](_regGetters[r]());
|
||||
}
|
||||
|
||||
private void ALUA_HL_(byte cmd) // ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,(HL)
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var op = (cmd & 0x38) >> 3;
|
||||
|
||||
var val = RDMEM(regs.HL);
|
||||
_alualg[op](val);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void ADDHLRR(byte cmd) // ADD HL,RR
|
||||
{
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
regs.MW = (ushort)(regs.HL + 1);
|
||||
regs.HL = ALU_ADDHLRR(regs.HL, _pairGetters[(cmd & 0x30) >> 4]());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region loads
|
||||
|
||||
private void LDA_RR_(byte cmd) // LD A,(RR)
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
var rrValue = _pairGetters[rr]();
|
||||
regs.A = RDMEM(rrValue);
|
||||
regs.MW = (ushort)(rrValue + 1);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LDA_NN_(byte cmd) // LD A,(nnnn)
|
||||
{
|
||||
// 13T (4, 3, 3, 3)
|
||||
|
||||
ushort adr = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
regs.A = RDMEM(adr);
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LDHL_NN_(byte cmd) // LD HL,(nnnn)
|
||||
{
|
||||
// 16T (4, 3, 3, 3, 3)
|
||||
|
||||
var adr = (ushort)RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
var val = (ushort)RDMEM(adr);
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
Tact += 3;
|
||||
|
||||
val += (ushort)(RDMEM(regs.MW) * 0x100);
|
||||
regs.HL = val;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LD_RR_A(byte cmd) // LD (RR),A
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
var rrValue = _pairGetters[rr]();
|
||||
WRMEM(rrValue, regs.A);
|
||||
regs.MH = regs.A;
|
||||
regs.ML = (byte)(rrValue + 1);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LD_NN_A(byte cmd) // LD (nnnn),A
|
||||
{
|
||||
// 13T (4, 3, 3, 3)
|
||||
|
||||
ushort adr = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(adr, regs.A);
|
||||
regs.MH = regs.A;
|
||||
regs.ML = (byte)(adr + 1);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LD_NN_HL(byte cmd) // LD (nnnn),HL
|
||||
{
|
||||
// 16T (4, 3, 3, 3, 3)
|
||||
|
||||
ushort adr = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(adr, regs.L);
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(regs.MW, regs.H);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LDRRNNNN(byte cmd) // LD RR,nnnn
|
||||
{
|
||||
// 10T (4, 3, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
ushort val = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
val |= (ushort)(RDMEM(regs.PC) << 8);
|
||||
regs.PC++;
|
||||
_pairSetters[rr](val);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LDRNN(byte cmd) // LD R,nn
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
_regSetters[r](RDMEM(regs.PC));
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LD_HL_NN(byte cmd) // LD (HL),nn
|
||||
{
|
||||
// 10T (4, 3, 3)
|
||||
|
||||
var val = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(regs.HL, val);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LDRdRs(byte cmd) // LD R1,R2
|
||||
{
|
||||
var rsrc = cmd & 0x07;
|
||||
var rdst = (cmd & 0x38) >> 3;
|
||||
_regSetters[rdst](_regGetters[rsrc]());
|
||||
}
|
||||
|
||||
private void LD_HL_R(byte cmd) // LD (HL),R
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var r = cmd & 0x07;
|
||||
|
||||
WRMEM(regs.HL, _regGetters[r]());
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void LDR_HL_(byte cmd) // LD R,(HL)
|
||||
{
|
||||
// 7T (4, 3)
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
_regSetters[r](RDMEM(regs.HL));
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INC/DEC
|
||||
|
||||
private void DECRR(byte cmd) // DEC RR
|
||||
{
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
_pairSetters[rr]((ushort)(_pairGetters[rr]() - 1));
|
||||
}
|
||||
|
||||
private void INCRR(byte cmd) // INC RR
|
||||
{
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
_pairSetters[rr]((ushort)(_pairGetters[rr]() + 1));
|
||||
}
|
||||
|
||||
private void DECR(byte cmd) // DEC R
|
||||
{
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
_regSetters[r](ALU_DECR(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void INCR(byte cmd) // INC R
|
||||
{
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
_regSetters[r](ALU_INCR(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void DEC_HL_(byte cmd) // DEC (HL)
|
||||
{
|
||||
// 11T (4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_DECR(val);
|
||||
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void INC_HL_(byte cmd) // INC (HL)
|
||||
{
|
||||
// 11T (4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_INCR(val);
|
||||
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void HALT(byte cmd)
|
||||
{
|
||||
HALTED = true;
|
||||
regs.PC--; // workaround for Z80 snapshot halt issue + comfortable debugging
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [CB prefixed opcodes part]
|
||||
* Date: 13.04.2007
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
private void CB_RLC(byte cmd) // RLC r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_RLC(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_RRC(byte cmd) // RRC r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_RRC(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_RL(byte cmd) // RL r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_RL(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_RR(byte cmd) // RR r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_RR(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_SLA(byte cmd) // SLA r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_SLA(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_SRA(byte cmd) // SRA r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_SRA(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_SLL(byte cmd) // *SLL r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_SLL(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_SRL(byte cmd) // SRL r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
_regSetters[r](ALU_SRL(_regGetters[r]()));
|
||||
}
|
||||
|
||||
private void CB_BIT(byte cmd) // BIT r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
var b = (cmd & 0x38) >> 3;
|
||||
|
||||
ALU_BIT(_regGetters[r](), b);
|
||||
}
|
||||
|
||||
private void CB_RES(byte cmd) // RES r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
var m = ~(1 << ((cmd & 0x38) >> 3));
|
||||
|
||||
_regSetters[r]((byte)(_regGetters[r]() & m));
|
||||
}
|
||||
|
||||
private void CB_SET(byte cmd) // SET r
|
||||
{
|
||||
var r = cmd & 7;
|
||||
var m = 1 << ((cmd & 0x38) >> 3);
|
||||
|
||||
_regSetters[r]((byte)(_regGetters[r]() | m));
|
||||
}
|
||||
|
||||
private void CB_RLCHL(byte cmd) // RLC (HL)
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_RLC(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_RRCHL(byte cmd) // RRC (HL)
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_RRC(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_RLHL(byte cmd) // RL (HL)
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_RL(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_RRHL(byte cmd) // RR (HL) [15T]
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_RR(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_SLAHL(byte cmd) // SLA (HL) [15T]
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_SLA(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_SRAHL(byte cmd) // SRA (HL) [15T]
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_SRA(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_SLLHL(byte cmd) // *SLL (HL) [15T]
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_SLL(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_SRLHL(byte cmd) // SRL (HL)
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val = ALU_SRL(val);
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_BITHL(byte cmd) // BIT (HL) [12T]
|
||||
{
|
||||
// 12T (4, 4, 4)
|
||||
var b = (cmd & 0x38) >> 3;
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 4;
|
||||
ALU_BITMEM(val, b);
|
||||
}
|
||||
|
||||
private void CB_RESHL(byte cmd) // RES (HL) [15T]
|
||||
{
|
||||
// 15 (4, 4, 4, 3)
|
||||
var m = (byte)~(1 << ((cmd & 0x38) >> 3));
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val &= m;
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void CB_SETHL(byte cmd) // SET (HL) [15T]
|
||||
{
|
||||
// 15T (4, 4, 4, 3)
|
||||
var m = (byte)(1 << ((cmd & 0x38) >> 3));
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
val |= m;
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,880 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [ED prefixed opcode part]
|
||||
* Date: 13.04.2007
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
private void ED_LDI(byte cmd)
|
||||
{
|
||||
// 16T (4, 4, 3, 5)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
WRMEM(regs.DE, val); Tact += 3;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
|
||||
regs.HL++;
|
||||
regs.DE++;
|
||||
regs.BC--;
|
||||
val += regs.A;
|
||||
|
||||
regs.F = (byte)((regs.F & CpuFlags.NotHPNF3F5) |
|
||||
(val & CpuFlags.F3) | ((val << 4) & CpuFlags.F5));
|
||||
if (regs.BC != 0) regs.F |= CpuFlags.P;
|
||||
}
|
||||
|
||||
private void ED_CPI(byte cmd)
|
||||
{
|
||||
// 16T (4, 4, 3, 5)
|
||||
|
||||
var cf = regs.F & CpuFlags.C;
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
|
||||
regs.HL++;
|
||||
regs.F = (byte)(CpuTables.Cpf8b[regs.A * 0x100 + val] + cf);
|
||||
if (--regs.BC != 0) regs.F |= CpuFlags.P;
|
||||
regs.MW++;
|
||||
}
|
||||
|
||||
private void ED_INI(byte cmd) // INI [16T]
|
||||
{
|
||||
// 16T (4, 5, 3, 4)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
var val = RDPORT(regs.BC); Tact += 3;
|
||||
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
|
||||
regs.MW = (ushort)(regs.BC + 1);
|
||||
regs.HL++;
|
||||
regs.B--;
|
||||
|
||||
//FUSE
|
||||
byte flgtmp = (byte)(val + regs.C + 1);
|
||||
regs.F = (byte)(CpuTables.Logf[regs.B] & CpuFlags.NotP);
|
||||
if ((CpuTables.Logf[(flgtmp & 0x07) ^ regs.B] & CpuFlags.P) != 0) regs.F |= CpuFlags.P;
|
||||
if (flgtmp < val) regs.F |= CpuFlags.HC;
|
||||
if ((val & 0x80) != 0) regs.F |= CpuFlags.N;
|
||||
|
||||
Tact++; //?? really?
|
||||
}
|
||||
|
||||
private void ED_OUTI(byte cmd) // OUTI [16T]
|
||||
{
|
||||
// 16 (4, 5, 3, 4)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
regs.B--;
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
WRPORT(regs.BC, val); Tact += 3;
|
||||
|
||||
regs.MW = (ushort)(regs.BC + 1);
|
||||
regs.HL++;
|
||||
|
||||
//FUSE
|
||||
byte flgtmp = (byte)(val + regs.L);
|
||||
regs.F = (byte)(CpuTables.Logf[regs.B] & CpuFlags.NotP);
|
||||
if ((CpuTables.Logf[(flgtmp & 0x07) ^ regs.B] & CpuFlags.P) != 0) regs.F |= CpuFlags.P;
|
||||
if (flgtmp < val) regs.F |= CpuFlags.HC;
|
||||
if ((val & 0x80) != 0) regs.F |= CpuFlags.N;
|
||||
|
||||
Tact++; //?? really?
|
||||
}
|
||||
|
||||
private void ED_LDD(byte cmd)
|
||||
{
|
||||
// 16T (4, 4, 3, 5)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
WRMEM(regs.DE, val); Tact += 3;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
|
||||
regs.HL--;
|
||||
regs.DE--;
|
||||
regs.BC--;
|
||||
val += regs.A;
|
||||
|
||||
regs.F = (byte)((regs.F & CpuFlags.NotHPNF3F5) |
|
||||
(val & CpuFlags.F3) | ((val << 4) & CpuFlags.F5));
|
||||
if (regs.BC != 0) regs.F |= CpuFlags.P;
|
||||
}
|
||||
|
||||
private void ED_CPD(byte cmd)
|
||||
{
|
||||
// 16T (4, 4, 3, 5)
|
||||
|
||||
var cf = regs.F & CpuFlags.C;
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
|
||||
regs.HL--;
|
||||
regs.BC--;
|
||||
regs.MW--;
|
||||
regs.F = (byte)(CpuTables.Cpf8b[regs.A * 0x100 + val] + cf);
|
||||
if (regs.BC != 0) regs.F |= CpuFlags.P;
|
||||
}
|
||||
|
||||
private void ED_IND(byte cmd) // IND [16T]
|
||||
{
|
||||
// 16T (4, 5, 3, 4)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
var val = RDPORT(regs.BC); Tact += 3;
|
||||
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
|
||||
regs.MW = (ushort)(regs.BC - 1);
|
||||
regs.HL--;
|
||||
regs.B--;
|
||||
|
||||
//FUSE
|
||||
byte flgtmp = (byte)(val + regs.C - 1);
|
||||
regs.F = (byte)(CpuTables.Logf[regs.B] & CpuFlags.NotP);
|
||||
if ((CpuTables.Logf[(flgtmp & 0x07) ^ regs.B] & CpuFlags.P) != 0) regs.F |= CpuFlags.P;
|
||||
if (flgtmp < val) regs.F |= CpuFlags.HC;
|
||||
if ((val & 0x80) != 0) regs.F |= CpuFlags.N;
|
||||
|
||||
Tact++; // ?? really?
|
||||
}
|
||||
|
||||
private void ED_OUTD(byte cmd) // OUTD [16T]
|
||||
{
|
||||
// 16T (4, 5, 3, 4)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
regs.B--;
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
WRPORT(regs.BC, val); Tact += 3;
|
||||
|
||||
regs.MW = (ushort)(regs.BC - 1);
|
||||
regs.HL--;
|
||||
|
||||
//FUSE
|
||||
byte flgtmp = (byte)(val + regs.L);
|
||||
regs.F = (byte)(CpuTables.Logf[regs.B] & CpuFlags.NotP);
|
||||
if ((CpuTables.Logf[(flgtmp & 0x07) ^ regs.B] & CpuFlags.P) != 0) regs.F |= CpuFlags.P;
|
||||
if (flgtmp < val) regs.F |= CpuFlags.HC;
|
||||
if ((val & 0x80) != 0) regs.F |= CpuFlags.N;
|
||||
|
||||
Tact++; // ?? really?
|
||||
}
|
||||
|
||||
private void ED_LDIR(byte cmd)
|
||||
{
|
||||
//BC==0 => 16T (4, 4, 3, 5)
|
||||
//BC!=0 => 21T (4, 4, 3, 5, 5)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
WRMEM(regs.DE, val); Tact += 3;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
|
||||
regs.BC--;
|
||||
val += regs.A;
|
||||
|
||||
regs.F &= CpuFlags.NotHPNF3F5;
|
||||
if (regs.BC != 0)
|
||||
{
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
regs.PC--;
|
||||
regs.MW = regs.PC;
|
||||
regs.PC--;
|
||||
|
||||
// YF = PCi.13; XF = PCi.11
|
||||
regs.F |= (byte)(regs.PCH & CpuFlags.F3F5);
|
||||
regs.F |= CpuFlags.P;
|
||||
}
|
||||
else
|
||||
{
|
||||
// YF = PCi.13; XF = PCi.11
|
||||
regs.F |= (byte)((val & CpuFlags.F3) | ((val << 4) & CpuFlags.F5));
|
||||
}
|
||||
regs.HL++;
|
||||
regs.DE++;
|
||||
}
|
||||
|
||||
private void ED_CPIR(byte cmd)
|
||||
{
|
||||
//BC==0 => 16T (4, 4, 3, 5)
|
||||
//BC!=0 => 21T (4, 4, 3, 5, 5)
|
||||
|
||||
regs.MW++;
|
||||
var cf = regs.F & CpuFlags.C;
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
|
||||
regs.BC--;
|
||||
regs.F = (byte)(CpuTables.Cpf8b[regs.A * 0x100 + val] + cf);
|
||||
|
||||
if (regs.BC != 0)
|
||||
{
|
||||
regs.F |= CpuFlags.P;
|
||||
if ((regs.F & CpuFlags.Z) == 0)
|
||||
{
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
regs.PC--;
|
||||
regs.MW = regs.PC;
|
||||
regs.PC--;
|
||||
|
||||
// YF = PCi.13; XF = PCi.11
|
||||
regs.F &= CpuFlags.NotF3F5;
|
||||
regs.F |= (byte)(regs.PCH & CpuFlags.F3F5);
|
||||
}
|
||||
}
|
||||
regs.HL++;
|
||||
}
|
||||
|
||||
private void ED_INIR(byte cmd) // INIR [16T/21T]
|
||||
{
|
||||
// B==0 => 16T (4, 5, 3, 4)
|
||||
// B!=0 => 21T (4, 5, 3, 4, 5)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
var val = RDPORT(regs.BC); Tact += 3;
|
||||
|
||||
var nf = (byte)((val >> 6) & CpuFlags.N);
|
||||
var t = val + ((regs.C + 1) & 0xff);
|
||||
var hcf = t > 255 ? CpuFlags.HC : 0;
|
||||
|
||||
WRMEM(regs.HL++, val); Tact += 3;
|
||||
regs.MW = (ushort)(regs.BC + 1);
|
||||
|
||||
regs.B--; Tact++;
|
||||
var pf = CpuTables.Parity[(t & 7) ^ regs.B];
|
||||
|
||||
if (regs.B != 0)
|
||||
{
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
regs.PC -= 2;
|
||||
|
||||
regs.F = (byte)(
|
||||
/* ZF = 0 */
|
||||
(regs.B & CpuFlags.S) | /* SF = Bo.7 */
|
||||
(regs.PCH & CpuFlags.F3F5) | /* YF = PCi.13; XF = PCi.11 */
|
||||
nf); /* NF = IO.7 */
|
||||
if (hcf != 0)
|
||||
{
|
||||
regs.F |= CpuFlags.C;
|
||||
if ((val & 0x80) != 0)
|
||||
{
|
||||
// PF = PF ^ Parity((B - 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x00;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B - 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x00)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity((B + 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x0F;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B + 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x0f)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity(B & 0x7) ^ 1;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[regs.B & 7] ^ CpuFlags.P);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.F = (byte)(CpuFlags.Z | /* ZF = 1; SF, YF, XF = 0 */
|
||||
hcf | /* HF, CF = T > 255 */
|
||||
pf | /* PF = ((T & 7) ^ Bo).parity */
|
||||
nf); /* NF = IO.7 */
|
||||
}
|
||||
}
|
||||
|
||||
private void ED_OTIR(byte cmd) // OTIR [16T/21T]
|
||||
{
|
||||
// B==0 => 16T (4, 5, 3, 4)
|
||||
// B!=0 => 21T (4, 5, 3, 4, 5)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
var val = RDMEM(regs.HL++); Tact += 3;
|
||||
regs.MW = (ushort)(regs.BC + 1);
|
||||
|
||||
var nf = (byte)((val >> 6) & CpuFlags.N);
|
||||
var t = val + regs.L;
|
||||
var hcf = t > 255 ? CpuFlags.HC : 0;
|
||||
|
||||
regs.B--;
|
||||
var pf = CpuTables.Parity[(t & 7) ^ regs.B];
|
||||
|
||||
WRPORT(regs.BC, val); Tact += 3;
|
||||
Tact++;
|
||||
|
||||
if (regs.B != 0)
|
||||
{
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
regs.PC -= 2;
|
||||
|
||||
regs.F = (byte)(
|
||||
/* ZF = 0 */
|
||||
(regs.B & CpuFlags.S) | /* SF = Bo.7 */
|
||||
(regs.PCH & CpuFlags.F3F5) |/* YF = PCi.13; XF = PCi.11 */
|
||||
nf); /* NF = IO.7 */
|
||||
if (hcf != 0)
|
||||
{
|
||||
regs.F |= CpuFlags.C;
|
||||
if ((val & 0x80) != 0)
|
||||
{
|
||||
// PF = PF ^ Parity((B - 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x00;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B - 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x00)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity((B + 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x0F;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B + 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x0f)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity(B & 0x7) ^ 1;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[regs.B & 7] ^ CpuFlags.P);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.F = (byte)(CpuFlags.Z | /* ZF = 1; SF, YF, XF = 0 */
|
||||
hcf | /* HF, CF = T > 255 */
|
||||
pf | /* PF = ((T & 7) ^ Bo).parity */
|
||||
nf); /* NF = IO.7 */
|
||||
}
|
||||
}
|
||||
|
||||
private void ED_LDDR(byte cmd)
|
||||
{
|
||||
//BC==0 => 16T (4, 4, 3, 5)
|
||||
//BC!=0 => 21T (4, 4, 3, 5, 5)
|
||||
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
WRMEM(regs.DE, val); Tact += 3;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
|
||||
regs.BC--;
|
||||
val += regs.A;
|
||||
|
||||
regs.F &= CpuFlags.NotHPNF3F5;
|
||||
if (regs.BC != 0)
|
||||
{
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
WRNOMREQ(regs.DE); Tact++;
|
||||
regs.PC--;
|
||||
regs.MW = regs.PC;
|
||||
regs.PC--;
|
||||
|
||||
// YF = PCi.13; XF = PCi.11
|
||||
regs.F |= (byte)(regs.PCH & CpuFlags.F3F5);
|
||||
regs.F |= CpuFlags.P;
|
||||
}
|
||||
else
|
||||
{
|
||||
// YF = PCi.13; XF = PCi.11
|
||||
regs.F |= (byte)((val & CpuFlags.F3) | ((val << 4) & CpuFlags.F5));
|
||||
}
|
||||
regs.HL--;
|
||||
regs.DE--;
|
||||
}
|
||||
|
||||
private void ED_CPDR(byte cmd)
|
||||
{
|
||||
// BC==0 => 16T (4, 4, 3, 5)
|
||||
// BC!=0 => 21T (4, 4, 3, 5, 5)
|
||||
|
||||
regs.MW--;
|
||||
var cf = regs.F & CpuFlags.C;
|
||||
var val = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
regs.BC--;
|
||||
regs.F = (byte)(CpuTables.Cpf8b[regs.A * 0x100 + val] + cf);
|
||||
|
||||
if (regs.BC != 0)
|
||||
{
|
||||
regs.F |= CpuFlags.P;
|
||||
if ((regs.F & CpuFlags.Z) == 0)
|
||||
{
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
regs.PC--;
|
||||
regs.MW = regs.PC;
|
||||
regs.PC--;
|
||||
|
||||
// YF = PCi.13; XF = PCi.11
|
||||
regs.F &= CpuFlags.NotF3F5;
|
||||
regs.F |= (byte)(regs.PCH & CpuFlags.F3F5);
|
||||
}
|
||||
}
|
||||
regs.HL--;
|
||||
}
|
||||
|
||||
private void ED_INDR(byte cmd) // INDR [16T/21T]
|
||||
{
|
||||
// B==0 => 16 (4, 5, 3, 4)
|
||||
// B!=0 => 21 (4, 5, 3, 4, 5)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
var val = RDPORT(regs.BC); Tact += 3;
|
||||
|
||||
var nf = (byte)((val >> 6) & CpuFlags.N);
|
||||
var t = val + ((regs.C - 1) & 0xff);
|
||||
var hcf = t > 255 ? CpuFlags.HC : 0;
|
||||
|
||||
WRMEM(regs.HL--, val); Tact += 3;
|
||||
regs.MW = (ushort)(regs.BC - 1);
|
||||
|
||||
regs.B--; Tact++;
|
||||
var pf = CpuTables.Parity[(t & 7) ^ regs.B];
|
||||
|
||||
if (regs.B != 0)
|
||||
{
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
WRNOMREQ(regs.HL); Tact++;
|
||||
regs.PC -= 2;
|
||||
|
||||
regs.F = (byte)(
|
||||
/* ZF = 0 */
|
||||
(regs.B & CpuFlags.S) | /* SF = Bo.7 */
|
||||
(regs.PCH & CpuFlags.F3F5) |/* YF = PCi.13; XF = PCi.11 */
|
||||
nf); /* NF = IO.7 */
|
||||
if (hcf != 0)
|
||||
{
|
||||
regs.F |= CpuFlags.C;
|
||||
if ((val & 0x80) != 0)
|
||||
{
|
||||
// PF = PF ^ Parity((B - 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x00;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B - 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x00)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity((B + 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x0F;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B + 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x0f)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity(B & 0x7) ^ 1;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[regs.B & 7] ^ CpuFlags.P);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.F = (byte)(CpuFlags.Z | /* ZF = 1; SF, YF, XF = 0 */
|
||||
hcf | /* HF, CF = T > 255 */
|
||||
pf | /* PF = ((T & 7) ^ Bo).parity */
|
||||
nf); /* NF = IO.7 */
|
||||
}
|
||||
}
|
||||
|
||||
private void ED_OTDR(byte cmd) //OTDR [16T/21T]
|
||||
{
|
||||
// B==0 => 16T (4, 5, 3, 4)
|
||||
// B!=0 => 21T (4, 5, 3, 4, 5)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
var val = RDMEM(regs.HL--); Tact += 3;
|
||||
regs.MW = (ushort)(regs.BC - 1);
|
||||
|
||||
var nf = (byte)((val >> 6) & CpuFlags.N);
|
||||
var t = val + regs.L;
|
||||
var hcf = t > 255 ? CpuFlags.HC : 0;
|
||||
|
||||
regs.B--;
|
||||
var pf = CpuTables.Parity[(t & 7) ^ regs.B];
|
||||
|
||||
WRPORT(regs.BC, val); Tact += 3;
|
||||
Tact++;
|
||||
|
||||
if (regs.B != 0)
|
||||
{
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
RDNOMREQ(regs.BC); Tact++;
|
||||
regs.PC -= 2;
|
||||
|
||||
regs.F = (byte)(
|
||||
/* ZF = 0 */
|
||||
(regs.B & CpuFlags.S) | /* SF = Bo.7 */
|
||||
(regs.PCH & CpuFlags.F3F5) |/* YF = PCi.13; XF = PCi.11 */
|
||||
nf); /* NF = IO.7 */
|
||||
if (hcf != 0)
|
||||
{
|
||||
regs.F |= CpuFlags.C;
|
||||
if ((val & 0x80) != 0)
|
||||
{
|
||||
// PF = PF ^ Parity((B - 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x00;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B - 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x00)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity((B + 1) & 0x7) ^ 1;
|
||||
// HF = (B & 0x0F) == 0x0F;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[(regs.B + 1) & 7] ^ CpuFlags.P);
|
||||
if ((regs.B & 0x0f) == 0x0f)
|
||||
regs.F |= CpuFlags.H;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PF = PF ^ Parity(B & 0x7) ^ 1;
|
||||
regs.F |= (byte)(pf ^ CpuTables.Parity[regs.B & 7] ^ CpuFlags.P);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.F = (byte)(CpuFlags.Z | /* ZF = 1; SF, YF, XF = 0 */
|
||||
hcf | /* HF, CF = T > 255 */
|
||||
pf | /* PF = ((T & 7) ^ Bo).parity */
|
||||
nf); /* NF = IO.7 */
|
||||
}
|
||||
}
|
||||
|
||||
private void ED_INRC(byte cmd) // in R,(c) [12T]
|
||||
{
|
||||
// 12T (4, 4, 4)
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
regs.MW = regs.BC;
|
||||
var pval = RDPORT(regs.BC);
|
||||
regs.MW++;
|
||||
if (r != CpuRegId.F)
|
||||
_regSetters[r](pval);
|
||||
regs.F = (byte)(CpuTables.Logf[pval] | (regs.F & CpuFlags.C));
|
||||
Tact += 4;
|
||||
}
|
||||
|
||||
private void ED_OUTCR_NMOS(byte cmd) // out (c),R [12T]
|
||||
{
|
||||
// 12T (4, 4, 4)
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
regs.MW = regs.BC;
|
||||
if (r != CpuRegId.F)
|
||||
WRPORT(regs.BC, _regGetters[r]());
|
||||
else
|
||||
WRPORT(regs.BC, 0x00); // 0 for Z80 and 0xFF for Z84
|
||||
regs.MW++;
|
||||
Tact += 4;
|
||||
}
|
||||
|
||||
private void ED_OUTCR_CMOS(byte cmd) // out (c),R [12T]
|
||||
{
|
||||
// 12T (4, 4, 4)
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
regs.MW = regs.BC;
|
||||
if (r != CpuRegId.F)
|
||||
WRPORT(regs.BC, _regGetters[r]());
|
||||
else
|
||||
WRPORT(regs.BC, 0xFF); // 0 for Z80 and 0xFF for Z84
|
||||
regs.MW++;
|
||||
Tact += 4;
|
||||
}
|
||||
|
||||
private void ED_ADCHLRR(byte cmd) // adc hl,RR
|
||||
{
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
regs.MW = (ushort)(regs.HL + 1);
|
||||
byte fl = (byte)((((regs.HL & 0x0FFF) + (_pairGetters[rr]() & 0x0FFF) + (regs.F & CpuFlags.C)) >> 8) & CpuFlags.H);
|
||||
uint tmp = (uint)((regs.HL & 0xFFFF) + (_pairGetters[rr]() & 0xFFFF) + (regs.F & CpuFlags.C)); // AF???
|
||||
if ((tmp & 0x10000) != 0) fl |= CpuFlags.C;
|
||||
if ((tmp & 0xFFFF) == 0) fl |= CpuFlags.Z;
|
||||
int ri = (int)(short)regs.HL + (int)(short)_pairGetters[rr]() + (int)(regs.F & CpuFlags.C);
|
||||
if (ri < -0x8000 || ri >= 0x8000) fl |= CpuFlags.P;
|
||||
regs.HL = (ushort)tmp;
|
||||
regs.F = (byte)(fl | (regs.H & CpuFlags.SF3F5));
|
||||
}
|
||||
|
||||
private void ED_SBCHLRR(byte cmd) // sbc hl,RR
|
||||
{
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
RDNOMREQ(regs.IR); Tact += 1;
|
||||
|
||||
regs.MW = (ushort)(regs.HL + 1);
|
||||
byte fl = CpuFlags.N;
|
||||
fl |= (byte)((((regs.HL & 0x0FFF) - (_pairGetters[rr]() & 0x0FFF) - (regs.F & CpuFlags.C)) >> 8) & CpuFlags.H);
|
||||
uint tmp = (uint)((regs.HL & 0xFFFF) - (_pairGetters[rr]() & 0xFFFF) - (regs.F & CpuFlags.C)); // AF???
|
||||
if ((tmp & 0x10000) != 0) fl |= CpuFlags.C;
|
||||
if ((tmp & 0xFFFF) == 0) fl |= CpuFlags.Z;
|
||||
int ri = (int)(short)regs.HL - (int)(short)_pairGetters[rr]() - (int)(regs.F & CpuFlags.C);
|
||||
if (ri < -0x8000 || ri >= 0x8000) fl |= CpuFlags.P;
|
||||
regs.HL = (ushort)tmp;
|
||||
regs.F = (byte)(fl | (regs.H & CpuFlags.SF3F5));
|
||||
}
|
||||
|
||||
private void ED_LDRR_NN_(byte cmd) // ld RR,(NN)
|
||||
{
|
||||
// 20T (4, 4, 3, 3, 3, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
var adr = (ushort)RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
Tact += 3;
|
||||
|
||||
var val = (ushort)RDMEM(adr);
|
||||
Tact += 3;
|
||||
|
||||
val += (ushort)(RDMEM(regs.MW) * 0x100);
|
||||
_pairSetters[rr](val);
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void ED_LD_NN_RR(byte cmd) // ld (NN),RR
|
||||
{
|
||||
// 20 (4, 4, 3, 3, 3, 3)
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
var adr = (ushort)RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
var val = _pairGetters[rr]();
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(adr, (byte)val);
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(regs.MW, (byte)(val >> 8));
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void ED_RETN(byte cmd) // reti/retn
|
||||
{
|
||||
// 14T (4, 4, 3, 3)
|
||||
|
||||
IFF1 = IFF2;
|
||||
var adr = (ushort)RDMEM(regs.SP);
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(++regs.SP) * 0x100);
|
||||
++regs.SP;
|
||||
regs.PC = adr;
|
||||
regs.MW = adr;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void ED_IM(byte cmd) // im X
|
||||
{
|
||||
var mode = (byte)((cmd & 0x18) >> 3);
|
||||
if (mode < 2) mode = 1;
|
||||
mode--;
|
||||
|
||||
IM = mode;
|
||||
}
|
||||
|
||||
private void ED_LDXRA(byte cmd) // ld I/R,a
|
||||
{
|
||||
var ir = (cmd & 0x08) == 0;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
if (ir) // I
|
||||
regs.I = regs.A;
|
||||
else
|
||||
regs.R = regs.A;
|
||||
}
|
||||
|
||||
private void ED_LDAXR(byte cmd) // ld a,I/R
|
||||
{
|
||||
var ir = (cmd & 0x08) == 0;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
|
||||
if (ir) // I
|
||||
regs.A = regs.I;
|
||||
else
|
||||
regs.A = regs.R;
|
||||
|
||||
regs.F = (byte)(((regs.F & CpuFlags.C) | CpuTables.Logf[regs.A]) & CpuFlags.NotP);
|
||||
switch (_type)
|
||||
{
|
||||
case CpuType.ZILOG_NMOS:
|
||||
case CpuType.NEC_NMOS:
|
||||
case CpuType.ST_CMOS:
|
||||
SCANSIG?.Invoke();
|
||||
if (!(INT && IFF1) && IFF2)
|
||||
{
|
||||
regs.F |= CpuFlags.P;
|
||||
}
|
||||
break;
|
||||
case CpuType.ZILOG_CMOS:
|
||||
if (IFF2)
|
||||
{
|
||||
regs.F |= CpuFlags.P;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private void ED_RRD(byte cmd) // RRD
|
||||
{
|
||||
// 18T (4, 4, 3, 4, 3)
|
||||
|
||||
var tmp = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
|
||||
regs.MW = (ushort)(regs.HL + 1);
|
||||
var val = (byte)((regs.A << 4) | (tmp >> 4));
|
||||
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
regs.A = (byte)((regs.A & 0xF0) | (tmp & 0x0F));
|
||||
regs.F = (byte)(CpuTables.Logf[regs.A] | (regs.F & CpuFlags.C));
|
||||
}
|
||||
|
||||
private void ED_RLD(byte cmd) // RLD
|
||||
{
|
||||
// 18T (4, 4, 3, 4, 3)
|
||||
|
||||
var tmp = RDMEM(regs.HL); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
RDNOMREQ(regs.HL); Tact++;
|
||||
|
||||
regs.MW = (ushort)(regs.HL + 1);
|
||||
var val = (byte)((regs.A & 0x0F) | (tmp << 4));
|
||||
|
||||
WRMEM(regs.HL, val); Tact += 3;
|
||||
regs.A = (byte)((regs.A & 0xF0) | (tmp >> 4));
|
||||
regs.F = (byte)(CpuTables.Logf[regs.A] | (regs.F & CpuFlags.C));
|
||||
}
|
||||
|
||||
private void ED_NEG(byte cmd) // NEG
|
||||
{
|
||||
regs.F = CpuTables.Sbcf[regs.A];
|
||||
regs.A = (byte)-regs.A;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [DD/FD prefixed opcode part]
|
||||
* Date: 13.04.2007
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
#region FXxx ops...
|
||||
|
||||
private void FX_LDSPHL(byte cmd) // LD SP,IX
|
||||
{
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.SP = regs.IX;
|
||||
else
|
||||
regs.SP = regs.IY;
|
||||
}
|
||||
|
||||
private void FX_EX_SP_HL(byte cmd) // EX (SP),IX
|
||||
{
|
||||
// 23T (4, 4, 3, 4, 3, 5)
|
||||
|
||||
var tmpsp = regs.SP;
|
||||
regs.MW = RDMEM(tmpsp); Tact += 3;
|
||||
tmpsp++;
|
||||
|
||||
regs.MW += (ushort)(RDMEM(tmpsp) * 0x100); Tact += 3;
|
||||
RDNOMREQ(tmpsp); Tact++;
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
{
|
||||
WRMEM(tmpsp, regs.XH); Tact += 3;
|
||||
tmpsp--;
|
||||
|
||||
WRMEM(tmpsp, regs.XL); Tact += 3;
|
||||
WRNOMREQ(tmpsp); Tact++;
|
||||
WRNOMREQ(tmpsp); Tact++;
|
||||
regs.IX = regs.MW;
|
||||
}
|
||||
else
|
||||
{
|
||||
WRMEM(tmpsp, regs.YH); Tact += 3;
|
||||
tmpsp--;
|
||||
|
||||
WRMEM(tmpsp, regs.YL); Tact += 3;
|
||||
WRNOMREQ(tmpsp); Tact++;
|
||||
WRNOMREQ(tmpsp); Tact++;
|
||||
regs.IY = regs.MW;
|
||||
}
|
||||
}
|
||||
|
||||
private void FX_JP_HL_(byte cmd) // JP (IX)
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.PC = regs.IX;
|
||||
else
|
||||
regs.PC = regs.IY;
|
||||
}
|
||||
|
||||
private void FX_PUSHIX(byte cmd) // PUSH IX
|
||||
{
|
||||
// 15 (4, 5, 3, 3)
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
var val = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)(val >> 8)); Tact += 3;
|
||||
regs.SP--;
|
||||
|
||||
WRMEM(regs.SP, (byte)val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_POPIX(byte cmd) // POP IX
|
||||
{
|
||||
// 14T (4, 4, 3, 3)
|
||||
|
||||
var val = (ushort)RDMEM(regs.SP);
|
||||
regs.SP++;
|
||||
Tact += 3;
|
||||
|
||||
val |= (ushort)(RDMEM(regs.SP) << 8);
|
||||
regs.SP++;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.IX = val;
|
||||
else
|
||||
regs.IY = val;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_ALUAXH(byte cmd) // ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,XH
|
||||
{
|
||||
byte val;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
val = (byte)(regs.IX >> 8);
|
||||
else
|
||||
val = (byte)(regs.IY >> 8);
|
||||
_alualg[(cmd & 0x38) >> 3](val);
|
||||
}
|
||||
|
||||
private void FX_ALUAXL(byte cmd) // ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,XL
|
||||
{
|
||||
byte val;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
val = (byte)regs.IX;
|
||||
else
|
||||
val = (byte)regs.IY;
|
||||
_alualg[(cmd & 0x38) >> 3](val);
|
||||
}
|
||||
|
||||
private void FX_ALUA_IX_(byte cmd) // ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,(IX)
|
||||
{
|
||||
// 19T (4, 4, 3, 5, 3)
|
||||
var op = (cmd & 0x38) >> 3;
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
|
||||
regs.PC++;
|
||||
regs.MW = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.MW = (ushort)(regs.MW + drel);
|
||||
|
||||
var val = RDMEM(regs.MW); Tact += 3;
|
||||
_alualg[op](val);
|
||||
}
|
||||
|
||||
private void FX_ADDIXRR(byte cmd) // ADD IX,RR
|
||||
{
|
||||
var rr = (cmd & 0x30) >> 4;
|
||||
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
var rde = rr switch
|
||||
{
|
||||
0 => regs.BC,
|
||||
1 => regs.DE,
|
||||
2 => FX == CpuModeIndex.Ix ? regs.IX : regs.IY,
|
||||
3 => regs.SP,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(cmd), "(cmd & 0x30) >> 4 is out of range"),
|
||||
};
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
{
|
||||
regs.MW = (ushort)(regs.IX + 1);
|
||||
regs.IX = ALU_ADDHLRR(regs.IX, rde);
|
||||
}
|
||||
else
|
||||
{
|
||||
regs.MW = (ushort)(regs.IY + 1);
|
||||
regs.IY = ALU_ADDHLRR(regs.IY, rde);
|
||||
}
|
||||
}
|
||||
|
||||
private void FX_DECIX(byte cmd) // DEC IX
|
||||
{
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.IX--;
|
||||
else
|
||||
regs.IY--;
|
||||
}
|
||||
|
||||
private void FX_INCIX(byte cmd) // INC IX
|
||||
{
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
RDNOMREQ(regs.IR); Tact++;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.IX++;
|
||||
else
|
||||
regs.IY++;
|
||||
}
|
||||
|
||||
private void FX_LDIX_N_(byte cmd) // LD IX,(nnnn)
|
||||
{
|
||||
// 20 (4, 4, 3, 3, 3, 3)
|
||||
|
||||
var adr = (ushort)RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
Tact += 3;
|
||||
|
||||
var val = (ushort)RDMEM(adr);
|
||||
Tact += 3;
|
||||
|
||||
val += (ushort)(RDMEM(regs.MW) * 0x100);
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.IX = val;
|
||||
else
|
||||
regs.IY = val;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_LD_NN_IX(byte cmd) // LD (nnnn),IX
|
||||
{
|
||||
// 20 (4, 4, 3, 3, 3, 3)
|
||||
|
||||
var hl = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
var adr = (ushort)RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
adr += (ushort)(RDMEM(regs.PC) * 0x100);
|
||||
regs.PC++;
|
||||
regs.MW = (ushort)(adr + 1);
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(adr, (byte)hl);
|
||||
Tact += 3;
|
||||
|
||||
WRMEM(regs.MW, (byte)(hl >> 8));
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_LDIXNNNN(byte cmd) // LD IX,nnnn
|
||||
{
|
||||
// 14 (4, 4, 3, 3)
|
||||
|
||||
var val = (ushort)RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
|
||||
val |= (ushort)(RDMEM(regs.PC) << 8);
|
||||
regs.PC++;
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.IX = val;
|
||||
else
|
||||
regs.IY = val;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_DEC_IX_(byte cmd) // DEC (IX)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
|
||||
regs.PC++;
|
||||
regs.MW = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.MW = (ushort)(regs.MW + drel);
|
||||
|
||||
var val = RDMEM(regs.MW); Tact += 3;
|
||||
RDNOMREQ(regs.MW); Tact++;
|
||||
val = ALU_DECR(val);
|
||||
WRMEM(regs.MW, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_INC_IX_(byte cmd) // INC (IX)
|
||||
{
|
||||
//23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
|
||||
regs.PC++;
|
||||
regs.MW = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.MW = (ushort)(regs.MW + drel);
|
||||
|
||||
var val = RDMEM(regs.MW); Tact += 3;
|
||||
RDNOMREQ(regs.MW); Tact++;
|
||||
val = ALU_INCR(val);
|
||||
WRMEM(regs.MW, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_LD_IX_NN(byte cmd) // LD (IX),nn
|
||||
{
|
||||
// 19 (4, 4, 3, 5, 3)
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
regs.PC++;
|
||||
|
||||
var val = RDMEM(regs.PC); Tact += 3;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
regs.PC++;
|
||||
regs.MW = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.MW = (ushort)(regs.MW + drel);
|
||||
WRMEM(regs.MW, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_LD_IX_R(byte cmd) // LD (IX),R
|
||||
{
|
||||
// 19T (4, 4, 3, 5, 3)
|
||||
var r = cmd & 0x07;
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
|
||||
regs.PC++;
|
||||
regs.MW = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.MW = (ushort)(regs.MW + drel);
|
||||
WRMEM(regs.MW, _regGetters[r]()); Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_LDR_IX_(byte cmd) // LD R,(IX)
|
||||
{
|
||||
// 19T (4, 4, 3, 5, 3)
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
|
||||
regs.PC++;
|
||||
regs.MW = FX == CpuModeIndex.Ix ? regs.IX : regs.IY;
|
||||
regs.MW = (ushort)(regs.MW + drel);
|
||||
|
||||
_regSetters[r](RDMEM(regs.MW)); Tact += 3;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RdRs...
|
||||
|
||||
private void FX_LDHL(byte cmd)
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XH = regs.XL;
|
||||
else
|
||||
regs.YH = regs.YL;
|
||||
}
|
||||
|
||||
private void FX_LDLH(byte cmd)
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XL = regs.XH;
|
||||
else
|
||||
regs.YL = regs.YH;
|
||||
}
|
||||
|
||||
private void FX_LDRL(byte cmd)
|
||||
{
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
_regSetters[r](regs.XL);
|
||||
else
|
||||
_regSetters[r](regs.YL);
|
||||
}
|
||||
|
||||
private void FX_LDRH(byte cmd)
|
||||
{
|
||||
var r = (cmd & 0x38) >> 3;
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
_regSetters[r](regs.XH);
|
||||
else
|
||||
_regSetters[r](regs.YH);
|
||||
}
|
||||
|
||||
private void FX_LDLR(byte cmd)
|
||||
{
|
||||
var r = cmd & 0x07;
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XL = _regGetters[r]();
|
||||
else
|
||||
regs.YL = _regGetters[r]();
|
||||
}
|
||||
|
||||
private void FX_LDHR(byte cmd)
|
||||
{
|
||||
var r = cmd & 0x07;
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XH = _regGetters[r]();
|
||||
else
|
||||
regs.YH = _regGetters[r]();
|
||||
}
|
||||
|
||||
private void FX_LDLNN(byte cmd) // LD XL,nn
|
||||
{
|
||||
// 11T (4, 4, 3)
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XL = RDMEM(regs.PC);
|
||||
else
|
||||
regs.YL = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_LDHNN(byte cmd) // LD XH,nn
|
||||
{
|
||||
// 11T (4, 4, 3)
|
||||
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XH = RDMEM(regs.PC);
|
||||
else
|
||||
regs.YH = RDMEM(regs.PC);
|
||||
regs.PC++;
|
||||
Tact += 3;
|
||||
}
|
||||
|
||||
private void FX_INCL(byte cmd) // INC XL
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XL = ALU_INCR(regs.XL);
|
||||
else
|
||||
regs.YL = ALU_INCR(regs.YL);
|
||||
}
|
||||
|
||||
private void FX_INCH(byte cmd) // INC XH
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XH = ALU_INCR(regs.XH);
|
||||
else
|
||||
regs.YH = ALU_INCR(regs.YH);
|
||||
}
|
||||
|
||||
private void FX_DECL(byte cmd) // DEC XL
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XL = ALU_DECR(regs.XL);
|
||||
else
|
||||
regs.YL = ALU_DECR(regs.YL);
|
||||
}
|
||||
|
||||
private void FX_DECH(byte cmd) // DEC XH
|
||||
{
|
||||
if (FX == CpuModeIndex.Ix)
|
||||
regs.XH = ALU_DECR(regs.XH);
|
||||
else
|
||||
regs.YH = ALU_DECR(regs.YH);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2007, 2011, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator [FXCB prefixed opcodes part]
|
||||
* Date: 25.09.2011
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
private void FXCB_RLC(byte cmd, ushort adr) // *RLC r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RLC(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RRC(byte cmd, ushort adr) // *RRC r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RRC(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RL(byte cmd, ushort adr) // *RL r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RL(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RR(byte cmd, ushort adr) // *RR r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RR(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SLA(byte cmd, ushort adr) // *SLA r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SLA(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SRA(byte cmd, ushort adr) // *SRA r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SRA(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SLL(byte cmd, ushort adr) // **SLL r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SLL(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SRL(byte cmd, ushort adr) // *SRL r
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SRL(val);
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RES(byte cmd, ushort adr) // *RES b,r,(IX+drel)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var m = (byte)~(1 << ((cmd & 0x38) >> 3));
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val &= m;
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SET(byte cmd, ushort adr) // *SET b,r,(IX+drel)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var m = (byte)(1 << ((cmd & 0x38) >> 3));
|
||||
var r = cmd & 7;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val |= m;
|
||||
_regSetters[r](val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RLCIX(byte cmd, ushort adr) // RLC (IX+) [23T]
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RLC(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RRCIX(byte cmd, ushort adr) // RRC (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RRC(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RLIX(byte cmd, ushort adr) // RL (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RL(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_RRIX(byte cmd, ushort adr) // RR (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_RR(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SLAIX(byte cmd, ushort adr) // SLA (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SLA(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SRAIX(byte cmd, ushort adr) // SRA (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SRA(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SLLIX(byte cmd, ushort adr) // *SLL (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SLL(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SRLIX(byte cmd, ushort adr) // SRL (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val = ALU_SRL(val);
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_BITIX(byte cmd, ushort adr) // BIT (IX+)
|
||||
{
|
||||
// 20T (4, 4, 3, 5, 4)
|
||||
var b = (cmd & 0x38) >> 3;
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
ALU_BITMEM(val, b);
|
||||
}
|
||||
|
||||
private void FXCB_RESIX(byte cmd, ushort adr) // RES (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var m = (byte)~(1 << ((cmd & 0x38) >> 3));
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val &= m;
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
|
||||
private void FXCB_SETIX(byte cmd, ushort adr) // SET (IX+)
|
||||
{
|
||||
// 23T (4, 4, 3, 5, 4, 3)
|
||||
var m = (byte)(1 << ((cmd & 0x38) >> 3));
|
||||
|
||||
var val = RDMEM(adr); Tact += 3;
|
||||
RDNOMREQ(adr); Tact++;
|
||||
val |= m;
|
||||
WRMEM(adr, val); Tact += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
private readonly Action<byte>[] _opcodes;
|
||||
private readonly Action<byte>[] _opcodesFx;
|
||||
private readonly Action<byte>[] _opcodesEd;
|
||||
private readonly Action<byte>[] _opcodesCb;
|
||||
private readonly Action<byte, ushort>[] _opcodesFxCb;
|
||||
private readonly Action<byte>[] _alualg;
|
||||
private readonly Func<ushort>[] _pairGetters;
|
||||
private readonly Action<ushort>[] _pairSetters;
|
||||
private readonly Func<byte>[] _regGetters;
|
||||
private readonly Action<byte>[] _regSetters;
|
||||
|
||||
|
||||
|
||||
private Action<byte>[] CreateOpcodes()
|
||||
{
|
||||
Action<byte> scf;
|
||||
Action<byte> ccf;
|
||||
switch (_type)
|
||||
{
|
||||
case CpuType.ZILOG_NMOS:
|
||||
case CpuType.ZILOG_CMOS:
|
||||
scf = SCF_ZILOG;
|
||||
ccf = CCF_ZILOG;
|
||||
break;
|
||||
case CpuType.NEC_NMOS:
|
||||
scf = SCF_NEC_NMOS;
|
||||
ccf = CCF_NEC_NMOS;
|
||||
break;
|
||||
case CpuType.ST_CMOS:
|
||||
scf = SCF_ST_CMOS;
|
||||
ccf = CCF_ST_CMOS;
|
||||
break;
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
|
||||
var opcodes = new Action<byte>[256]
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
null, LDRRNNNN, LD_RR_A, INCRR, INCR, DECR, LDRNN, RLCA, EXAFAF, ADDHLRR, LDA_RR_, DECRR, INCR, DECR, LDRNN, RRCA, // 00..0F
|
||||
DJNZ, LDRRNNNN, LD_RR_A, INCRR, INCR, DECR, LDRNN, RLA, JRNN, ADDHLRR, LDA_RR_, DECRR, INCR, DECR, LDRNN, RRA, // 10..1F
|
||||
JRXNN, LDRRNNNN, LD_NN_HL, INCRR, INCR, DECR, LDRNN, DAA, JRXNN, ADDHLRR, LDHL_NN_, DECRR, INCR, DECR, LDRNN, CPL, // 20..2F
|
||||
JRXNN, LDRRNNNN, LD_NN_A, INCRR, INC_HL_, DEC_HL_, LD_HL_NN, scf, JRXNN, ADDHLRR, LDA_NN_, DECRR, INCR, DECR, LDRNN, ccf, // 30..3F
|
||||
|
||||
null, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDR_HL_, LDRdRs, LDRdRs, null, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDR_HL_, LDRdRs, // 40..4F
|
||||
LDRdRs, LDRdRs, null, LDRdRs, LDRdRs, LDRdRs, LDR_HL_, LDRdRs, LDRdRs, LDRdRs, LDRdRs, null, LDRdRs, LDRdRs, LDR_HL_, LDRdRs, // 50..5F
|
||||
LDRdRs, LDRdRs, LDRdRs, LDRdRs, null, LDRdRs, LDR_HL_, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDRdRs, null, LDR_HL_, LDRdRs, // 60..6F
|
||||
LD_HL_R, LD_HL_R, LD_HL_R, LD_HL_R, LD_HL_R, LD_HL_R, HALT, LD_HL_R, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDRdRs, LDR_HL_, null, // 70..7F
|
||||
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, // 80..8F
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, // 90..9F
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, // A0..AF
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, ALUA_HL_, ALUAR, // B0..BF
|
||||
|
||||
RETX, POPRR, JPXNN, JPNNNN, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, RET, JPXNN, null, CALLXNNNN, CALLNNNN, ALUAN, RSTNN, // C0..CF
|
||||
RETX, POPRR, JPXNN, OUT_NN_A, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, EXX, JPXNN, INA_NN_, CALLXNNNN, null, ALUAN, RSTNN, // D0..DF
|
||||
RETX, POPRR, JPXNN, EX_SP_HL, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, JP_HL_, JPXNN, EXDEHL, CALLXNNNN, null, ALUAN, RSTNN, // E0..EF
|
||||
RETX, POPRR, JPXNN, DI, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, LDSPHL, JPXNN, EI, CALLXNNNN, null, ALUAN, RSTNN, // F0..FF
|
||||
};
|
||||
return opcodes;
|
||||
// patch opcodes with optimized version
|
||||
//for (var cmd = 0; cmd < 0x100; cmd++)
|
||||
//{
|
||||
// opcodes[cmd] =
|
||||
// EmitOpcodeLdRegReg(cmd) ??
|
||||
// EmitOpcodeJrXdisp(cmd) ??
|
||||
// opcodes[cmd];
|
||||
//}
|
||||
//return opcodes;
|
||||
}
|
||||
|
||||
private Action<byte>[] CreateOpcodesFx()
|
||||
{
|
||||
Action<byte> scf;
|
||||
Action<byte> ccf;
|
||||
switch (_type)
|
||||
{
|
||||
case CpuType.ZILOG_NMOS:
|
||||
case CpuType.ZILOG_CMOS:
|
||||
scf = SCF_ZILOG;
|
||||
ccf = CCF_ZILOG;
|
||||
break;
|
||||
case CpuType.NEC_NMOS:
|
||||
scf = SCF_NEC_NMOS;
|
||||
ccf = CCF_NEC_NMOS;
|
||||
break;
|
||||
case CpuType.ST_CMOS:
|
||||
scf = SCF_ST_CMOS;
|
||||
ccf = CCF_ST_CMOS;
|
||||
break;
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return
|
||||
[
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
null, LDRRNNNN, LD_RR_A, INCRR, INCR, DECR, LDRNN, RLCA, EXAFAF, FX_ADDIXRR, LDA_RR_, DECRR, INCR, DECR, LDRNN, RRCA, // 00..0F
|
||||
DJNZ, LDRRNNNN, LD_RR_A, INCRR, INCR, DECR, LDRNN, RLA, JRNN, FX_ADDIXRR, LDA_RR_, DECRR, INCR, DECR, LDRNN, RRA, // 10..1F
|
||||
JRXNN, FX_LDIXNNNN, FX_LD_NN_IX, FX_INCIX, FX_INCH, FX_DECH, FX_LDHNN, DAA, JRXNN, FX_ADDIXRR, FX_LDIX_N_, FX_DECIX, FX_INCL, FX_DECL, FX_LDLNN, CPL, // 20..2F
|
||||
JRXNN, LDRRNNNN, LD_NN_A, INCRR, FX_INC_IX_, FX_DEC_IX_, FX_LD_IX_NN, scf, JRXNN, FX_ADDIXRR, LDA_NN_, DECRR, INCR, DECR, LDRNN, ccf, // 30..3F
|
||||
|
||||
null, LDRdRs, LDRdRs, LDRdRs, FX_LDRH, FX_LDRL, FX_LDR_IX_, LDRdRs, LDRdRs, null, LDRdRs, LDRdRs, FX_LDRH, FX_LDRL, FX_LDR_IX_, LDRdRs, // 40..4F
|
||||
LDRdRs, LDRdRs, null, LDRdRs, FX_LDRH, FX_LDRL, FX_LDR_IX_, LDRdRs, LDRdRs, LDRdRs, LDRdRs, null, FX_LDRH, FX_LDRL, FX_LDR_IX_, LDRdRs, // 50..5F
|
||||
FX_LDHR, FX_LDHR, FX_LDHR, FX_LDHR, null, FX_LDHL, FX_LDR_IX_, FX_LDHR, FX_LDLR, FX_LDLR, FX_LDLR, FX_LDLR, FX_LDLH, null, FX_LDR_IX_, FX_LDLR,// 60..6F
|
||||
FX_LD_IX_R, FX_LD_IX_R, FX_LD_IX_R, FX_LD_IX_R, FX_LD_IX_R, FX_LD_IX_R, HALT, FX_LD_IX_R, LDRdRs, LDRdRs, LDRdRs, LDRdRs, FX_LDRH, FX_LDRL, FX_LDR_IX_, null, // 70..7F
|
||||
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, // 80..8F
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, // 90..9F
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, // A0..AF
|
||||
ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, ALUAR, ALUAR, ALUAR, ALUAR, FX_ALUAXH, FX_ALUAXL, FX_ALUA_IX_, ALUAR, // B0..BF
|
||||
|
||||
RETX, POPRR, JPXNN, JPNNNN, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, RET, JPXNN, null, CALLXNNNN, CALLNNNN, ALUAN, RSTNN, // C0..CF
|
||||
RETX, POPRR, JPXNN, OUT_NN_A, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, EXX, JPXNN, INA_NN_, CALLXNNNN, null, ALUAN, RSTNN, // D0..DF
|
||||
RETX, FX_POPIX, JPXNN, FX_EX_SP_HL, CALLXNNNN, FX_PUSHIX, ALUAN, RSTNN, RETX, FX_JP_HL_, JPXNN, EXDEHL, CALLXNNNN, null, ALUAN, RSTNN, // E0..EF
|
||||
RETX, POPRR, JPXNN, DI, CALLXNNNN, PUSHRR, ALUAN, RSTNN, RETX, FX_LDSPHL, JPXNN, EI, CALLXNNNN, null, ALUAN, RSTNN, // F0..FF
|
||||
];
|
||||
}
|
||||
|
||||
private Action<byte>[] CreateOpcodesEd()
|
||||
{
|
||||
Action<byte> ed_outcr = _type switch
|
||||
{
|
||||
CpuType.ZILOG_NMOS or CpuType.NEC_NMOS => ED_OUTCR_NMOS,
|
||||
CpuType.ST_CMOS or CpuType.ZILOG_CMOS => ED_OUTCR_CMOS,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
return
|
||||
[
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // 00..0F
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // 10..1F
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // 20..2F
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // 30..3F
|
||||
ED_INRC, ed_outcr, ED_SBCHLRR, ED_LD_NN_RR, ED_NEG, ED_RETN, ED_IM, ED_LDXRA, ED_INRC, ed_outcr, ED_ADCHLRR, ED_LDRR_NN_, ED_NEG, ED_RETN, ED_IM, ED_LDXRA, // 40..4F
|
||||
ED_INRC, ed_outcr, ED_SBCHLRR, ED_LD_NN_RR, ED_NEG, ED_RETN, ED_IM, ED_LDAXR, ED_INRC, ed_outcr, ED_ADCHLRR, ED_LDRR_NN_, ED_NEG, ED_RETN, ED_IM, ED_LDAXR, // 50..5F
|
||||
ED_INRC, ed_outcr, ED_SBCHLRR, ED_LD_NN_RR, ED_NEG, ED_RETN, ED_IM, ED_RRD, ED_INRC, ed_outcr, ED_ADCHLRR, ED_LDRR_NN_, ED_NEG, ED_RETN, ED_IM, ED_RLD, // 60..6F
|
||||
ED_INRC, ed_outcr, ED_SBCHLRR, ED_LD_NN_RR, ED_NEG, ED_RETN, ED_IM, null, ED_INRC, ed_outcr, ED_ADCHLRR, ED_LDRR_NN_, ED_NEG, ED_RETN, ED_IM, null, // 70..7F
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // 80..8F
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // 90..9F
|
||||
ED_LDI, ED_CPI, ED_INI, ED_OUTI, null, null, null, null, ED_LDD, ED_CPD, ED_IND, ED_OUTD, null, null, null, null, // A0..AF
|
||||
ED_LDIR, ED_CPIR, ED_INIR, ED_OTIR, null, null, null, null, ED_LDDR, ED_CPDR, ED_INDR, ED_OTDR, null, null, null, null, // B0..BF
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // C0..CF
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // D0..DF
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, // E0..EF
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null // F0..FF
|
||||
];
|
||||
}
|
||||
|
||||
private Action<byte>[] CreateOpcodesCb()
|
||||
{
|
||||
return
|
||||
[
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
CB_RLC, CB_RLC, CB_RLC, CB_RLC, CB_RLC, CB_RLC, CB_RLCHL, CB_RLC, CB_RRC, CB_RRC, CB_RRC, CB_RRC, CB_RRC, CB_RRC, CB_RRCHL, CB_RRC, // 00..0F
|
||||
CB_RL, CB_RL, CB_RL, CB_RL, CB_RL, CB_RL, CB_RLHL, CB_RL, CB_RR, CB_RR, CB_RR, CB_RR, CB_RR, CB_RR, CB_RRHL, CB_RR, // 10..1F
|
||||
CB_SLA, CB_SLA, CB_SLA, CB_SLA, CB_SLA, CB_SLA, CB_SLAHL, CB_SLA, CB_SRA, CB_SRA, CB_SRA, CB_SRA, CB_SRA, CB_SRA, CB_SRAHL, CB_SRA, // 20..2F
|
||||
CB_SLL, CB_SLL, CB_SLL, CB_SLL, CB_SLL, CB_SLL, CB_SLLHL, CB_SLL, CB_SRL, CB_SRL, CB_SRL, CB_SRL, CB_SRL, CB_SRL, CB_SRLHL, CB_SRL, // 30..3F
|
||||
CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, // 40..4F
|
||||
CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, // 50..5F
|
||||
CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, // 60..6F
|
||||
CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BIT, CB_BITHL, CB_BIT, // 70..7F
|
||||
CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, // 80..8F
|
||||
CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, // 90..9F
|
||||
CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, // A0..AF
|
||||
CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RES, CB_RESHL, CB_RES, // B0..BF
|
||||
CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, // C0..CF
|
||||
CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, // D0..DF
|
||||
CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, // E0..EF
|
||||
CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SET, CB_SETHL, CB_SET, // F0..FF
|
||||
];
|
||||
}
|
||||
|
||||
private Action<byte, ushort>[] CreateOpcodesFxCb()
|
||||
{
|
||||
return
|
||||
[
|
||||
FXCB_RLC, FXCB_RLC, FXCB_RLC, FXCB_RLC, FXCB_RLC, FXCB_RLC, FXCB_RLCIX, FXCB_RLC, FXCB_RRC, FXCB_RRC, FXCB_RRC, FXCB_RRC, FXCB_RRC, FXCB_RRC, FXCB_RRCIX, FXCB_RRC, // 00..0F
|
||||
FXCB_RL, FXCB_RL, FXCB_RL, FXCB_RL, FXCB_RL, FXCB_RL, FXCB_RLIX, FXCB_RL, FXCB_RR, FXCB_RR, FXCB_RR, FXCB_RR, FXCB_RR, FXCB_RR, FXCB_RRIX, FXCB_RR, // 10..1F
|
||||
FXCB_SLA, FXCB_SLA, FXCB_SLA, FXCB_SLA, FXCB_SLA, FXCB_SLA, FXCB_SLAIX, FXCB_SLA, FXCB_SRA, FXCB_SRA, FXCB_SRA, FXCB_SRA, FXCB_SRA, FXCB_SRA, FXCB_SRAIX, FXCB_SRA, // 20..2F
|
||||
FXCB_SLL, FXCB_SLL, FXCB_SLL, FXCB_SLL, FXCB_SLL, FXCB_SLL, FXCB_SLLIX, FXCB_SLL, FXCB_SRL, FXCB_SRL, FXCB_SRL, FXCB_SRL, FXCB_SRL, FXCB_SRL, FXCB_SRLIX, FXCB_SRL, // 30..3F
|
||||
FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, // 40..4F
|
||||
FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, // 50..5F
|
||||
FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, // 60..6F
|
||||
FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, FXCB_BITIX, // 70..7F
|
||||
FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, // 80..8F
|
||||
FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, // 90..9F
|
||||
FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, // A0..AF
|
||||
FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RES, FXCB_RESIX, FXCB_RES, // B0..BF
|
||||
FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, // C0..CF
|
||||
FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, // D0..DF
|
||||
FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, // E0..EF
|
||||
FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SET, FXCB_SETIX, FXCB_SET, // F0..FF
|
||||
];
|
||||
}
|
||||
|
||||
private Action<byte>[] CreateAluAlg()
|
||||
{
|
||||
return
|
||||
[
|
||||
ALU_ADDR, ALU_ADCR, ALU_SUBR, ALU_SBCR,
|
||||
ALU_ANDR, ALU_XORR, ALU_ORR, ALU_CPR,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region Optimized emitters
|
||||
|
||||
//private Action<byte> EmitOpcodeLdRegReg(int cmd)
|
||||
//{
|
||||
// if (cmd < 0x40 || cmd >= 0x80)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// var rsrc = cmd & 0x07;
|
||||
// var rdst = (cmd & 0x38) >> 3;
|
||||
// if (rsrc == rdst)
|
||||
// {
|
||||
// return rsrc == 6 ? HALT : (Action<byte>)null;
|
||||
// }
|
||||
// var getter = rsrc != 6 ? regs.CreateRegGetter(rsrc) :
|
||||
// new Func<byte>(() =>
|
||||
// {
|
||||
// // LD R,(HL)
|
||||
// // 7T (4, 3)
|
||||
// var value = RDMEM(regs.HL); Tact += 3;
|
||||
// return value;
|
||||
// });
|
||||
// var setter = rdst != 6 ? regs.CreateRegSetter(rdst) :
|
||||
// new Action<byte>(arg =>
|
||||
// {
|
||||
// // LD (HL),R
|
||||
// // 7T (4, 3)
|
||||
// WRMEM(regs.HL, arg); Tact += 3;
|
||||
// });
|
||||
// return arg => setter(getter());
|
||||
//}
|
||||
|
||||
//private Action<byte> EmitOpcodeJrXdisp(int cmd)
|
||||
//{
|
||||
// if (cmd < 0x20 || cmd >= 0x40 || (cmd & 7) != 0)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// // JR x,disp
|
||||
// // false => 7T (4, 3)
|
||||
// // true => 12 (4, 3, 5)
|
||||
// var cond = (cmd & 0x18) >> 3;
|
||||
// var mask = s_conds[cond >> 1];
|
||||
// var xor = (cond & 1) == 0 ? -1 : 0;
|
||||
// return new Action<byte>(arg =>
|
||||
// {
|
||||
// int drel = (sbyte)RDMEM(regs.PC); Tact += 3;
|
||||
// regs.PC++;
|
||||
// var f = (regs.AF ^ xor) & mask;
|
||||
// if (f == 0)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// RDNOMREQ(regs.PC); Tact++;
|
||||
// RDNOMREQ(regs.PC); Tact++;
|
||||
// RDNOMREQ(regs.PC); Tact++;
|
||||
// RDNOMREQ(regs.PC); Tact++;
|
||||
// RDNOMREQ(regs.PC); Tact++;
|
||||
// regs.MW = (ushort)(regs.PC + drel);
|
||||
// regs.PC = regs.MW;
|
||||
// });
|
||||
//}
|
||||
|
||||
#endregion Optimized emitters
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Description: Z80 CPU Emulator
|
||||
* Date: 13.04.2007
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Processor
|
||||
{
|
||||
public partial class Z80Cpu
|
||||
{
|
||||
public readonly CpuRegs regs = new();
|
||||
public int RzxCounter;
|
||||
public long Tact;
|
||||
public bool HALTED;
|
||||
public bool IFF1;
|
||||
public bool IFF2;
|
||||
public byte IM;
|
||||
public bool BINT; // last opcode was EI or DD/FD prefix (to prevent INT handling)
|
||||
public CpuModeIndex FX;
|
||||
public CpuModeEx XFX;
|
||||
public ushort LPC; // last opcode PC
|
||||
|
||||
public bool INT;
|
||||
public bool NMI;
|
||||
public bool RST;
|
||||
public byte BUS = 0xFF; // state of free data bus
|
||||
|
||||
public Action RESET;
|
||||
public Action NMIACK_M1;
|
||||
public Action INTACK_M1;
|
||||
public Func<ushort, byte> RDMEM_M1;
|
||||
public Func<ushort, byte> RDMEM;
|
||||
public Action<ushort, byte> WRMEM;
|
||||
public Func<ushort, byte> RDPORT;
|
||||
public Action<ushort, byte> WRPORT;
|
||||
public Action<ushort> RDNOMREQ;
|
||||
public Action<ushort> WRNOMREQ;
|
||||
public Action SCANSIG;
|
||||
|
||||
private CpuType _type = CpuType.NEC_NMOS;
|
||||
public CpuType Type
|
||||
{
|
||||
get { return _type; }
|
||||
set { _type = value; InitOpcodeTables(); }
|
||||
}
|
||||
|
||||
public Z80Cpu()
|
||||
{
|
||||
_pairGetters = [.. Enumerable.Range(0, 4).Select(regs.CreatePairGetter)];
|
||||
_pairSetters = [.. Enumerable.Range(0, 4).Select(regs.CreatePairSetter)];
|
||||
_regGetters = [.. Enumerable.Range(0, 8).Select(regs.CreateRegGetter)];
|
||||
_regSetters = [.. Enumerable.Range(0, 8).Select(regs.CreateRegSetter)];
|
||||
_alualg = CreateAluAlg();
|
||||
|
||||
_opcodes = new Action<byte>[256];
|
||||
_opcodesFx = new Action<byte>[256];
|
||||
_opcodesEd = new Action<byte>[256];
|
||||
_opcodesCb = new Action<byte>[256];
|
||||
_opcodesFxCb = new Action<byte, ushort>[256];
|
||||
InitOpcodeTables();
|
||||
|
||||
regs.AF = 0xFF;
|
||||
regs.BC = 0xFF;
|
||||
regs.DE = 0xFF;
|
||||
regs.HL = 0xFF;
|
||||
regs._AF = 0xFF;
|
||||
regs._BC = 0xFF;
|
||||
regs._DE = 0xFF;
|
||||
regs._HL = 0xFF;
|
||||
regs.IX = 0xFF;
|
||||
regs.IY = 0xFF;
|
||||
regs.IR = 0xFF;
|
||||
regs.PC = 0xFF;
|
||||
regs.SP = 0xFF;
|
||||
regs.MW = 0xFF;
|
||||
}
|
||||
|
||||
private void InitOpcodeTables()
|
||||
{
|
||||
InitOpcodeTable(_opcodes, CreateOpcodes());
|
||||
InitOpcodeTable(_opcodesFx, CreateOpcodesFx());
|
||||
InitOpcodeTable(_opcodesEd, CreateOpcodesEd());
|
||||
InitOpcodeTable(_opcodesCb, CreateOpcodesCb());
|
||||
InitOpcodeTable(_opcodesFxCb, CreateOpcodesFxCb());
|
||||
}
|
||||
|
||||
private static void InitOpcodeTable<T>(T[] opcodes, T[] actions)
|
||||
{
|
||||
if (opcodes.Length != actions.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(opcodes));
|
||||
|
||||
for (var i = 0; i < opcodes.Length; i++)
|
||||
{
|
||||
opcodes[i] = actions[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ExecCycle()
|
||||
{
|
||||
byte cmd = 0;
|
||||
if (XFX == CpuModeEx.None && FX == CpuModeIndex.None)
|
||||
{
|
||||
if (ProcessSignals())
|
||||
return;
|
||||
LPC = regs.PC;
|
||||
cmd = RDMEM_M1(LPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ProcessSignals())
|
||||
return;
|
||||
cmd = RDMEM(regs.PC);
|
||||
}
|
||||
Tact += 3;
|
||||
regs.PC++;
|
||||
if (XFX == CpuModeEx.Cb)
|
||||
{
|
||||
BINT = false;
|
||||
if (FX != CpuModeIndex.None)
|
||||
{
|
||||
// elapsed T: 4, 4, 3
|
||||
// will be T: 4, 4, 3, 5
|
||||
int drel = (sbyte)cmd;
|
||||
|
||||
regs.MW = FX == CpuModeIndex.Ix ? (ushort)(regs.IX + drel) : (ushort)(regs.IY + drel);
|
||||
cmd = RDMEM(regs.PC); Tact += 3;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
RDNOMREQ(regs.PC); Tact++;
|
||||
|
||||
regs.PC++;
|
||||
_opcodesFxCb[cmd](cmd, regs.MW);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
_opcodesCb[cmd](cmd);
|
||||
}
|
||||
XFX = CpuModeEx.None;
|
||||
FX = CpuModeIndex.None;
|
||||
}
|
||||
else if (XFX == CpuModeEx.Ed)
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
BINT = false;
|
||||
_opcodesEd[cmd]?.Invoke(cmd);
|
||||
|
||||
XFX = CpuModeEx.None;
|
||||
FX = CpuModeIndex.None;
|
||||
}
|
||||
else if (cmd == 0xDD)
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
FX = CpuModeIndex.Ix;
|
||||
BINT = true;
|
||||
}
|
||||
else if (cmd == 0xFD)
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
FX = CpuModeIndex.Iy;
|
||||
BINT = true;
|
||||
}
|
||||
else if (cmd == 0xCB)
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
XFX = CpuModeEx.Cb;
|
||||
BINT = true;
|
||||
}
|
||||
else if (cmd == 0xED)
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
XFX = CpuModeEx.Ed;
|
||||
BINT = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
BINT = false;
|
||||
(FX == CpuModeIndex.None ? _opcodes[cmd] : _opcodesFx[cmd])?.Invoke(cmd);
|
||||
FX = CpuModeIndex.None;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ProcessSignals()
|
||||
{
|
||||
if (RST) // RESET
|
||||
{
|
||||
// 3T
|
||||
RESET();
|
||||
//Refresh(); //+1T
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
|
||||
FX = CpuModeIndex.None;
|
||||
XFX = CpuModeEx.None;
|
||||
HALTED = false;
|
||||
|
||||
IFF1 = false;
|
||||
IFF2 = false;
|
||||
regs.PC = 0;
|
||||
regs.IR = 0;
|
||||
IM = 0;
|
||||
//regs.SP = 0xFFFF;
|
||||
//regs.AF = 0xFFFF;
|
||||
|
||||
Tact += 2; // total should be 3T?
|
||||
return true;
|
||||
}
|
||||
else if (NMI)
|
||||
{
|
||||
// 11T (5, 3, 3)
|
||||
|
||||
if (HALTED) // workaround for Z80 snapshot halt issue + comfortable debugging
|
||||
regs.PC++;
|
||||
|
||||
// M1
|
||||
NMIACK_M1();
|
||||
Tact += 4;
|
||||
//Refresh();
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
RzxCounter++;
|
||||
|
||||
|
||||
IFF2 = IFF1;
|
||||
IFF1 = false;
|
||||
HALTED = false;
|
||||
regs.SP--;
|
||||
|
||||
// M2
|
||||
WRMEM(regs.SP, (byte)(regs.PC >> 8));
|
||||
Tact += 3;
|
||||
regs.SP--;
|
||||
|
||||
// M3
|
||||
WRMEM(regs.SP, (byte)regs.PC);
|
||||
regs.PC = 0x0066;
|
||||
Tact += 3;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (INT && (!BINT) && IFF1)
|
||||
{
|
||||
// http://www.z80.info/interrup.htm
|
||||
// IM0: 13T (7,3,3) [RST]
|
||||
// IM1: 13T (7,3,3)
|
||||
// IM2: 19T (7,3,3,3,3)
|
||||
|
||||
if (HALTED) // workaround for Z80 snapshot halt issue + comfortable debugging
|
||||
regs.PC++;
|
||||
|
||||
|
||||
INTACK_M1();
|
||||
// M1: 7T = interrupt acknowledgement; SP--
|
||||
regs.SP--;
|
||||
//if (HALTED) ??
|
||||
// Tact += 2;
|
||||
Tact += 4 + 2;
|
||||
//Refresh();
|
||||
//RzxCounter--; // fix because INTAK should not be calculated
|
||||
regs.R = (byte)(((regs.R + 1) & 0x7F) | (regs.R & 0x80));
|
||||
Tact += 1;
|
||||
|
||||
|
||||
IFF1 = false;
|
||||
IFF2 = false; // proof?
|
||||
HALTED = false;
|
||||
|
||||
// M2
|
||||
WRMEM(regs.SP, (byte)(regs.PC >> 8)); // M2: 3T write PCH; SP--
|
||||
regs.SP--;
|
||||
Tact += 3;
|
||||
|
||||
// M3
|
||||
WRMEM(regs.SP, (byte)regs.PC); // M3: 3T write PCL
|
||||
Tact += 3;
|
||||
|
||||
if (IM == 0) // IM 0: execute instruction taken from BUS with timing T+2???
|
||||
{
|
||||
regs.MW = 0x0038; // workaround: just execute #FF
|
||||
}
|
||||
else if (IM == 1) // IM 1: execute #FF with timing T+2 (11+2=13T)
|
||||
{
|
||||
regs.MW = 0x0038;
|
||||
}
|
||||
else // IM 2: VH=reg.I; VL=BUS; PC=[V]
|
||||
{
|
||||
// M4
|
||||
ushort adr = (ushort)((regs.IR & 0xFF00) | BUS);
|
||||
regs.MW = RDMEM(adr); // M4: 3T read VL
|
||||
Tact += 3;
|
||||
|
||||
// M5
|
||||
regs.MW += (ushort)(RDMEM(++adr) * 0x100); // M5: 3T read VH, PC=V
|
||||
Tact += 3;
|
||||
}
|
||||
regs.PC = regs.MW;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright 2001, 2007, 2015 Alex Makeev
|
||||
*
|
||||
* This file is part of ZXMAK2 (ZX Spectrum virtual machine).
|
||||
*
|
||||
* ZXMAK2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ZXMAK2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ZXMAK2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using ZXMAK2.Engine.Cpu.Processor;
|
||||
|
||||
|
||||
namespace ZXMAK2.Engine.Cpu.Tools
|
||||
{
|
||||
public class TimingTool(Z80Cpu cpu, Func<ushort, byte> reader)
|
||||
{
|
||||
private readonly Z80Cpu _cpu = cpu;
|
||||
private readonly Func<ushort, byte> _memRead = reader;
|
||||
|
||||
public string GetTimingString(int addr)
|
||||
{
|
||||
var t = GetTiming(addr);
|
||||
return t.HasValue ? string.Format("{0}T", t) : "N/A";
|
||||
}
|
||||
|
||||
public int? GetTiming(int addr)
|
||||
{
|
||||
if (_memRead == null || _cpu == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tableNumber = 0;
|
||||
var perfTime = 0;
|
||||
var offset = 0;
|
||||
var opCode = -1;
|
||||
while (true)
|
||||
{
|
||||
opCode = _memRead((ushort)(addr + offset));
|
||||
var res = s_tables[tableNumber][opCode];
|
||||
if (res < 0xF0)
|
||||
{
|
||||
return res + perfTime;
|
||||
}
|
||||
tableNumber = res - 0xF0;
|
||||
if (tableNumber >= 5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
perfTime += 4;
|
||||
offset++;
|
||||
if (tableNumber == 4)
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
if (perfTime > 1500000)
|
||||
{
|
||||
System.Console.Error.WriteLine("TimingTool.GetTiming: {0}T reached!", perfTime);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
switch (opCode)
|
||||
{
|
||||
case 0x10:
|
||||
return DjnzTime(perfTime, 0x08, 0x0D);
|
||||
|
||||
case 0xB1:
|
||||
case 0xB2:
|
||||
case 0xB9:
|
||||
case 0xBA:
|
||||
return DjnzTime(perfTime, 0x0C, 0x11);
|
||||
|
||||
case 0x20: return FlagTime(perfTime, 0x07, 0x0C, 0x40);
|
||||
case 0x28: return FlagTime(perfTime, 0x0C, 0x07, 0x40);
|
||||
case 0x30: return FlagTime(perfTime, 0x07, 0x0C, 0x01);
|
||||
case 0x38: return FlagTime(perfTime, 0x0C, 0x07, 0x01);
|
||||
case 0xC0: return FlagTime(perfTime, 0x05, 0x0B, 0x40);
|
||||
case 0xC8: return FlagTime(perfTime, 0x0B, 0x05, 0x40);
|
||||
case 0xD0: return FlagTime(perfTime, 0x05, 0x0B, 0x01);
|
||||
case 0xD8: return FlagTime(perfTime, 0x0B, 0x05, 0x01);
|
||||
case 0xE0: return FlagTime(perfTime, 0x05, 0x0B, 0x04);
|
||||
case 0xE8: return FlagTime(perfTime, 0x0B, 0x05, 0x04);
|
||||
case 0xF0: return FlagTime(perfTime, 0x05, 0x0B, 0x80);
|
||||
case 0xF8: return FlagTime(perfTime, 0x0B, 0x05, 0x80);
|
||||
case 0xC4: return FlagTime(perfTime, 0x0A, 0x11, 0x40);
|
||||
case 0xCC: return FlagTime(perfTime, 0x11, 0x0A, 0x40);
|
||||
case 0xD4: return FlagTime(perfTime, 0x0A, 0x11, 0x01);
|
||||
case 0xDC: return FlagTime(perfTime, 0x11, 0x0A, 0x01);
|
||||
case 0xE4: return FlagTime(perfTime, 0x0A, 0x11, 0x04);
|
||||
case 0xEC: return FlagTime(perfTime, 0x11, 0x0A, 0x04);
|
||||
case 0xF4: return FlagTime(perfTime, 0x0A, 0x11, 0x80);
|
||||
case 0xFC: return FlagTime(perfTime, 0x11, 0x0A, 0x80);
|
||||
|
||||
case 0xB0:
|
||||
case 0xB8:
|
||||
return RepTime(perfTime, 0x0C, 0x11);
|
||||
|
||||
case 0xB3:
|
||||
case 0xBB:
|
||||
return RepFlagTime(perfTime, 0x0C, 0x0C, 0x11);
|
||||
}
|
||||
System.Console.Error.WriteLine(
|
||||
"TimingTool.GetTiming: unexpected opCode #{0:2X}",
|
||||
opCode);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
#region Private
|
||||
|
||||
private int DjnzTime(int timeBase, int timeEnd, int timeNoEnd)
|
||||
{
|
||||
var ifTime = _cpu.regs.B == 0x01 ? timeEnd : timeNoEnd;
|
||||
return timeBase + ifTime;
|
||||
}
|
||||
|
||||
private int FlagTime(int timeBase, int timeOn, int timeOff, int flagMask)
|
||||
{
|
||||
var ifTime = (_cpu.regs.F & flagMask) != 0 ? timeOn : timeOff;
|
||||
return timeBase + ifTime;
|
||||
}
|
||||
|
||||
private int RepTime(int perfTime, int timeEnd, int timeNoEnd)
|
||||
{
|
||||
var ifTime = _cpu.regs.BC == 0x0001 ? timeEnd : timeNoEnd;
|
||||
return perfTime + ifTime;
|
||||
}
|
||||
|
||||
private int RepFlagTime(int timeEnd, int timeOn, int timeOff, int perfTime)
|
||||
{
|
||||
if (_cpu.regs.BC == 0x0001)
|
||||
{
|
||||
return perfTime + timeEnd;
|
||||
}
|
||||
var data = _memRead(_cpu.regs.HL);
|
||||
var ifTime = _cpu.regs.F == data ? timeOn : timeOff;
|
||||
return perfTime + ifTime;
|
||||
}
|
||||
|
||||
#endregion Private
|
||||
|
||||
|
||||
#region Tables
|
||||
|
||||
private static readonly int[] s_tableDirect =
|
||||
[
|
||||
0x04,0x0A,0x07,0x06,0x04,0x04,0x07,0x04, //;00h-07h
|
||||
0x04,0x0B,0x07,0x06,0x04,0x04,0x07,0x04, //;08h-0Fh
|
||||
0xFF,0x0A,0x07,0x06,0x04,0x04,0x07,0x04, //;10h-17h
|
||||
0x0C,0x0B,0x07,0x06,0x04,0x04,0x07,0x04, //;18h-1Fh
|
||||
0xFF,0x0A,0x10,0x06,0x04,0x04,0x07,0x04, //;20h-27h
|
||||
0xFF,0x0B,0x10,0x06,0x04,0x04,0x07,0x04, //;28h-2Fh
|
||||
0xFF,0x0A,0x0D,0x06,0x0B,0x0B,0x0A,0x04, //;30h-37h
|
||||
0xFF,0x0B,0x0D,0x06,0x04,0x04,0x07,0x04, //;38h-3Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;40h-47h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;48h-4Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;50h-57h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;58h-5Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;60h-67h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;68h-6Fh
|
||||
0x07,0x07,0x07,0x07,0x07,0x07,0x04,0x07, //;70h-77h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;78h-7Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;80h-87h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;88h-8Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;90h-97h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;98h-9Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;A0h-A7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;A8h-AFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;B0h-B7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x04, //;B8h-BFh
|
||||
0xFF,0x0A,0x0A,0x0A,0xFF,0x0B,0x07,0x0B, //;C0h-C7h
|
||||
0xFF,0x0A,0x0A,0xF1,0xFF,0x11,0x07,0x0B, //;C8h-CFh
|
||||
0xFF,0x0A,0x0A,0x0B,0xFF,0x0B,0x07,0x0B, //;D0h-D7h
|
||||
0xFF,0x04,0x0A,0x0B,0xFF,0xF3,0x07,0x0B, //;D8h-DFh
|
||||
0xFF,0x0A,0x0A,0x13,0xFF,0x0B,0x07,0x0B, //;E0h-E7h
|
||||
0xFF,0x04,0x0A,0x04,0xFF,0xF2,0x07,0x0B, //;E8h-EFh
|
||||
0xFF,0x0A,0x0A,0x04,0xFF,0x0B,0x07,0x0B, //;F0h-F7h
|
||||
0xFF,0x06,0x0A,0x04,0xFF,0xF3,0x07,0x0B //;F8h-FFh
|
||||
];
|
||||
|
||||
private static readonly int[] s_tableCb =
|
||||
[
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;00h-07h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;08h-0Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;10h-17h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;18h-1Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;20h-27h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;28h-2Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;30h-37h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;38h-3Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;40h-47h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;48h-4Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;50h-57h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;58h-5Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;60h-67h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;68h-6Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;70h-77h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04, // ;78h-7Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;80h-87h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;88h-8Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;90h-97h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;98h-9Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;A0h-A7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;A8h-AFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;B0h-B7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;B8h-BFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;C0h-C7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;C8h-CFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;D0h-D7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;D8h-DFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;E0h-E7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;E8h-EFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04, // ;F0h-F7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0B,0x04 // ;F8h-FFh
|
||||
];
|
||||
|
||||
private static readonly int[] s_tableEd =
|
||||
[
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;00h-07h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;08h-0Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;10h-17h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;18h-1Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;20h-27h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;28h-2Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;30h-37h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;38h-3Fh
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x05, // ;40h-47h
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x05, // ;48h-4Fh
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x05, // ;50h-57h
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x05, // ;58h-5Fh
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x0E, // ;60h-67h
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x0E, // ;68h-6Fh
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x04, // ;70h-77h
|
||||
0x08,0x08,0x0B,0x10,0x04,0x0A,0x04,0x04, // ;78h-7Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;80h-87h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;88h-8Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;90h-97h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;98h-9Fh
|
||||
0x0C,0x0C,0x0C,0x0C,0x04,0x04,0x04,0x04, // ;A0h-A7h
|
||||
0x0C,0x0C,0x0C,0x0C,0x04,0x04,0x04,0x04, // ;A8h-AFh
|
||||
0xFF,0xFF,0xFF,0xFF,0x04,0x04,0x04,0x04, // ;B0h-B7h
|
||||
0xFF,0xFF,0xFF,0xFF,0x04,0x04,0x04,0x04, // ;B8h-BFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;C0h-C7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;C8h-CFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;D0h-D7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;D8h-DFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;E0h-E7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;E8h-EFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, // ;F0h-F7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 // ;F8h-FFh
|
||||
];
|
||||
|
||||
|
||||
private static readonly int[] s_tableDdFd =
|
||||
[
|
||||
0x04,0x0A,0x07,0x06,0x04,0x04,0x07,0x04, // ;00h-07h
|
||||
0x04,0x0B,0x07,0x06,0x04,0x04,0x07,0x04, // ;08h-0Fh
|
||||
0xFF,0x0A,0x07,0x06,0x04,0x04,0x07,0x04, // ;10h-17h
|
||||
0x0C,0x0B,0x07,0x06,0x04,0x04,0x07,0x04, // ;18h-1Fh
|
||||
0xFF,0x0A,0x10,0x06,0x04,0x04,0x07,0x04, // ;20h-27h
|
||||
0xFF,0x0B,0x10,0x06,0x04,0x04,0x07,0x04, // ;28h-2Fh
|
||||
0xFF,0x0A,0x0D,0x06,0x13,0x13,0x0F,0x04, // ;30h-37h
|
||||
0xFF,0x0B,0x0D,0x06,0x04,0x04,0x0F,0x04, // ;38h-3Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;40h-47h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;48h-4Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;50h-57h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;58h-5Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;60h-67h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;68h-6Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x04,0x0F, // ;70h-77h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;78h-7Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;80h-87h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;88h-8Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;90h-97h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;98h-9Fh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;A0h-A7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;A8h-AFh
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;B0h-B7h
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x0F,0x04, // ;B8h-BFh
|
||||
0xFF,0x0A,0x0A,0x0A,0xFF,0x0B,0x0F,0x0B, // ;C0h-C7h
|
||||
0xFF,0x0A,0x0A,0xF4,0xFF,0x11,0x0F,0x0B, // ;C8h-CFh
|
||||
0xFF,0x0A,0x0A,0x0B,0xFF,0x0B,0x0F,0x0B, // ;D0h-D7h
|
||||
0xFF,0x04,0x0A,0x0B,0xFF,0xF3,0x0F,0x0B, // ;D8h-DFh
|
||||
0xFF,0x0A,0x0A,0x13,0xFF,0x0B,0x0F,0x0B, // ;E0h-E7h
|
||||
0xFF,0x04,0x0A,0x04,0xFF,0xF2,0x0F,0x0B, // ;E8h-EFh
|
||||
0xFF,0x0A,0x0A,0x04,0xFF,0x0B,0x0F,0x0B, // ;F0h-F7h
|
||||
0xFF,0x06,0x0A,0x04,0xFF,0xF3,0x0F,0x0B // ;F8h-FFh
|
||||
];
|
||||
|
||||
private static readonly int[] s_tableDdCbFdCb =
|
||||
[
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;00h-07h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;08h-0Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;10h-17h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;18h-1Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;20h-27h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;28h-2Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;30h-37h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;38h-3Fh
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;40h-47h
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;48h-4Fh
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;50h-57h
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;58h-5Fh
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;60h-67h
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;68h-6Fh
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;70h-77h
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // ;78h-7Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;80h-87h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;88h-8Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;90h-97h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;98h-9Fh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;A0h-A7h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;A8h-AFh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;B0h-B7h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;B8h-BFh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;C0h-C7h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;C8h-CFh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;D0h-D7h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;D8h-DFh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;E0h-E7h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;E8h-EFh
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // ;F0h-F7h
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F // ;F8h-FFh
|
||||
];
|
||||
|
||||
private static readonly int[][] s_tables =
|
||||
[
|
||||
s_tableDirect,
|
||||
s_tableCb,
|
||||
s_tableEd,
|
||||
s_tableDdFd,
|
||||
s_tableDdCbFdCb,
|
||||
];
|
||||
|
||||
#endregion Tables
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user