Merge branch ucsim-034-pre3 to main trunk; new version 0.4
[fw/sdcc] / sim / ucsim / z80.src / inst.cc
index fc1befe5cd255f23dd17874c86d7a206666248a9..e3f24b5136057a8b1a3179dd4350e1cad4ec68d7 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Simulator of microcontrollers (inst.cc)
  *
+ * some z80 code base from Karl Bongers karl@turbobit.com
+ *
  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
  * 
  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
@@ -30,6 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 // local
 #include "z80cl.h"
 #include "regsz80.h"
+#include "z80mac.h"
 
 
 /*
@@ -40,10 +43,1317 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  */
 
 int
-cl_z80::nop(t_mem code)
+cl_z80::inst_nop(t_mem code)
+{
+  return(resGO);
+}
+
+/*
+ * Load Instruction
+ * LD
+ * 
+ *----------------------------------------------------------------------------
+ */
+
+int
+cl_z80::inst_ld(t_mem code)
+{
+  switch(code) {
+    case 1:  // LD BC,nnnn
+      regs.BC = fetch2();
+    break;
+    case 2: // LD (BC),A
+      store1(regs.BC, regs.A);
+    break;
+    case 6: // LD B,nn
+      regs.bc.h = fetch();
+    break;
+    case 0xa: // LD A,(BC)
+      regs.A = get1(regs.BC);
+    break;
+    case 0x0e: // LD C,nn
+      regs.bc.l = fetch();
+    break;
+    case 0x11: // LD DE,nnnn
+      regs.DE = fetch2();
+    break;
+    case 0x12: // LD (DE),A
+      store1(regs.DE, regs.A);
+    break;
+    case 0x16: // LD D,nn
+      regs.de.h = fetch();
+    break;
+    case 0x1A: // LD A,(DE)
+      regs.A = get1(regs.DE);
+    break;
+    case 0x1E: // LD E,nn
+      regs.de.l = fetch();
+    break;
+    case 0x21: // LD HL,nnnn
+        regs.HL = fetch2();
+    break;
+    case 0x22: // LD (nnnn),HL
+      {
+         unsigned short tw;
+         tw = fetch2();
+         store2(tw, regs.HL);
+      }
+    break;
+    case 0x26: // LD H,nn
+      regs.hl.h = fetch();
+    break;
+    case 0x2A: // LD HL,(nnnn)
+      {
+         unsigned short tw;
+         tw = fetch2();
+         regs.HL = get2(tw);
+      }
+    break;
+    case 0x2E: // LD L,nn
+      regs.hl.l = fetch();
+    break;
+    case 0x31: // LD SP,nnnn
+      regs.SP = fetch2();
+    break;
+    case 0x32: // LD (nnnn),A
+      {
+         unsigned short tw;
+         tw = fetch2();
+         store1(tw, regs.A);
+      }
+    break;
+    case 0x36: // LD (HL),nn
+      store1(regs.HL, fetch());
+    break;
+    case 0x3A: // LD A,(nnnn)
+      regs.A = get1(fetch2());
+    break;
+    case 0x3E: // LD A,nn
+      regs.A = fetch();
+    break;
+    case 0x40: // LD B,B
+    break;
+    case 0x41: // LD B,C
+      regs.bc.h = regs.bc.l;
+    break;
+    case 0x42: // LD B,D
+      regs.bc.h = regs.de.h;
+    break;
+    case 0x43: // LD B,E
+      regs.bc.h = regs.de.l;
+    break;
+    case 0x44: // LD B,H
+      regs.bc.h = regs.hl.h;
+    break;
+    case 0x45: // LD B,L
+      regs.bc.h = regs.hl.l;
+    break;
+    case 0x46: // LD B,(HL)
+      regs.bc.h = get1(regs.HL);
+    break;
+    case 0x47: // LD B,A
+      regs.bc.h = regs.A;
+    break;
+    case 0x48: // LD C,B
+      regs.bc.l = regs.bc.h;
+    break;
+    case 0x49: // LD C,C
+    break;
+    case 0x4A: // LD C,D
+      regs.bc.l = regs.de.h;
+    break;
+    case 0x4B: // LD C,E
+      regs.bc.l = regs.de.l;
+    break;
+    case 0x4C: // LD C,H
+      regs.bc.l = regs.hl.h;
+    break;
+    case 0x4D: // LD C,L
+      regs.bc.l = regs.hl.l;
+    break;
+    case 0x4E: // LD C,(HL)
+      regs.bc.l = get1(regs.HL);
+    break;
+    case 0x4F: // LD C,A
+      regs.bc.l = regs.A;
+    break;
+    case 0x50: // LD D,B
+      regs.de.h = regs.bc.h;
+    break;
+    case 0x51: // LD D,C
+      regs.de.h = regs.bc.l;
+    break;
+    case 0x52: // LD D,D
+    break;
+    case 0x53: // LD D,E
+      regs.de.h = regs.de.l;
+    break;
+    case 0x54: // LD D,H
+      regs.de.h = regs.hl.h;
+    break;
+    case 0x55: // LD D,L
+      regs.de.h = regs.hl.l;
+    break;
+    case 0x56: // LD D,(HL)
+      regs.de.h = get1(regs.HL);
+    break;
+    case 0x57: // LD D,A
+      regs.de.h = regs.A;
+    break;
+    case 0x58: // LD E,B
+      regs.de.l = regs.bc.h;
+    break;
+    case 0x59: // LD E,C
+      regs.de.l = regs.bc.l;
+    break;
+    case 0x5A: // LD E,D
+      regs.de.l = regs.de.h;
+    break;
+    case 0x5B: // LD E,E
+    break;
+    case 0x5C: // LD E,H
+      regs.de.l = regs.hl.h;
+    break;
+    case 0x5D: // LD E,L
+      regs.de.l = regs.hl.l;
+    break;
+    case 0x5E: // LD E,(HL)
+      regs.de.l = get1(regs.HL);
+    break;
+    case 0x5F: // LD E,A
+      regs.de.l = regs.A;
+    break;
+    case 0x60: // LD H,B
+      regs.hl.h = regs.bc.h;
+    break;
+    case 0x61: // LD H,C
+      regs.hl.h = regs.bc.l;
+    break;
+    case 0x62: // LD H,D
+      regs.hl.h = regs.de.h;
+    break;
+    case 0x63: // LD H,E
+      regs.hl.h = regs.de.l;
+    break;
+    case 0x64: // LD H,H
+      regs.hl.h = regs.hl.h;
+    break;
+    case 0x65: // LD H,L
+      regs.hl.h = regs.hl.l;
+    break;
+    case 0x66: // LD H,(HL)
+      regs.hl.h = get1(regs.HL);
+    break;
+    case 0x67: // LD H,A
+      regs.hl.h = regs.A;
+    break;
+    case 0x68: // LD L,B
+      regs.hl.l = regs.bc.h;
+    break;
+    case 0x69: // LD L,C
+      regs.hl.l = regs.bc.l;
+    break;
+    case 0x6A: // LD L,D
+      regs.hl.l = regs.de.h;
+    break;
+    case 0x6B: // LD L,E
+      regs.hl.l = regs.de.l;
+    break;
+    case 0x6C: // LD L,H
+      regs.hl.l = regs.hl.h;
+    break;
+    case 0x6D: // LD L,L
+    break;
+    case 0x6E: // LD L,(HL)
+      regs.hl.l = get1(regs.HL);
+    break;
+    case 0x6F: // LD L,A
+      regs.hl.l = regs.A;
+    break;
+    case 0x70: // LD (HL),B
+      store1(regs.HL, regs.bc.h);
+    break;
+    case 0x71: // LD (HL),C
+      store1(regs.HL, regs.bc.l);
+    break;
+    case 0x72: // LD (HL),D
+      store1(regs.HL, regs.de.h);
+    break;
+    case 0x73: // LD (HL),E
+      store1(regs.HL, regs.de.l);
+    break;
+    case 0x74: // LD (HL),H
+      store1(regs.HL, regs.hl.h);
+    break;
+    case 0x75: // LD (HL),L
+      store1(regs.HL, regs.hl.l);
+    break;
+    case 0x76: // HALT
+    return(resHALT);
+
+    case 0x77: // LD (HL),A
+      store1(regs.HL, regs.A);
+    break;
+    case 0x78: // LD A,B
+      regs.A = regs.bc.h;
+    break;
+    case 0x79: // LD A,C
+      regs.A = regs.bc.l;
+    break;
+    case 0x7A: // LD A,D
+      regs.A = regs.de.h;
+    break;
+    case 0x7B: // LD A,E
+      regs.A = regs.de.l;
+    break;
+    case 0x7C: // LD A,H
+      regs.A = regs.hl.h;
+    break;
+    case 0x7D: // LD A,L
+      regs.A = regs.hl.l;
+    break;
+    case 0x7E: // LD A,(HL)
+      regs.A = get1(regs.HL);
+    break;
+    case 0x7F: // LD A,A
+    break;
+    case 0xF9: // LD SP,HL
+      regs.SP = regs.HL;
+    break;
+    default:
+      return(resINV_INST);
+    break;
+  }
+  return(resGO);
+}
+
+int
+cl_z80::inst_inc(t_mem code)
+{
+  switch(code) {
+    case 0x03: // INC BC
+      ++regs.BC;
+    break;
+    case 0x04: // INC B
+      inc(regs.bc.h);
+    break;
+    case 0x0C: // INC C
+      inc(regs.bc.l);
+    break;
+    case 0x13: // INC DE
+      ++regs.DE;
+    break;
+    case 0x14: // INC D
+      inc(regs.de.h);
+    break;
+    case 0x1C: // INC E
+      inc(regs.de.l);
+    break;
+    case 0x23: // INC HL
+      ++regs.HL;
+    break;
+    case 0x24: // INC H
+      inc(regs.hl.h);
+    break;
+    case 0x2C: // INC L
+      inc(regs.hl.l);
+    break;
+    case 0x33: // INC SP
+      ++regs.SP;
+    break;
+    case 0x34: // INC (HL)
+      {unsigned char t=get1(regs.HL);
+         inc(t);
+         store1(regs.HL, t);
+      }
+    break;
+    case 0x3C: // INC A
+      inc(regs.A);
+    break;
+    default:
+      return(resINV_INST);
+    break;
+  }
+  return(resGO);
+}
+
+int
+cl_z80::inst_dec(t_mem code)
+{
+  switch(code) {
+    case 0x05: // DEC B
+      dec(regs.bc.h);
+    break;
+    case 0x0B: // DEC BC
+      --regs.BC;
+    break;
+    case 0x0D: // DEC C
+      dec(regs.bc.l);
+    break;
+    case 0x15: // DEC D
+      dec(regs.de.h);
+    break;
+    case 0x1B: // DEC DE
+      --regs.DE;
+    break;
+    case 0x1D: // DEC E
+      dec(regs.de.l);
+    break;
+    case 0x25: // DEC H
+      dec(regs.hl.h);
+    break;
+    case 0x2B: // DEC HL
+      --regs.HL;
+    break;
+    case 0x2D: // DEC L
+      dec(regs.hl.l);
+    break;
+    case 0x35: // DEC (HL)
+      {unsigned char t=get1(regs.HL);
+         dec(t);
+         store1(regs.HL, t);
+      }
+    break;
+    case 0x3B: // DEC SP
+      --regs.SP;
+    break;
+    case 0x3D: // DEC A
+      dec(regs.A);
+    break;
+    default:
+      return(resINV_INST);
+    break;
+  }
+  return(resGO);
+}
+
+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:
+          ::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.A = get1(regs.SP++);
+      regs.F = 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);
+}
 
 /* End of z80.src/inst.cc */