/** Z80: portable Z80 emulator **********************************************/ /** **/ /** CodeED.c **/ /** **/ /** This file contains the emulation of ED XX opcodes **/ /** **/ /** Copyright (C) Marat Fayzullin 1994,1995,1996 **/ /** Marcel de Kogel 1996 **/ /** You are not allowed to distribute this software commercially **/ /** Please, notify me, if you make any changes to this file **/ /****************************************************************************/ #include "Z80.h" #include typedef void (*FnPtr)(void); extern void Z80_BadOpcode (void); static void adc_hl_bc(void){ M_ADCW(BC);} static void adc_hl_de(void){ M_ADCW(DE);} static void adc_hl_hl(void){ M_ADCW(HL);} static void adc_hl_sp(void){ M_ADCW(SP);} static void sbc_hl_bc(void){ M_SBCW(BC);} static void sbc_hl_de(void){ M_SBCW(DE);} static void sbc_hl_hl(void){ M_SBCW(HL);} static void sbc_hl_sp(void){ M_SBCW(SP);} static void fuck (void) { Z80_BadOpcode (); } static void ld_xworde_hl(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); M_WRMEM(J.W.l,R.HL.B.l);J.W.l++; M_WRMEM(J.W.l,R.HL.B.h); } static void ld_xworde_de(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); M_WRMEM(J.W.l,R.DE.B.l);J.W.l++; M_WRMEM(J.W.l,R.DE.B.h); } static void ld_xworde_bc(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); M_WRMEM(J.W.l,R.BC.B.l);J.W.l++; M_WRMEM(J.W.l,R.BC.B.h); } static void ld_xworde_sp(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); M_WRMEM(J.W.l,R.SP.B.l);J.W.l++; M_WRMEM(J.W.l,R.SP.B.h); } static void ld_hl_xworde(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); R.HL.B.l=M_RDMEM((J.W.l++)); R.HL.B.h=M_RDMEM(J.W.l); } static void ld_de_xworde(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); R.DE.B.l=M_RDMEM((J.W.l++)); R.DE.B.h=M_RDMEM(J.W.l); } static void ld_bc_xworde(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); R.BC.B.l=M_RDMEM((J.W.l++)); R.BC.B.h=M_RDMEM(J.W.l); } static void ld_sp_xworde(void){pair J; J.B.l=M_RDMEM_OPCODE(); J.B.h=M_RDMEM_OPCODE(); R.SP.B.l=M_RDMEM((J.W.l++)); R.SP.B.h=M_RDMEM(J.W.l); } static void rrd(void){ byte I;pair J; I=M_RDMEM(R.HL.D); J.B.l=(I>>4)|(R.AF.B.h<<4); M_WRMEM(R.HL.D,J.B.l); R.AF.B.h=(I&0x0F)|(R.AF.B.h&0xF0); R.AF.B.l= ZSPTable[R.AF.B.h]|(R.AF.B.l&C_FLAG); } static void rld(void){ byte I;pair J; I=M_RDMEM(R.HL.D); J.B.l=(I<<4)|(R.AF.B.h&0x0F); M_WRMEM(R.HL.D,J.B.l); R.AF.B.h=(I>>4)|(R.AF.B.h&0xF0); R.AF.B.l= ZSPTable[R.AF.B.h]|(R.AF.B.l&C_FLAG); } static void ld_a_i(void){ R.AF.B.h=R.I; R.AF.B.l= (R.AF.B.l&C_FLAG)|(R.IFF&0x40? P_FLAG:0)| (R.AF.B.h? 0:Z_FLAG)|(R.AF.B.h&S_FLAG); } static void ld_a_r(void){ R.AF.B.h=(R.R&0x7F)|(R.R2&0x80); R.AF.B.l= (R.AF.B.l&C_FLAG)|(R.IFF&0x40? P_FLAG:0)| (R.AF.B.h? 0:Z_FLAG)|(R.AF.B.h&S_FLAG); } static void ld_i_a(void){ R.I=R.AF.B.h;} static void ld_r_a(void){ R.R=R.R2=R.AF.B.h; }; static void im_0(void) { R.IFF&=0xF9; } static void im_1(void) { R.IFF=(R.IFF&0xF9)|2; } static void im_2(void) { R.IFF=(R.IFF&0xF9)|4; } static void reti(void) { M_RET; } static void retn(void) { if (R.IFF&0x40) R.IFF|=1; else R.IFF&=0xFE; M_RET; } static void neg(void){ byte I; I=R.AF.B.h;R.AF.B.h=0;M_SUB(I);} static void in_b_xc(void){ M_IN(R.BC.B.h);} static void in_c_xc(void){ M_IN(R.BC.B.l);} static void in_d_xc(void){ M_IN(R.DE.B.h);} static void in_e_xc(void){ M_IN(R.DE.B.l);} static void in_h_xc(void){ M_IN(R.HL.B.h);} static void in_l_xc(void){ M_IN(R.HL.B.l);} static void in_a_xc(void){ M_IN(R.AF.B.h);} static void in_f_xc(void){pair J; M_IN(J.B.l);} static void out_xc_b(void){ DoOut(R.BC.B.l,R.BC.B.h);} static void out_xc_c(void){ DoOut(R.BC.B.l,R.BC.B.l);} static void out_xc_d(void){ DoOut(R.BC.B.l,R.DE.B.h);} static void out_xc_e(void){ DoOut(R.BC.B.l,R.DE.B.l);} static void out_xc_h(void){ DoOut(R.BC.B.l,R.HL.B.h);} static void out_xc_l(void){ DoOut(R.BC.B.l,R.HL.B.l);} static void out_xc_a(void){ DoOut(R.BC.B.l,R.AF.B.h);} static void ini(void) { M_WRMEM(R.HL.D,DoIn(R.BC.B.l));R.HL.W.l++;R.BC.B.h--; R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); } static void inir(void) { R.R-=2; do { R.R+=2; M_WRMEM(R.HL.D,DoIn(R.BC.B.l));R.HL.W.l++;R.BC.B.h--; ICount-=21; } while (R.BC.B.h && ICount>0); R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); if (R.BC.B.h) R.PC.W.l-=2; else ICount+=5; } static void ind(void) { M_WRMEM(R.HL.D,DoIn(R.BC.B.l));R.HL.W.l--;R.BC.B.h--; R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); } static void indr(void) { R.R-=2; do { R.R+=2; M_WRMEM(R.HL.D,DoIn(R.BC.B.l));R.HL.W.l--;R.BC.B.h--; ICount-=21; } while (R.BC.B.h && ICount>0); R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); if (R.BC.B.h) R.PC.W.l-=2; else ICount+=5; } static void outi(void) { DoOut(R.BC.B.l,M_RDMEM(R.HL.D));R.HL.W.l++;R.BC.B.h--; R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); } static void otir(void) { R.R-=2; do { R.R+=2; DoOut(R.BC.B.l,M_RDMEM(R.HL.D));R.HL.W.l++;R.BC.B.h--; ICount-=21; } while (R.BC.B.h && ICount>0); R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); if (R.BC.B.h) R.PC.W.l-=2; else ICount+=5; } static void outd(void) { DoOut(R.BC.B.l,M_RDMEM(R.HL.D));R.HL.W.l--;R.BC.B.h--; R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); } static void otdr(void) { R.R-=2; do { R.R+=2; DoOut(R.BC.B.l,M_RDMEM(R.HL.D));R.HL.W.l--;R.BC.B.h--; ICount-=21; } while (R.BC.B.h && ICount>0); R.AF.B.l=N_FLAG|(R.BC.B.h? 0:Z_FLAG); if (R.BC.B.h) R.PC.W.l-=2; else ICount+=5; } static void ldi(void) { byte I; I=M_RDMEM(R.HL.D);R.HL.W.l++;M_WRMEM(R.DE.D,I);R.DE.W.l++;R.BC.W.l--; R.AF.B.l=(R.AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R.BC.W.l? P_FLAG:0); } static void ldir(void) { byte I; R.R-=2; do { R.R+=2; I=M_RDMEM(R.HL.D);R.HL.W.l++;M_WRMEM(R.DE.D,I);R.DE.W.l++;R.BC.W.l--; ICount-=21; } while (R.BC.W.l && ICount>0); R.AF.B.l=(R.AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R.BC.W.l? P_FLAG:0); if (R.BC.W.l) R.PC.W.l-=2; else ICount+=5; } static void ldd(void) { byte I; I=M_RDMEM(R.HL.D);R.HL.W.l--;M_WRMEM(R.DE.D,I);R.DE.W.l--;R.BC.W.l--; R.AF.B.l=(R.AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R.BC.W.l? P_FLAG:0); } static void lddr(void) { byte I; R.R-=2; do { R.R+=2; I=M_RDMEM(R.HL.D);R.HL.W.l--;M_WRMEM(R.DE.D,I);R.DE.W.l--;R.BC.W.l--; ICount-=21; } while (R.BC.W.l && ICount>0); R.AF.B.l=(R.AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R.BC.W.l? P_FLAG:0); if (R.BC.W.l) R.PC.W.l-=2; else ICount+=5; } static void cpi(void) { byte I,J; I=M_RDMEM(R.HL.D);R.HL.W.l++;J=R.AF.B.h-I;R.BC.W.l--; R.AF.B.l= N_FLAG|(R.AF.B.l&C_FLAG)|ZSTable[J]| ((R.AF.B.h^I^J)&H_FLAG)|(R.BC.W.l? P_FLAG:0); } static void cpir(void) { byte I,J; R.R-=2; do { R.R+=2; I=M_RDMEM(R.HL.D);R.HL.W.l++;J=R.AF.B.h-I;R.BC.W.l--; ICount-=21; } while (R.BC.W.l && J && ICount>0); R.AF.B.l= N_FLAG|(R.AF.B.l&C_FLAG)|ZSTable[J]| ((R.AF.B.h^I^J)&H_FLAG)|(R.BC.W.l? P_FLAG:0); if (R.BC.W.l && J) R.PC.W.l-=2; else ICount+=5; } static void cpd(void) { byte I,J; I=M_RDMEM(R.HL.D);R.HL.W.l--;J=R.AF.B.h-I;R.BC.W.l--; R.AF.B.l= N_FLAG|(R.AF.B.l&C_FLAG)|ZSTable[J]| ((R.AF.B.h^I^J)&H_FLAG)|(R.BC.W.l? P_FLAG:0); } static void cpdr(void) { byte I,J; R.R-=2; do { R.R+=2; I=M_RDMEM(R.HL.D);R.HL.W.l--;J=R.AF.B.h-I;R.BC.W.l--; ICount-=21; } while (R.BC.W.l && J && ICount>0); R.AF.B.l= N_FLAG|(R.AF.B.l&C_FLAG)|ZSTable[J]| ((R.AF.B.h^I^J)&H_FLAG)|(R.BC.W.l? P_FLAG:0); if (R.BC.W.l && J) R.PC.W.l-=2; else ICount+=5; } static void patch (void) { Patch (&R); } FnPtr FnED[256]= { fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, in_b_xc,out_xc_b,sbc_hl_bc,ld_xworde_bc,neg,retn,im_0,ld_i_a, in_c_xc,out_xc_c,adc_hl_bc,ld_bc_xworde,fuck,reti,fuck,ld_r_a, in_d_xc,out_xc_d,sbc_hl_de,ld_xworde_de,fuck,fuck,im_1,ld_a_i, in_e_xc,out_xc_e,adc_hl_de,ld_de_xworde,fuck,fuck,im_2,ld_a_r, in_h_xc,out_xc_h,sbc_hl_hl,ld_xworde_hl,fuck,fuck,fuck,rrd, in_l_xc,out_xc_l,adc_hl_hl,ld_hl_xworde,fuck,fuck,fuck,rld, in_f_xc,fuck,sbc_hl_sp,ld_xworde_sp,fuck,fuck,fuck,fuck, in_a_xc,out_xc_a,adc_hl_sp,ld_sp_xworde,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, ldi,cpi,ini,outi,fuck,fuck,fuck,fuck, ldd,cpd,ind,outd,fuck,fuck,fuck,fuck, ldir,cpir,inir,otir,fuck,fuck,fuck,fuck, lddr,cpdr,indr,otdr,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,fuck,fuck, fuck,fuck,fuck,fuck,fuck,fuck,patch,fuck }; unsigned CyclesED[256]= { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 12,12,15,20,8,14,8,9, 12,12,15,20,0,14,0,9, 12,12,15,20,0,0,8,9, 12,12,15,20,0,0,8,9, 12,12,15,20,0,0,0,18, 12,12,15,20,0,0,0,18, 12,00,15,20,0,0,0,0, 12,12,15,20,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 16,16,16,16,0,0,0,0, 16,16,16,16,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, };