Add OPL4 playback and analyzer support
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user