/*
    Z80 emulator

    Copyright (c) 1996-2003,2004 Alessandro Scotti
    http://www.ascotti.org/

    This program 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 2 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#include "z80.h"

Z80::OpcodeInfo Z80::OpInfoED_[256] = {
    { 0, 0 }, // 0x00
    { 0, 0 }, // 0x01
    { 0, 0 }, // 0x02
    { 0, 0 }, // 0x03
    { 0, 0 }, // 0x04
    { 0, 0 }, // 0x05
    { 0, 0 }, // 0x06
    { 0, 0 }, // 0x07
    { 0, 0 }, // 0x08
    { 0, 0 }, // 0x09
    { 0, 0 }, // 0x0A
    { 0, 0 }, // 0x0B
    { 0, 0 }, // 0x0C
    { 0, 0 }, // 0x0D
    { 0, 0 }, // 0x0E
    { 0, 0 }, // 0x0F
    { 0, 0 }, // 0x10
    { 0, 0 }, // 0x11
    { 0, 0 }, // 0x12
    { 0, 0 }, // 0x13
    { 0, 0 }, // 0x14
    { 0, 0 }, // 0x15
    { 0, 0 }, // 0x16
    { 0, 0 }, // 0x17
    { 0, 0 }, // 0x18
    { 0, 0 }, // 0x19
    { 0, 0 }, // 0x1A
    { 0, 0 }, // 0x1B
    { 0, 0 }, // 0x1C
    { 0, 0 }, // 0x1D
    { 0, 0 }, // 0x1E
    { 0, 0 }, // 0x1F
    { 0, 0 }, // 0x20
    { 0, 0 }, // 0x21
    { 0, 0 }, // 0x22
    { 0, 0 }, // 0x23
    { 0, 0 }, // 0x24
    { 0, 0 }, // 0x25
    { 0, 0 }, // 0x26
    { 0, 0 }, // 0x27
    { 0, 0 }, // 0x28
    { 0, 0 }, // 0x29
    { 0, 0 }, // 0x2A
    { 0, 0 }, // 0x2B
    { 0, 0 }, // 0x2C
    { 0, 0 }, // 0x2D
    { 0, 0 }, // 0x2E
    { 0, 0 }, // 0x2F
    { 0, 0 }, // 0x30
    { 0, 0 }, // 0x31
    { 0, 0 }, // 0x32
    { 0, 0 }, // 0x33
    { 0, 0 }, // 0x34
    { 0, 0 }, // 0x35
    { 0, 0 }, // 0x36
    { 0, 0 }, // 0x37
    { 0, 0 }, // 0x38
    { 0, 0 }, // 0x39
    { 0, 0 }, // 0x3A
    { 0, 0 }, // 0x3B
    { 0, 0 }, // 0x3C
    { 0, 0 }, // 0x3D
    { 0, 0 }, // 0x3E
    { 0, 0 }, // 0x3F
    { &Z80::opcode_ed_40, 12 }, // IN B, (C)
    { &Z80::opcode_ed_41, 12 }, // OUT (C), B
    { &Z80::opcode_ed_42, 15 }, // SBC HL, BC
    { &Z80::opcode_ed_43, 20 }, // LD (nn), BC
    { &Z80::opcode_ed_44,  8 }, // NEG
    { &Z80::opcode_ed_45, 14 }, // RETN
    { &Z80::opcode_ed_46,  8 }, // IM 0
    { &Z80::opcode_ed_47,  9 }, // LD I, A
    { &Z80::opcode_ed_48, 12 }, // IN C, (C)
    { &Z80::opcode_ed_49, 12 }, // OUT (C), C
    { &Z80::opcode_ed_4a, 15 }, // ADC HL, BC
    { &Z80::opcode_ed_4b, 20 }, // LD BC, (nn)
    { &Z80::opcode_ed_4c,  8 }, // NEG
    { &Z80::opcode_ed_4d, 14 }, // RETI
    { &Z80::opcode_ed_4e,  8 }, // IM 0/1
    { &Z80::opcode_ed_4f,  9 }, // LD R, A
    { &Z80::opcode_ed_50, 12 }, // IN D, (C)
    { &Z80::opcode_ed_51, 12 }, // OUT (C), D
    { &Z80::opcode_ed_52, 15 }, // SBC HL, DE
    { &Z80::opcode_ed_53, 20 }, // LD (nn), DE
    { &Z80::opcode_ed_54,  8 }, // NEG
    { &Z80::opcode_ed_55, 14 }, // RETN
    { &Z80::opcode_ed_56,  8 }, // IM 1
    { &Z80::opcode_ed_57,  9 }, // LD A, I
    { &Z80::opcode_ed_58, 12 }, // IN E, (C)
    { &Z80::opcode_ed_59, 12 }, // OUT (C), E
    { &Z80::opcode_ed_5a, 15 }, // ADC HL, DE
    { &Z80::opcode_ed_5b, 20 }, // LD DE, (nn)
    { &Z80::opcode_ed_5c,  8 }, // NEG
    { &Z80::opcode_ed_5d, 14 }, // RETN
    { &Z80::opcode_ed_5e,  8 }, // IM 2
    { &Z80::opcode_ed_5f,  9 }, // LD A, R
    { &Z80::opcode_ed_60, 12 }, // IN H, (C)
    { &Z80::opcode_ed_61, 12 }, // OUT (C), H
    { &Z80::opcode_ed_62, 15 }, // SBC HL, HL
    { &Z80::opcode_ed_63, 20 }, // LD (nn), HL
    { &Z80::opcode_ed_64,  8 }, // NEG
    { &Z80::opcode_ed_65, 14 }, // RETN
    { &Z80::opcode_ed_66,  8 }, // IM 0
    { &Z80::opcode_ed_67, 18 }, // RRD
    { &Z80::opcode_ed_68, 12 }, // IN L, (C)
    { &Z80::opcode_ed_69, 12 }, // OUT (C), L
    { &Z80::opcode_ed_6a, 15 }, // ADC HL, HL
    { &Z80::opcode_ed_6b, 20 }, // LD HL, (nn)
    { &Z80::opcode_ed_6c,  8 }, // NEG
    { &Z80::opcode_ed_6d, 14 }, // RETN
    { &Z80::opcode_ed_6e,  8 }, // IM 0/1
    { &Z80::opcode_ed_6f, 18 }, // RLD
    { &Z80::opcode_ed_70, 12 }, // IN (C) / IN F, (C)
    { &Z80::opcode_ed_71, 12 }, // OUT (C), 0
    { &Z80::opcode_ed_72, 15 }, // SBC HL, SP
    { &Z80::opcode_ed_73, 20 }, // LD (nn), SP
    { &Z80::opcode_ed_74,  8 }, // NEG
    { &Z80::opcode_ed_75, 14 }, // RETN
    { &Z80::opcode_ed_76,  8 }, // IM 1
    { 0, 0 }, // 0x77
    { &Z80::opcode_ed_78, 12 }, // IN A, (C)
    { &Z80::opcode_ed_79, 12 }, // OUT (C), A
    { &Z80::opcode_ed_7a, 15 }, // ADC HL, SP
    { &Z80::opcode_ed_7b, 20 }, // LD SP, (nn)
    { &Z80::opcode_ed_7c,  8 }, // NEG
    { &Z80::opcode_ed_7d, 14 }, // RETN
    { &Z80::opcode_ed_7e,  8 }, // IM 2
    { 0, 0 }, // 0x7F
    { 0, 0 }, // 0x80
    { 0, 0 }, // 0x81
    { 0, 0 }, // 0x82
    { 0, 0 }, // 0x83
    { 0, 0 }, // 0x84
    { 0, 0 }, // 0x85
    { 0, 0 }, // 0x86
    { 0, 0 }, // 0x87
    { 0, 0 }, // 0x88
    { 0, 0 }, // 0x89
    { 0, 0 }, // 0x8A
    { 0, 0 }, // 0x8B
    { 0, 0 }, // 0x8C
    { 0, 0 }, // 0x8D
    { 0, 0 }, // 0x8E
    { 0, 0 }, // 0x8F
    { 0, 0 }, // 0x90
    { 0, 0 }, // 0x91
    { 0, 0 }, // 0x92
    { 0, 0 }, // 0x93
    { 0, 0 }, // 0x94
    { 0, 0 }, // 0x95
    { 0, 0 }, // 0x96
    { 0, 0 }, // 0x97
    { 0, 0 }, // 0x98
    { 0, 0 }, // 0x99
    { 0, 0 }, // 0x9A
    { 0, 0 }, // 0x9B
    { 0, 0 }, // 0x9C
    { 0, 0 }, // 0x9D
    { 0, 0 }, // 0x9E
    { 0, 0 }, // 0x9F
    { &Z80::opcode_ed_a0, 16 }, // LDI
    { &Z80::opcode_ed_a1, 16 }, // CPI
    { &Z80::opcode_ed_a2, 16 }, // INI
    { &Z80::opcode_ed_a3, 16 }, // OUTI
    { 0, 0 }, // 0xA4
    { 0, 0 }, // 0xA5
    { 0, 0 }, // 0xA6
    { 0, 0 }, // 0xA7
    { &Z80::opcode_ed_a8, 16 }, // LDD
    { &Z80::opcode_ed_a9, 16 }, // CPD
    { &Z80::opcode_ed_aa, 16 }, // IND
    { &Z80::opcode_ed_ab, 16 }, // OUTD
    { 0, 0 }, // 0xAC
    { 0, 0 }, // 0xAD
    { 0, 0 }, // 0xAE
    { 0, 0 }, // 0xAF
    { &Z80::opcode_ed_b0,  0 }, // LDIR
    { &Z80::opcode_ed_b1,  0 }, // CPIR
    { &Z80::opcode_ed_b2,  0 }, // INIR
    { &Z80::opcode_ed_b3,  0 }, // OTIR
    { 0, 0 }, // 0xB4
    { 0, 0 }, // 0xB5
    { 0, 0 }, // 0xB6
    { 0, 0 }, // 0xB7
    { &Z80::opcode_ed_b8,  0 }, // LDDR
    { &Z80::opcode_ed_b9,  0 }, // CPDR
    { &Z80::opcode_ed_ba,  0 }, // INDR
    { &Z80::opcode_ed_bb,  0 }, // OTDR
    { 0, 0 }, // 0xBC
    { 0, 0 }, // 0xBD
    { 0, 0 }, // 0xBE
    { 0, 0 }, // 0xBF
    { 0, 0 }, // 0xC0
    { 0, 0 }, // 0xC1
    { 0, 0 }, // 0xC2
    { 0, 0 }, // 0xC3
    { 0, 0 }, // 0xC4
    { 0, 0 }, // 0xC5
    { 0, 0 }, // 0xC6
    { 0, 0 }, // 0xC7
    { 0, 0 }, // 0xC8
    { 0, 0 }, // 0xC9
    { 0, 0 }, // 0xCA
    { 0, 0 }, // 0xCB
    { 0, 0 }, // 0xCC
    { 0, 0 }, // 0xCD
    { 0, 0 }, // 0xCE
    { 0, 0 }, // 0xCF
    { 0, 0 }, // 0xD0
    { 0, 0 }, // 0xD1
    { 0, 0 }, // 0xD2
    { 0, 0 }, // 0xD3
    { 0, 0 }, // 0xD4
    { 0, 0 }, // 0xD5
    { 0, 0 }, // 0xD6
    { 0, 0 }, // 0xD7
    { 0, 0 }, // 0xD8
    { 0, 0 }, // 0xD9
    { 0, 0 }, // 0xDA
    { 0, 0 }, // 0xDB
    { 0, 0 }, // 0xDC
    { 0, 0 }, // 0xDD
    { 0, 0 }, // 0xDE
    { 0, 0 }, // 0xDF
    { 0, 0 }, // 0xE0
    { 0, 0 }, // 0xE1
    { 0, 0 }, // 0xE2
    { 0, 0 }, // 0xE3
    { 0, 0 }, // 0xE4
    { 0, 0 }, // 0xE5
    { 0, 0 }, // 0xE6
    { 0, 0 }, // 0xE7
    { 0, 0 }, // 0xE8
    { 0, 0 }, // 0xE9
    { 0, 0 }, // 0xEA
    { 0, 0 }, // 0xEB
    { 0, 0 }, // 0xEC
    { 0, 0 }, // 0xED
    { 0, 0 }, // 0xEE
    { 0, 0 }, // 0xEF
    { 0, 0 }, // 0xF0
    { 0, 0 }, // 0xF1
    { 0, 0 }, // 0xF2
    { 0, 0 }, // 0xF3
    { 0, 0 }, // 0xF4
    { 0, 0 }, // 0xF5
    { 0, 0 }, // 0xF6
    { 0, 0 }, // 0xF7
    { 0, 0 }, // 0xF8
    { 0, 0 }, // 0xF9
    { 0, 0 }, // 0xFA
    { 0, 0 }, // 0xFB
    { 0, 0 }, // 0xFC
    { 0, 0 }, // 0xFD
    { 0, 0 }, // 0xFE
    { 0, 0 }  // 0xFF
};

void Z80::opcode_ed_40()    // IN B, (C)
{
    B = inpReg();
}

void Z80::opcode_ed_41()    // OUT (C), B
{
    env_.writePort( C, B );
}

void Z80::opcode_ed_42()    // SBC HL, BC
{
    unsigned char a;

    a = A;
    A = L; L = subByte( C, F & Carry );
    A = H; H = subByte( B, F & Carry );
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_43()    // LD (nn), BC
{
    unsigned addr = fetchWord();

    env_.writeByte( addr, C );
    env_.writeByte( addr+1, B );
}

void Z80::opcode_ed_44()    // NEG
{
    unsigned char   a = A;

    A = 0;
    A = subByte( a, 0 );
}

void Z80::opcode_ed_45()    // RETN
{
    retFromSub();
    iflags_ &= ~IFF1; 
    if( iflags_ & IFF2 ) iflags_ |= IFF1;
}

void Z80::opcode_ed_46()    // IM 0
{
    setInterruptMode( 0 );
}

void Z80::opcode_ed_47()    // LD I, A
{
    I = A;
}

void Z80::opcode_ed_48()    // IN C, (C)
{
    C = inpReg();
}

void Z80::opcode_ed_49()    // OUT (C), C
{
    env_.writePort( C, C );
}

void Z80::opcode_ed_4a()    // ADC HL, BC
{
    unsigned char a;

    a = A;
    A = L; addByte( C, F & Carry ); L = A;
    A = H; addByte( B, F & Carry ); H = A;
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_4b()    // LD BC, (nn)
{
    unsigned    addr = fetchWord();

    C = env_.readByte( addr );
    B = env_.readByte( addr+1 );
}

void Z80::opcode_ed_4c()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_4d()    // RETI
{
    retFromSub();
    env_.onReturnFromInterrupt();
}

void Z80::opcode_ed_4e()    // IM 0/1
{
    setInterruptMode( 0 );
}

void Z80::opcode_ed_4f()    // LD R, A
{
    R = A;
}

void Z80::opcode_ed_50()    // IN D, (C)
{
    D = inpReg();
}

void Z80::opcode_ed_51()    // OUT (C), D
{
    env_.writePort( C, D );
}

void Z80::opcode_ed_52()    // SBC HL, DE
{
    unsigned char a;

    a = A;
    A = L; L = subByte( E, F & Carry );
    A = H; H = subByte( D, F & Carry );
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_53()    // LD (nn), DE
{
    unsigned addr = fetchWord();

    env_.writeByte( addr, E );
    env_.writeByte( addr+1, D );
}

void Z80::opcode_ed_54()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_55()    // RETN
{
    opcode_ed_45();
}

void Z80::opcode_ed_56()    // IM 1
{
    setInterruptMode( 1 );
}

void Z80::opcode_ed_57()    // LD A, I
{
    A = I;
    setFlags35PSZ();
    F &= ~(Halfcarry | Parity | AddSub);
    if( iflags_ & IFF2 ) F |= Parity;
}

void Z80::opcode_ed_58()    // IN E, (C)
{
    E = inpReg();
}

void Z80::opcode_ed_59()    // OUT (C), E
{
    env_.writePort( C, E );
}

void Z80::opcode_ed_5a()    // ADC HL, DE
{
    unsigned char a;

    a = A;
    A = L; addByte( E, F & Carry ); L = A;
    A = H; addByte( D, F & Carry ); H = A;
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_5b()    // LD DE, (nn)
{
    unsigned    addr = fetchWord();

    E = env_.readByte( addr );
    D = env_.readByte( addr+1 );
}

void Z80::opcode_ed_5c()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_5d()    // RETN
{
    opcode_ed_45();
}

void Z80::opcode_ed_5e()    // IM 2
{
    setInterruptMode( 2 );
}

void Z80::opcode_ed_5f()    // LD A, R
{
    A = R;
    setFlags35PSZ();
    F &= ~(Halfcarry | Parity | AddSub);
    if( iflags_ & IFF2 ) F |= Parity;
}

void Z80::opcode_ed_60()    // IN H, (C)
{
    H = inpReg();
}

void Z80::opcode_ed_61()    // OUT (C), H
{
    env_.writePort( C, H );
}

void Z80::opcode_ed_62()    // SBC HL, HL
{
    unsigned char a;

    a = A;
    A = L; L = subByte( L, F & Carry );
    A = H; H = subByte( H, F & Carry );
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_63()    // LD (nn), HL
{
    unsigned addr = fetchWord();

    env_.writeByte( addr, L );
    env_.writeByte( addr+1, H );
}

void Z80::opcode_ed_64()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_65()    // RETN
{
    opcode_ed_45();
}

void Z80::opcode_ed_66()    // IM 0
{
    setInterruptMode( 0 );
}

void Z80::opcode_ed_67()    // RRD
{
    unsigned char   x = env_.readByte( HL() );

    env_.writeByte( HL(), (A << 4) | (x >> 4) );
    A = (A & 0xF0) | (x & 0x0F);
    setFlags35PSZ();
    F &= ~(Halfcarry | AddSub);
}

void Z80::opcode_ed_68()    // IN L, (C)
{
    L = inpReg();
}

void Z80::opcode_ed_69()    // OUT (C), L
{
    env_.writePort( C, L );
}

void Z80::opcode_ed_6a()    // ADC HL, HL
{
    unsigned char a;

    a = A;
    A = L; addByte( L, F & Carry ); L = A;
    A = H; addByte( H, F & Carry ); H = A;
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_6b()    // LD HL, (nn)
{
    unsigned    addr = fetchWord();

    L = env_.readByte( addr );
    H = env_.readByte( addr+1 );
}

void Z80::opcode_ed_6c()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_6d()    // RETN
{
    opcode_ed_45();
}

void Z80::opcode_ed_6e()    // IM 0/1
{
    setInterruptMode( 0 );
}

void Z80::opcode_ed_6f()    // RLD
{
    unsigned char   x = env_.readByte( HL() );

    env_.writeByte( HL(), (x << 4) | (A & 0x0F) );
    A = (A & 0xF0) | (x >> 4);
    setFlags35PSZ();
    F &= ~(Halfcarry | AddSub);
}

void Z80::opcode_ed_70()    // IN (C) / IN F, (C)
{
    inpReg();
}

void Z80::opcode_ed_71()    // OUT (C), 0
{
    env_.writePort( C, 0 );
}

void Z80::opcode_ed_72()    // SBC HL, SP
{
    unsigned char a;

    a = A;
    A = L; L = subByte( SP & 0xFF, F & Carry );
    A = H; H = subByte( (SP >> 8) & 0xFF, F & Carry );
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_73()    // LD (nn), SP
{
    writeWord( fetchWord(), SP );
}

void Z80::opcode_ed_74()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_75()    // RETN
{
    opcode_ed_45();
}

void Z80::opcode_ed_76()    // IM 1
{
    setInterruptMode( 1 );
}

void Z80::opcode_ed_78()    // IN A, (C)
{
    A = inpReg();
}

void Z80::opcode_ed_79()    // OUT (C), A
{
    env_.writePort( C, A );
}

void Z80::opcode_ed_7a()    // ADC HL, SP
{
    unsigned char a;

    a = A;
    A = L; addByte( SP & 0xFF, F & Carry ); L = A;
    A = H; addByte( (SP >> 8) & 0xFF, F & Carry ); H = A;
    A = a;
    if( HL() == 0 ) F |= Zero; else F &= ~Zero;
}

void Z80::opcode_ed_7b()    // LD SP, (nn)
{
    SP = readWord( fetchWord() );
}

void Z80::opcode_ed_7c()    // NEG
{
    opcode_ed_44();
}

void Z80::opcode_ed_7d()    // RETN
{
    opcode_ed_45();
}

void Z80::opcode_ed_7e()    // IM 2
{
    setInterruptMode( 2 );
}

void Z80::opcode_ed_a0()    // LDI
{
    env_.writeByte( DE(), env_.readByte( HL() ) );
    if( ++L == 0 ) ++H; // HL++
    if( ++E == 0 ) ++D; // DE++
    if( C-- == 0 ) --B; // BC--
    F &= ~(Halfcarry | Subtraction | Parity);
    if( BC() ) F |= Parity;
}

void Z80::opcode_ed_a1()    // CPI
{
    unsigned char f = F;

    cmpByte( env_.readByte( HL() ) );
    if( ++L == 0 ) ++H; // HL++
    if( C-- == 0 ) --B; // BC--
    F = (F & ~(Carry | Parity)) | (f & Carry);
    if( BC() ) F |= Parity;
}

void Z80::opcode_ed_a2()    // INI
{
    env_.writeByte( HL(), env_.readPort( C ) );
    if( ++L == 0 ) ++H; // HL++
    B = decByte( B );
}

void Z80::opcode_ed_a3()    // OUTI
{
    env_.writePort( C, env_.readByte( HL() ) );
    if( ++L == 0 ) ++H; // HL++
    B = decByte( B );
}

void Z80::opcode_ed_a8()    // LDD
{
    env_.writeByte( DE(), env_.readByte( HL() ) );
    if( L-- == 0 ) --H; // HL--
    if( E-- == 0 ) --D; // DE--
    if( C-- == 0 ) --B; // BC--
    F &= ~(Halfcarry | Subtraction | Parity);
    if( BC() ) F |= Parity;
}

void Z80::opcode_ed_a9()    // CPD
{
    unsigned char f = F;

    cmpByte( env_.readByte( HL() ) );
    if( L-- == 0 ) --H; // HL--
    if( C-- == 0 ) --B; // BC--
    F = (F & ~(Carry | Parity)) | (f & Carry);
    if( BC() ) F |= Parity;
}

void Z80::opcode_ed_aa()    // IND
{
    env_.writeByte( HL(), env_.readPort( C ) );
    if( L-- == 0 ) --H; // HL--
    B = decByte( B );
}

void Z80::opcode_ed_ab()    // OUTD
{
    env_.writePort( C, env_.readByte( HL() ) );
    if( L-- == 0 ) --H; // HL--
    B = decByte( B );
}

void Z80::opcode_ed_b0()    // LDIR
{
    opcode_ed_a0(); // LDI
    if( F & Parity ) { // After LDI, the Parity flag will be zero when BC=0
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}

void Z80::opcode_ed_b1()    // CPIR
{
    opcode_ed_a1(); // CPI
    if( (F & Parity) && !(F & Zero) ) { // Parity clear when BC=0, Zero set when A=(HL)
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}

void Z80::opcode_ed_b2()    // INIR
{
    opcode_ed_a2(); // INI
    if( B != 0 ) {
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}

void Z80::opcode_ed_b3()    // OTIR
{
    opcode_ed_a3(); // OUTI
    if( B != 0 ) {
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}

void Z80::opcode_ed_b8()    // LDDR
{
    opcode_ed_a8(); // LDD
    if( F & Parity ) { // After LDD, the Parity flag will be zero when BC=0
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}

void Z80::opcode_ed_b9()    // CPDR
{
    opcode_ed_a9(); // CPD
    if( (F & Parity) && !(F & Zero) ) { // Parity clear when BC=0, Zero set when A=(HL)
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}

void Z80::opcode_ed_ba()    // INDR
{
    opcode_ed_aa(); // IND
    if( B != 0 ) {
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}
                            
void Z80::opcode_ed_bb()    // OTDR
{
    opcode_ed_ab(); // OUTD
    if( B != 0 ) {
        cycles_ += 5;
        PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur)
    }
}
