/* Bug: did I get "ld ($4db3),hl" the wrong way round??? mem[0x4dc1] = RA; dumpregs(0x0e62, "// ld hl,$0101 ; [0e62] 21 01 01 \n"); HL=0x0101; dumpregs(0x0e65, "// ld ($4db1),hl ; [0e65] 22 B1 4D \n"); HL = mem[0x4db1]; dumpregs(0x0e68, "// ld ($4db3),hl ; [0e68] 22 B3 4D \n"); HL = mem[0x4db3]; dumpregs(0x0e6b, "// ret ; [0e6b] C9 \n"); */ // to do: rst 10 => RA = mem[HL+RA]; // table lookup // rst 8 => save byte in A at *HL++ while --RB // rst 18 HL = mem[HL=HL + B*2] + mem[DE = HL+1]<<8 // 16bit table lookup // STATUS: all opcodes are now translated and the code runs a considerable // way, BUT there are still some obvious bugs to be fixed because of // a lot of register-pair consolidation and splitting remains to be done. // remember to edit out the loop in the init code where it waits // for a test interrupt. Need a mechanism to do high-level edits // to the code driven by the disasm.info config file. //------------------------------------------------------------------------- // This is a static translator which generates C from Z80 code - the // C is the same as would have been executed if the code were run in // an emulator. For a description of the technique which was used to // create this, see http://www.gtoal.com/sbt/ // I am not doing all the tricks that are described in that paper // because the Z80 is a nicer architecture for emulation and there // is not as much need to optimise flags for example. // taking some liberties!: in an accurate emulator, we make sure that // wraparound in the address space works exactly as the computer, // even though no good program would do that. We assume the programs // this is going to be used on are well behaved. If they are not, // you can tweak the output by hand. // I am taking out all the masking which was done in this code // and have declared the variables as "register unsigned char" // or "register unsigned short" and will trust the compiler to // use the appropriate code - either a byte access, or a word // access (32 bit) plus a mask operation. I reckon it can't be // any worse than an explicit mask, and it may be better if the // mask is not needed. // The generated code needs to be run in a harness, and probably // tweaked a little to remove unnecessary stuff (such as interrupt // handler initialisation). Ideally we want to craft it so that // a call on the encapsulating procedure executes a single frame // of play and returns to the caller. Although this is relatively // general purpose code, I'm writing it specifically to run Ms Pacman // on my GP32 handheld. (I own a MS Pacman cabinet, but it's hard // to carry around with you :-) ) // pending: need to use def/use code to merge byte register pairs // and split them apart only when needed: // the default is to keep the master copy of AF/BC/DE in the byte registers // and consolidate them when a word register is needed; then // if a word register is written to as a unit, the byte registers // must be extracted from it; and to keep HL/IX/IY in word registers // and do the reverse; SP and PC are always word variables. They // could even be kept in regular ints, which are 32 bit on this // system. (We are however trying to remain byte-sex independant) // (note: although this makes for more efficient code, in practise it // is much easier to debug if both copies are kept in sync, so I am // adding some redundant merge/split instructions for now) // Once we can remove the redundant labels and calculate some // basic blocks, the dead code removal should remove some of // this overhead. Would be nice if the compiler did this for us // but we may end up requiring to do this explicitly ourselves. // when the generated code is encapsulated in a procedure, we will // be able to use the register attribute as below. [see emu.c] // We can still handle multiple register sets by copy-in/copy-out. // pending: daatable ... have a table for chnflags too. (i|=1024 etc) // *or* remap the flag bit posns in RF! - hacky... only needs to // be unmapped on PUSH F/POP F... /* register */ unsigned char RA, RF, RB, RC, RD, RE; unsigned short AF, BC, DE; unsigned char RH, RL, RI, RJ, RX, RY; /* register */ unsigned short HL, IX, IY; unsigned short SP, PC; unsigned short AF2, BC2, DE2, HL2; /* IX -> RI,RX IY -> RJ,RY */ /*** Z80Em: Portable Z80 emulator *******************************************/ /*** ***/ /*** Z80.c ***/ /*** ***/ /*** This file contains the emulation code ***/ /*** ***/ /*** Copyright (C) Marcel de Kogel 1996,1997 ***/ /*** You are not allowed to distribute this software commercially ***/ /*** Please, notify me, if you make any changes to this file ***/ /****************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> unsigned char mem[0x10000]; char *S(char *format, ...) { static char buffs[256*256]; char *buff; static int nextbuff = 0; va_list ap; nextbuff = (nextbuff+1)&255; buff = &buffs[nextbuff*256]; va_start(ap, format); vsprintf(buff, format, ap); va_end(ap); return(buff); } char *H2(int i) { static char buffs[16][16]; char *buff; static int nextbuff = 0; nextbuff = (nextbuff+1)&15; buff = &buffs[nextbuff][0]; sprintf(buff, "0x%02x", i&255); return(buff); } char *H4(int i) { static char buffs[16][16]; char *buff; static int nextbuff = 0; nextbuff = (nextbuff+1)&15; buff = &buffs[nextbuff][0]; sprintf(buff, "0x%04x", i&65535); return(buff); } void D(char *s, ...) { static char buff[4096]; va_list ap; va_start(ap, s); vsprintf(buff, s, ap); puts(buff); // yes, the appended \n is deliberate va_end(ap); } #include "Z80.h" int debug = (0!=0); int counting_cycles = (0!=0); int counting_r = (0!=0); //#define M_RDMEM(A) S("mem[%s]", #A) #define M_WRMEM(A,V) D(" i = %s; mem[i] = %s; /* force order */", #A, #V) #define M_RDOP(A) Z80_RDOP(A) #define M_RDOP_ARG(A) Z80_RDOP_ARG(A) #define M_RDSTACK(A) Z80_RDSTACK(A) #define M_WRSTACK(A,V) D(" i = %s; mem[i] = %s; /* force order */", #A, #V) #define DoIn(lo,hi) Z80_In((lo)+(((unsigned)(hi))<<8)) #define DoOut(lo,hi,v) Z80_Out((lo)+(((unsigned)(hi))<<8),v) static void Interrupt(int j); static void ei(void); #define S_FLAG 0x80 #define Z_FLAG 0x40 #define H_FLAG 0x10 #define V_FLAG 0x04 #define N_FLAG 0x02 #define C_FLAG 0x01 #define M_SKIP_CALL "PC+=2" #define M_SKIP_JP "PC+=2" #define M_SKIP_JR "PC+=1" #define M_SKIP_RET "" static Z80_Regs R; int Z80_Running=1; int Z80_IPeriod=50000; int Z80_ICount=50000; #ifdef TRACE static unsigned pc_trace[256]; static unsigned pc_count=0; #endif static unsigned char PostIncCarry[256]; static unsigned char AddFlags[256][256]; static byte PTable[512]; static byte ZSTable[512]; static byte IncTable[512]; static byte DecTable[512]; static byte ZSPTable[512]; static byte ZSPHTable[512]; #include "Z80DAA.h" typedef void (*opcode_fn) (void); #define M_C "(RF&C_FLAG)" #define M_NC "(!(RF&C_FLAG))" #define M_Z "(RF&Z_FLAG)" #define M_NZ "(!(RF&Z_FLAG))" #define M_M "(RF&S_FLAG)" #define M_P "(!(RF&S_FLAG))" #define M_PE "(RF&V_FLAG)" #define M_PO "(!(RF&V_FLAG))" /* Get next opcode argument and increment program counter */ unsigned M_RDMEM_OPCODE (void) { unsigned retval; retval=mem[PC]; PC++; return retval; } unsigned M_RDMEM_OPCODE_WORD (void) { int i; i=M_RDMEM_OPCODE(); i+=M_RDMEM_OPCODE()<<8; return i; } #define M_XIX S("(IX+(signed char)%s)", H2(M_RDMEM_OPCODE())) #define M_XIY S("(IY+(signed char)%s)", H2(M_RDMEM_OPCODE())) #define M_RD_XHL mem[HL] #define M_RD_XIX S("mem[IX+(signed char)%s]", H2(M_RDMEM_OPCODE())) #define M_RD_XIY S("mem[IY+(signed char)%s]", H2(M_RDMEM_OPCODE())) void M_WR_XIX_S(char * a) { D(" mem[%s] = %s;", M_XIX, a); // I had tagged this as a bug but I think it's fixed now } #define M_WR_XIX(s) M_WR_XIX_S(#s) void M_WR_XIY_S(char *a) { D(" mem[%s] = %s;", M_XIY, a); // I had tagged this as a bug but I think it's fixed now } #define M_WR_XIY(s) M_WR_XIY_S(#s) #ifdef X86_ASM #include "Z80CDx86.h" #else #include "Z80Codes.h" #endif static void adc_a_xhl(void) { D(" %s;", M_ADC(mem[HL])); } static void adc_a_xix(void) { D(" %s;", M_ADC(M_RD_XIX)); } static void adc_a_xiy(void) { D(" %s;", M_ADC(M_RD_XIY)); } static void adc_a_a(void) { D(" %s;", M_ADC(RA)); } static void adc_a_b(void) { D(" %s;", M_ADC(RB)); } static void adc_a_c(void) { D(" %s;", M_ADC(RC)); } static void adc_a_d(void) { D(" %s;", M_ADC(RD)); } static void adc_a_e(void) { D(" %s;", M_ADC(RE)); } static void adc_a_h(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_ADC(RH)); } static void adc_a_l(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_ADC(RL)); } static void adc_a_ixl(void) { D(" RI=IX>>8;RX=IX;%s;IX=(RX<<8)+RI;", M_ADC(RX)); } static void adc_a_ixh(void) { D(" RI=IX>>8;RX=IX;%s;IX=(RX<<8)+RI;", M_ADC(RI)); } static void adc_a_iyl(void) { D(" RJ=IY>>8;RY=IY;%s;IY=(RJ<<8)+RY;", M_ADC(RY)); } static void adc_a_iyh(void) { D(" RJ=IY>>8;RY=IY;%s;IY=(RJ<<8)+RY;", M_ADC(RJ)); } static void adc_a_byte(void) { D(" %s;", M_ADC_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void adc_hl_bc(void) { D(" BC=(RB<<8)+RC;%s;/* Wait - who does this add it to??? RC=BC;RB=BC>>8;*/", M_ADCW(BC)); } static void adc_hl_de(void) { D(" DE=(RD<<8)+RE;%s;/* Ditto RE=DE;RD=DE>>8;*/", M_ADCW(DE)); } static void adc_hl_hl(void) { D(" %s;", M_ADCW(HL)); } static void adc_hl_sp(void) { D(" %s;", M_ADCW(SP)); } static void add_a_xhl(void) { D(" %s;", M_ADD(mem[HL])); } static void add_a_xix(void) { D(" %s;", M_ADD_S(M_RD_XIX)); } static void add_a_xiy(void) { D(" %s;", M_ADD_S(M_RD_XIY)); } static void add_a_a(void) { D(" %s;",M_ADD(RA)); } static void add_a_b(void) { D(" %s;",M_ADD(RB)); } static void add_a_c(void) { D(" %s;",M_ADD(RC)); } static void add_a_d(void) { D(" %s;",M_ADD(RD)); } static void add_a_e(void) { D(" %s;",M_ADD(RE)); } static void add_a_h(void) { D(" RH=HL>>8;%s;",M_ADD(RH)); } static void add_a_l(void) { D(" RL=HL;%s;",M_ADD(RL)); } static void add_a_ixl(void) { D(" RX=IX>>8;%s;",M_ADD(RX)); } static void add_a_ixh(void) { D(" RI=IX;%s;",M_ADD(RI)); } static void add_a_iyl(void) { D(" RY=IY>>8;%s;",M_ADD(RY)); } static void add_a_iyh(void) { D(" RJ=IY;%s;",M_ADD(RJ)); } static void add_a_byte(void) { D(" %s;", M_ADD_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void add_hl_bc(void) { D(" BC=(RB<<8)+RC;%s;RB=BC>>8;RC=BC;", M_ADDW(HL,BC)); } static void add_hl_de(void) { D(" DE=(RD<<8)+RE;%s;RD=DE>>8;RE=DE;", M_ADDW(HL,DE)); } static void add_hl_hl(void) { D(" %s;", M_ADDW(HL,HL)); } static void add_hl_sp(void) { D(" %s;", M_ADDW(HL,SP)); } static void add_ix_bc(void) { D(" BC=(RB<<8)+RC;%s;RB=BC>>8;RC=BC;", M_ADDW(IX,BC)); } static void add_ix_de(void) { D(" DE=(RD<<8)+RE;%s;RD=DE>>8;RE=DE;", M_ADDW(IX,DE)); } static void add_ix_ix(void) { D(" %s;", M_ADDW(IX,IX)); } static void add_ix_sp(void) { D(" %s;", M_ADDW(IX,SP)); } static void add_iy_bc(void) { D(" BC=(RB<<8)+RC;%s;RB=BC>>8;RC=BC;", M_ADDW(IY,BC)); } static void add_iy_de(void) { D(" DE=(RD<<8)+RE;%s;RD=DE>>8;RE=DE;", M_ADDW(IY,DE)); } static void add_iy_iy(void) { D(" %s;", M_ADDW(IY,IY)); } static void add_iy_sp(void) { D(" %s;", M_ADDW(IY,SP)); } static void and_xhl(void) { D(" %s;", M_AND(mem[HL])); } static void and_xix(void) { D(" %s;", M_AND_S(M_RD_XIX)); } static void and_xiy(void) { D(" %s;", M_AND_S(M_RD_XIY)); } static void and_a(void) { D(" RF=ZSPHTable[RA];"); } static void and_b(void) { D(" %s;", M_AND(RB)); } static void and_c(void) { D(" %s;", M_AND(RC)); } static void and_d(void) { D(" %s;", M_AND(RD)); } static void and_e(void) { D(" %s;", M_AND(RE)); } static void and_h(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_AND(RH)); } static void and_l(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_AND(RL)); } static void and_ixh(void) { D(" RI=IX>>8;RX=IX;%s;IX=(RI<<8)+RX;", M_AND(RI)); } static void and_ixl(void) { D(" RI=IX>>8;RX=IX;%s;IX=(RI<<8)+RX;", M_AND(RX)); } static void and_iyh(void) { D(" RJ=IY>>8;RY=IY;%s;IY=(RJ<<8)+RY;", M_AND(RJ)); } static void and_iyl(void) { D(" RJ=IY>>8;RY=IY;%s;IY=(RJ<<8)+RY;", M_AND(RY)); } static void and_byte(void) { D(" %s;", M_AND_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void bit_0_xhl(void) { D(" %s;", M_BIT(0,mem[HL])); } static void bit_0_xix(void) { D(" %s;", M_BIT_S("0", M_RD_XIX)); } static void bit_0_xiy(void) { D(" %s;", M_BIT_S("0", M_RD_XIY)); } static void bit_0_a(void) { D(" %s;", M_BIT(0,RA)); } static void bit_0_b(void) { D(" %s;", M_BIT(0,RB)); } static void bit_0_c(void) { D(" %s;", M_BIT(0,RC)); } static void bit_0_d(void) { D(" %s;", M_BIT(0,RD)); } static void bit_0_e(void) { D(" %s;", M_BIT(0,RE)); } static void bit_0_h(void) { D(" RH=HL>>8;%s;", M_BIT(0,RH)); } static void bit_0_l(void) { D(" RL=HL;%s;", M_BIT(0,RL)); } static void bit_1_xhl(void) { D(" %s;", M_BIT(1,mem[HL])); } static void bit_1_xix(void) { D(" %s;", M_BIT_S("1", M_RD_XIX)); } static void bit_1_xiy(void) { D(" %s;", M_BIT_S("1", M_RD_XIY)); } static void bit_1_a(void) { D(" %s;", M_BIT(1,RA)); } static void bit_1_b(void) { D(" %s;", M_BIT(1,RB)); } static void bit_1_c(void) { D(" %s;", M_BIT(1,RC)); } static void bit_1_d(void) { D(" %s;", M_BIT(1,RD)); } static void bit_1_e(void) { D(" %s;", M_BIT(1,RE)); } static void bit_1_h(void) { D(" RH=HL>>8;%s;", M_BIT(1,RH)); } static void bit_1_l(void) { D(" RL=HL;%s;", M_BIT(1,RL)); } static void bit_2_xhl(void) { D(" %s;", M_BIT(2,mem[HL])); } static void bit_2_xix(void) { D(" %s;", M_BIT_S("2", M_RD_XIX)); } static void bit_2_xiy(void) { D(" %s;", M_BIT_S("2", M_RD_XIY)); } static void bit_2_a(void) { D(" %s;", M_BIT(2,RA)); } static void bit_2_b(void) { D(" %s;", M_BIT(2,RB)); } static void bit_2_c(void) { D(" %s;", M_BIT(2,RC)); } static void bit_2_d(void) { D(" %s;", M_BIT(2,RD)); } static void bit_2_e(void) { D(" %s;", M_BIT(2,RE)); } static void bit_2_h(void) { D(" RH=HL>>8;%s;", M_BIT(2,RH)); } static void bit_2_l(void) { D(" RL=HL;%s;", M_BIT(2,RL)); } static void bit_3_xhl(void) { D(" %s;", M_BIT(3,mem[HL])); } static void bit_3_xix(void) { D(" %s;", M_BIT_S("3", M_RD_XIX)); } static void bit_3_xiy(void) { D(" %s;", M_BIT_S("3", M_RD_XIY)); } static void bit_3_a(void) { D(" %s;", M_BIT(3,RA)); } static void bit_3_b(void) { D(" %s;", M_BIT(3,RB)); } static void bit_3_c(void) { D(" %s;", M_BIT(3,RC)); } static void bit_3_d(void) { D(" %s;", M_BIT(3,RD)); } static void bit_3_e(void) { D(" %s;", M_BIT(3,RE)); } static void bit_3_h(void) { D(" RH=HL>>8;%s;", M_BIT(3,RH)); } static void bit_3_l(void) { D(" RL=HL;%s;", M_BIT(3,RL)); } static void bit_4_xhl(void) { D(" %s;", M_BIT(4,mem[HL])); } static void bit_4_xix(void) { D(" %s;", M_BIT_S("4", M_RD_XIX)); } static void bit_4_xiy(void) { D(" %s;", M_BIT_S("4", M_RD_XIY)); } static void bit_4_a(void) { D(" %s;", M_BIT(4,RA)); } static void bit_4_b(void) { D(" %s;", M_BIT(4,RB)); } static void bit_4_c(void) { D(" %s;", M_BIT(4,RC)); } static void bit_4_d(void) { D(" %s;", M_BIT(4,RD)); } static void bit_4_e(void) { D(" %s;", M_BIT(4,RE)); } static void bit_4_h(void) { D(" RH=HL>>8;%s;", M_BIT(4,RH)); } static void bit_4_l(void) { D(" RL=HL;%s;", M_BIT(4,RL)); } static void bit_5_xhl(void) { D(" %s;", M_BIT(5,mem[HL])); } static void bit_5_xix(void) { D(" %s;", M_BIT_S("5", M_RD_XIX)); } static void bit_5_xiy(void) { D(" %s;", M_BIT_S("5", M_RD_XIY)); } static void bit_5_a(void) { D(" %s;", M_BIT(5,RA)); } static void bit_5_b(void) { D(" %s;", M_BIT(5,RB)); } static void bit_5_c(void) { D(" %s;", M_BIT(5,RC)); } static void bit_5_d(void) { D(" %s;", M_BIT(5,RD)); } static void bit_5_e(void) { D(" %s;", M_BIT(5,RE)); } static void bit_5_h(void) { D(" RH=HL>>8;%s;", M_BIT(5,RH)); } static void bit_5_l(void) { D(" RL=HL;%s;", M_BIT(5,RL)); } static void bit_6_xhl(void) { D(" %s;", M_BIT(6,mem[HL])); } static void bit_6_xix(void) { D(" %s;", M_BIT_S("6", M_RD_XIX)); } static void bit_6_xiy(void) { D(" %s;", M_BIT_S("6", M_RD_XIY)); } static void bit_6_a(void) { D(" %s;", M_BIT(6,RA)); } static void bit_6_b(void) { D(" %s;", M_BIT(6,RB)); } static void bit_6_c(void) { D(" %s;", M_BIT(6,RC)); } static void bit_6_d(void) { D(" %s;", M_BIT(6,RD)); } static void bit_6_e(void) { D(" %s;", M_BIT(6,RE)); } static void bit_6_h(void) { D(" RH=HL>>8;%s;", M_BIT(6,RH)); } static void bit_6_l(void) { D(" RL=HL;%s;", M_BIT(6,RL)); } static void bit_7_xhl(void) { D(" %s;", M_BIT(7,mem[HL])); } static void bit_7_xix(void) { D(" %s;", M_BIT_S("7", M_RD_XIX)); } static void bit_7_xiy(void) { D(" %s;", M_BIT_S("7", M_RD_XIY)); } static void bit_7_a(void) { D(" %s;", M_BIT(7,RA)); } static void bit_7_b(void) { D(" %s;", M_BIT(7,RB)); } static void bit_7_c(void) { D(" %s;", M_BIT(7,RC)); } static void bit_7_d(void) { D(" %s;", M_BIT(7,RD)); } static void bit_7_e(void) { D(" %s;", M_BIT(7,RE)); } static void bit_7_h(void) { D(" RH=HL>>8;%s;", M_BIT(7,RH)); } static void bit_7_l(void) { D(" RL=HL;%s;", M_BIT(7,RL)); } static void call_c(void) { D(" if (%s) {%s;}", M_C, M_CALL); } static void call_m(void) { D(" if (%s) {%s;}", M_M, M_CALL); } static void call_nc(void) { D(" if (%s) {%s;}", M_NC, M_CALL); } static void call_nz(void) { D(" if (%s) {%s;}", M_NZ, M_CALL); } static void call_p(void) { D(" if (%s) {%s;}", M_P, M_CALL); } static void call_pe(void) { D(" if (%s) {%s;}", M_PE, M_CALL); } static void call_po(void) { D(" if (%s) {%s;}", M_PO, M_CALL); } static void call_z(void) { D(" if (%s) {%s;}", M_Z, M_CALL); } static void call(void) { D(" %s;", M_CALL); } static void ccf(void) { D(" RF=((RF&0xED)|((RF&1)<<4))^1;"); } static void cp_xhl(void) { D(" %s;", M_CP(mem[HL])); } static void cp_xix(void) { D(" %s;", M_CP_S(M_RD_XIX)); } static void cp_xiy(void) { D(" %s;", M_CP_S(M_RD_XIY)); } static void cp_a(void) { D(" %s;", M_CP(RA)); } static void cp_b(void) { D(" %s;", M_CP(RB)); } static void cp_c(void) { D(" %s;", M_CP(RC)); } static void cp_d(void) { D(" %s;", M_CP(RD)); } static void cp_e(void) { D(" %s;", M_CP(RE)); } static void cp_h(void) { D(" RH=HL>>8;%s;", M_CP(RH)); } static void cp_l(void) { D(" RL=HL;%s;", M_CP(RL)); } static void cp_ixh(void) { D(" RI=IX>>8;%s;", M_CP(RI)); } static void cp_ixl(void) { D(" RX=IX;%s;", M_CP(RX)); } static void cp_iyh(void) { D(" RJ=IY>>8;%s;", M_CP(RJ)); } static void cp_iyl(void) { D(" RY=IY;%s;", M_CP(RY)); } static void cp_byte(void) { D(" %s;", M_CP_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void cpd(void) { D(" BC=(RB<<8)+RC;"); D(" i = mem[HL]; j=RA-i;"); D(" --HL;"); D(" --BC;"); D(" RF=(RF&C_FLAG)|ZSTable[j]|((RA^i^j)&H_FLAG)|(BC? V_FLAG:0)|N_FLAG;"); D(" RB=BC>>8;RC=BC;"); } static void cpdr(void) { D(" BC=(RB<<8)+RC;"); D(" {"); D(" i = mem[HL]; j=RA-i;"); D(" --HL;"); D(" --BC;"); D(" RF=(RF&C_FLAG)|ZSTable[j]|((RA^i^j)&H_FLAG)|(BC? V_FLAG:0)|N_FLAG;"); // cpd (); D(" } while (BC && !(RF&Z_FLAG));"); D(" RB=BC>>8;RC=BC;"); } static void cpi(void) { D(" BC=(RB<<8)+RC;"); D(" i = mem[HL];j=RA-i;"); D(" ++HL;"); D(" --BC;"); D(" RF=(RF&C_FLAG)|ZSTable[j]|((RA^i^j)&H_FLAG)|(BC? V_FLAG:0)|N_FLAG;"); D(" RB=BC>>8;RC=BC;"); } static void cpir(void) { D(" BC=(RB<<8)+RC;"); D(" do {"); D(" i = mem[HL];j=RA-i;"); D(" ++HL;"); D(" --BC;"); D(" RF=(RF&C_FLAG)|ZSTable[j]|((RA^i^j)&H_FLAG)|(BC? V_FLAG:0)|N_FLAG;"); // cpi (); D(" } while (BC && !(RF&Z_FLAG));"); D(" RB=BC>>8;RC=BC;"); } static void cpl(void) { D(" RA^=0xFF; RF|=(H_FLAG|N_FLAG);"); } static void daa(void) { //D(" int i;"); D(" i=RA;"); D(" if (RF&C_FLAG) i|=256;"); D(" if (RF&H_FLAG) i|=512;"); D(" if (RF&N_FLAG) i|=1024;"); D(" RF=(AF=DAATable[i]); RA = AF>>8;"); }; static void dec_xhl(void) { D(" %s;", M_DEC(mem[HL])); } static void dec_xix(void) { D(" %s;", M_DEC_S(S("mem[%s]", M_XIX))); } static void dec_xiy(void) { D(" %s;", M_DEC_S(S("mem[%s]", M_XIY))); } static void dec_a(void) { D(" %s;", M_DEC(RA)); } static void dec_b(void) { D(" %s;", M_DEC(RB)); } static void dec_c(void) { D(" %s;", M_DEC(RC)); } static void dec_d(void) { D(" %s;", M_DEC(RD)); } static void dec_e(void) { D(" %s;", M_DEC(RE)); } static void dec_h(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_DEC(RH)); } static void dec_l(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_DEC(RL)); } static void dec_ixh(void) { D(" RI=IX>>8;RX=IX;%s;IX=(RI<<8)+RX;", M_DEC(RI)); } static void dec_ixl(void) { D(" RI=IX>>8;RX=IX;%s;IX=(RI<<8)+RX;", M_DEC(RX)); } static void dec_iyh(void) { D(" RJ=IY>>8;RY=IY;%s;IY=(RJ<<8)+RY;", M_DEC(RJ)); } static void dec_iyl(void) { D(" RJ=IY>>8;RY=IY;%s;IY=(RJ<<8)+RY;", M_DEC(RY)); } static void dec_bc(void) { D(" RB=BC>>8;RC=BC;--BC;BC=(RB<<8)+RC;"); } static void dec_de(void) { D(" RD=DE>>8;RE=DE;--DE;DE=(RD<<8)+RE;"); } static void dec_hl(void) { D(" --HL;"); } static void dec_ix(void) { D(" --IX;"); } static void dec_iy(void) { D(" --IY;"); } static void dec_sp(void) { D(" --SP;"); } static void di(void) { D(" IFF1=IFF2=0;"); } static void djnz(void) { D(" if (--RB) %s;", M_JR); } static void ex_xsp_hl(void) { D(" i=mem[SP]+(mem[SP+1]<<8);"); D(" mem[SP]=HL; mem[SP+1]=HL>>8;"); D(" HL=i;"); } static void ex_xsp_ix(void) { D(" i=mem[SP]+(mem[SP+1]<<8);"); D(" mem[SP]=IX&255; mem[SP+1]=IX>>8;"); D(" IX=i;"); } static void ex_xsp_iy(void) { D(" i=mem[SP]+(mem[SP+1]<<8);"); D(" mem[SP]=IY&255; mem[SP+1]=IY>>8;"); D(" IY=i;"); } static void ex_af_af(void) { D(" AF=(RA<<8)+RF;"); D(" i=AF;"); D(" RF=(AF=AF2);"); D(" AF2=i;"); D(" RA=AF>>8;RF=AF;"); } static void ex_de_hl(void) { D(" i=(RD<<8)+RE;"); D(" DE=HL; RD=DE>>8;RE=DE;"); D(" HL=i;"); } static void exx(void) { D(" i=(RB<<8)+RC;"); D(" BC=BC2; RB=BC>>8;RC=BC;"); D(" BC2=i;"); D(" i=(RD<<8)+RE;"); D(" DE=DE2; RD=DE>>8;RE=DE;"); D(" DE2=i;"); D(" i=HL;"); D(" HL=HL2;"); D(" HL2=i;"); } static void halt(void) { // In Ms Pacman, the code does EI:HALT then waits for an // interrupt which takes us to address 3000... D(" R.HALT=1; goto L3000;"); } static void im_0(void) { D(" R.IM=0;"); } static void im_1(void) { D(" R.IM=1;"); } static void im_2(void) { D(" R.IM=2;"); } static void in_a_c(void) { D(" %s;", M_IN(RA)); } static void in_b_c(void) { D(" %s;", M_IN(RB)); } static void in_c_c(void) { D(" %s;", M_IN(RC)); } static void in_d_c(void) { D(" %s;", M_IN(RD)); } static void in_e_c(void) { D(" %s;", M_IN(RE)); } static void in_h_c(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_IN(RH)); } static void in_l_c(void) { D(" RH=HL>>8;RL=HL;%s;HL=(RH<<8)+RL;", M_IN(RL)); } static void in_0_c(void) { D(" %s;", M_IN(i)); } static void in_a_byte(void) { D(" RA=DoIn(0x%02x,RA);", M_RDMEM_OPCODE()); } static void inc_xhl(void) { D(" %s;", M_INC(mem[HL])); } static void inc_xix(void) { D(" j=%s;", M_XIX); D(" i = mem[j];"); D(" %s;", M_INC(i)); D(" mem[j] = i;"); } static void inc_xiy(void) { D(" j=%s;", M_XIY); D(" i = mem[j];"); D(" %s;", M_INC(i)); D(" mem[j] = i;"); } static void inc_a(void) { D(" %s;", M_INC(RA)); } static void inc_b(void) { D(" %s;", M_INC(RB)); } static void inc_c(void) { D(" %s;", M_INC(RC)); } static void inc_d(void) { D(" %s;", M_INC(RD)); } static void inc_e(void) { D(" %s;", M_INC(RE)); } static void inc_h(void) { D(" RH=HL>>8;RL=HL&255;%s;HL=(RH<<8)+RL;", M_INC(RH)); } static void inc_l(void) { D(" RH=HL>>8;RL=HL&255;%s;HL=(RH<<8)+RL;", M_INC(RL)); } static void inc_ixh(void) { D(" RI=IX>>8;RX=IX&255;%s;IX=(RI<<8)+RX;", M_INC(RI)); } static void inc_ixl(void) { D(" RI=IX>>8;RX=IX&255;%s;IX=(RI<<8)+RX", M_INC(RX)); } static void inc_iyh(void) { D(" RJ=IY>>8;RY=IY&255;%s;IY=(RJ<<8)+RY;", M_INC(RJ)); } static void inc_iyl(void) { D(" RJ=IY>>8;RY=IY&255;%s;IY=(RJ<<8)+RY", M_INC(RY)); } static void inc_bc(void) { D(" RB += PostIncCarry[++RC];"); } static void inc_de(void) { D(" RD += PostIncCarry[++RE];"); } static void inc_hl(void) { D(" ++HL;"); } static void inc_ix(void) { D(" ++IX;"); } static void inc_iy(void) { D(" ++IY;"); } static void inc_sp(void) { D(" ++SP;"); } static void ind(void) { D(" --RB;"); D(" mem[HL] = DoIn(RC,RB);"); D(" --HL;"); D(" RF=(RB)? N_FLAG:(N_FLAG|Z_FLAG);"); } static void indr(void) { ind (); D(" if (RB) { Z80_ICount-=5; PC-=2; }"); } static void ini(void) { D(" --RB;"); D(" mem[HL] = DoIn(RC,RB);"); D(" ++HL;"); D(" RF=(RB)? N_FLAG:(N_FLAG|Z_FLAG);"); } static void inir(void) { ini (); D(" if (RB) { Z80_ICount-=5; PC-=2; }"); } static void jp(void) { D(" %s;", M_JP); } static void jp_hl(void) { D(" PC=HL; goto *lab[PC];"); } static void jp_ix(void) { D(" PC=IX; goto *lab[PC];"); } static void jp_iy(void) { D(" PC=IY; goto *lab[PC];"); } static void jp_c(void) { D(" if (%s) {%s;}", M_C, M_JP); } static void jp_m(void) { D(" if (%s) {%s;}", M_M, M_JP); } static void jp_nc(void) { D(" if (%s) {%s;}", M_NC, M_JP); } static void jp_nz(void) { D(" if (%s) {%s;}", M_NZ, M_JP); } static void jp_p(void) { D(" if (%s) {%s;}", M_P, M_JP); } static void jp_pe(void) { D(" if (%s) {%s;}", M_PE, M_JP); } static void jp_po(void) { D(" if (%s) {%s;}", M_PO, M_JP); } static void jp_z(void) { D(" if (%s) {%s;}", M_Z, M_JP); } static void jr(void) { D(" %s;", M_JR); } static void jr_c(void) { D(" if (%s) {%s;}", M_C, M_JR); } static void jr_nc(void) { D(" if (%s) {%s;}", M_NC, M_JR); } static void jr_nz(void) { D(" if (%s) {%s;}", M_NZ, M_JR); } static void jr_z(void) { D(" if (%s) {%s;}", M_Z, M_JR); } static void ld_xbc_a(void) { D(" BC=(RB<<8)+RC;mem[BC] = RA;"); } static void ld_xde_a(void) { D(" DE=(RD<<8)+RE;mem[DE] = RA;"); } static void ld_xhl_a(void) { D(" mem[HL] = RA;"); } static void ld_xhl_b(void) { D(" mem[HL] = RB;"); } static void ld_xhl_c(void) { D(" mem[HL] = RC;"); } static void ld_xhl_d(void) { D(" mem[HL] = RD;"); } static void ld_xhl_e(void) { D(" mem[HL] = RE;"); } static void ld_xhl_h(void) { D(" RH=HL>>8;mem[HL] = RH;"); } static void ld_xhl_l(void) { D(" RL=HL;mem[HL] = RL;"); } static void ld_xhl_byte(void) { D(" mem[HL] = 0x%02x;", M_RDMEM_OPCODE()); } static void ld_xix_a(void) { M_WR_XIX(RA); } static void ld_xix_b(void) { M_WR_XIX(RB); } static void ld_xix_c(void) { M_WR_XIX(RC); } static void ld_xix_d(void) { M_WR_XIX(RD); } static void ld_xix_e(void) { M_WR_XIX(RE); } static void ld_xix_h(void) { D(" RH = HL>>8;"); M_WR_XIX(RH); } static void ld_xix_l(void) { D(" RL = HL;"); M_WR_XIX(RL); } static void ld_xix_byte(void) { //D(" int i;"); char *s = M_XIX; // force correct order of evaluation D(" mem[%s] = 0x%02x;", s, M_RDMEM_OPCODE()); } static void ld_xiy_a(void) { M_WR_XIY(RA); } static void ld_xiy_b(void) { M_WR_XIY(RB); } static void ld_xiy_c(void) { M_WR_XIY(RC); } static void ld_xiy_d(void) { M_WR_XIY(RD); } static void ld_xiy_e(void) { M_WR_XIY(RE); } static void ld_xiy_h(void) { D("RH=HL>>8;"); M_WR_XIY(RH); } static void ld_xiy_l(void) { D("RL=HL;"); M_WR_XIY(RL); } static void ld_xiy_byte(void) { //D(" int i;"); char *s = M_XIY; // force correct order of evaluation D(" mem[%s] = 0x%02x;", s, M_RDMEM_OPCODE()); } static void ld_xbyte_a(void) { int i=M_RDMEM_OPCODE_WORD(); D(" mem[0x%04x] = RA;", i); } static void ld_xword_bc(void) { D(" RC = (BC = mem[0x%04x]) /* is this reversed??? */; RD=BC>>8;", M_RDMEM_OPCODE_WORD()); } static void ld_xword_de(void) { D(" RE = (DE = mem[0x%04x]) /* is this reversed??? */; RD=RD>>8;", M_RDMEM_OPCODE_WORD()); } static void ld_xword_hl(void) { D(" HL = mem[0x%04x] /* is this reversed??? */;", M_RDMEM_OPCODE_WORD()); } static void ld_xword_ix(void) { D(" IX = mem[0x%04x] /* is this reversed??? */;", M_RDMEM_OPCODE_WORD()); } static void ld_xword_iy(void) { D(" IY = mem[0x%04x] /* is this reversed??? */;", M_RDMEM_OPCODE_WORD()); } static void ld_xword_sp(void) { D(" SP = mem[0x%04x] /* is this reversed??? */;", M_RDMEM_OPCODE_WORD()); } static void ld_a_xbc(void) { D(" RA=mem[BC=(RB<<8)+RC];"); } static void ld_a_xde(void) { D(" RA=mem[DE=(RD<<8)+RE];"); } static void ld_a_xhl(void) { D(" RA=mem[HL];"); } static void ld_a_xix(void) { D(" RA=%s;", M_RD_XIX); } static void ld_a_xiy(void) { D(" RA=%s;", M_RD_XIY); } static void ld_a_xbyte(void) { D(" RA=mem[0x%04x];", M_RDMEM_OPCODE_WORD()); } static void ld_a_byte(void) { D(" RA=0x%02x;", M_RDMEM_OPCODE()); } static void ld_b_byte(void) { D(" RB=0x%02x;", M_RDMEM_OPCODE()); } static void ld_c_byte(void) { D(" RC=0x%02x;", M_RDMEM_OPCODE()); } static void ld_d_byte(void) { D(" RD=0x%02x;", M_RDMEM_OPCODE()); } static void ld_e_byte(void) { D(" RE=0x%02x;", M_RDMEM_OPCODE()); } static void ld_h_byte(void) { D(" RH=0x%02x;RL=HL;HL=(RH<<8)+RL;", M_RDMEM_OPCODE()); } static void ld_l_byte(void) { D(" RL=0x%02x;RH=HL>>8;HL=(RH<<8)+RL;", M_RDMEM_OPCODE()); } static void ld_ixh_byte(void) { D(" RI=0x%02x;RX=IX;IX=(RI<<8)+RX;", M_RDMEM_OPCODE()); } static void ld_ixl_byte(void) { D(" RX=0x%02x;RI=IX>>8;IX=(RI<<8)+RX;", M_RDMEM_OPCODE()); } static void ld_iyh_byte(void) { D(" RJ=0x%02x;RY=IY;IY=(RJ<<8)+RY;", M_RDMEM_OPCODE()); } static void ld_iyl_byte(void) { D(" RY=0x%02x;RJ=IY>>8;IY=(RJ<<8)+RY;", M_RDMEM_OPCODE()); } static void ld_b_xhl(void) { D(" RB=mem[HL];"); } static void ld_c_xhl(void) { D(" RC=mem[HL];"); } static void ld_d_xhl(void) { D(" RD=mem[HL];"); } static void ld_e_xhl(void) { D(" RE=mem[HL];"); } static void ld_h_xhl(void) { D(" RH=mem[HL];RL=HL;HL=(RH<<8)+RL;"); } static void ld_l_xhl(void) { D(" RL=mem[HL];RH=HL>>8;HL=(RH<<8)+RL;"); } static void ld_b_xix(void) { D(" RB=%s;", M_RD_XIX); } static void ld_c_xix(void) { D(" RC=%s;", M_RD_XIX); } static void ld_d_xix(void) { D(" RD=%s;", M_RD_XIX); } static void ld_e_xix(void) { D(" RE=%s;", M_RD_XIX); } static void ld_h_xix(void) { D(" RH=%s;RL=HL;HL=(RH<<8)+RL;", M_RD_XIX); } static void ld_l_xix(void) { D(" RL=%s;RH=HL>>8;HL=(RH<<8)+RL;", M_RD_XIX); } static void ld_b_xiy(void) { D(" RB = %s;", M_RD_XIY); } static void ld_c_xiy(void) { D(" RC = %s;", M_RD_XIY); } static void ld_d_xiy(void) { D(" RD = %s;", M_RD_XIY); } static void ld_e_xiy(void) { D(" RE = %s;", M_RD_XIY); } static void ld_h_xiy(void) { D(" RH = %s;RL=HL;HL=(RH<<8)+RL;", M_RD_XIY); } static void ld_l_xiy(void) { D(" RL = %s;RH=HL>>8;HL=(RH<<8)+RL;", M_RD_XIY); } static void ld_a_a(void) { } static void ld_a_b(void) { D(" RA=RB;"); } static void ld_a_c(void) { D(" RA=RC;"); } static void ld_a_d(void) { D(" RA=RD;"); } static void ld_a_e(void) { D(" RA=RE;"); } static void ld_a_h(void) { D(" RH=HL>>8;HL=(RH<<8)+RL;RA=RH;"); } static void ld_a_l(void) { D(" RL=HL;HL=(RH<<8)+RL;RA=RL;"); } static void ld_a_ixh(void) { D(" RI=IX>>8;RA=RI;"); } static void ld_a_ixl(void) { D(" RX=IX;RA=RX;"); } static void ld_a_iyh(void) { D(" RJ=IY>>8;RA=RJ;"); } static void ld_a_iyl(void) { D(" RY=IY;RA=RY;"); } static void ld_b_b(void) { } static void ld_b_a(void) { D(" RB=RA;"); } static void ld_b_c(void) { D(" RB=RC;"); } static void ld_b_d(void) { D(" RB=RD;"); } static void ld_b_e(void) { D(" RB=RE;"); } static void ld_b_h(void) { D(" RH=HL>>8;HL=(RH<<8)+RL;RB=RH;"); } static void ld_b_l(void) { D(" RH=HL>>8;HL=(RH<<8)+RL;RB=RL;"); } static void ld_b_ixh(void) { D(" RI=IX>>8;RB=RI;"); } static void ld_b_ixl(void) { D(" RX=IX;RB=RX;"); } static void ld_b_iyh(void) { D(" RJ=IY>>8;RB=RJ;"); } static void ld_b_iyl(void) { D(" RY=IY;RB=RY;"); } static void ld_c_c(void) { } static void ld_c_a(void) { D(" RC=RA;"); } static void ld_c_b(void) { D(" RC=RB;"); } static void ld_c_d(void) { D(" RC=RD;"); } static void ld_c_e(void) { D(" RC=RE;"); } static void ld_c_h(void) { D(" RC=RH;"); } // to do: continue from here... static void ld_c_l(void) { D(" RC=RL;"); } static void ld_c_ixh(void) { D(" RC=RI;"); } static void ld_c_ixl(void) { D(" RC=RX;"); } static void ld_c_iyh(void) { D(" RC=RJ;"); } static void ld_c_iyl(void) { D(" RC=RY;"); } static void ld_d_d(void) { } static void ld_d_a(void) { D(" RD=RA;"); } static void ld_d_c(void) { D(" RD=RC;"); } static void ld_d_b(void) { D(" RD=RB;"); } static void ld_d_e(void) { D(" RD=RE;"); } static void ld_d_h(void) { D(" RD=RH;"); } static void ld_d_l(void) { D(" RD=RL;"); } static void ld_d_ixh(void) { D(" RD=RI;"); } static void ld_d_ixl(void) { D(" RD=RX;"); } static void ld_d_iyh(void) { D(" RD=RJ;"); } static void ld_d_iyl(void) { D(" RD=RY;"); } static void ld_e_e(void) { } static void ld_e_a(void) { D(" RE=RA;"); } static void ld_e_c(void) { D(" RE=RC;"); } static void ld_e_b(void) { D(" RE=RB;"); } static void ld_e_d(void) { D(" RE=RD;"); } static void ld_e_h(void) { D(" RE=RH;"); } static void ld_e_l(void) { D(" RE=RL;"); } static void ld_e_ixh(void) { D(" RE=RI;"); } static void ld_e_ixl(void) { D(" RE=RX;"); } static void ld_e_iyh(void) { D(" RE=RJ;"); } static void ld_e_iyl(void) { D(" RE=RY;"); } static void ld_h_h(void) { } static void ld_h_a(void) { D(" RH=RA;"); } static void ld_h_c(void) { D(" RH=RC;"); } static void ld_h_b(void) { D(" RH=RB;"); } static void ld_h_e(void) { D(" RH=RE;"); } static void ld_h_d(void) { D(" RH=RD;"); } static void ld_h_l(void) { D(" RH=RL;"); } static void ld_l_l(void) { } static void ld_l_a(void) { D(" RL=RA;"); } static void ld_l_c(void) { D(" RL=RC;"); } static void ld_l_b(void) { D(" RL=RB;"); } static void ld_l_e(void) { D(" RL=RE;"); } static void ld_l_d(void) { D(" RL=RD;"); } static void ld_l_h(void) { D(" RL=RH;"); } static void ld_ixh_a(void) { D(" RI=RA;"); } static void ld_ixh_b(void) { D(" RI=RB;"); } static void ld_ixh_c(void) { D(" RI=RC;"); } static void ld_ixh_d(void) { D(" RI=RD;"); } static void ld_ixh_e(void) { D(" RI=RE;"); } static void ld_ixh_ixh(void) { } static void ld_ixh_ixl(void) { D(" RI=RX;"); } static void ld_ixl_a(void) { D(" RX=RA;"); } static void ld_ixl_b(void) { D(" RX=RB;"); } static void ld_ixl_c(void) { D(" RX=RC;"); } static void ld_ixl_d(void) { D(" RX=RD;"); } static void ld_ixl_e(void) { D(" RX=RE;"); } static void ld_ixl_ixh(void) { D(" RX=RI;"); } static void ld_ixl_ixl(void) { } static void ld_iyh_a(void) { D(" RJ=RA;"); } static void ld_iyh_b(void) { D(" RJ=RB;"); } static void ld_iyh_c(void) { D(" RJ=RC;"); } static void ld_iyh_d(void) { D(" RJ=RD;"); } static void ld_iyh_e(void) { D(" RJ=RE;"); } static void ld_iyh_iyh(void) { } static void ld_iyh_iyl(void) { D(" RJ=RY;"); } static void ld_iyl_a(void) { D(" RY=RA;"); } static void ld_iyl_b(void) { D(" RY=RB;"); } static void ld_iyl_c(void) { D(" RY=RC;"); } static void ld_iyl_d(void) { D(" RY=RD;"); } static void ld_iyl_e(void) { D(" RY=RE;"); } static void ld_iyl_iyh(void) { D(" RY=RJ;"); } static void ld_iyl_iyl(void) { } static void ld_bc_xword(void) { int i = M_RDMEM_OPCODE_WORD(); D(" RB=mem[0x%04x];RC=mem[0x%04x]; /* Order? */", i+1, i); } static void ld_bc_word(void) { int i = M_RDMEM_OPCODE_WORD(); D(" RB=0x%02x;RC=0x%02x; /* Order? */", i>>8, i&255); } static void ld_de_xword(void) { int i = M_RDMEM_OPCODE_WORD(); D(" RD=mem[0x%04x];RE=mem[0x%04x]; /* Order? */", i+1, i); } static void ld_de_word(void) { int i = M_RDMEM_OPCODE_WORD(); D(" RD=0x%02x;RE=0x%02x; /* Order? */", i>>8, i&255); } //static void ld_de_xword(void) { D(" DE=M_RDMEM_WORD(0x%04x);RD=DE>>7;RE=DE&255; /* Order? */", M_RDMEM_OPCODE_WORD()); } //static void ld_de_word(void) { D(" DE=0x%04x;RD=DE>>8;RE=DE&255; /* Order? */", M_RDMEM_OPCODE_WORD()); } static void ld_hl_xword(void) { int i = M_RDMEM_OPCODE_WORD(); D(" HL=mem[0x%04x]+(mem[0x%04x]<<8);", i, i+1); } static void ld_hl_word(void) { D(" HL=0x%04x;", M_RDMEM_OPCODE_WORD()); } static void ld_ix_xword(void) { int i = M_RDMEM_OPCODE_WORD(); D(" IX=mem[0x%04x]+(mem[0x%04x]<<8);", i, i+1); } static void ld_ix_word(void) { D(" IX=0x%04x;", M_RDMEM_OPCODE_WORD()); } static void ld_iy_xword(void) { int i = M_RDMEM_OPCODE_WORD(); D(" IY=mem[0x%04x]+(mem[0x%04x]<<8);", i, i+1); } static void ld_iy_word(void) { D(" IY=0x%04x;", M_RDMEM_OPCODE_WORD()); } static void ld_sp_xword(void) { int i = M_RDMEM_OPCODE_WORD(); D(" SP=mem[0x%04x]+(mem[0x%04x]<<8);", i, i+1); } static void ld_sp_word(void) { D(" SP=0x%04x;", M_RDMEM_OPCODE_WORD()); } static void ld_sp_hl(void) { D(" SP=HL;"); } static void ld_sp_ix(void) { D(" SP=IX;"); } static void ld_sp_iy(void) { D(" SP=IY;"); } static void ld_a_i(void) { D(" RA=R.I;"); D(" RF=(RF&C_FLAG)|ZSTable[R.I]|(IFF2<<2);"); } static void ld_i_a(void) { D(" R.I=RA;"); } static void ld_a_r(void) { D(" RA=rand(); // RA=(R.R&127)|(R.R2&128);"); D(" RF=(RF&C_FLAG)|ZSTable[RA]|(IFF2<<2);"); } static void ld_r_a(void) { D(" // R.R=R.R2=RA;"); } static void ldd(void) { D(" BC=(RB<<8)+RC;"); D(" DE = (RD<<8)+RE;"); D(" mem[DE] = mem[HL];"); D(" --DE;"); D(" --HL;"); D(" --BC;"); D(" RF=(RF&0xE9)|(BC? V_FLAG:0);"); D(" RB=BC>>8;RC=BC;"); D(" RD=DE>>8;RE=DE;"); } static void lddr(void) { D(" BC = (RB<<8)+RC;"); D(" DE = (RD<<8)+RE;"); D(" do { /* Might later optimise to a memmove() call? */"); D(" mem[DE--] = mem[HL--];"); // ldd (); D(" } while (--BC);"); D(" RC=BC;RB=BC>>8;"); D(" RE=DE;RD=DE>>8;"); D(" RF&=0xE9;"); //D(" if (BC) { Z80_ICount-=5; PC-=2; }"); } static void ldi(void) { D(" BC=(RB<<8)+RC;"); D(" DE=(RD<<8)+RE;"); D(" mem[DE] = mem[HL];"); D(" ++DE;"); D(" ++HL;"); D(" --BC;"); D(" RF=(RF&0xE9)|(BC? V_FLAG:0);"); D(" RC=BC;RB=BC>>8;"); D(" RE=DE;RD=DE>>8;"); } static void ldir(void) { D(" BC = (RB<<8)+RC;"); D(" DE = (RD<<8)+RE;"); D(" do { /* Might later optimise to a memmove() call? */"); D(" mem[DE++] = mem[HL++];"); // ldi (); D(" } while (--BC);"); D(" RF&=0xE9;"); D(" RC=BC;RB=BC>>8;"); D(" RE=DE;RD=DE>>8;"); //D(" if (BC) { Z80_ICount-=5; PC-=2; }"); } static void neg(void) { //D(" byte i;"); D(" i=RA;"); D(" RA=0;"); D(" %s;", M_SUB(i)); } static void nop(void) { }; static void or_xhl(void) { D(" %s;", M_OR(mem[HL])); } static void or_xix(void) { D(" %s;", M_OR_S(M_RD_XIX)); } static void or_xiy(void) { D(" %s;", M_OR_S(M_RD_XIY)); } static void or_a(void) { D(" RF=ZSPTable[RA];"); } static void or_b(void) { D(" %s;", M_OR(RB)); } static void or_c(void) { D(" %s;", M_OR(RC)); } static void or_d(void) { D(" %s;", M_OR(RD)); } static void or_e(void) { D(" %s;", M_OR(RE)); } static void or_h(void) { D(" %s;", M_OR(RH)); } static void or_l(void) { D(" %s;", M_OR(RL)); } static void or_ixh(void) { D(" %s;", M_OR(RI)); } static void or_ixl(void) { D(" %s;", M_OR(RX)); } static void or_iyh(void) { D(" %s;", M_OR(RJ)); } static void or_iyl(void) { D(" %s;", M_OR(RY)); } static void or_byte(void) { D(" %s;", M_OR_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void outd(void) { D(" --RB;"); D(" DoOut (RC,RB,mem[HL]);"); D(" --HL;"); D(" RF=(RB)? N_FLAG:(Z_FLAG|N_FLAG);"); } static void otdr(void) { D(" do {"); outd (); D(" } while (RB);"); //D(" if (RB) { Z80_ICount-=5; PC-=2; }"); } static void outi(void) { D(" --RB;"); D(" DoOut (RC,RB,mem[HL]);"); D(" ++HL;"); D(" RF=(RB)? N_FLAG:(Z_FLAG|N_FLAG);"); } static void otir(void) { D(" do {"); outi (); D(" } while (RB);"); //D(" if (RB) { Z80_ICount-=5; PC-=2; }"); } static void out_c_a(void) { D(" DoOut(RC,RB,RA);"); } static void out_c_b(void) { D(" DoOut(RC,RB,RB);"); } static void out_c_c(void) { D(" DoOut(RC,RB,RC);"); } static void out_c_d(void) { D(" DoOut(RC,RB,RD);"); } static void out_c_e(void) { D(" DoOut(RC,RB,RE);"); } static void out_c_h(void) { D(" DoOut(RC,RB,RH);"); } static void out_c_l(void) { D(" DoOut(RC,RB,RL);"); } static void out_c_0(void) { D(" DoOut(RC,RB,0);"); } static void out_byte_a(void) { D(" DoOut(0x%02x,RA,RA);", M_RDMEM_OPCODE()); } static void pop_af(void) { D(" %s;", M_POP2(RA,RF)); } static void pop_bc(void) { D(" %s;", M_POP2X(BC,RB,RC)); } static void pop_de(void) { D(" %s;", M_POP2X(DE,RD,RE)); } static void pop_hl(void) { D(" %s;", M_POP(HL)); } static void pop_ix(void) { D(" %s;", M_POP(IX)); } static void pop_iy(void) { D(" %s;", M_POP(IY)); } static void push_af(void) { M_PUSH2(RA, RF); } static void push_bc(void) { M_PUSH2(RB, RC); } static void push_de(void) { M_PUSH2(RD, RE); } static void push_hl(void) { M_PUSH(HL); } static void push_ix(void) { M_PUSH(IX); } static void push_iy(void) { M_PUSH(IY); } static void res_0_xhl(void) { D(" %s;", M_RES(0,mem[HL])); }; static void res_0_xix(void) { //D(" byte i;"); ////D(" int j;"); D(" j=%s;", M_XIX); D(" i = mem[j];"); D(" %s;", M_RES(0,i)); D(" mem[j] = i;"); }; static void res_0_xiy(void) { //D(" byte i;"); ////D(" int j;"); D(" j=%s;", M_XIY); D(" i = mem[j];"); D(" %s;", M_RES(0,i)); D(" mem[j] = i;"); }; static void res_0_a(void) { D(" %s;", M_RES(0,RA)); }; static void res_0_b(void) { D(" %s;", M_RES(0,RB)); }; static void res_0_c(void) { D(" %s;", M_RES(0,RC)); }; static void res_0_d(void) { D(" %s;", M_RES(0,RD)); }; static void res_0_e(void) { D(" %s;", M_RES(0,RE)); }; static void res_0_h(void) { D(" %s;", M_RES(0,RH)); }; static void res_0_l(void) { D(" %s;", M_RES(0,RL)); }; static void res_1_xhl(void) { D(" %s;", M_RES(1,mem[HL])); }; static void res_1_xix(void) { //D(" byte i;"); ////D(" int j;"); D(" j=%s;", M_XIX); D(" i = mem[j];"); D(" %s;", M_RES(1,i)); D(" mem[j] = i;"); }; static void res_1_xiy(void) { //D(" byte i;"); ////D(" int j;"); D(" j=%s;", M_XIY); D(" i = mem[j];"); D(" %s;", M_RES(1,i)); D(" mem[j] = i;"); }; static void res_1_a(void) { D(" %s;", M_RES(1,RA)); }; static void res_1_b(void) { D(" %s;", M_RES(1,RB)); }; static void res_1_c(void) { D(" %s;", M_RES(1,RC)); }; static void res_1_d(void) { D(" %s;", M_RES(1,RD)); }; static void res_1_e(void) { D(" %s;", M_RES(1,RE)); }; static void res_1_h(void) { D(" %s;", M_RES(1,RH)); }; static void res_1_l(void) { D(" %s;", M_RES(1,RL)); }; static void res_2_xhl(void) { D(" %s;", M_RES(2,mem[HL])); }; static void res_2_xix(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" %s;", M_RES(2,i)); D(" mem[j] = i;"); }; static void res_2_xiy(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" %s;", M_RES(2,i)); D(" mem[j] = i;"); }; static void res_2_a(void) { D(" %s;", M_RES(2,RA)); }; static void res_2_b(void) { D(" %s;", M_RES(2,RB)); }; static void res_2_c(void) { D(" %s;", M_RES(2,RC)); }; static void res_2_d(void) { D(" %s;", M_RES(2,RD)); }; static void res_2_e(void) { D(" %s;", M_RES(2,RE)); }; static void res_2_h(void) { D(" %s;", M_RES(2,RH)); }; static void res_2_l(void) { D(" %s;", M_RES(2,RL)); }; static void res_3_xhl(void) { D(" %s;", M_RES(3,mem[HL])); }; static void res_3_xix(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" %s;", M_RES(3,i)); D(" mem[j] = i;"); }; static void res_3_xiy(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" %s;", M_RES(3,i)); D(" mem[j] = i;"); }; static void res_3_a(void) { D(" %s;", M_RES(3,RA)); }; static void res_3_b(void) { D(" %s;", M_RES(3,RB)); }; static void res_3_c(void) { D(" %s;", M_RES(3,RC)); }; static void res_3_d(void) { D(" %s;", M_RES(3,RD)); }; static void res_3_e(void) { D(" %s;", M_RES(3,RE)); }; static void res_3_h(void) { D(" %s;", M_RES(3,RH)); }; static void res_3_l(void) { D(" %s;", M_RES(3,RL)); }; static void res_4_xhl(void) { D(" %s;", M_RES(4,mem[HL])); }; static void res_4_xix(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" %s;", M_RES(4,i)); D(" mem[j] = i;"); }; static void res_4_xiy(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" %s;", M_RES(4,i)); D(" mem[j] = i;"); }; static void res_4_a(void) { D(" %s;", M_RES(4,RA)); }; static void res_4_b(void) { D(" %s;", M_RES(4,RB)); }; static void res_4_c(void) { D(" %s;", M_RES(4,RC)); }; static void res_4_d(void) { D(" %s;", M_RES(4,RD)); }; static void res_4_e(void) { D(" %s;", M_RES(4,RE)); }; static void res_4_h(void) { D(" %s;", M_RES(4,RH)); }; static void res_4_l(void) { D(" %s;", M_RES(4,RL)); }; static void res_5_xhl(void) { D(" %s;", M_RES(5,mem[HL])); }; static void res_5_xix(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" %s;", M_RES(5,i)); D(" mem[j] = i;"); }; static void res_5_xiy(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" %s;", M_RES(5,i)); D(" mem[j] = i;"); }; static void res_5_a(void) { D(" %s;", M_RES(5,RA)); }; static void res_5_b(void) { D(" %s;", M_RES(5,RB)); }; static void res_5_c(void) { D(" %s;", M_RES(5,RC)); }; static void res_5_d(void) { D(" %s;", M_RES(5,RD)); }; static void res_5_e(void) { D(" %s;", M_RES(5,RE)); }; static void res_5_h(void) { D(" %s;", M_RES(5,RH)); }; static void res_5_l(void) { D(" %s;", M_RES(5,RL)); }; static void res_6_xhl(void) { D(" %s;", M_RES(6,mem[HL])); }; static void res_6_xix(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" %s;", M_RES(6,i)); D(" mem[j] = i;"); }; static void res_6_xiy(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" %s;", M_RES(6,i)); D(" mem[j] = i;"); }; static void res_6_a(void) { D(" %s;", M_RES(6,RA)); }; static void res_6_b(void) { D(" %s;", M_RES(6,RB)); }; static void res_6_c(void) { D(" %s;", M_RES(6,RC)); }; static void res_6_d(void) { D(" %s;", M_RES(6,RD)); }; static void res_6_e(void) { D(" %s;", M_RES(6,RE)); }; static void res_6_h(void) { D(" %s;", M_RES(6,RH)); }; static void res_6_l(void) { D(" %s;", M_RES(6,RL)); }; static void res_7_xhl(void) { D(" %s;", M_RES(7,mem[HL])); }; static void res_7_xix(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" %s;", M_RES(7,i)); D(" mem[j] = i;"); }; static void res_7_xiy(void) { //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" %s;", M_RES(7,i)); D(" mem[j] = i;"); }; static void res_7_a(void) { D(" %s;", M_RES(7,RA)); }; static void res_7_b(void) { D(" %s;", M_RES(7,RB)); }; static void res_7_c(void) { D(" %s;", M_RES(7,RC)); }; static void res_7_d(void) { D(" %s;", M_RES(7,RD)); }; static void res_7_e(void) { D(" %s;", M_RES(7,RE)); }; static void res_7_h(void) { D(" %s;", M_RES(7,RH)); }; static void res_7_l(void) { D(" %s;", M_RES(7,RL)); }; static void ret(void) { D(" %s;", M_RET); deflab(PC); } #ifdef COUNTINGCYCLES static void ret_c(void) { D(" if (%s) { %s; } else { %s; }", M_C, M_RET, M_SKIP_RET); } static void ret_m(void) { D(" if (%s) { %s; } else { %s; }", M_M, M_RET, M_SKIP_RET); } static void ret_nc(void) { D(" if (%s) { %s; } else { %s; }", M_NC, M_RET, M_SKIP_RET); } static void ret_nz(void) { D(" if (%s) { %s; } else { %s; }", M_NZ, M_RET, M_SKIP_RET); } static void ret_p(void) { D(" if (%s) { %s; } else { %s; }", M_P, M_RET, M_SKIP_RET); } static void ret_pe(void) { D(" if (%s) { %s; } else { %s; }", M_PE, M_RET, M_SKIP_RET); } static void ret_po(void) { D(" if (%s) { %s; } else { %s; }", M_PO, M_RET, M_SKIP_RET); } static void ret_z(void) { D(" if (%s) { %s; } else { %s; }", M_Z, M_RET, M_SKIP_RET); } #else static void ret_c(void) { D(" if (%s) {%s;}", M_C, M_RET); } static void ret_m(void) { D(" if (%s) {%s;}", M_M, M_RET); } static void ret_nc(void) { D(" if (%s) {%s;}", M_NC, M_RET); } static void ret_nz(void) { D(" if (%s) {%s;}", M_NZ, M_RET); } static void ret_p(void) { D(" if (%s) {%s;}", M_P, M_RET); } static void ret_pe(void) { D(" if (%s) {%s;}", M_PE, M_RET); } static void ret_po(void) { D(" if (%s) {%s;}", M_PO, M_RET); } static void ret_z(void) { D(" if (%s) {%s;}", M_Z, M_RET); } #endif static void reti(void) { D(" Z80_Reti(); %s;", M_RET); } static void retn(void) { D(" IFF1=IFF2; Z80_Retn(); %s;", M_RET); } static void rl_xhl(void) { D(" %s;", M_RL(mem[HL])); } static void rl_xix(void) { D(" %s;", M_RL_S(S("mem[%s]", M_XIX))); } static void rl_xiy(void) { D(" %s;", M_RL_S(S("mem[%s]", M_XIY))); } static void rl_a(void) { D(" %s;", M_RL(RA)); } static void rl_b(void) { D(" %s;", M_RL(RB)); } static void rl_c(void) { D(" %s;", M_RL(RC)); } static void rl_d(void) { D(" %s;", M_RL(RD)); } static void rl_e(void) { D(" %s;", M_RL(RE)); } static void rl_h(void) { D(" %s;", M_RL(RH)); } static void rl_l(void) { D(" %s;", M_RL(RL)); } static void rla(void) { D(" %s;", M_RLA); } static void rlc_xhl(void) { D(" %s;", M_RLC(mem[HL)); } static void rlc_xix(void) { D(" %s;", M_RLC_S(S("mem[%s]", M_XIX))); } static void rlc_xiy(void) { D(" %s;", M_RLC_S(S("mem[%s]", M_XIY))); } static void rlc_a(void) { D(" %s;", M_RLC(RA)); } static void rlc_b(void) { D(" %s;", M_RLC(RB)); } static void rlc_c(void) { D(" %s;", M_RLC(RC)); } static void rlc_d(void) { D(" %s;", M_RLC(RD)); } static void rlc_e(void) { D(" %s;", M_RLC(RE)); } static void rlc_h(void) { D(" %s;", M_RLC(RH)); } static void rlc_l(void) { D(" %s;", M_RLC(RL)); } static void rlca(void) { D(" %s;", M_RLCA); } static void rld(void) { //D(" byte i;"); D(" i=mem[HL];"); D(" mem[HL] = (i<<4|(RA&0x0F));"); D(" RA=(RA&0xF0)|(i>>4);"); D(" RF=(RF&C_FLAG)|ZSPTable[RA];"); } static void rr_xhl(void) { D(" %s;", M_RR(mem[HL])); } static void rr_xix(void) { D(" %s;", M_RR_S(S("mem[%s]", M_XIX))); } static void rr_xiy(void) { D(" %s;", M_RR_S(S("mem[%s]", M_XIY))); } static void rr_a(void) { D(" %s;", M_RR(RA)); } static void rr_b(void) { D(" %s;", M_RR(RB)); } static void rr_c(void) { D(" %s;", M_RR(RC)); } static void rr_d(void) { D(" %s;", M_RR(RD)); } static void rr_e(void) { D(" %s;", M_RR(RE)); } static void rr_h(void) { D(" %s;", M_RR(RH)); } static void rr_l(void) { D(" %s;", M_RR(RL)); } static void rra(void) { D(" %s;", M_RRA); } static void rrc_xhl(void) { D(" M_RRC(mem[HL]);"); } static void rrc_xix(void) { D(" %s;", M_RRC_S(S("mem[%s]", M_XIX))); } static void rrc_xiy(void) { D(" %s;", M_RRC_S(S("mem[%s]", M_XIY))); } static void rrc_a(void) { D(" %s;", M_RRC(RA)); } static void rrc_b(void) { D(" %s;", M_RRC(RB)); } static void rrc_c(void) { D(" %s;", M_RRC(RC)); } static void rrc_d(void) { D(" %s;", M_RRC(RD)); } static void rrc_e(void) { D(" %s;", M_RRC(RE)); } static void rrc_h(void) { D(" %s;", M_RRC(RH)); } static void rrc_l(void) { D(" %s;", M_RRC(RL)); } static void rrca(void) { D(" %s;", M_RRCA); } static void rrd(void) { //D(" byte i;"); D(" i=mem[HL];"); D(" mem[HL] = (i>>4|(RA<<4));"); D(" RA=(RA&0xF0)|(i&0x0F);"); D(" RF=(RF&C_FLAG)|ZSPTable[RA];"); } void M_RST(int addr) { M_PUSH2_S(H2(PC>>8), H2(PC&255)); D(" goto L%04x;", addr); // Generally there is no drop-through code following these // except for: if (addr <= 0x18) deflab(PC); } static void rst_00(void) { M_RST(0x00); } static void rst_08(void) { M_RST(0x08); } static void rst_10(void) { M_RST(0x10); } static void rst_18(void) { M_RST(0x18); } static void rst_20(void) { M_RST(0x20); (void)(M_RDMEM_OPCODE(), M_RDMEM_OPCODE(), M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } static void rst_28(void) { M_RST(0x28); (void)(M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } static void rst_30(void) { M_RST(0x30); (void)(M_RDMEM_OPCODE(), M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } static void rst_38(void) { M_RST(0x38); } //static void rst_00(void) { D(" M_RST00();"); } //static void rst_08(void) { D(" M_RST08();"); } //static void rst_10(void) { D(" M_RST10();"); } //static void rst_18(void) { D(" M_RST18();"); } //// trying ... static void rst_20(void) { D(" M_RST20(0x%02x, 0x%02x); /* to do: should this gobble 4 bytes instead? */", M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } //static void rst_20(void) { D(" M_RST20(0x%02x, 0x%02x, 0x%02x, 0x%02x); /* trying to gobble 4 bytes instead... */", M_RDMEM_OPCODE(), M_RDMEM_OPCODE(), M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } //static void rst_28(void) { D(" M_RST28(0x%02x, 0x%02x);", M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } //static void rst_30(void) { D(" M_RST30(0x%02x, 0x%02x, 0x%02x);", M_RDMEM_OPCODE(), M_RDMEM_OPCODE(), M_RDMEM_OPCODE()); deflab(PC); } //static void rst_38(void) { D(" M_RST38();"); } static void sbc_a_byte(void) { D(" %s;", M_SBC_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void sbc_a_xhl(void) { D(" %s;", M_SBC(mem[HL])); } static void sbc_a_xix(void) { D(" %s;", M_SBC_S(M_RD_XIX)); } static void sbc_a_xiy(void) { D(" %s;", M_SBC_S(M_RD_XIY)); } static void sbc_a_a(void) { D(" %s;", M_SBC(RA)); } static void sbc_a_b(void) { D(" %s;", M_SBC(RB)); } static void sbc_a_c(void) { D(" %s;", M_SBC(RC)); } static void sbc_a_d(void) { D(" %s;", M_SBC(RD)); } static void sbc_a_e(void) { D(" %s;", M_SBC(RE)); } static void sbc_a_h(void) { D(" %s;", M_SBC(RH)); } static void sbc_a_l(void) { D(" %s;", M_SBC(RL)); } static void sbc_a_ixh(void) { D(" %s;", M_SBC(RI)); } static void sbc_a_ixl(void) { D(" %s;", M_SBC(RX)); } static void sbc_a_iyh(void) { D(" %s;", M_SBC(RJ)); } static void sbc_a_iyl(void) { D(" %s;", M_SBC(RY)); } static void sbc_hl_bc(void) { D(" BC=(RB<<8)+RC;%s;RB=BC>>8;RC=BC;", M_SBCW(BC)); } static void sbc_hl_de(void) { D(" DE=(RD<<8)+RE;%s;RD=DE>>8;RE=DE;", M_SBCW(DE)); } static void sbc_hl_hl(void) { D(" %s;", M_SBCW(HL)); } static void sbc_hl_sp(void) { D(" %s;", M_SBCW(SP)); } static void scf(void) { D(" RF=(RF&0xEC)|C_FLAG;"); } static void set_0_xhl(void) { D(" %s;", M_SET(0,mem[HL])); }; static void set_0_xix(void) { D(" %s;", M_SET_S("0",S("mem[%s]", M_XIX))); }; static void set_0_xiy(void) { D(" %s;", M_SET_S("0",S("mem[%s]", M_XIY))); }; static void set_0_a(void) { D(" %s;", M_SET(0,RA)); }; static void set_0_b(void) { D(" %s;", M_SET(0,RB)); }; static void set_0_c(void) { D(" %s;", M_SET(0,RC)); }; static void set_0_d(void) { D(" %s;", M_SET(0,RD)); }; static void set_0_e(void) { D(" %s;", M_SET(0,RE)); }; static void set_0_h(void) { D(" %s;", M_SET(0,RH)); }; static void set_0_l(void) { D(" %s;", M_SET(0,RL)); }; static void set_1_xhl(void) { D(" %s;", M_SET(1,mem[HL])); }; static void set_1_xix(void) { D(" %s;", M_SET_S("1",S("mem[%s]", M_XIX))); }; static void set_1_xiy(void) { D(" %s;", M_SET_S("1",S("mem[%s]", M_XIY))); }; static void set_1_a(void) { D(" %s;", M_SET(1,RA)); }; static void set_1_b(void) { D(" %s;", M_SET(1,RB)); }; static void set_1_c(void) { D(" %s;", M_SET(1,RC)); }; static void set_1_d(void) { D(" %s;", M_SET(1,RD)); }; static void set_1_e(void) { D(" %s;", M_SET(1,RE)); }; static void set_1_h(void) { D(" %s;", M_SET(1,RH)); }; static void set_1_l(void) { D(" %s;", M_SET(1,RL)); }; static void set_2_xhl(void) { D(" %s;", M_SET(2,mem[HL])); }; static void set_2_xix(void) { D(" %s;", M_SET_S("2",S("mem[%s]", M_XIX))); }; static void set_2_xiy(void) { D(" %s;", M_SET_S("2",S("mem[%s]", M_XIY))); }; static void set_2_a(void) { D(" %s;", M_SET(2,RA)); }; static void set_2_b(void) { D(" %s;", M_SET(2,RB)); }; static void set_2_c(void) { D(" %s;", M_SET(2,RC)); }; static void set_2_d(void) { D(" %s;", M_SET(2,RD)); }; static void set_2_e(void) { D(" %s;", M_SET(2,RE)); }; static void set_2_h(void) { D(" %s;", M_SET(2,RH)); }; static void set_2_l(void) { D(" %s;", M_SET(2,RL)); }; static void set_3_xhl(void) { D(" %s;", M_SET(3,mem[HL])); }; static void set_3_xix(void) { D(" %s;", M_SET_S("3",S("mem[%s]", M_XIX))); }; static void set_3_xiy(void) { D(" %s;", M_SET_S("3",S("mem[%s]", M_XIY))); }; static void set_3_a(void) { D(" %s;", M_SET(3,RA)); }; static void set_3_b(void) { D(" %s;", M_SET(3,RB)); }; static void set_3_c(void) { D(" %s;", M_SET(3,RC)); }; static void set_3_d(void) { D(" %s;", M_SET(3,RD)); }; static void set_3_e(void) { D(" %s;", M_SET(3,RE)); }; static void set_3_h(void) { D(" %s;", M_SET(3,RH)); }; static void set_3_l(void) { D(" %s;", M_SET(3,RL)); }; static void set_4_xhl(void) { D(" %s;", M_SET(4,mem[HL])); }; static void set_4_xix(void) { D(" %s;", M_SET_S("4",S("mem[%s]", M_XIX))); }; static void set_4_xiy(void) { D(" %s;", M_SET_S("4",S("mem[%s]", M_XIY))); }; static void set_4_a(void) { D(" %s;", M_SET(4,RA)); }; static void set_4_b(void) { D(" %s;", M_SET(4,RB)); }; static void set_4_c(void) { D(" %s;", M_SET(4,RC)); }; static void set_4_d(void) { D(" %s;", M_SET(4,RD)); }; static void set_4_e(void) { D(" %s;", M_SET(4,RE)); }; static void set_4_h(void) { D(" %s;", M_SET(4,RH)); }; static void set_4_l(void) { D(" %s;", M_SET(4,RL)); }; static void set_5_xhl(void) { D(" %s;", M_SET(5,mem[HL])); }; static void set_5_xix(void) { D(" %s;", M_SET_S("5",S("mem[%s]", M_XIX))); }; static void set_5_xiy(void) { D(" %s;", M_SET_S("5",S("mem[%s]", M_XIY))); }; static void set_5_a(void) { D(" %s;", M_SET(5,RA)); }; static void set_5_b(void) { D(" %s;", M_SET(5,RB)); }; static void set_5_c(void) { D(" %s;", M_SET(5,RC)); }; static void set_5_d(void) { D(" %s;", M_SET(5,RD)); }; static void set_5_e(void) { D(" %s;", M_SET(5,RE)); }; static void set_5_h(void) { D(" %s;", M_SET(5,RH)); }; static void set_5_l(void) { D(" %s;", M_SET(5,RL)); }; static void set_6_xhl(void) { D(" %s;", M_SET(6,mem[HL])); }; static void set_6_xix(void) { D(" %s;", M_SET_S("6",S("mem[%s]", M_XIX))); }; static void set_6_xiy(void) { D(" %s;", M_SET_S("6",S("mem[%s]", M_XIY))); }; static void set_6_a(void) { D(" %s;", M_SET(6,RA)); }; static void set_6_b(void) { D(" %s;", M_SET(6,RB)); }; static void set_6_c(void) { D(" %s;", M_SET(6,RC)); }; static void set_6_d(void) { D(" %s;", M_SET(6,RD)); }; static void set_6_e(void) { D(" %s;", M_SET(6,RE)); }; static void set_6_h(void) { D(" %s;", M_SET(6,RH)); }; static void set_6_l(void) { D(" %s;", M_SET(6,RL)); }; static void set_7_xhl(void) { D(" %s;", M_SET(7,mem[HL])); }; static void set_7_xix(void) { D(" %s;", M_SET_S("7",S("mem[%s]", M_XIX))); }; static void set_7_xiy(void) { D(" %s;", M_SET_S("7",S("mem[%s]", M_XIY))); }; static void set_7_a(void) { D(" %s;", M_SET(7,RA)); }; static void set_7_b(void) { D(" %s;", M_SET(7,RB)); }; static void set_7_c(void) { D(" %s;", M_SET(7,RC)); }; static void set_7_d(void) { D(" %s;", M_SET(7,RD)); }; static void set_7_e(void) { D(" %s;", M_SET(7,RE)); }; static void set_7_h(void) { D(" %s;", M_SET(7,RH)); }; static void set_7_l(void) { D(" %s;", M_SET(7,RL)); }; static void sla_xhl(void) { D(" {"); //D(" byte i;"); D(" i=mem[HL];"); D(" M_SLA(i);"); D(" mem[HL] = i;"); D(" }"); } static void sla_xix(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" M_SLA(i);"); D(" mem[j] = i;"); D(" }"); } static void sla_xiy(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" M_SLA(i);"); D(" mem[j] = i;"); D(" }"); } static void sla_a(void) { D(" %s;", M_SLA(RA)); } static void sla_b(void) { D(" %s;", M_SLA(RB)); } static void sla_c(void) { D(" %s;", M_SLA(RC)); } static void sla_d(void) { D(" %s;", M_SLA(RD)); } static void sla_e(void) { D(" %s;", M_SLA(RE)); } static void sla_h(void) { D(" %s;", M_SLA(RH)); } static void sla_l(void) { D(" %s;", M_SLA(RL)); } static void sll_xhl(void) { D(" {"); //D(" byte i;"); D(" i=mem[HL];"); D(" M_SLL(i);"); D(" mem[HL] = i;"); D(" }"); } static void sll_xix(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" M_SLL(i);"); D(" mem[j] = i;"); D(" }"); } static void sll_xiy(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" M_SLL(i);"); D(" mem[j] = i;"); D(" }"); } static void sll_a(void) { D(" %s;", M_SLL(RA)); } static void sll_b(void) { D(" %s;", M_SLL(RB)); } static void sll_c(void) { D(" %s;", M_SLL(RC)); } static void sll_d(void) { D(" %s;", M_SLL(RD)); } static void sll_e(void) { D(" %s;", M_SLL(RE)); } static void sll_h(void) { D(" %s;", M_SLL(RH)); } static void sll_l(void) { D(" %s;", M_SLL(RL)); } static void sra_xhl(void) { D(" {"); //D(" byte i;"); D(" i=mem[HL];"); D(" M_SRA(i);"); D(" mem[HL] = i;"); D(" }"); } static void sra_xix(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" M_SRA(i);"); D(" mem[j] = i;"); D(" }"); } static void sra_xiy(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" M_SRA(i);"); D(" mem[j] = i;"); D(" }"); } static void sra_a(void) { D(" %s;", M_SRA(RA)); } static void sra_b(void) { D(" %s;", M_SRA(RB)); } static void sra_c(void) { D(" %s;", M_SRA(RC)); } static void sra_d(void) { D(" %s;", M_SRA(RD)); } static void sra_e(void) { D(" %s;", M_SRA(RE)); } static void sra_h(void) { D(" %s;", M_SRA(RH)); } static void sra_l(void) { D(" %s;", M_SRA(RL)); } static void srl_xhl(void) { D(" {"); //D(" byte i;"); D(" i=mem[HL];"); D(" M_SRL(i);"); D(" mem[HL] = i;"); D(" }"); } static void srl_xix(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIX); D(" i=mem[j];"); D(" M_SRL(i);"); D(" mem[j] = i;"); D(" }"); } static void srl_xiy(void) { D(" {"); //D(" byte i;"); //D(" int j;"); D(" j=%s;", M_XIY); D(" i=mem[j];"); D(" M_SRL(i);"); D(" mem[j] = i;"); D(" }"); } static void srl_a(void) { D(" %s;", M_SRL(RA)); } static void srl_b(void) { D(" %s;", M_SRL(RB)); } static void srl_c(void) { D(" %s;", M_SRL(RC)); } static void srl_d(void) { D(" %s;", M_SRL(RD)); } static void srl_e(void) { D(" %s;", M_SRL(RE)); } static void srl_h(void) { D(" %s;", M_SRL(RH)); } static void srl_l(void) { D(" %s;", M_SRL(RL)); } static void sub_xhl(void) { D(" %s;", M_SUB(mem[HL])); } static void sub_xix(void) { D(" %s;", M_SUB_S(M_RD_XIX)); } static void sub_xiy(void) { D(" %s;", M_SUB_S(M_RD_XIY)); } static void sub_a(void) { D(" RA=0;RF=(AF=Z_FLAG|N_FLAG);"); } static void sub_b(void) { D(" %s;", M_SUB(RB)); } static void sub_c(void) { D(" %s;", M_SUB(RC)); } static void sub_d(void) { D(" %s;", M_SUB(RD)); } static void sub_e(void) { D(" %s;", M_SUB(RE)); } static void sub_h(void) { D(" %s;", M_SUB(RH)); } static void sub_l(void) { D(" %s;", M_SUB(RL)); } static void sub_ixh(void) { D(" %s;", M_SUB(RI)); } static void sub_ixl(void) { D(" %s;", M_SUB(RX)); } static void sub_iyh(void) { D(" %s;", M_SUB(RJ)); } static void sub_iyl(void) { D(" %s;", M_SUB(RY)); } static void sub_byte(void) { D(" %s;", M_SUB_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void xor_xhl(void) { D(" %s;", M_XOR(mem[HL])); } static void xor_xix(void) { D(" %s;", M_XOR_S(M_RD_XIX)); } static void xor_xiy(void) { D(" %s;", M_XOR_S(M_RD_XIY)); } static void xor_a(void) { D(" RA=0;RF=(AF=Z_FLAG|V_FLAG);"); } static void xor_b(void) { D(" %s;", M_XOR(RB)); } static void xor_c(void) { D(" %s;", M_XOR(RC)); } static void xor_d(void) { D(" %s;", M_XOR(RD)); } static void xor_e(void) { D(" %s;", M_XOR(RE)); } static void xor_h(void) { D(" %s;", M_XOR(RH)); } static void xor_l(void) { D(" %s;", M_XOR(RL)); } static void xor_ixh(void) { D(" %s;", M_XOR(RI)); } static void xor_ixl(void) { D(" %s;", M_XOR(RX)); } static void xor_iyh(void) { D(" %s;", M_XOR(RJ)); } static void xor_iyl(void) { D(" %s;", M_XOR(RY)); } static void xor_byte(void) { D(" %s;", M_XOR_S(S("0x%02x", M_RDMEM_OPCODE()))); } static void no_op(void) { D(" --PC;"); } static void patch(void) { Z80_Patch(&R); } static unsigned cycles_main[256]= { 4,10,7,6,4,4,7,4, 4,11,7,6,4,4,7,4, 8,10,7,6,4,4,7,4, 7,11,7,6,4,4,7,4, 7,10,16,6,4,4,7,4, 7,11,16,6,4,4,7,4, 7,10,13,6,11,11,10,4, 7,11,13,6,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 7,7,7,7,7,7,4,7, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 4,4,4,4,4,4,7,4, 5,10,10,10,10,11,7,11, 5,4,10,0,10,10,7,11, 5,10,10,11,10,11,7,11, 5,4,10,11,10,0,7,11, 5,10,10,19,10,11,7,11, 5,4,10,4,10,0,7,11, 5,10,10,4,10,11,7,11, 5,6,10,4,10,0,7,11 }; static unsigned cycles_cb[256]= { 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,12,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8, 8,8,8,8,8,8,15,8 }; static unsigned cycles_xx_cb[]= { 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0, 0,0,0,0,0,0,23,0 }; static unsigned cycles_xx[256]= { 0,0,0,0,0,0,0,0, 0,15,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,15,0,0,0,0,0,0, 0,14,20,10,9,9,9,0, 0,15,20,10,9,9,9,0, 0,0,0,0,23,23,19,0, 0,15,0,0,0,0,0,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9, 19,19,19,19,19,19,19,19, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,0, 0,0,0,0,9,9,19,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,14,0,23,0,15,0,0, 0,8,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,10,0,0,0,0,0,0 }; static unsigned cycles_ed[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,8,8,9, 12,12,15,20,8,8,8,9, 12,12,15,20,8,8,8,9, 12,12,15,20,8,8,8,9, 12,12,15,20,8,8,8,18, 12,12,15,20,8,8,8,18, 12,12,15,20,8,8,8,0, 12,12,15,20,8,8,8,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 }; static void no_op_xx(void) { D(" ++PC;"); } static opcode_fn opcode_dd_cb[256]= { no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rlc_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rrc_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rl_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rr_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sla_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sra_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sll_xix ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,srl_xix ,no_op_xx , bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix, bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix, bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix, bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix, bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix, bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix, bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix, bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix, no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_0_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_1_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_2_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_3_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_4_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_5_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_6_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_7_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_0_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_1_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_2_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_3_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_4_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_5_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_6_xix,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_7_xix,no_op_xx }; static opcode_fn opcode_fd_cb[256]= { no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rlc_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rrc_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rl_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rr_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sla_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sra_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sll_xiy ,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,srl_xiy ,no_op_xx , bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy, bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy, bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy, bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy, bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy, bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy, bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy, bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy, no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_0_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_1_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_2_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_3_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_4_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_5_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_6_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_7_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_0_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_1_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_2_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_3_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_4_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_5_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_6_xiy,no_op_xx , no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_7_xiy,no_op_xx }; static void dd_cb(void) { unsigned opcode; opcode=M_RDOP_ARG((PC+1)&0xFFFF); if (counting_cycles) D(" Z80_ICount-=cycles_xx_cb[opcode];"); (*(opcode_dd_cb[opcode]))(); ++PC; }; static void fd_cb(void) { unsigned opcode; opcode=M_RDOP_ARG((PC+1)&0xFFFF); if (counting_cycles) D(" Z80_ICount-=cycles_xx_cb[opcode];"); (*(opcode_fd_cb[opcode]))(); ++PC; }; static opcode_fn opcode_cb[256]= { rlc_b ,rlc_c ,rlc_d ,rlc_e ,rlc_h ,rlc_l ,rlc_xhl ,rlc_a , rrc_b ,rrc_c ,rrc_d ,rrc_e ,rrc_h ,rrc_l ,rrc_xhl ,rrc_a , rl_b ,rl_c ,rl_d ,rl_e ,rl_h ,rl_l ,rl_xhl ,rl_a , rr_b ,rr_c ,rr_d ,rr_e ,rr_h ,rr_l ,rr_xhl ,rr_a , sla_b ,sla_c ,sla_d ,sla_e ,sla_h ,sla_l ,sla_xhl ,sla_a , sra_b ,sra_c ,sra_d ,sra_e ,sra_h ,sra_l ,sra_xhl ,sra_a , sll_b ,sll_c ,sll_d ,sll_e ,sll_h ,sll_l ,sll_xhl ,sll_a , srl_b ,srl_c ,srl_d ,srl_e ,srl_h ,srl_l ,srl_xhl ,srl_a , bit_0_b,bit_0_c,bit_0_d,bit_0_e,bit_0_h,bit_0_l,bit_0_xhl,bit_0_a, bit_1_b,bit_1_c,bit_1_d,bit_1_e,bit_1_h,bit_1_l,bit_1_xhl,bit_1_a, bit_2_b,bit_2_c,bit_2_d,bit_2_e,bit_2_h,bit_2_l,bit_2_xhl,bit_2_a, bit_3_b,bit_3_c,bit_3_d,bit_3_e,bit_3_h,bit_3_l,bit_3_xhl,bit_3_a, bit_4_b,bit_4_c,bit_4_d,bit_4_e,bit_4_h,bit_4_l,bit_4_xhl,bit_4_a, bit_5_b,bit_5_c,bit_5_d,bit_5_e,bit_5_h,bit_5_l,bit_5_xhl,bit_5_a, bit_6_b,bit_6_c,bit_6_d,bit_6_e,bit_6_h,bit_6_l,bit_6_xhl,bit_6_a, bit_7_b,bit_7_c,bit_7_d,bit_7_e,bit_7_h,bit_7_l,bit_7_xhl,bit_7_a, res_0_b,res_0_c,res_0_d,res_0_e,res_0_h,res_0_l,res_0_xhl,res_0_a, res_1_b,res_1_c,res_1_d,res_1_e,res_1_h,res_1_l,res_1_xhl,res_1_a, res_2_b,res_2_c,res_2_d,res_2_e,res_2_h,res_2_l,res_2_xhl,res_2_a, res_3_b,res_3_c,res_3_d,res_3_e,res_3_h,res_3_l,res_3_xhl,res_3_a, res_4_b,res_4_c,res_4_d,res_4_e,res_4_h,res_4_l,res_4_xhl,res_4_a, res_5_b,res_5_c,res_5_d,res_5_e,res_5_h,res_5_l,res_5_xhl,res_5_a, res_6_b,res_6_c,res_6_d,res_6_e,res_6_h,res_6_l,res_6_xhl,res_6_a, res_7_b,res_7_c,res_7_d,res_7_e,res_7_h,res_7_l,res_7_xhl,res_7_a, set_0_b,set_0_c,set_0_d,set_0_e,set_0_h,set_0_l,set_0_xhl,set_0_a, set_1_b,set_1_c,set_1_d,set_1_e,set_1_h,set_1_l,set_1_xhl,set_1_a, set_2_b,set_2_c,set_2_d,set_2_e,set_2_h,set_2_l,set_2_xhl,set_2_a, set_3_b,set_3_c,set_3_d,set_3_e,set_3_h,set_3_l,set_3_xhl,set_3_a, set_4_b,set_4_c,set_4_d,set_4_e,set_4_h,set_4_l,set_4_xhl,set_4_a, set_5_b,set_5_c,set_5_d,set_5_e,set_5_h,set_5_l,set_5_xhl,set_5_a, set_6_b,set_6_c,set_6_d,set_6_e,set_6_h,set_6_l,set_6_xhl,set_6_a, set_7_b,set_7_c,set_7_d,set_7_e,set_7_h,set_7_l,set_7_xhl,set_7_a }; static opcode_fn opcode_dd[256]= { no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,add_ix_bc ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,add_ix_de ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,ld_ix_word,ld_xword_ix,inc_ix ,inc_ixh ,dec_ixh ,ld_ixh_byte,no_op , no_op ,add_ix_ix ,ld_ix_xword,dec_ix ,inc_ixl ,dec_ixl ,ld_ixl_byte,no_op , no_op ,no_op ,no_op ,no_op ,inc_xix ,dec_xix ,ld_xix_byte,no_op , no_op ,add_ix_sp ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,ld_b_ixh ,ld_b_ixl ,ld_b_xix ,no_op , no_op ,no_op ,no_op ,no_op ,ld_c_ixh ,ld_c_ixl ,ld_c_xix ,no_op , no_op ,no_op ,no_op ,no_op ,ld_d_ixh ,ld_d_ixl ,ld_d_xix ,no_op , no_op ,no_op ,no_op ,no_op ,ld_e_ixh ,ld_e_ixl ,ld_e_xix ,no_op , ld_ixh_b,ld_ixh_c ,ld_ixh_d ,ld_ixh_e ,ld_ixh_ixh ,ld_ixh_ixl ,ld_h_xix ,ld_ixh_a, ld_ixl_b,ld_ixl_c ,ld_ixl_d ,ld_ixl_e ,ld_ixl_ixh ,ld_ixl_ixl ,ld_l_xix ,ld_ixl_a, ld_xix_b,ld_xix_c ,ld_xix_d ,ld_xix_e ,ld_xix_h ,ld_xix_l ,no_op ,ld_xix_a, no_op ,no_op ,no_op ,no_op ,ld_a_ixh ,ld_a_ixl ,ld_a_xix ,no_op , no_op ,no_op ,no_op ,no_op ,add_a_ixh ,add_a_ixl ,add_a_xix ,no_op , no_op ,no_op ,no_op ,no_op ,adc_a_ixh ,adc_a_ixl ,adc_a_xix ,no_op , no_op ,no_op ,no_op ,no_op ,sub_ixh ,sub_ixl ,sub_xix ,no_op , no_op ,no_op ,no_op ,no_op ,sbc_a_ixh ,sbc_a_ixl ,sbc_a_xix ,no_op , no_op ,no_op ,no_op ,no_op ,and_ixh ,and_ixl ,and_xix ,no_op , no_op ,no_op ,no_op ,no_op ,xor_ixh ,xor_ixl ,xor_xix ,no_op , no_op ,no_op ,no_op ,no_op ,or_ixh ,or_ixl ,or_xix ,no_op , no_op ,no_op ,no_op ,no_op ,cp_ixh ,cp_ixl ,cp_xix ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,dd_cb ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,pop_ix ,no_op ,ex_xsp_ix,no_op ,push_ix ,no_op ,no_op , no_op ,jp_ix ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,ld_sp_ix ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op }; static opcode_fn opcode_ed[256]= { nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , in_b_c,out_c_b,sbc_hl_bc,ld_xword_bc,neg,retn,im_0 ,ld_i_a, in_c_c,out_c_c,adc_hl_bc,ld_bc_xword,neg,reti,im_0 ,ld_r_a, in_d_c,out_c_d,sbc_hl_de,ld_xword_de,neg,retn,im_1 ,ld_a_i, in_e_c,out_c_e,adc_hl_de,ld_de_xword,neg,reti,im_2 ,ld_a_r, in_h_c,out_c_h,sbc_hl_hl,ld_xword_hl,neg,retn,im_0 ,rrd , in_l_c,out_c_l,adc_hl_hl,ld_hl_xword,neg,reti,im_0 ,rld , in_0_c,out_c_0,sbc_hl_sp,ld_xword_sp,neg,retn,im_1 ,nop , in_a_c,out_c_a,adc_hl_sp,ld_sp_xword,neg,reti,im_2 ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , ldi ,cpi ,ini ,outi ,nop,nop ,nop ,nop , ldd ,cpd ,ind ,outd ,nop,nop ,nop ,nop , ldir ,cpir ,inir ,otir ,nop,nop ,nop ,nop , lddr ,cpdr ,indr ,otdr ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , nop ,nop ,nop ,nop ,nop,nop ,patch,nop }; static opcode_fn opcode_fd[256]= { no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,add_iy_bc ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,add_iy_de ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,ld_iy_word,ld_xword_iy,inc_iy ,inc_iyh ,dec_iyh ,ld_iyh_byte,no_op , no_op ,add_iy_iy ,ld_iy_xword,dec_iy ,inc_iyl ,dec_iyl ,ld_iyl_byte,no_op , no_op ,no_op ,no_op ,no_op ,inc_xiy ,dec_xiy ,ld_xiy_byte,no_op , no_op ,add_iy_sp ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,ld_b_iyh ,ld_b_iyl ,ld_b_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,ld_c_iyh ,ld_c_iyl ,ld_c_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,ld_d_iyh ,ld_d_iyl ,ld_d_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,ld_e_iyh ,ld_e_iyl ,ld_e_xiy ,no_op , ld_iyh_b,ld_iyh_c ,ld_iyh_d ,ld_iyh_e ,ld_iyh_iyh ,ld_iyh_iyl ,ld_h_xiy ,ld_iyh_a, ld_iyl_b,ld_iyl_c ,ld_iyl_d ,ld_iyl_e ,ld_iyl_iyh ,ld_iyl_iyl ,ld_l_xiy ,ld_iyl_a, ld_xiy_b,ld_xiy_c ,ld_xiy_d ,ld_xiy_e ,ld_xiy_h ,ld_xiy_l ,no_op ,ld_xiy_a, no_op ,no_op ,no_op ,no_op ,ld_a_iyh ,ld_a_iyl ,ld_a_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,add_a_iyh ,add_a_iyl ,add_a_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,adc_a_iyh ,adc_a_iyl ,adc_a_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,sub_iyh ,sub_iyl ,sub_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,sbc_a_iyh ,sbc_a_iyl ,sbc_a_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,and_iyh ,and_iyl ,and_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,xor_iyh ,xor_iyl ,xor_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,or_iyh ,or_iyl ,or_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,cp_iyh ,cp_iyl ,cp_xiy ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,fd_cb ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,pop_iy ,no_op ,ex_xsp_iy,no_op ,push_iy ,no_op ,no_op , no_op ,jp_iy ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , no_op ,ld_sp_iy ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op }; static void cb(void) { unsigned opcode; opcode=M_RDOP(PC); PC++; if (counting_cycles) D(" Z80_ICount-=cycles_cb[opcode];"); (*(opcode_cb[opcode]))(); } static void dd(void) { unsigned opcode; opcode=M_RDOP(PC); PC++; if (counting_r) D(" Z80_ICount-=cycles_xx[opcode];"); (*(opcode_dd[opcode]))(); } static void ed(void) // TODO: this opcode decodes further info therefore { // must update virtual PC. Check for other similar ones unsigned opcode; opcode=M_RDOP(PC); PC++; if (counting_cycles) D(" Z80_ICount-=cycles_ed[opcode];"); (*(opcode_ed[opcode]))(); } static void fd (void) { unsigned opcode; opcode=M_RDOP(PC); PC++; if (counting_cycles) D(" Z80_ICount-=cycles_xx[opcode];"); (*(opcode_fd[opcode]))(); } static opcode_fn opcode_main[256]= { nop ,ld_bc_word,ld_xbc_a ,inc_bc ,inc_b ,dec_b ,ld_b_byte ,rlca , ex_af_af,add_hl_bc ,ld_a_xbc ,dec_bc ,inc_c ,dec_c ,ld_c_byte ,rrca , djnz ,ld_de_word,ld_xde_a ,inc_de ,inc_d ,dec_d ,ld_d_byte ,rla , jr ,add_hl_de ,ld_a_xde ,dec_de ,inc_e ,dec_e ,ld_e_byte ,rra , jr_nz ,ld_hl_word,ld_xword_hl,inc_hl ,inc_h ,dec_h ,ld_h_byte ,daa , jr_z ,add_hl_hl ,ld_hl_xword,dec_hl ,inc_l ,dec_l ,ld_l_byte ,cpl , jr_nc ,ld_sp_word,ld_xbyte_a ,inc_sp ,inc_xhl ,dec_xhl ,ld_xhl_byte,scf , jr_c ,add_hl_sp ,ld_a_xbyte ,dec_sp ,inc_a ,dec_a ,ld_a_byte ,ccf , ld_b_b ,ld_b_c ,ld_b_d ,ld_b_e ,ld_b_h ,ld_b_l ,ld_b_xhl ,ld_b_a , ld_c_b ,ld_c_c ,ld_c_d ,ld_c_e ,ld_c_h ,ld_c_l ,ld_c_xhl ,ld_c_a , ld_d_b ,ld_d_c ,ld_d_d ,ld_d_e ,ld_d_h ,ld_d_l ,ld_d_xhl ,ld_d_a , ld_e_b ,ld_e_c ,ld_e_d ,ld_e_e ,ld_e_h ,ld_e_l ,ld_e_xhl ,ld_e_a , ld_h_b ,ld_h_c ,ld_h_d ,ld_h_e ,ld_h_h ,ld_h_l ,ld_h_xhl ,ld_h_a , ld_l_b ,ld_l_c ,ld_l_d ,ld_l_e ,ld_l_h ,ld_l_l ,ld_l_xhl ,ld_l_a , ld_xhl_b,ld_xhl_c ,ld_xhl_d ,ld_xhl_e ,ld_xhl_h,ld_xhl_l,halt ,ld_xhl_a, ld_a_b ,ld_a_c ,ld_a_d ,ld_a_e ,ld_a_h ,ld_a_l ,ld_a_xhl ,ld_a_a , add_a_b ,add_a_c ,add_a_d ,add_a_e ,add_a_h ,add_a_l ,add_a_xhl ,add_a_a , adc_a_b ,adc_a_c ,adc_a_d ,adc_a_e ,adc_a_h ,adc_a_l ,adc_a_xhl ,adc_a_a , sub_b ,sub_c ,sub_d ,sub_e ,sub_h ,sub_l ,sub_xhl ,sub_a , sbc_a_b ,sbc_a_c ,sbc_a_d ,sbc_a_e ,sbc_a_h ,sbc_a_l ,sbc_a_xhl ,sbc_a_a , and_b ,and_c ,and_d ,and_e ,and_h ,and_l ,and_xhl ,and_a , xor_b ,xor_c ,xor_d ,xor_e ,xor_h ,xor_l ,xor_xhl ,xor_a , or_b ,or_c ,or_d ,or_e ,or_h ,or_l ,or_xhl ,or_a , cp_b ,cp_c ,cp_d ,cp_e ,cp_h ,cp_l ,cp_xhl ,cp_a , ret_nz ,pop_bc ,jp_nz ,jp ,call_nz ,push_bc ,add_a_byte ,rst_00 , ret_z ,ret ,jp_z ,cb ,call_z ,call ,adc_a_byte ,rst_08 , ret_nc ,pop_de ,jp_nc ,out_byte_a,call_nc ,push_de ,sub_byte ,rst_10 , ret_c ,exx ,jp_c ,in_a_byte ,call_c ,dd ,sbc_a_byte ,rst_18 , ret_po ,pop_hl ,jp_po ,ex_xsp_hl ,call_po ,push_hl ,and_byte ,rst_20 , ret_pe ,jp_hl ,jp_pe ,ex_de_hl ,call_pe ,ed ,xor_byte ,rst_28 , ret_p ,pop_af ,jp_p ,di ,call_p ,push_af ,or_byte ,rst_30 , ret_m ,ld_sp_hl ,jp_m ,ei ,call_m ,fd ,cp_byte ,rst_38 }; static void ei(void) { unsigned opcode; /* If interrupts were disabled, execute one more instruction and check the */ /* IRQ line. If not, simply set interrupt flip-flop 2 */ D(" if (!IFF1)"); D(" { /* After EI, the interrupt is not taken until after the next instruction... */"); D(" IFF1=IFF2=1; /* We look ahead to the next instruction and execute it now */"); D(" /* - we need to be careful about cycle counts, debugging, etc */"); D(" /* A halt or jump could cause real confusion, and halt is quite */"); D(" /* likely as it is a mechanism to wait for interrupt. FIX THIS! */"); opcode=M_RDOP(PC); if (debug) D(" PC++;"); if (debug) D(" Z80_ICount-=cycles_main[opcode];"); (*(opcode_main[opcode]))(); D(" Interrupt(Z80_IRQ);"); D(" }"); D(" else"); D(" IFF2=1;"); } /****************************************************************************/ /* Reset registers to their initial values */ /****************************************************************************/ void Z80_Reset (void) { memset (&R,0,sizeof(Z80_Regs)); SP=0xF000; R.R=rand(); Z80_ICount=Z80_IPeriod; } /****************************************************************************/ /* Initialise the various lookup tables used by the emulation code */ /****************************************************************************/ static void InitTables (void) { static int InitTables_virgin=1; byte zs; int i,p; if (!InitTables_virgin) return; InitTables_virgin=0; for (i=0;i<256;++i) { zs=0; if (i==0) zs|=Z_FLAG; if (i&0x80) zs|=S_FLAG; p=0; if (i&1) ++p; if (i&2) ++p; if (i&4) ++p; if (i&8) ++p; if (i&16) ++p; if (i&32) ++p; if (i&64) ++p; if (i&128) ++p; PTable[i]=(p&1)? 0:V_FLAG; ZSTable[i]=zs; IncTable[i]=zs|((i==0x80)?V_FLAG:0)|((i&0x0F)?0:H_FLAG); DecTable[i]=(zs&C_FLAG)|N_FLAG|((i==0x7f)?V_FLAG:0)|(((i+1)&0x0F)?0:H_FLAG)|ZSTable[i]; ZSPTable[i]=zs|PTable[i]; ZSPHTable[i]=zs|PTable[i]|H_FLAG; } for (i=0;i<256;++i) { PostIncCarry[i] = 0; ZSTable[i+256]=ZSTable[i]|C_FLAG; ZSPTable[i+256]=ZSPTable[i]|C_FLAG; ZSPHTable[i+256]=ZSPTable[i]|C_FLAG; IncTable[i+256]=IncTable[i]|C_FLAG; DecTable[i+256]=DecTable[i]|C_FLAG; PTable[i+256]=PTable[i]|C_FLAG; } {int RA, RB, i; for (RA = 0; RA < 256; RA++) { for (RB = 0; RB < 256; RB++) { i = RA+RB; AddFlags[RA][RB] = ZSTable[i&255]|((i&256)>>8)|((RA^i^RB)&H_FLAG)|(((RB^RA^0x80)&(RB^i)&0x80)>>5); } } } PostIncCarry[0] = 1; // ff -> 00 means next byte gets a carry } /****************************************************************************/ /* Issue an interrupt if necessary */ /****************************************************************************/ static void Interrupt (int j) { #ifdef NEVER if (j==Z80_IGNORE_INT) return; if (j==Z80_NMI_INT || IFF1) { /* Clear interrupt flip-flop 1 */ IFF1=0; /* Check if processor was halted */ if (R.HALT) { ++PC; R.HALT=0; } if (j==Z80_NMI_INT) { M_PUSH (PC); PC=0x0066; } else { /* Interrupt mode 2. Call [R.I:databyte] */ if (R.IM==2) { M_PUSH (PC); PC=M_RDMEM_WORD((j&255)|(R.I<<8)); } else /* Interrupt mode 1. RST 38h */ if (R.IM==1) { Z80_ICount-=cycles_main[0xFF]; (*(opcode_main[0xFF]))(); } else /* Interrupt mode 0. We check for CALL and JP instructions, if neither */ /* of these were found we assume a 1 byte opcode was placed on the */ /* databus */ { switch (j&0xFF0000) { case 0xCD: M_PUSH(PC); case 0xC3: PC=j&0xFFFF; break; default: j&=255; Z80_ICount-=cycles_main[j]; (*(opcode_main[j]))(); break; } } } } #endif } /****************************************************************************/ /* Set all registers to given values */ /****************************************************************************/ void Z80_SetRegs (Z80_Regs *Regs) { R=*Regs; } /****************************************************************************/ /* Get all registers in given buffer */ /****************************************************************************/ void Z80_GetRegs (Z80_Regs *Regs) { *Regs=R; } /****************************************************************************/ /* Return program counter */ /****************************************************************************/ unsigned Z80_GetPC (void) { return PC; } /****************************************************************************/ /* Execute IPeriod T-States. Return 0 if emulation should be stopped */ /****************************************************************************/ int Z80_Translate (int pc) { int i; unsigned opcode = mem[pc&65535]; PC = (pc+1)&65535; if (counting_cycles) D(" Z80_ICount-=cycles_main[opcode];"); (*(opcode_main[opcode]))(); } /****************************************************************************/ /* Interpret Z80 code */ /****************************************************************************/ word Z80 (void) { // while (Z80_Execute()); return(PC); } /****************************************************************************/ /* Dump register contents and (optionally) a PC trace to stdout */ /****************************************************************************/ void Z80_RegisterDump (void) { #ifdef NEVER int i; printf ( "AF:%04X HL:%04X DE:%04X BC:%04X PC:%04X SP:%04X IX:%04X IY:%04X\n", AF,HL,DE,BC,PC,SP,IX,IY ); printf ("STACK: "); for (i=0;i<10;++i) printf ("%04X ",M_RDMEM_WORD((SP+i*2)&0xFFFF)); puts (""); #ifdef TRACE puts ("PC TRACE:"); for (i=1;i<=256;++i) printf ("%04X\n",pc_trace[(pc_count-i)&255]); #endif #endif } /****************************************************************************/ /* Set number of memory refresh wait states (i.e. extra cycles inserted */ /* when the refresh register is being incremented) */ /****************************************************************************/ void Z80_SetWaitStates (int n) { int i; for (i=0;i<256;++i) { cycles_main[i]+=n; cycles_cb[i]+=n; cycles_ed[i]+=n; cycles_xx[i]+=n; } }