240 lines
10 KiB
C
240 lines
10 KiB
C
|
/*====================================================================/*
|
||
|
opcodes_dd_fd.c -> This file executes the DD/FD PREFIX opcodes.
|
||
|
|
||
|
The DD prefix "creates" some new instructions by changing HL to IX
|
||
|
on the opcode defined by the next byte on memory.
|
||
|
|
||
|
The FD prefix "creates" some new instructions by changing HL to IY
|
||
|
on the opcode defined by the next byte on memory.
|
||
|
|
||
|
Change the REGISTER variable to IX or HY before including this file.
|
||
|
Something like:
|
||
|
|
||
|
#define REGISTER regs->IX
|
||
|
#include "op_dd_fd.c"
|
||
|
#undef REGISTER
|
||
|
|
||
|
On this code, this REGISTER variable is used as REGISTER.W or
|
||
|
REGISTER.B.h and REGISTER.B.l ...
|
||
|
|
||
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
|
||
|
Copyright (c) 2000 Santiago Romero Iglesias.
|
||
|
Email: sromero@escomposlinux.org
|
||
|
=====================================================================*/
|
||
|
|
||
|
/* 8 clock cycles minimum = DD opcode = FD opcode = 4 + 4 */
|
||
|
|
||
|
#define REG REGISTER.W
|
||
|
#define REGL REGISTER.B.l
|
||
|
#define REGH REGISTER.B.h
|
||
|
|
||
|
opcode = Z80ReadMem( r_PC );
|
||
|
r_PC++;
|
||
|
|
||
|
switch(opcode)
|
||
|
{
|
||
|
case ADD_IXY_BC : ADD_WORD(REG, r_BC); AddCycles( 4+4+7 ); break;
|
||
|
case ADD_IXY_DE : ADD_WORD(REG, r_DE); AddCycles( 4+4+7 ); break;
|
||
|
case ADD_IXY_SP : ADD_WORD(REG, r_SP); AddCycles( 4+4+7 ); break;
|
||
|
case ADD_IXY_IXY : ADD_WORD(REG, REG); AddCycles( 4+4+7 ); break;
|
||
|
case DEC_IXY : REG--; AddCycles( 4+4+2 ); break;
|
||
|
case INC_IXY : REG++; AddCycles( 4+4 ); break;
|
||
|
|
||
|
case JP_IXY : r_PC = REG; AddCycles( 4+4 );break;
|
||
|
case LD_SP_IXY : r_SP = REG; AddCycles( 4+4+2 ); break;
|
||
|
|
||
|
case PUSH_IXY : PUSH_IXYr(); AddCycles( 4+4+3+3+1 ); break;
|
||
|
case POP_IXY : POP_IXYr(); AddCycles( 4+4+3+3 ); break;
|
||
|
|
||
|
case EX_IXY_xSP : r_meml = Z80ReadMem(r_SP);
|
||
|
r_memh = Z80ReadMem(r_SP+1);
|
||
|
Z80WriteMem( r_SP, REGL, regs );
|
||
|
Z80WriteMem( r_SP+1, REGH, regs );
|
||
|
REGL=r_meml; REGH=r_memh;
|
||
|
AddCycles( 4+4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case LD_A_xIXY : r_A = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_B_xIXY : r_B = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_C_xIXY : r_C = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_D_xIXY : r_D = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_E_xIXY : r_E = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case LD_xIXY_A : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_A, regs );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_xIXY_B : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_B, regs );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_xIXY_C : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_C, regs );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_xIXY_D : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_D, regs );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_xIXY_E : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_E, regs );
|
||
|
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case INC_xIXY : r_mem = REG+(offset)Z80ReadMem(r_PC);
|
||
|
r_PC++;
|
||
|
tmpreg.B.l = Z80ReadMem(r_mem);
|
||
|
INC(tmpreg.B.l);
|
||
|
Z80WriteMem(r_mem, tmpreg.B.l, regs );
|
||
|
AddCycles( 4+3+3 + 3+3+3+ 3+1); break;
|
||
|
case DEC_xIXY : r_mem = REG+(offset)Z80ReadMem(r_PC);
|
||
|
r_PC++;
|
||
|
tmpreg.B.l = Z80ReadMem(r_mem);
|
||
|
DEC(tmpreg.B.l);
|
||
|
Z80WriteMem(r_mem, tmpreg.B.l, regs );
|
||
|
AddCycles( 4+3+3 + 3+3+3+ 3+1); break;
|
||
|
|
||
|
case ADC_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC)); r_PC++;
|
||
|
ADC(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case SBC_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
SBC(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case ADD_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
ADD(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case SUB_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
SUB(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case AND_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
AND(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case OR_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
OR(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case XOR_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
XOR(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case CP_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
|
||
|
r_PC++;
|
||
|
CP(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case LD_IXY_NN : REGL = Z80ReadMem(r_PC); r_PC++;
|
||
|
REGH = Z80ReadMem(r_PC); r_PC++;
|
||
|
AddCycles( 4+1+3+3+3 ); break;
|
||
|
|
||
|
case LD_xIXY_N : r_mem = REG + (offset) Z80ReadMem(r_PC); r_PC++;
|
||
|
Z80WriteMem( r_mem, Z80ReadMem(r_PC), regs ); r_PC++;
|
||
|
AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case LD_IXY_xNN : LOAD_rr_nn(REG);
|
||
|
AddCycles( 4+3+3+3+3+3+1 ); break;
|
||
|
|
||
|
case LD_xNN_IXY : STORE_nn_rr(REG);
|
||
|
AddCycles( 4+3+3+ 3+3+3+1 ); break;
|
||
|
|
||
|
|
||
|
/* some undocumented opcodes: may be wrong: */
|
||
|
case LD_A_IXYh : r_A = REGH; AddCycles(4+4); break;
|
||
|
case LD_A_IXYl : r_A = REGL; AddCycles(4+4); break;
|
||
|
case LD_B_IXYh : r_B = REGH; AddCycles(4+4); break;
|
||
|
case LD_B_IXYl : r_B = REGL; AddCycles(4+4); break;
|
||
|
case LD_C_IXYh : r_C = REGH; AddCycles(4+4); break;
|
||
|
case LD_C_IXYl : r_C = REGL; AddCycles(4+4); break;
|
||
|
case LD_D_IXYh : r_D = REGH; AddCycles(4+4); break;
|
||
|
case LD_D_IXYl : r_D = REGL; AddCycles(4+4); break;
|
||
|
case LD_E_IXYh : r_E = REGH; AddCycles(4+4); break;
|
||
|
case LD_E_IXYl : r_E = REGL; AddCycles(4+4); break;
|
||
|
case LD_IXYh_A : REGH = r_A; AddCycles(4+4); break;
|
||
|
case LD_IXYh_B : REGH = r_B; AddCycles(4+4); break;
|
||
|
case LD_IXYh_C : REGH = r_C; AddCycles(4+4); break;
|
||
|
case LD_IXYh_D : REGH = r_D; AddCycles(4+4); break;
|
||
|
case LD_IXYh_E : REGH = r_E; AddCycles(4+4); break;
|
||
|
case LD_IXYh_IXYh : AddCycles(4+4); break;
|
||
|
case LD_IXYh_IXYl : REGH = REGL; AddCycles(4+4); break;
|
||
|
case LD_IXYl_A : REGL = r_A; AddCycles(4+4); break;
|
||
|
case LD_IXYl_B : REGL = r_B; AddCycles(4+4); break;
|
||
|
case LD_IXYl_C : REGL = r_C; AddCycles(4+4); break;
|
||
|
case LD_IXYl_D : REGL = r_D; AddCycles(4+4); break;
|
||
|
case LD_IXYl_E : REGL = r_E; AddCycles(4+4); break;
|
||
|
case LD_IXYl_IXYh : REGL = REGH; AddCycles(4+4); break;
|
||
|
case LD_IXYl_IXYl : AddCycles(4+4); break;
|
||
|
case LD_IXYh_N : REGH = Z80ReadMem(r_PC); r_PC++;
|
||
|
AddCycles(4+4+3); break;
|
||
|
case LD_IXYl_N : REGL = Z80ReadMem(r_PC); r_PC++;
|
||
|
AddCycles(4+4+3); break;
|
||
|
|
||
|
|
||
|
case ADD_IXYh : ADD(REGH); AddCycles(4+4); break;
|
||
|
case ADD_IXYl : ADD(REGL); AddCycles(4+4); break;
|
||
|
case ADC_IXYh : ADC(REGH); AddCycles(4+4); break;
|
||
|
case ADC_IXYl : ADC(REGL); AddCycles(4+4); break;
|
||
|
case SUB_IXYh : SUB(REGH); AddCycles(4+4); break;
|
||
|
case SUB_IXYl : SUB(REGL); AddCycles(4+4); break;
|
||
|
case SBC_IXYh : SBC(REGH); AddCycles(4+4); break;
|
||
|
case SBC_IXYl : SBC(REGL); AddCycles(4+4); break;
|
||
|
case AND_IXYh : AND(REGH); AddCycles(4+4); break;
|
||
|
case AND_IXYl : AND(REGL); AddCycles(4+4); break;
|
||
|
case XOR_IXYh : XOR(REGH); AddCycles(4+4); break;
|
||
|
case XOR_IXYl : XOR(REGL); AddCycles(4+4); break;
|
||
|
case OR_IXYh : OR(REGH); AddCycles(4+4); break;
|
||
|
case OR_IXYl : OR(REGL); AddCycles(4+4); break;
|
||
|
case CP_IXYh : CP(REGH); AddCycles(4+4); break;
|
||
|
case CP_IXYl : CP(REGL); AddCycles(4+4); break;
|
||
|
case INC_IXYh : INC(REGH); AddCycles(4+4); break;
|
||
|
case INC_IXYl : INC(REGL); AddCycles(4+4); break;
|
||
|
case DEC_IXYh : DEC(REGH); AddCycles(4+4); break;
|
||
|
case DEC_IXYl : DEC(REGL); AddCycles(4+4); break;
|
||
|
|
||
|
case LD_xIXY_H : r_meml =Z80ReadMem(r_PC); r_PC++;
|
||
|
Z80WriteMem( REG+(offset)(r_meml), r_H, regs );
|
||
|
AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_xIXY_L : r_meml =Z80ReadMem(r_PC); r_PC++;
|
||
|
Z80WriteMem( REG+(offset)(r_meml), r_L, regs );
|
||
|
AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_H_xIXY : r_meml =Z80ReadMem(r_PC); r_PC++;
|
||
|
r_H = Z80ReadMem( REG+(offset)(r_meml));
|
||
|
AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
case LD_L_xIXY : r_meml =Z80ReadMem(r_PC); r_PC++;
|
||
|
r_L = Z80ReadMem( REG+(offset)(r_meml));
|
||
|
AddCycles( 4+3+3+3+3+3 ); break;
|
||
|
|
||
|
case PREFIX_CB:
|
||
|
#include "opddfdcb.c"
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
case PREFIX_DD:
|
||
|
case PREFIX_FD: AddCycles( 4 );
|
||
|
r_PC--; // decode it the next time :)
|
||
|
break;
|
||
|
*/
|
||
|
|
||
|
default: AddCycles( 4 );
|
||
|
r_PC--; /* decode it the next time :) */
|
||
|
SubR(1);
|
||
|
|
||
|
// exit(1);
|
||
|
// if( regs->DecodingErrors )
|
||
|
// {
|
||
|
// printf("z80 core: Unknown instruction: ");
|
||
|
// if ( regs->we_are_on_ddfd == WE_ARE_ON_DD )
|
||
|
// printf("DD ");
|
||
|
// else
|
||
|
// printf("FD ");
|
||
|
// printf("%02Xh at PC=%04Xh.\n", Z80ReadMem(r_PC-1), r_PC-2 );
|
||
|
// }
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#undef REG
|
||
|
#undef REGL
|
||
|
#undef REGH
|