+int
+cl_z80::inst_rlca(t_mem code)
+{
+ rlc_byte(regs.A);
+
+ return(resGO);
+}
+
+int
+cl_z80::inst_rrca(t_mem code)
+{
+ rrc_byte(regs.A);
+ return(resGO);
+}
+
+int
+cl_z80::inst_ex(t_mem code)
+{
+ /* 0x08 // EX AF,AF' */
+ unsigned char tmp;
+ TYPE_UWORD tempw;
+
+ switch (code) {
+ case 0x08: // EX AF,AF'
+ tmp = regs.aA;
+ regs.aA = regs.A;
+ regs.A = tmp;
+
+ tmp = regs.aF;
+ regs.aF = regs.F;
+ regs.F = tmp;
+ break;
+
+ case 0xE3: // EX (SP),HL
+ tempw = regs.HL;
+ regs.HL = get2(regs.SP);
+ store2(regs.SP, tempw);
+ break;
+
+ case 0xEB: // EX DE,HL
+ tempw = regs.DE;
+ regs.DE = regs.HL;
+ regs.HL = tempw;
+ break;
+
+ default:
+ return(resINV_INST);
+ break;
+ }
+
+ return(resGO);
+}
+
+int
+cl_z80::inst_add(t_mem code)
+{
+#define add_HL_Word(wr) { \
+ unsigned int tmp; \
+ regs.F &= ~(BIT_ALL); /* clear these */ \
+ tmp = (unsigned int)regs.HL + (unsigned int)(wr); \
+ if (tmp > 0xffff) regs.F |= BIT_C; \
+ regs.HL = (unsigned short) tmp; }
+
+ switch(code) {
+ case 0x09: // ADD HL,BC
+ add_HL_Word(regs.BC);
+ break;
+ case 0x19: // ADD HL,DE
+ add_HL_Word(regs.DE);
+ break;
+ case 0x29: // ADD HL,HL
+ add_HL_Word(regs.HL);
+ break;
+ case 0x39: // ADD HL,SP
+ add_HL_Word(regs.SP);
+ break;
+
+ case 0x80: // ADD A,B
+ add_A_bytereg(regs.bc.h);
+ break;
+ case 0x81: // ADD A,C
+ add_A_bytereg(regs.bc.l);
+ break;
+ case 0x82: // ADD A,D
+ add_A_bytereg(regs.de.h);
+ break;
+ case 0x83: // ADD A,E
+ add_A_bytereg(regs.de.l);
+ break;
+ case 0x84: // ADD A,H
+ add_A_bytereg(regs.hl.h);
+ break;
+ case 0x85: // ADD A,L
+ add_A_bytereg(regs.hl.l);
+ break;
+
+ case 0x86: // ADD A,(HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ add_A_bytereg(utmp);
+ }
+ break;
+
+ case 0x87: // ADD A,A
+ add_A_bytereg(regs.A);
+ break;
+
+ case 0xC6: // ADD A,nn
+ {
+ unsigned char utmp1;
+ utmp1 = fetch();
+ add_A_bytereg(utmp1);
+ }
+ break;
+
+ default:
+ return(resINV_INST);
+ break;
+ }
+
+ return(resGO);
+}
+
+int
+cl_z80::inst_djnz(t_mem code)
+{
+ signed char j;
+
+ // 0x10: DJNZ dd
+
+ j = fetch1();
+ if ((--regs.bc.h != 0)) {
+ PC += j;
+ } else {
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_rra(t_mem code)
+{
+ rr_byte(regs.A);
+ return(resGO);
+}
+
+int
+cl_z80::inst_rla(t_mem code)
+{
+ rl_byte(regs.A);
+ return(resGO);
+}
+
+int
+cl_z80::inst_jr(t_mem code)
+{
+ signed char j;
+
+ j = fetch1();
+ switch(code) {
+ case 0x18: // JR dd
+ PC += j;
+ break;
+ case 0x20: // JR NZ,dd
+ if (!(regs.F & BIT_Z)) {
+ PC += j;
+ }
+ break;
+ case 0x28: // JR Z,dd
+ if ((regs.F & BIT_Z)) {
+ PC += j;
+ }
+ break;
+ case 0x30: // JR NC,dd
+ if (!(regs.F & BIT_C)) {
+ PC += j;
+ }
+ break;
+ case 0x38: // JR C,dd
+ if ((regs.F & BIT_C)) {
+ PC += j;
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_daa(t_mem code)
+{
+ /************* from MH's z80ops.c:
+ unsigned char incr=0, carry=cy;
+ if((f&0x10) || (a&0x0f)>9) incr=6;
+ if((f&1) || (a>>4)>9) incr|=0x60;
+ if(f&2)suba(incr,0);
+ else {
+ if(a>0x90 && (a&15)>9)incr|=0x60;
+ adda(incr,0);
+ }
+ f=((f|carry)&0xfb);
+ ********/
+ /* I have not tried to understand this archaic bit of BCD logic(kpb),
+ taking the lazy way out for now and just transcribing MH's code.
+ */
+ unsigned char incr;
+ if ((regs.F & BIT_A) || ((regs.A & 0x0f) > 9))
+ incr = 6;
+ else incr = 0;
+
+ if ((regs.F & BIT_C) || ((regs.A & 0xf0) > 0x90))
+ incr |= 0x60;
+
+ if (regs.F & BIT_N) { /* not addition */
+ sub_A_bytereg(incr);
+ } else {
+ if ((regs.A > 0x90) && ((regs.A & 0x0f) >9)) incr |= 0x60;
+ add_A_bytereg(incr);
+ }
+
+ return(resGO);
+}
+
+int
+cl_z80::inst_cpl(t_mem code)
+{
+ regs.F |= (BIT_A | BIT_N);
+ regs.A = ~regs.A;
+ return(resGO);
+}
+
+int
+cl_z80::inst_scf(t_mem code)
+{
+ /* Set Carry Flag */
+ regs.F |= BIT_C;
+ return(resGO);
+}
+
+int
+cl_z80::inst_ccf(t_mem code)
+{
+ /* Compliment Carry Flag */
+ regs.F ^= BIT_C;
+ return(resGO);
+}
+
+int
+cl_z80::inst_halt(t_mem code)
+{
+ return(resHALT);
+}
+
+int
+cl_z80::inst_adc(t_mem code)
+{
+ switch(code) {
+ case 0x88: // ADC A,B
+ adc_A_bytereg(regs.bc.h);
+ break;
+ case 0x89: // ADC A,C
+ adc_A_bytereg(regs.bc.l);
+ break;
+ case 0x8A: // ADC A,D
+ adc_A_bytereg(regs.de.h);
+ break;
+ case 0x8B: // ADC A,E
+ adc_A_bytereg(regs.de.l);
+ break;
+ case 0x8C: // ADC A,H
+ adc_A_bytereg(regs.hl.h);
+ break;
+ case 0x8D: // ADC A,L
+ adc_A_bytereg(regs.hl.l);
+ break;
+ case 0x8E: // ADC A,(HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ adc_A_bytereg(utmp);
+ }
+ break;
+ case 0x8F: // ADC A,A
+ adc_A_bytereg(regs.A);
+ break;
+
+ case 0xCE: // ADC A,nn
+ { unsigned char utmp;
+ utmp = fetch();
+ adc_A_bytereg(utmp);
+ }
+ break;
+
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_sbc(t_mem code)
+{
+ switch(code) {
+ case 0x98: // SBC A,B
+ sbc_A_bytereg(regs.bc.h);
+ break;
+ case 0x99: // SBC A,C
+ sbc_A_bytereg(regs.bc.l);
+ break;
+ case 0x9A: // SBC A,D
+ sbc_A_bytereg(regs.de.h);
+ break;
+ case 0x9B: // SBC A,E
+ sbc_A_bytereg(regs.de.l);
+ break;
+ case 0x9C: // SBC A,H
+ sbc_A_bytereg(regs.hl.h);
+ break;
+ case 0x9D: // SBC A,L
+ sbc_A_bytereg(regs.hl.l);
+ break;
+ case 0x9E: // SBC A,(HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ sbc_A_bytereg(utmp);
+ }
+ break;
+ case 0x9F: // SBC A,A
+ sbc_A_bytereg(regs.A);
+ break;
+ case 0xDE: // SBC A,nn
+ { unsigned char utmp;
+ utmp = fetch();
+ sbc_A_bytereg(utmp);
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_and(t_mem code)
+{
+ switch(code) {
+ case 0xA0: // AND B
+ and_A_bytereg(regs.bc.h);
+ break;
+ case 0xA1: // AND C
+ and_A_bytereg(regs.bc.l);
+ break;
+ case 0xA2: // AND D
+ and_A_bytereg(regs.de.h);
+ break;
+ case 0xA3: // AND E
+ and_A_bytereg(regs.de.l);
+ break;
+ case 0xA4: // AND H
+ and_A_bytereg(regs.hl.h);
+ break;
+ case 0xA5: // AND L
+ and_A_bytereg(regs.hl.l);
+ break;
+ case 0xA6: // AND (HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ and_A_bytereg(utmp);
+ }
+ break;
+ case 0xA7: // AND A
+ and_A_bytereg(regs.A);
+ break;
+ case 0xE6: // AND nn
+ and_A_bytereg(fetch());
+ break;
+
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_xor(t_mem code)
+{
+ switch(code) {
+ case 0xA8: // XOR B
+ xor_A_bytereg(regs.bc.h);
+ break;
+ case 0xA9: // XOR C
+ xor_A_bytereg(regs.bc.l);
+ break;
+ case 0xAA: // XOR D
+ xor_A_bytereg(regs.de.h);
+ break;
+ case 0xAB: // XOR E
+ xor_A_bytereg(regs.de.l);
+ break;
+ case 0xAC: // XOR H
+ xor_A_bytereg(regs.hl.h);
+ break;
+ case 0xAD: // XOR L
+ xor_A_bytereg(regs.hl.l);
+ break;
+ case 0xAE: // XOR (HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ xor_A_bytereg(utmp);
+ }
+ break;
+ case 0xAF: // XOR A
+ xor_A_bytereg(regs.A);
+ break;
+ case 0xEE: // XOR nn
+ xor_A_bytereg(fetch());
+ break;
+
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_or(t_mem code)
+{
+ switch(code) {
+ case 0xB0: // OR B
+ or_A_bytereg(regs.bc.h);
+ break;
+ case 0xB1: // OR C
+ or_A_bytereg(regs.bc.l);
+ break;
+ case 0xB2: // OR D
+ or_A_bytereg(regs.de.h);
+ break;
+ case 0xB3: // OR E
+ or_A_bytereg(regs.de.l);
+ break;
+ case 0xB4: // OR H
+ or_A_bytereg(regs.hl.h);
+ break;
+ case 0xB5: // OR L
+ or_A_bytereg(regs.hl.l);
+ break;
+ case 0xB6: // OR (HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ or_A_bytereg(utmp);
+ }
+ break;
+ case 0xB7: // OR A
+ or_A_bytereg(regs.A);
+ break;
+ case 0xF6: // OR nn
+ or_A_bytereg(fetch());
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_cp(t_mem code)
+{
+ /* Compare with Accumulator - subtract and test, leave A unchanged */
+ switch(code) {
+ case 0xB8: // CP B
+ cp_bytereg(regs.bc.h);
+ break;
+ case 0xB9: // CP C
+ cp_bytereg(regs.bc.l);
+ break;
+ case 0xBA: // CP D
+ cp_bytereg(regs.de.h);
+ break;
+ case 0xBB: // CP E
+ cp_bytereg(regs.de.l);
+ break;
+ case 0xBC: // CP H
+ cp_bytereg(regs.hl.h);
+ break;
+ case 0xBD: // CP L
+ cp_bytereg(regs.hl.l);
+ break;
+ case 0xBE: // CP (HL)
+ { unsigned char utmp;
+ utmp = get1(regs.HL);
+ cp_bytereg(utmp);
+ }
+ break;
+ case 0xBF: // CP A
+ cp_bytereg(regs.A);
+ break;
+ case 0xFE: // CP nn
+ { unsigned char utmp;
+ utmp = fetch();
+ cp_bytereg(utmp);
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_rst(t_mem code)
+{
+ switch(code) {
+ case 0xC7: // RST 0
+ push2(PC+2);
+ PC = 0x0;
+ break;
+ case 0xCF: // RST 8
+ //PC = 0x08;
+ switch (regs.A) {
+ case 0:
+ return(resBREAKPOINT);
+// ::exit(0);
+ break;
+
+ case 1:
+ //printf("PUTCHAR-----> %xH\n", regs.hl.l);
+ putchar(regs.hl.l);
+ fflush(stdout);
+ break;
+ }
+ break;
+ case 0xD7: // RST 10H
+ push2(PC+2);
+ PC = 0x10;
+ break;
+ case 0xDF: // RST 18H
+ push2(PC+2);
+ PC = 0x18;
+ break;
+ case 0xE7: // RST 20H
+ push2(PC+2);
+ PC = 0x20;
+ break;
+ case 0xEF: // RST 28H
+ push2(PC+2);
+ PC = 0x28;
+ break;
+ case 0xF7: // RST 30H
+ push2(PC+2);
+ PC = 0x30;
+ break;
+ case 0xFF: // RST 38H
+ push2(PC+2);
+ PC = 0x38;
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_ret(t_mem code)
+{
+ switch(code) {
+ case 0xC0: // RET NZ
+ if (!(regs.F & BIT_Z)) {
+ pop2(PC);
+ }
+ break;
+ case 0xC8: // RET Z
+ if ((regs.F & BIT_Z)) {
+ pop2(PC);
+ }
+ break;
+ case 0xC9: // RET
+ pop2(PC);
+ break;
+ case 0xD0: // RET NC
+ if (!(regs.F & BIT_C)) {
+ pop2(PC);
+ }
+ break;
+ case 0xD8: // RET C
+ if ((regs.F & BIT_C)) {
+ pop2(PC);
+ }
+ break;
+ case 0xE0: // RET PO
+ if (!(regs.F & BIT_P)) {
+ pop2(PC);
+ }
+ break;
+ case 0xE8: // RET PE
+ if ((regs.F & BIT_P)) {
+ pop2(PC);
+ }
+ break;
+ case 0xF0: // RET P
+ if (!(regs.F & BIT_S)) {
+ pop2(PC);
+ }
+ break;
+ case 0xF8: // RET M
+ if ((regs.F & BIT_S)) {
+ pop2(PC);
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_call(t_mem code)
+{
+ int jnk;
+
+ switch(code) {
+ case 0xC4: // CALL NZ,nnnn
+ if (!(regs.F & BIT_Z)) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xCC: // CALL Z,nnnn
+ if (regs.F & BIT_Z) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xCD: // CALL nnnn
+ push2(PC+2);
+ PC = fetch2();
+ break;
+ case 0xD4: // CALL NC,nnnn
+ if (!(regs.F & BIT_C)) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xDC: // CALL C,nnnn
+ if (regs.F & BIT_C) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xE4: // CALL PO,nnnn
+ if (!(regs.F & BIT_P)) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xEC: // CALL PE,nnnn
+ if (regs.F & BIT_P) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xF4: // CALL P,nnnn
+ if (!(regs.F & BIT_S)) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ case 0xFC: // CALL M,nnnn
+ if (regs.F & BIT_S) {
+ push2(PC+2);
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+
+ return(resGO);
+}
+
+int
+cl_z80::inst_out(t_mem code)
+{
+ return(resGO);
+}
+
+int
+cl_z80::inst_push(t_mem code)
+{
+ switch(code) {
+ case 0xC5: // PUSH BC
+ push2(regs.BC);
+ break;
+ case 0xD5: // PUSH DE
+ push2(regs.DE);
+ break;
+ case 0xE5: // PUSH HL
+ push2(regs.HL);
+ break;
+ case 0xF5: // PUSH AF
+ push1(regs.A);
+ push1(regs.F);
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_exx(t_mem code)
+{
+ /* case 0xD9: // EXX - swap BC,DE,HL with alternates */
+ TYPE_UWORD tempw;
+
+ tempw = regs.aBC;
+ regs.BC = regs.aBC;
+ regs.aBC = tempw;
+
+ tempw = regs.aDE;
+ regs.DE = regs.aDE;
+ regs.aDE = tempw;
+
+ tempw = regs.aDE;
+ regs.DE = regs.aDE;
+ regs.aDE = tempw;
+
+ return(resGO);
+}
+
+int
+cl_z80::inst_in(t_mem code)
+{
+ return(resGO);
+}
+
+int
+cl_z80::inst_sub(t_mem code)
+{
+ switch(code) {
+ case 0x90: // SUB B
+ sub_A_bytereg(regs.bc.h);
+ break;
+ case 0x91: // SUB C
+ sub_A_bytereg(regs.bc.l);
+ break;
+ case 0x92: // SUB D
+ sub_A_bytereg(regs.de.h);
+ break;
+ case 0x93: // SUB E
+ sub_A_bytereg(regs.de.l);
+ break;
+ case 0x94: // SUB H
+ sub_A_bytereg(regs.hl.h);
+ break;
+ case 0x95: // SUB L
+ sub_A_bytereg(regs.hl.l);
+ break;
+ case 0x96: // SUB (HL)
+ { unsigned char tmp1;
+ tmp1 = get1(regs.HL);
+ sub_A_bytereg(tmp1);
+ }
+ break;
+ case 0x97: // SUB A
+ regs.A = 0;
+ break;
+ case 0xD6: // SUB nn
+ { unsigned char tmp1;
+ tmp1 = fetch();
+ sub_A_bytereg(tmp1);
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_pop(t_mem code)
+{
+ switch (code) {
+ case 0xC1: // POP BC
+ regs.BC = get2(regs.SP);
+ regs.SP+=2;
+ break;
+ case 0xD1: // POP DE
+ regs.DE = get2(regs.SP);
+ regs.SP+=2;
+ break;
+ case 0xE1: // POP HL
+ regs.HL = get2(regs.SP);
+ regs.SP+=2;
+ break;
+ case 0xF1: // POP AF
+ regs.F = get1(regs.SP++);
+ regs.A = get1(regs.SP++);
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_jp(t_mem code)
+{
+ int jnk;
+
+ switch (code) {
+ case 0xC2: // JP NZ,nnnn
+ if (!(regs.F & BIT_Z)) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xC3: // JP nnnn
+ PC = fetch2();
+ break;
+
+ case 0xCA: // JP Z,nnnn
+ if (regs.F & BIT_Z) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xD2: // JP NC,nnnn
+ if (!(regs.F & BIT_C)) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xDA: // JP C,nnnn
+ if (regs.F & BIT_C) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xE2: // JP PO,nnnn
+ if (regs.F & BIT_P) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xE9: // JP (HL)
+ PC = regs.HL;
+ break;
+
+ case 0xea: // JP PO,nnnn
+ if (!(regs.F & BIT_P)) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xF2: // JP P,nnnn (positive)
+ if (!(regs.F & BIT_S)) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+
+ case 0xfa: // JP M,nnnn (sign negative)
+ if (regs.F & BIT_S) {
+ PC = fetch2();
+ } else {
+ jnk = fetch2();
+ }
+ break;
+ default:
+ return(resINV_INST);
+ break;
+ }
+ return(resGO);
+}
+
+int
+cl_z80::inst_di(t_mem code)
+{
+ /* disable interrupts */
+ return(resGO);
+}
+
+int
+cl_z80::inst_ei(t_mem code)
+{
+ /* enable interrupts */
+ return(resGO);
+}